Compare commits

..

1 Commits

Author SHA1 Message Date
ZeldaZach
7daa9a0ca9 Attempt fix crash case 2025-02-08 20:18:06 -05:00
1222 changed files with 92610 additions and 186847 deletions

View File

@@ -7,7 +7,6 @@ RUN pacman --sync --refresh --sysupgrade --needed --noconfirm \
git \ git \
gtest \ gtest \
mariadb-libs \ mariadb-libs \
ninja \
protobuf \ protobuf \
qt6-base \ qt6-base \
qt6-imageformats \ qt6-imageformats \

View File

@@ -16,7 +16,6 @@ RUN apt-get update && \
libqt5sql5-mysql \ libqt5sql5-mysql \
libqt5svg5-dev \ libqt5svg5-dev \
libqt5websockets5-dev \ libqt5websockets5-dev \
ninja-build \
protobuf-compiler \ protobuf-compiler \
qt5-image-formats-plugins \ qt5-image-formats-plugins \
qtmultimedia5-dev \ qtmultimedia5-dev \

View File

@@ -15,14 +15,13 @@ RUN apt-get update && \
libprotobuf-dev \ libprotobuf-dev \
libqt6multimedia6 \ libqt6multimedia6 \
libqt6sql6-mysql \ libqt6sql6-mysql \
ninja-build \ qt6-svg-dev \
qt6-websockets-dev \
protobuf-compiler \ protobuf-compiler \
qt6-image-formats-plugins \ qt6-image-formats-plugins \
qt6-l10n-tools \ qt6-l10n-tools \
qt6-multimedia-dev \ qt6-multimedia-dev \
qt6-svg-dev \
qt6-tools-dev \ qt6-tools-dev \
qt6-tools-dev-tools \ qt6-tools-dev-tools \
qt6-websockets-dev \
&& apt-get clean \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*

View File

@@ -1,29 +0,0 @@
FROM debian:13
RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
build-essential \
ca-certificates \
ccache \
clang-format \
cmake \
file \
g++ \
git \
libgl-dev \
liblzma-dev \
libmariadb-dev-compat \
libprotobuf-dev \
libqt6multimedia6 \
libqt6sql6-mysql \
ninja-build \
protobuf-compiler \
qt6-image-formats-plugins \
qt6-l10n-tools \
qt6-multimedia-dev \
qt6-svg-dev \
qt6-tools-dev \
qt6-tools-dev-tools \
qt6-websockets-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -1,4 +1,4 @@
FROM fedora:42 FROM fedora:40
RUN dnf install -y \ RUN dnf install -y \
ccache \ ccache \
@@ -6,7 +6,6 @@ RUN dnf install -y \
gcc-c++ \ gcc-c++ \
git \ git \
mariadb-devel \ mariadb-devel \
ninja-build \
protobuf-devel \ protobuf-devel \
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \ qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
qt6-qtimageformats \ qt6-qtimageformats \

View File

@@ -1,4 +1,4 @@
FROM fedora:43 FROM fedora:41
RUN dnf install -y \ RUN dnf install -y \
ccache \ ccache \
@@ -6,7 +6,6 @@ RUN dnf install -y \
gcc-c++ \ gcc-c++ \
git \ git \
mariadb-devel \ mariadb-devel \
ninja-build \
protobuf-devel \ protobuf-devel \
qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \ qt6-{qttools,qtsvg,qtmultimedia,qtwebsockets}-devel \
qt6-qtimageformats \ qt6-qtimageformats \

View File

@@ -1,4 +1,4 @@
FROM debian:11 FROM ubuntu:20.04
RUN apt-get update && \ RUN apt-get update && \
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
@@ -9,12 +9,17 @@ RUN apt-get update && \
file \ file \
g++ \ g++ \
git \ git \
liblzma-dev \
libmariadb-dev-compat \ libmariadb-dev-compat \
libprotobuf-dev \ libprotobuf-dev \
libqt5multimedia5-plugins \
libqt5sql5-mysql \ libqt5sql5-mysql \
libqt5svg5-dev \
libqt5websockets5-dev \ libqt5websockets5-dev \
ninja-build \
protobuf-compiler \ protobuf-compiler \
qt5-default \
qt5-image-formats-plugins \
qtmultimedia5-dev \
qttools5-dev \ qttools5-dev \
qttools5-dev-tools \ qttools5-dev-tools \
&& apt-get clean \ && apt-get clean \

View File

@@ -17,7 +17,6 @@ RUN apt-get update && \
libqt6sql6-mysql \ libqt6sql6-mysql \
libqt6svg6-dev \ libqt6svg6-dev \
libqt6websockets6-dev \ libqt6websockets6-dev \
ninja-build \
protobuf-compiler \ protobuf-compiler \
qt6-image-formats-plugins \ qt6-image-formats-plugins \
qt6-l10n-tools \ qt6-l10n-tools \

View File

@@ -15,14 +15,13 @@ RUN apt-get update && \
libprotobuf-dev \ libprotobuf-dev \
libqt6multimedia6 \ libqt6multimedia6 \
libqt6sql6-mysql \ libqt6sql6-mysql \
ninja-build \ qt6-svg-dev \
qt6-websockets-dev \
protobuf-compiler \ protobuf-compiler \
qt6-image-formats-plugins \ qt6-image-formats-plugins \
qt6-l10n-tools \ qt6-l10n-tools \
qt6-multimedia-dev \ qt6-multimedia-dev \
qt6-svg-dev \
qt6-tools-dev \ qt6-tools-dev \
qt6-tools-dev-tools \ qt6-tools-dev-tools \
qt6-websockets-dev \
&& apt-get clean \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*

View File

@@ -11,9 +11,9 @@
# --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
# --dir <dir> sets the name of the build dir, default is "build" # --dir <dir> sets the name of the build dir, default is "build"
# --target-macos-version <version> sets the min os version - only used for macOS builds # --parallel <core count> sets how many cores cmake should build with in parallel
# uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_NO_CLIENT MAKE_TEST USE_CCACHE CCACHE_SIZE BUILD_DIR CMAKE_GENERATOR TARGET_MACOS_VERSION # uses env: BUILDTYPE MAKE_INSTALL MAKE_PACKAGE PACKAGE_TYPE PACKAGE_SUFFIX MAKE_SERVER MAKE_TEST USE_CCACHE CCACHE_SIZE BUILD_DIR PARALLEL_COUNT
# (correspond to args: --debug/--release --install --package <package type> --suffix <suffix> --server --test --ccache <ccache_size> --dir <dir>) # (correspond to args: --debug/--release --install --package <package type> --suffix <suffix> --server --test --ccache <ccache_size> --dir <dir> --parallel <core_count>)
# exitcode: 1 for failure, 3 for invalid arguments # exitcode: 1 for failure, 3 for invalid arguments
# Read arguments # Read arguments
@@ -47,10 +47,6 @@ while [[ $# != 0 ]]; do
MAKE_SERVER=1 MAKE_SERVER=1
shift shift
;; ;;
'--no-client')
MAKE_NO_CLIENT=1
shift
;;
'--test') '--test')
MAKE_TEST=1 MAKE_TEST=1
shift shift
@@ -71,10 +67,6 @@ while [[ $# != 0 ]]; do
shift shift
fi fi
;; ;;
'--vcpkg')
USE_VCPKG=1
shift
;;
'--dir') '--dir')
shift shift
if [[ $# == 0 ]]; then if [[ $# == 0 ]]; then
@@ -84,13 +76,13 @@ while [[ $# != 0 ]]; do
BUILD_DIR="$1" BUILD_DIR="$1"
shift shift
;; ;;
'--target-macos-version') '--parallel')
shift shift
if [[ $# == 0 ]]; then if [[ $# == 0 ]]; then
echo "::error file=$0::--target-macos-version expects an argument" echo "::error file=$0::--parallel expects an argument"
exit 3 exit 3
fi fi
TARGET_MACOS_VERSION="$1" PARALLEL_COUNT="$1"
shift shift
;; ;;
*) *)
@@ -113,17 +105,11 @@ fi
mkdir -p "$BUILD_DIR" mkdir -p "$BUILD_DIR"
cd "$BUILD_DIR" cd "$BUILD_DIR"
# Set minimum CMake Version
export CMAKE_POLICY_VERSION_MINIMUM=3.10
# Add cmake flags # Add cmake flags
flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE") flags=("-DCMAKE_BUILD_TYPE=$BUILDTYPE")
if [[ $MAKE_SERVER ]]; then if [[ $MAKE_SERVER ]]; then
flags+=("-DWITH_SERVER=1") flags+=("-DWITH_SERVER=1")
fi fi
if [[ $MAKE_NO_CLIENT ]]; then
flags+=("-DWITH_CLIENT=0" "-DWITH_ORACLE=0" "-DWITH_DBCONVERTER=0")
fi
if [[ $MAKE_TEST ]]; then if [[ $MAKE_TEST ]]; then
flags+=("-DTEST=1") flags+=("-DTEST=1")
fi fi
@@ -137,12 +123,19 @@ fi
if [[ $PACKAGE_TYPE ]]; then if [[ $PACKAGE_TYPE ]]; then
flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE") flags+=("-DCPACK_GENERATOR=$PACKAGE_TYPE")
fi fi
if [[ $USE_VCPKG ]]; then
flags+=("-DUSE_VCPKG=1")
fi
# Add cmake --build flags # Add cmake --build flags
buildflags=(--config "$BUILDTYPE") buildflags=(--config "$BUILDTYPE")
if [[ $PARALLEL_COUNT ]]; then
if [[ $(cmake --build /not_a_dir --parallel 2>&1 | head -1) =~ parallel ]]; then
# workaround for bionic having an old cmake
echo "this version of cmake does not support --parallel, using native build tool -j instead"
buildflags+=(-- -j "$PARALLEL_COUNT")
# note, no normal build flags should be added after this
else
buildflags+=(--parallel "$PARALLEL_COUNT")
fi
fi
function ccachestatsverbose() { function ccachestatsverbose() {
# note, verbose only works on newer ccache, discard the error # note, verbose only works on newer ccache, discard the error
@@ -155,72 +148,6 @@ function ccachestatsverbose() {
} }
# Compile # Compile
if [[ $RUNNER_OS == macOS ]]; then
if [[ $TARGET_MACOS_VERSION ]]; then
# CMAKE_OSX_DEPLOYMENT_TARGET is a vanilla cmake flag needed to compile to target macOS version
flags+=("-DCMAKE_OSX_DEPLOYMENT_TARGET=$TARGET_MACOS_VERSION")
# vcpkg dependencies need a vcpkg triplet file to compile to the target macOS version
# an easy way is to copy the x64-osx.cmake file and modify it
triplets_dir="/tmp/cmake/triplets"
triplet_version="custom-triplet"
triplet_file="$triplets_dir/$triplet_version.cmake"
arch=$(uname -m)
if [[ $arch == x86_64 ]]; then
arch="x64"
fi
mkdir -p "$triplets_dir"
cp "../vcpkg/triplets/$arch-osx.cmake" "$triplet_file"
echo "set(VCPKG_CMAKE_SYSTEM_VERSION $TARGET_MACOS_VERSION)" >>"$triplet_file"
echo "set(VCPKG_OSX_DEPLOYMENT_TARGET $TARGET_MACOS_VERSION)" >>"$triplet_file"
flags+=("-DVCPKG_OVERLAY_TRIPLETS=$triplets_dir")
flags+=("-DVCPKG_HOST_TRIPLET=$triplet_version")
flags+=("-DVCPKG_TARGET_TRIPLET=$triplet_version")
echo "::group::Generated triplet $triplet_file"
cat "$triplet_file"
echo "::endgroup::"
fi
echo "::group::Signing Certificate"
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]; then
echo "$MACOS_CERTIFICATE" | base64 --decode >"certificate.p12"
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
security default-keychain -s build.keychain
security set-keychain-settings -t 3600 -l build.keychain
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain
echo "macOS signing certificate successfully imported and keychain configured."
else
echo "No signing certificate configured. Skipping set up of keychain in macOS environment."
fi
echo "::endgroup::"
if [[ $MAKE_PACKAGE ]]; then
# Workaround https://github.com/actions/runner-images/issues/7522
# have hdiutil repeat the command 10 times in hope of success
hdiutil_script="/tmp/hdiutil.sh"
# shellcheck disable=SC2016
echo '#!/bin/bash
i=0
while ! hdiutil "$@"; do
if (( ++i >= 10 )); then
echo "Error: hdiutil failed $i times!" >&2
break
fi
sleep 1
done' >"$hdiutil_script"
chmod +x "$hdiutil_script"
flags+=(-DCPACK_COMMAND_HDIUTIL="$hdiutil_script")
fi
elif [[ $RUNNER_OS == Windows ]]; then
# 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
buildflags+=(-- -p:UseMultiToolTask=true -p:EnableClServerMode=true)
fi
if [[ $USE_CCACHE ]]; then if [[ $USE_CCACHE ]]; then
echo "::group::Show ccache stats" echo "::group::Show ccache stats"
ccachestatsverbose ccachestatsverbose
@@ -229,13 +156,17 @@ fi
echo "::group::Configure cmake" echo "::group::Configure cmake"
cmake --version cmake --version
echo "Running cmake with flags: ${flags[*]}"
cmake .. "${flags[@]}" cmake .. "${flags[@]}"
echo "::endgroup::" echo "::endgroup::"
echo "::group::Build project" echo "::group::Build project"
echo "Running cmake --build with flags: ${buildflags[*]}" if [[ $RUNNER_OS == Windows ]]; then
# 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
cmake --build . "${buildflags[@]}" -- -p:UseMultiToolTask=true -p:EnableClServerMode=true
else
cmake --build . "${buildflags[@]}" cmake --build . "${buildflags[@]}"
fi
echo "::endgroup::" echo "::endgroup::"
if [[ $USE_CCACHE ]]; then if [[ $USE_CCACHE ]]; then
@@ -244,19 +175,6 @@ if [[ $USE_CCACHE ]]; then
echo "::endgroup::" echo "::endgroup::"
fi fi
if [[ $RUNNER_OS == macOS ]]; then
echo "::group::Inspect Mach-O binaries"
for app in cockatrice oracle servatrice dbconverter; do
binary="$GITHUB_WORKSPACE/build/$app/$app.app/Contents/MacOS/$app"
echo "Inspecting $app..."
vtool -show-build "$binary"
file "$binary"
lipo -info "$binary"
echo ""
done
echo "::endgroup::"
fi
if [[ $MAKE_TEST ]]; then if [[ $MAKE_TEST ]]; then
echo "::group::Run tests" echo "::group::Run tests"
ctest -C "$BUILDTYPE" --output-on-failure ctest -C "$BUILDTYPE" --output-on-failure
@@ -271,6 +189,12 @@ fi
if [[ $MAKE_PACKAGE ]]; then if [[ $MAKE_PACKAGE ]]; then
echo "::group::Create package" echo "::group::Create package"
if [[ $RUNNER_OS == macOS ]]; then
# Workaround https://github.com/actions/runner-images/issues/7522
echo "killing XProtectBehaviorService"; sudo pkill -9 XProtect >/dev/null || true;
echo "waiting for XProtectBehaviorService kill"; while pgrep "XProtect"; do sleep 3; done;
fi
cmake --build . --target package --config "$BUILDTYPE" cmake --build . --target package --config "$BUILDTYPE"
echo "::endgroup::" echo "::endgroup::"

View File

@@ -137,11 +137,10 @@ if [[ $SAVE ]]; then
fi fi
# Set compile function, runs the compile script on the image, passes arguments to the script # Set compile function, runs the compile script on the image, passes arguments to the script
# shellcheck disable=2120
function RUN () function RUN ()
{ {
echo "running image:" echo "running image:"
if [[ $(docker images) =~ $IMAGE_NAME ]]; then if [[ $(docker images) =~ "$IMAGE_NAME" ]]; then
local args=(--mount "type=bind,source=$PWD,target=/src") local args=(--mount "type=bind,source=$PWD,target=/src")
args+=(--workdir "/src") args+=(--workdir "/src")
args+=(--user "$(id -u):$(id -g)") args+=(--user "$(id -u):$(id -g)")
@@ -149,10 +148,6 @@ function RUN ()
args+=(--mount "type=bind,source=$CCACHE_DIR,target=/.ccache") args+=(--mount "type=bind,source=$CCACHE_DIR,target=/.ccache")
args+=(--env "CCACHE_DIR=/.ccache") args+=(--env "CCACHE_DIR=/.ccache")
fi fi
if [[ -n "$CMAKE_GENERATOR" ]]; then
args+=(--env "CMAKE_GENERATOR=$CMAKE_GENERATOR")
fi
# shellcheck disable=2086
docker run "${args[@]}" $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS "$@" docker run "${args[@]}" $RUN_ARGS "$IMAGE_NAME" bash "$BUILD_SCRIPT" $RUN_OPTS "$@"
return $? return $?
else else
@@ -166,6 +161,5 @@ function RUN ()
if [[ $INTERACTIVE ]]; then if [[ $INTERACTIVE ]]; then
export BUILD_SCRIPT="-i" export BUILD_SCRIPT="-i"
export RUN_ARGS="$RUN_ARGS -it" export RUN_ARGS="$RUN_ARGS -it"
# shellcheck disable=2119
RUN RUN
fi fi

View File

@@ -11,19 +11,11 @@ if ! git merge-base origin/master HEAD; then
fi fi
# Check formatting using format.sh # Check formatting using format.sh
echo "Checking your code using format.sh..." echo "Checking your code using clang-format/cmake-format..."
diff="$(./format.sh --diff --cmake --shell --print-version --branch origin/master)" diff="$(./format.sh --diff --cmake --cf-version --branch origin/master)"
err=$? err=$?
sep="
----------
"
used_version="${diff%%"$sep"*}"
diff="${diff#*"$sep"}"
changes_to_make="${diff%%"$sep"*}"
files_to_edit="${diff#*"$sep"}"
case $err in case $err in
1) 1)
cat <<EOM cat <<EOM
@@ -41,13 +33,14 @@ case $err in
*********************************************************** ***********************************************************
Used version: Used version:
$used_version ${diff%%
----------
Affected files: *}
$files_to_edit
The following changes should be made: The following changes should be made:
$changes_to_make ${diff#*
----------
}
Exiting... Exiting...
EOM EOM
@@ -65,9 +58,6 @@ EOM
*** *** *** ***
*********************************************************** ***********************************************************
Used version:
$used_version
Exiting... Exiting...
EOM EOM
exit 0 exit 0

View File

@@ -4,30 +4,24 @@
git push -d origin --REPLACE-WITH-BETA-LIST-- git push -d origin --REPLACE-WITH-BETA-LIST--
--> -->
<!-- This list of binaries should be updated every time the CI is changed to include all targets --> <!-- This list of binaries should be updated every time the CI is changed to
include different targets -->
<pre> <pre>
Available pre-compiled binaries for installation: <b>Pre-compiled binaries we serve:</b>
- <kbd>Windows 10+</kbd>
- <kbd>Windows 7+</kbd>
- <kbd>macOS 14+</kbd> ("Sonoma") / Apple M
- <kbd>macOS 13+</kbd> ("Ventura") / Intel
- <kbd>Ubuntu 24.04 LTS</kbd> ("Noble Numbat")
- <kbd>Ubuntu 22.04 LTS</kbd> ("Jammy Jellyfish")
- <kbd>Ubuntu 20.04 LTS</kbd> ("Focal Fossa")
- <kbd>Debian 12</kbd> ("Bookworm")
- <kbd>Debian 11</kbd> ("Bullseye")
- <kbd>Fedora 41</kbd>
- <kbd>Fedora 40</kbd>
<b>Windows</b> <i>We are also packaged in <kbd>Arch Linux</kbd>'s official "extra" repository, courtesy of @FFY00</i>
• <kbd>Windows 10+</kbd> <i>General Linux support is available via a <kbd>flatpak</kbd> package (Flathub)</i>
• <kbd>Windows 7+</kbd>
<b>macOS</b>
• <kbd>macOS 15+</kbd> <sub><i>Sequoia</i></sub> <sub>Apple M</sub>
• <kbd>macOS 14+</kbd> <sub><i>Sonoma</i></sub> <sub>Apple M</sub>
• <kbd>macOS 13+</kbd> <sub><i>Ventura</i></sub> <sub>Intel</sub>
<b>Linux</b>
• <kbd>Ubuntu 24.04 LTS</kbd> <sub><i>Noble Numbat</i></sub>
• <kbd>Ubuntu 22.04 LTS</kbd> <sub><i>Jammy Jellyfish</i></sub>
• <kbd>Debian 13</kbd> <sub><i>Trixie</i></sub>
• <kbd>Debian 12</kbd> <sub><i>Bookworm</i></sub>
• <kbd>Debian 11</kbd> <sub><i>Bullseye</i></sub>
• <kbd>Fedora 43</kbd>
• <kbd>Fedora 42</kbd>
<sub>We are also packaged in <kbd>Arch Linux</kbd>'s <a href="https://archlinux.org/packages/extra/x86_64/cockatrice">official extra repository</a>, courtesy of @FFY00.</sub>
<sub>General Linux support is available via a <kbd>flatpak</kbd> package at <a href="https://flathub.org/apps/io.github.Cockatrice.cockatrice">Flathub</a>!</sub>
</pre> </pre>
@@ -41,7 +35,7 @@ If you ever encounter a bug, have a suggestion or idea, or feel a need for a dev
For basic information related to the app and getting started, please take a look at our official site: **https://cockatrice.github.io** For basic information related to the app and getting started, please take a look at our official site: **https://cockatrice.github.io**
If you'd like to help and contribute to Cockatrice in any way, check out our [README](https://github.com/Cockatrice/Cockatrice#contribute). If you'd like to help and contribute to Cockatrice in any way, check out our [README](https://github.com/Cockatrice/Cockatrice#get-involved-).
We're always available to answer questions you may have on how the program works and how you can provide a meaningful contribution. We're always available to answer questions you may have on how the program works and how you can provide a meaningful contribution.

View File

@@ -10,5 +10,5 @@ Last changes are based on commit {{ .commit }}.
*This PR is automatically generated and updated by the workflow at `.github/workflows/translations-push.yml`. Review [action runs][2].*<br> *This PR is automatically generated and updated by the workflow at `.github/workflows/translations-push.yml`. Review [action runs][2].*<br>
*After merging, all changes to the source language are available for translation at [Transifex][1] shortly.* *After merging, all changes to the source language are available for translation at [Transifex][1] shortly.*
[1]: https://explore.transifex.com/cockatrice/cockatrice/ [1]: https://app.transifex.com/cockatrice/cockatrice/
[2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-push.yml?query=branch%3Amaster [2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-push.yml?query=branch%3Amaster

View File

@@ -25,9 +25,6 @@ IndentCaseLabels: true
PointerAlignment: Right PointerAlignment: Right
SortIncludes: true SortIncludes: true
IncludeBlocks: Regroup IncludeBlocks: Regroup
StatementAttributeLikeMacros: [emit]
# requires clang-format 16
# RemoveSemicolon: true
--- ---
Language: Proto Language: Proto
AllowShortFunctionsOnASingleLine: None AllowShortFunctionsOnASingleLine: None

View File

@@ -1,5 +1,3 @@
<!--! @page contributing Contributing -->
&nbsp; [Introduction](#contributing-to-cockatrice) | [Code Style Guide]( &nbsp; [Introduction](#contributing-to-cockatrice) | [Code Style Guide](
#code-style-guide) | [Translations](#translations) | [Release Management]( #code-style-guide) | [Translations](#translations) | [Release Management](
#release-management) #release-management)
@@ -9,33 +7,32 @@
<br> <br>
# Contributing to Cockatrice # # Contributing to Cockatrice #
First off, thanks for taking the time to contribute to our project! 🎉 ❤ ️✨
First off, thanks for taking the time and considering to lend a helping hand to our project! 🎉 ❤ ️✨ The following is a set of guidelines for contributing to Cockatrice. These are
mostly guidelines, not rules. Use your best judgment, and feel free to propose
> [!NOTE] changes to this document in a pull request.
> The following is a set of guidelines for contributing to Cockatrice.
> These are mostly guidelines, not rules. Use your best judgment, and feel free to
> propose changes to this document in a pull request.
>
> [![Discord](
> https://img.shields.io/discord/314987288398659595?label=Discord&logo=discord&logoColor=white)](
> https://discord.gg/3Z9yzmA)
> If you'd like to ask questions, get advice, or just want to say "Hi",
> the Cockatrice Development Team uses [Discord](https://discord.gg/ZASRzKu)
> for communications and you can reach out in the `#dev` channel.
# Recommended Setups # # Recommended Setups #
For those developers on **Linux** or **macOS** environment, many of our For those developers who like the Linux or MacOS environment, many of our
developers like working with a nifty program called [CLion]( developers like working with a nifty program called [CLion](
https://www.jetbrains.com/clion/). The program is a great asset and one of the https://www.jetbrains.com/clion/). The program's a great asset and one of the
best tools you'll find on these systems. best tools you'll find on these systems, but you're welcomed to use any IDE
you most enjoy.
Developers on **Windows** systems tend to find [Visual Studio]( Developers who like Windows development tend to find [Visual Studio](
https://www.visualstudio.com/) the best tool for the job. https://www.visualstudio.com/) the best tool for the job.
But you're welcomed to use any IDE you enjoy most of course! [![Discord](https://img.shields.io/discord/314987288398659595?label=Discord&logo=discord&logoColor=white&color=7289da)](https://discord.gg/ZASRzKu)
[![Gitter Chat](https://img.shields.io/gitter/room/Cockatrice/Cockatrice.svg)](https://gitter.im/Cockatrice/Cockatrice)
If you'd like to ask questions, get advice, or just want to say hi,
the Cockatrice Development Team uses [Discord](https://discord.gg/ZASRzKu)
for communications in the #dev channel. If you're not into Discord, we also
have a [Gitter](https://gitter.im/Cockatrice/Cockatrice) channel available,
albeit slightly less active.
# Code Style Guide # # Code Style Guide #
@@ -67,7 +64,7 @@ information on our formatting guidelines.
### Compatibility ### ### Compatibility ###
Cockatrice is currently compiled on all platforms using <kbd>C++20</kbd>. Cockatrice is currently compiled on all platforms using <kbd>C++11</kbd>.
You'll notice <kbd>C++03</kbd> code throughout the codebase. Please feel free You'll notice <kbd>C++03</kbd> code throughout the codebase. Please feel free
to help convert it over! to help convert it over!
@@ -81,12 +78,11 @@ or other appropriate conversion.
### Formatting ### ### Formatting ###
The handy tool `clang-format` can format your code for you, it is available for The handy tool `clang-format` can format your code for you, it is available for
almost any environment. A special [`.clang-format`]( almost any environment. A special `.clang-format` configuration file is
https://github.com/Cockatrice/Cockatrice/blob/master/.clang-format) configuration file is
included in the project and is used to format your code. included in the project and is used to format your code.
We've also included a bash script, `format.sh`, that will use clang-format to We've also included a bash script, `format.sh`, that will use clang-format to
format all files in your PR in one go. Use `./format.sh --help` to show a full format all files in your pr in one go. Use `./format.sh --help` to show a full
help page. help page.
To run clang-format on a single source file simply use the command To run clang-format on a single source file simply use the command
@@ -94,10 +90,10 @@ To run clang-format on a single source file simply use the command
clang-format with a specific version number appended, clang-format with a specific version number appended,
`find /usr/bin -name clang-format*` should find it for you) `find /usr/bin -name clang-format*` should find it for you)
See the [clang-format documentation]( See [the clang-format documentation](
https://clang.llvm.org/docs/ClangFormat.html) for more information about the tool. https://clang.llvm.org/docs/ClangFormat.html) for more information about the tool.
#### Header Files #### #### Header files ####
Use header files with the extension `.h` and source files with the extension Use header files with the extension `.h` and source files with the extension
`.cpp`. `.cpp`.
@@ -238,7 +234,7 @@ mutating objects.)
When pointers can't be avoided, try to use a smart pointer of some sort, such When pointers can't be avoided, try to use a smart pointer of some sort, such
as `QScopedPointer`, or, less preferably, `QSharedPointer`. as `QScopedPointer`, or, less preferably, `QSharedPointer`.
### Database Migrations ### ### Database migrations ###
The servatrice database's schema can be found at `servatrice/servatrice.sql`. The servatrice database's schema can be found at `servatrice/servatrice.sql`.
Everytime the schema gets modified, some other steps are due: Everytime the schema gets modified, some other steps are due:
@@ -259,7 +255,7 @@ Ensure that the migration produces the expected effects; e.g. if you add a
new column, make sure the migration places it in the same order as new column, make sure the migration places it in the same order as
servatrice.sql. servatrice.sql.
### Protocol Buffer ### ### Protocol buffer ###
Cockatrice and Servatrice exchange data using binary messages. The syntax of Cockatrice and Servatrice exchange data using binary messages. The syntax of
these messages is defined in the `proto` files in the `common/pb` folder. These these messages is defined in the `proto` files in the `common/pb` folder. These
@@ -272,7 +268,6 @@ new clients incompatible to the old server and vice versa.
You can find more information on how we use Protobuf on [our wiki!]( You can find more information on how we use Protobuf on [our wiki!](
https://github.com/Cockatrice/Cockatrice/wiki/Client-server-protocol) https://github.com/Cockatrice/Cockatrice/wiki/Client-server-protocol)
# Reviewing Pull Requests # # Reviewing Pull Requests #
After you have finished your changes to the project you should put them on a After you have finished your changes to the project you should put them on a
@@ -291,7 +286,6 @@ all changes have been approved your pull request will be squashed into a single
commit and merged into the master branch by a team member. Your change will then commit and merged into the master branch by a team member. Your change will then
be included in the next release 👍 be included in the next release 👍
# Translations # # Translations #
Basic workflow for translations: Basic workflow for translations:
@@ -300,16 +294,16 @@ Basic workflow for translations:
3. Maintainer verifies and merges the change; 3. Maintainer verifies and merges the change;
4. Transifex picks up the new files from GitHub automatically; 4. Transifex picks up the new files from GitHub automatically;
5. Translators translate the new untranslated strings on Transifex; 5. Translators translate the new untranslated strings on Transifex;
6. Before a release, a maintainer fetches the newest translations from Transifex. 6. Before a release, a maintainer fetches the updated translations from Transifex.
### Using Translations (for developers) ### ### Using Translations (for developers) ###
All user interface strings inside Cockatrice's source code must be written All user interface strings inside Cockatrice's source code must be written
in English (US). in English (US).
Translations to other languages are managed using [Transifex]( Translations to other languages are managed using [Transifex](
https://transifex.com/cockatrice/cockatrice/). https://www.transifex.com/projects/p/cockatrice/).
Adding a new string for translation is as easy as adding the string in the Adding a new string to translate is as easy as adding the string in the
`tr("")` function, the string will be picked up as translatable automatically `tr("")` function, the string will be picked up as translatable automatically
and translated as needed. and translated as needed.
For example, setting the text of a label in the way that the string For example, setting the text of a label in the way that the string
@@ -321,9 +315,9 @@ nameLabel.setText(tr("My name is:"));
To translate a string that would have plural forms you can add the amount to To translate a string that would have plural forms you can add the amount to
the tr() call, also you can add an extra string as a hint for translators: the tr() call, also you can add an extra string as a hint for translators:
```c++ ```c++
QString message = tr("Everyone draws %n cards", "english hint for translators", amount); QString message = tr("Everyone draws %n cards", "pop up message", amount);
``` ```
See [Qt's wiki on translations]( See [QT's wiki on translations](
https://doc.qt.io/qt-5/i18n-source-translation.html#handling-plurals) https://doc.qt.io/qt-5/i18n-source-translation.html#handling-plurals)
If you're about to propose a change that adds or modifies any translatable If you're about to propose a change that adds or modifies any translatable
@@ -331,7 +325,7 @@ string in the code, you don't need to take care of adding the new strings to
the translation files.<br> the translation files.<br>
We have an automated process to update our language source files on a schedule We have an automated process to update our language source files on a schedule
and provide the translators on Transifex with the new contents.<br> and provide the translators on Transifex with the new contents.<br>
Maintainers can also manually trigger this workflow on demand via GitHub Actions. Maintainers can also manually trigger this on demand.
### Maintaining Translations (for maintainers) ### ### Maintaining Translations (for maintainers) ###
@@ -395,27 +389,27 @@ Now you are ready to commit your changes and open a PR.
</details> </details>
Once the changes get merged, Transifex will pick up the modified files Once the changes get merged, Transifex will pick up the modified files
automatically (checked every few hours) and update the web editor where automatically (checked every few hours) and update their online editor where
translators will be able to translate the new strings right in the browser. translators will be able to translate the new strings right in the browser.
### Releasing Translations (for maintainers) ### ### Releasing Translations (for maintainers) ###
Before publishing a new release, a maintainer should fetch the most up to date Before rushing out a new release, a maintainer should fetch the most up to date
translations from Transifex and commit them into the Cockatrice source code. translations from Transifex and commit them into the Cockatrice source code.
We utilize the official GitHub integration to push all languages that are 100% This can be done manually from the Transifex web interface, but it's quite time
translated from Transifex to our GitHub repo automatically. consuming.
On top, it runs on a quarterly schedule to update changes for incomplete languages.
A synchronisation/update can also be triggered manually from the Transifex web interface As an alternative, you can install the Transifex CLI:
and a translation treshold can be set.
http://docs.transifex.com/developer/client/
As an alternative, you can install the [Transifex CLI](https://developers.transifex.com/docs/cli).
You'll then be able to use a git-like cli command to push and pull translations You'll then be able to use a git-like cli command to push and pull translations
from Transifex to the source code and vice versa. from Transifex to the source code and vice versa.
### Adding Translations (for translators) ### ### Adding Translations (for translators) ###
As a translator, you can help to translate new strings on [Transifex]( As a translator you can help translate the new strings on [Transifex](
https://www.transifex.com/projects/p/cockatrice/) to your native language. https://www.transifex.com/projects/p/cockatrice/).
Please have a look at the specific [FAQ for translators]( Please have a look at the specific [FAQ for translators](
https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ). https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ).
@@ -425,9 +419,9 @@ https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ).
### Publishing A New Release ### ### Publishing A New Release ###
We use [GitHub Releases](https://github.com/Cockatrice/Cockatrice/releases) to We use [GitHub Releases](https://github.com/Cockatrice/Cockatrice/releases) to
publish new stable versions and beta releases. publish new stable versions and betas.
Whenever a git tag is pushed to the repository, GitHub will create a draft Whenever a git tag is pushed to the repository github will create a draft
release and upload binaries from our CI automatically. release and upload binaries automatically.
To create a tag, simply do the following: To create a tag, simply do the following:
```bash ```bash
@@ -439,16 +433,18 @@ git push $UPSTREAM $TAG_NAME
``` ```
You should define the variables as such: You should define the variables as such:
- `$UPSTREAM`: the remote for `git@github.com:Cockatrice/Cockatrice.git` ```
- `$TAG_NAME` should be formatted as: `$UPSTREAM` - the remote for git@github.com:Cockatrice/Cockatrice.git
`$TAG_NAME` should be formatted as:
- `YYYY-MM-DD-Release-MAJ.MIN.PATCH` for **stable releases** - `YYYY-MM-DD-Release-MAJ.MIN.PATCH` for **stable releases**
- `YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X` for **beta releases**<br> - `YYYY-MM-DD-Development-MAJ.MIN.PATCH-beta.X` for **beta releases**<br>
With <kbd>MAJ</kbd>.<kbd>MIN</kbd>.<kbd>PATCH</kbd> being the NEXT release version! With *MAJ.MIN.PATCH* being the NEXT release version!
```
This will cause a tagged release to be established on the GitHub repository, This will cause a tagged release to be established on the GitHub repository,
with the binaries being added to the release whenever they are done building in CI. with the binaries being added to the release whenever they are ready.
The release is initially a draft, where the release notes can be edited and after The release is initially a draft, where the path notes can be edited and after
all is checked and ready, it can be published as GitHub release. all is good and ready it can be published on GitHub.
If you use a SemVer tag including "beta", the release that will be created at If you use a SemVer tag including "beta", the release that will be created at
GitHub will be marked as a "Pre-release" automatically. GitHub will be marked as a "Pre-release" automatically.
The target of the `.../latest` URL will not be changed in that case, it always The target of the `.../latest` URL will not be changed in that case, it always
@@ -461,7 +457,7 @@ revoke the tag by doing the following:
git push --delete upstream $TAG_NAME git push --delete upstream $TAG_NAME
git tag -d $TAG_NAME git tag -d $TAG_NAME
``` ```
You can also do this on GitHub, you'll also want to delete the false release. You can also do this on GitHub, you'll also want to delete the new release.
In the first lines of [CMakeLists.txt]( In the first lines of [CMakeLists.txt](
https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt) https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt)
@@ -472,24 +468,25 @@ coming from the tag title, it's good practice to increment the ones at CMake
after every full release to stress that master is ahead of the last stable after every full release to stress that master is ahead of the last stable
release. release.
The preferred flow of operation is: The preferred flow of operation is:
- Just before a release, make sure the version number in CMakeLists.txt is set * Just before a release, make sure the version number in CMakeLists.txt is set
to the same release version you are about to tag. to the same release version you are about to tag.
- This is also the time to change the pretty name in CMakeLists.txt called * This is also the time to change the pretty name in CMakeLists.txt called
`GIT_TAG_RELEASENAME` and commit and push these changes. GIT_TAG_RELEASENAME and commit and push these changes.
- Tag the release following the previously described syntax in order to get it * Tag the release following the previously described syntax in order to get it
correctly built and deployed by CI. correctly built and deployed by CI.
- Wait for the configuration step to create the release and update the patch * Wait for the configure step to create the release and update the patch
notes. notes.
- Check on the GitHub Actions page for build progress which should be the top * Check on the github actions page for build progress which should be the top
listed [here]( listed [here](
https://github.com/Cockatrice/Cockatrice/actions?query=event%3Apush+-branch%3Amaster https://github.com/Cockatrice/Cockatrice/actions?query=event%3Apush+-branch%3Amaster
). ).
- When the build has been completed, you can verify if all uploaded files on the * When the build has been completed you can verify all uploaded files on the
draft release are included and hit the publish button. release are in order and hit the publish button.
- After the release is complete, update the CMake version number again to the * After the release is complete, update the CMake version number again to the
next targeted beta version, typically increasing `PROJECT_VERSION_PATCH` by next targeted beta version, typically increasing `PROJECT_VERSION_PATCH` by
one. one.
When releasing a new stable version, all previous beta releases (and tags) When releasing a new stable version, all previous beta releases (and tags)
should be deleted as well. should be deleted. This is needed for Cockatrice to update users of the "Beta"
release channel correctly to the latest stable version as well.
This can be done the same way as revoking tags, mentioned above. This can be done the same way as revoking tags, mentioned above.

View File

@@ -2,31 +2,20 @@
name: "🐛 Bug Report" name: "🐛 Bug Report"
about: Report an issue encountered while using Cockatrice about: Report an issue encountered while using Cockatrice
title: '' title: ''
type: 'Bug' labels: 'Bug'
labels: ''
assignees: '' assignees: ''
--- ---
<!-- READ THIS BEFORE POSTING <!-- READ THIS BEFORE POSTING
In Cockatrice, go to "Help""View Debug Log" and copy all information displayed at the Go to "Help → View Debug Log" in Cockatrice and copy all information at the
top (above the separation line "----"), to below "System Information" section in this ticket! top (above the separation line) below "System Information" in this ticket!
If you can't start Cockatrice to access these details, make If you can't start Cockatrice to access these details, make
sure to post your OS and the file name of the setup binary instead. sure to post your OS and the file name of the setup binary instead. -->
-->
**System Information:** **System Information:**
<!-- Read the hint above on where to find the important information to provide here! -->
<details><summary>Debug Log:</summary>
<!--
In Cockatrice, go to "Help" → "View Debug Log", click the "Copy to clickboard" button and paste the output here.
-->
</details>
_______________________________________________________________________________________ _______________________________________________________________________________________
<!-- Explain your issue in detail here! Please attach screenshots if possible. --> <!-- Explain your issue in detail here! Please attach screenshots if possible. -->
@@ -36,7 +25,7 @@ ________________________________________________________________________________
_______________________________________________________________________________________ _______________________________________________________________________________________
<!-- Describe the sequence of actions needed to experience the bug. --> <!-- Describe the sequence of actions needed to experience the bug -->
**Steps to reproduce:** **Steps to reproduce:**
- Do A - Do A

View File

@@ -4,6 +4,6 @@ contact_links:
url: https://discord.gg/3Z9yzmA url: https://discord.gg/3Z9yzmA
about: Need help with using the client? Want to find some games? Try the Discord server! about: Need help with using the client? Want to find some games? Try the Discord server!
- name: 🌐 Translations (Help improve the localization of the app) - name: 🌐 Translations (Help improve the localization of the app)
url: https://explore.transifex.com/cockatrice/cockatrice/ url: https://www.transifex.com/cockatrice/cockatrice/
# it is not possible to add a link to the wiki to this description # it is not possible to add a link to the wiki to this description
about: For more information and guidance check our Translation FAQ on our wiki! about: For more information and guidance check our Translation FAQ on our wiki!

View File

@@ -1,9 +1,8 @@
--- ---
name: "💡 Feature Request" name: "💡 Feature Request"
about: Request a new feature for Cockatrice about: Request a new feature
title: '' title: ''
type: 'Feature' labels: 'Feature Request'
labels: ''
assignees: '' assignees: ''
--- ---

View File

@@ -1,42 +1,22 @@
name: Build Desktop name: Build Desktop
permissions:
contents: write
id-token: write
attestations: write
actions: write # needed for ccache action to be able to delete gha caches
on: on:
push: push:
branches: branches:
- master - master
paths: paths-ignore:
- '*/**' # matches all files not in root - '**.md'
- '!**.md' - 'webclient/**'
- '!.github/**' - '.github/workflows/web-*.yml'
- '!.husky/**' - '.github/workflows/translations-*.yml'
- '!.tx/**'
- '!doc/**'
- '!webclient/**'
- '.github/workflows/desktop-build.yml'
- 'CMakeLists.txt'
- 'vcpkg.json'
- 'vcpkg'
tags: tags:
- '*' - '*'
pull_request: pull_request:
paths: paths-ignore:
- '*/**' # matches all files not in root - '**.md'
- '!**.md' - 'webclient/**'
- '!.github/**' - '.github/workflows/web-*.yml'
- '!.husky/**' - '.github/workflows/translations-*.yml'
- '!.tx/**'
- '!doc/**'
- '!webclient/**'
- '.github/workflows/desktop-build.yml'
- 'CMakeLists.txt'
- 'vcpkg.json'
- 'vcpkg'
# Cancel earlier, unfinished runs of this workflow on the same branch (unless on master) # Cancel earlier, unfinished runs of this workflow on the same branch (unless on master)
concurrency: concurrency:
@@ -70,7 +50,7 @@ jobs:
- name: Checkout - name: Checkout
if: steps.configure.outputs.tag != null if: steps.configure.outputs.tag != null
uses: actions/checkout@v6 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -114,30 +94,25 @@ jobs:
- distro: Debian - distro: Debian
version: 11 version: 11
package: DEB package: DEB
test: skip # Running tests on all distros is superfluous
- distro: Servatrice_Debian
version: 11
package: DEB
test: skip
server_only: yes
- distro: Debian - distro: Debian
version: 12 version: 12
package: DEB package: DEB
- distro: Fedora
version: 40
package: RPM
test: skip # Running tests on all distros is superfluous test: skip # Running tests on all distros is superfluous
- distro: Debian - distro: Fedora
version: 13 version: 41
package: RPM
- distro: Ubuntu
version: 20.04
package: DEB package: DEB
test: skip # Ubuntu 20.04 has a broken Qt for debug builds
- distro: Fedora
version: 42
package: RPM
test: skip # Running tests on all distros is superfluous
- distro: Fedora
version: 43
package: RPM
- distro: Ubuntu - distro: Ubuntu
version: 22.04 version: 22.04
@@ -154,25 +129,29 @@ jobs:
continue-on-error: ${{matrix.allow-failure == 'yes'}} continue-on-error: ${{matrix.allow-failure == 'yes'}}
env: env:
NAME: ${{matrix.distro}}${{matrix.version}} NAME: ${{matrix.distro}}${{matrix.version}}
CACHE: ${{github.workspace}}/.cache/${{matrix.distro}}${{matrix.version}} # directory for caching docker image and ccache CACHE: /tmp/${{matrix.distro}}${{matrix.version}}-cache # ${{runner.temp}} does not work?
# Cache size over the entire repo is 10Gi: # Cache size over the entire repo is 10Gi:
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy # https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#usage-limits-and-eviction-policy
CCACHE_SIZE: 500M CCACHE_SIZE: 200M
CMAKE_GENERATOR: 'Ninja'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Restore compiler cache (ccache) - name: Generate cache timestamp
id: ccache_restore id: cache_timestamp
uses: actions/cache/restore@v5 shell: bash
run: echo "timestamp=$(date -u '+%Y%m%d%H%M%S')" >>"$GITHUB_OUTPUT"
- name: Restore cache
uses: actions/cache@v4
env: env:
BRANCH_NAME: ${{ github.head_ref || github.ref_name }} timestamp: ${{steps.cache_timestamp.outputs.timestamp}}
with: with:
path: ${{env.CACHE}} path: ${{env.CACHE}}
key: ccache-${{matrix.distro}}${{matrix.version}}-${{env.BRANCH_NAME}} key: docker-${{matrix.distro}}${{matrix.version}}-cache-${{env.timestamp}}
restore-keys: ccache-${{matrix.distro}}${{matrix.version}}- restore-keys: |
docker-${{matrix.distro}}${{matrix.version}}-cache-
- name: Build ${{matrix.distro}} ${{matrix.version}} Docker image - name: Build ${{matrix.distro}} ${{matrix.version}} Docker image
shell: bash shell: bash
@@ -181,11 +160,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:
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
run: | run: |
source .ci/docker.sh source .ci/docker.sh
RUN --server --debug --test --ccache "$CCACHE_SIZE" RUN --server --debug --test --ccache "$CCACHE_SIZE" --parallel 4
- name: Build release package - name: Build release package
id: build id: build
@@ -194,33 +171,22 @@ jobs:
env: env:
BUILD_DIR: build BUILD_DIR: build
SUFFIX: '-${{matrix.distro}}${{matrix.version}}' SUFFIX: '-${{matrix.distro}}${{matrix.version}}'
package: '${{matrix.package}}' type: '${{matrix.package}}'
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
NO_CLIENT: ${{matrix.server_only == 'yes' && '--no-client' || '' }}
run: | run: |
source .ci/docker.sh source .ci/docker.sh
RUN --server --release --package "$package" --dir "$BUILD_DIR" \ RUN --server --release --package "$type" --dir "$BUILD_DIR" \
--ccache "$CCACHE_SIZE" $NO_CLIENT --ccache "$CCACHE_SIZE" --parallel 4
.ci/name_build.sh .ci/name_build.sh
- name: Save compiler cache (ccache)
if: github.ref == 'refs/heads/master'
uses: actions/cache/save@v5
with:
path: ${{env.CACHE}}
key: ${{ steps.ccache_restore.outputs.cache-primary-key }}
- name: Upload artifact - name: Upload artifact
id: upload_artifact
if: matrix.package != 'skip' if: matrix.package != 'skip'
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v4
with: with:
name: ${{matrix.distro}}${{matrix.version}}-package name: ${{matrix.distro}}${{matrix.version}}-package
path: ${{steps.build.outputs.path}} path: ${{steps.build.outputs.path}}
if-no-files-found: error if-no-files-found: error
- name: Upload to release - name: Upload to release
id: upload_release
if: matrix.package != 'skip' && needs.configure.outputs.tag != null if: matrix.package != 'skip' && needs.configure.outputs.tag != null
shell: bash shell: bash
env: env:
@@ -230,181 +196,94 @@ jobs:
asset_name: ${{steps.build.outputs.name}} asset_name: ${{steps.build.outputs.name}}
run: gh release upload "$tag_name" "$asset_path#$asset_name" run: gh release upload "$tag_name" "$asset_path#$asset_name"
- name: Attest binary provenance build-macos:
id: attestation
if: steps.upload_release.outcome == 'success'
uses: actions/attest-build-provenance@v3
with:
subject-name: ${{steps.build.outputs.name}}
subject-digest: sha256:${{ steps.upload_artifact.outputs.artifact-digest }}
- name: Verify binary attestation
if: steps.attestation.outcome == 'success'
shell: bash
env:
GH_TOKEN: ${{github.token}}
run: gh attestation verify ${{steps.build.outputs.path}} -R Cockatrice/Cockatrice
build-vcpkg:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- os: macOS - target: 13
target: 13
runner: macos-15-intel
soc: Intel soc: Intel
xcode: "16.4" os: macos-13
xcode: "14.3.1"
type: Release type: Release
override_target: 13 core_count: 4
make_package: 1 make_package: 1
package_suffix: "-macOS13_Intel"
artifact_name: macOS13_Intel-package
qt_version: 6.6.*
qt_arch: clang_64
qt_modules: qtimageformats qtmultimedia qtwebsockets
cache_qt: false # qt caches take too much space for macOS (1.1Gi)
cmake_generator: Ninja
use_ccache: 1
- os: macOS - target: 14
target: 14
runner: macos-14
soc: Apple soc: Apple
os: macos-14
xcode: "15.4" xcode: "15.4"
type: Release type: Release
core_count: 3
make_package: 1 make_package: 1
package_suffix: "-macOS14"
artifact_name: macOS14-package
qt_version: 6.6.*
qt_arch: clang_64
qt_modules: qtimageformats qtmultimedia qtwebsockets
cache_qt: false
cmake_generator: Ninja
use_ccache: 1
- os: macOS - target: 15
target: 15
runner: macos-15
soc: Apple soc: Apple
xcode: "16.4" os: macos-15
xcode: "16.2"
type: Release type: Release
core_count: 3
make_package: 1 make_package: 1
package_suffix: "-macOS15"
artifact_name: macOS15-package
qt_version: 6.6.*
qt_arch: clang_64
qt_modules: qtimageformats qtmultimedia qtwebsockets
cache_qt: false
cmake_generator: Ninja
use_ccache: 1
- os: macOS - target: 15
target: 15
runner: macos-15
soc: Apple soc: Apple
xcode: "16.4" os: macos-15
xcode: "16.2"
type: Debug type: Debug
qt_version: 6.6.* core_count: 3
qt_arch: clang_64
qt_modules: qtimageformats qtmultimedia qtwebsockets
cache_qt: false
cmake_generator: Ninja
use_ccache: 1
- os: Windows name: macOS ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }}
target: 7
runner: windows-2022
type: Release
make_package: 1
package_suffix: "-Win7"
artifact_name: Windows7-installer
qt_version: 5.15.*
qt_arch: win64_msvc2019_64
cache_qt: true
cmake_generator: "Visual Studio 17 2022"
cmake_generator_platform: x64
- os: Windows
target: 10
runner: windows-2022
type: Release
make_package: 1
package_suffix: "-Win10"
artifact_name: Windows10-installer
qt_version: 6.6.*
qt_arch: win64_msvc2019_64
qt_modules: qtimageformats qtmultimedia qtwebsockets
cache_qt: true
cmake_generator: "Visual Studio 17 2022"
cmake_generator_platform: x64
name: ${{matrix.os}} ${{matrix.target}}${{ matrix.soc == 'Intel' && ' Intel' || '' }}${{ matrix.type == 'Debug' && ' Debug' || '' }}
needs: configure needs: configure
runs-on: ${{matrix.runner}} runs-on: ${{matrix.os}}
continue-on-error: ${{matrix.allow-failure == 'yes'}}
env:
DEVELOPER_DIR:
/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v4
with:
submodules: recursive
- name: Add msbuild to PATH - name: Install dependencies using Homebrew
if: matrix.os == 'Windows'
id: add-msbuild
uses: microsoft/setup-msbuild@v2
with:
msbuild-architecture: x64
# Using jianmingyong/ccache-action to setup ccache without using brew
# It tries to download a binary of ccache from GitHub Release and falls back to building from source if it fails
- name: Setup ccache
if: matrix.use_ccache == 1
uses: jianmingyong/ccache-action@v1
with:
install-type: "binary"
ccache-key-prefix: ccache-${{matrix.runner}}-${{matrix.soc}}-${{matrix.type}}
max-size: 500M
gh-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install Qt ${{matrix.qt_version}}
uses: jurplel/install-qt-action@v4
with:
version: ${{matrix.qt_version}}
arch: ${{matrix.qt_arch}}
modules: ${{matrix.qt_modules}}
cache: ${{matrix.cache_qt}}
- name: Setup vcpkg cache
id: vcpkg-cache
uses: TAServers/vcpkg-cache@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
# uses environment variables, see compile.sh for more details
- name: Build Cockatrice
id: build
shell: bash shell: bash
# CMake cannot find the MySQL connector
# Neither of these works: mariadb-connector-c mysql-connector-c++
env:
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
run: |
brew update
brew install protobuf qt --force-bottle
- name: Build & Sign on Xcode ${{matrix.xcode}}
shell: bash
id: build
env: env:
BUILDTYPE: '${{matrix.type}}' BUILDTYPE: '${{matrix.type}}'
MAKE_TEST: 1
MAKE_PACKAGE: '${{matrix.make_package}}' MAKE_PACKAGE: '${{matrix.make_package}}'
PACKAGE_SUFFIX: '${{matrix.package_suffix}}' PACKAGE_SUFFIX: '-macOS${{matrix.target}}_${{matrix.soc}}'
CMAKE_GENERATOR: ${{matrix.cmake_generator}}
CMAKE_GENERATOR_PLATFORM: ${{matrix.cmake_generator_platform}}
USE_CCACHE: ${{matrix.use_ccache}}
VCPKG_DISABLE_METRICS: 1
VCPKG_BINARY_SOURCES: 'clear;files,${{ steps.vcpkg-cache.outputs.path }},readwrite'
# macOS-specific environment variables, will be ignored on Windows
MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }} MACOS_CERTIFICATE: ${{ secrets.PROD_MACOS_CERTIFICATE }}
MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }} MACOS_CERTIFICATE_PWD: ${{ secrets.PROD_MACOS_CERTIFICATE_PWD }}
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }} MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
DEVELOPER_DIR: '/Applications/Xcode_${{matrix.xcode}}.app/Contents/Developer' # macOS runner have 3 cores usually - only the macos-13 image has 4:
TARGET_MACOS_VERSION: ${{ matrix.override_target }} # https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories
run: .ci/compile.sh --server --test --vcpkg # https://github.com/actions/runner-images?tab=readme-ov-file#available-images
run: |
if [[ -n "$MACOS_CERTIFICATE_NAME" ]]
then
echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12
security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
security default-keychain -s build.keychain
security set-keychain-settings -t 3600 -l build.keychain
security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain
fi
.ci/compile.sh --server --parallel ${{matrix.core_count}}
- name: Sign app bundle - name: Sign app bundle
if: matrix.os == 'macOS' && matrix.make_package && (github.ref == 'refs/heads/master' || needs.configure.outputs.tag != null) if: matrix.make_package
env: env:
MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }} MACOS_CERTIFICATE_NAME: ${{ secrets.PROD_MACOS_CERTIFICATE_NAME }}
MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }} MACOS_CI_KEYCHAIN_PWD: ${{ secrets.PROD_MACOS_CI_KEYCHAIN_PWD }}
@@ -416,7 +295,7 @@ jobs:
fi fi
- name: Notarize app bundle - name: Notarize app bundle
if: matrix.os == 'macOS' && matrix.make_package && (github.ref == 'refs/heads/master' || needs.configure.outputs.tag != null) if: matrix.make_package
env: env:
MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }} MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }} MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
@@ -448,27 +327,15 @@ jobs:
fi fi
- name: Upload artifact - name: Upload artifact
id: upload_artifact
if: matrix.make_package if: matrix.make_package
uses: actions/upload-artifact@v5 uses: actions/upload-artifact@v4
with: with:
name: ${{matrix.artifact_name}} name: macOS${{matrix.target}}${{ matrix.soc == 'Intel' && '_Intel' || '' }}${{ matrix.type == 'Debug' && '_Debug' || '' }}-dmg
path: ${{steps.build.outputs.path}} path: ${{steps.build.outputs.path}}
if-no-files-found: error if-no-files-found: error
- name: Upload pdb database
if: matrix.os == 'Windows'
uses: actions/upload-artifact@v5
with:
name: Windows${{matrix.target}}-debug-pdbs
path: |
build/cockatrice/Release/*.pdb
build/servatrice/Release/*.pdb
if-no-files-found: error
- name: Upload to release - name: Upload to release
id: upload_release if: matrix.package != 'skip' && needs.configure.outputs.tag != null
if: needs.configure.outputs.tag != null
shell: bash shell: bash
env: env:
GH_TOKEN: ${{github.token}} GH_TOKEN: ${{github.token}}
@@ -477,17 +344,91 @@ jobs:
asset_name: ${{steps.build.outputs.name}} asset_name: ${{steps.build.outputs.name}}
run: gh release upload "$tag_name" "$asset_path#$asset_name" run: gh release upload "$tag_name" "$asset_path#$asset_name"
- name: Attest binary provenance build-windows:
id: attestation strategy:
if: steps.upload_release.outcome == 'success' fail-fast: false
uses: actions/attest-build-provenance@v3 matrix:
with: include:
subject-name: ${{steps.build.outputs.name}} - target: 7
subject-digest: sha256:${{ steps.upload_artifact.outputs.artifact-digest }} qt_version: 5.15.*
qt_arch: msvc2019_64
- name: Verify binary attestation - target: 10
if: steps.attestation.outcome == 'success' qt_version: 6.6.*
qt_arch: msvc2019_64
qt_modules: "qtimageformats qtmultimedia qtwebsockets"
name: Windows ${{matrix.target}}
needs: configure
runs-on: windows-2022
env:
CMAKE_GENERATOR: 'Visual Studio 17 2022'
steps:
- name: Add msbuild to PATH
id: add-msbuild
uses: microsoft/setup-msbuild@v2
with:
msbuild-architecture: x64
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Qt ${{matrix.qt_version}}
uses: jurplel/install-qt-action@v4
with:
cache: true
setup-python: false
version: ${{matrix.qt_version}}
arch: win64_${{matrix.qt_arch}}
tools: ${{matrix.qt_tools}}
modules: ${{matrix.qt_modules}}
- name: Run vcpkg
uses: lukka/run-vcpkg@v11
with:
runVcpkgInstall: true
doNotCache: false
env:
VCPKG_DEFAULT_TRIPLET: 'x64-windows'
VCPKG_DISABLE_METRICS: 1
- name: Build Cockatrice
id: build
shell: bash
env:
PACKAGE_SUFFIX: '-Win${{matrix.target}}'
CMAKE_GENERATOR: '${{env.CMAKE_GENERATOR}}'
CMAKE_GENERATOR_PLATFORM: 'x64'
QTDIR: '${{github.workspace}}\Qt\${{matrix.qt_version}}\win64_${{matrix.qt_arch}}'
# No need for --parallel flag, MTT is added in the compile script to let cmake/msbuild manage core count,
# project and process parallelism: https://devblogs.microsoft.com/cppblog/improved-parallelism-in-msbuild/
run: .ci/compile.sh --server --release --test --package
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: Windows${{matrix.target}}-installer
path: ${{steps.build.outputs.path}}
if-no-files-found: error
- name: Upload pdb database
uses: actions/upload-artifact@v4
with:
name: Windows${{matrix.target}}-debug-pdbs
path: |
build/cockatrice/Release/*.pdb
build/servatrice/Release/*.pdb
if-no-files-found: error
- name: Upload to release
if: matrix.package != 'skip' && needs.configure.outputs.tag != null
shell: bash shell: bash
env: env:
GH_TOKEN: ${{github.token}} GH_TOKEN: ${{github.token}}
run: gh attestation verify ${{steps.build.outputs.path}} -R Cockatrice/Cockatrice tag_name: ${{needs.configure.outputs.tag}}
asset_path: ${{steps.build.outputs.path}}
asset_name: ${{steps.build.outputs.name}}
run: gh release upload "$tag_name" "$asset_path#$asset_name"

View File

@@ -1,22 +1,12 @@
name: Code Style (C++) name: Code Style (C++)
on: on:
# push trigger not needed for linting, we do not allow direct pushes to master
pull_request: pull_request:
paths: paths-ignore:
- '*/**' # matches all files not in root - '**.md'
- '!**.md' - 'webclient/**'
- '!.ci/**' - '.github/workflows/web-*.yml'
- '!.github/**' - '.github/workflows/translations-*.yml'
- '!.husky/**'
- '!.tx/**'
- '!doc/**'
- '!webclient/**'
- '.ci/lint_cpp.sh'
- '.github/workflows/desktop-lint.yml'
- '.clang-format'
- '.cmake-format.json'
- 'format.sh'
jobs: jobs:
format: format:
@@ -24,7 +14,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v4
with: with:
fetch-depth: 20 # should be enough to find merge base fetch-depth: 20 # should be enough to find merge base
@@ -32,7 +22,7 @@ jobs:
shell: bash shell: bash
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install -y --no-install-recommends clang-format cmake-format shellcheck sudo apt-get install -y --no-install-recommends clang-format cmake-format
- name: Check code formatting - name: Check code formatting
shell: bash shell: bash

View File

@@ -1,66 +0,0 @@
name: Build Docker Image
on:
push:
tags:
- '*Release*'
branches:
- master
pull_request:
branches:
- master
paths:
- '.github/workflows/docker-release.yml'
- 'Dockerfile'
jobs:
docker:
name: amd64 & arm64
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Docker metadata
id: metadata
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/cockatrice/servatrice
labels: |
org.opencontainers.image.title=Servatrice
org.opencontainers.image.url=https://cockatrice.github.io/
org.opencontainers.image.description=Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games
annotations: |
org.opencontainers.image.title=Servatrice
org.opencontainers.image.url=https://cockatrice.github.io/
org.opencontainers.image.description=Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
if: github.ref_type == 'tag'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ github.token }}
- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.ref_type == 'tag' }}
tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

View File

@@ -1,61 +0,0 @@
name: Generate Docs
on:
push:
tags:
- '*' # Only re-generate docs when a new tagged version is pushed
pull_request:
paths:
- 'doc/doxygen/**'
- '.github/workflows/documentation-build.yml'
- 'Doxyfile'
workflow_dispatch:
env:
COCKATRICE_REF: ${{ github.ref_name }} # Tag name if the commit is tagged, otherwise branch name
jobs:
docs:
name: Doxygen
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install Graphviz
run: |
sudo apt-get install -y graphviz
dot -V
- name: Install Doxygen
uses: ssciwr/doxygen-install@v1
with:
version: "1.14.0"
- name: Update Doxygen Configuration
run: |
git diff Doxyfile
doxygen -u Doxyfile
if git diff --quiet Doxyfile; then
echo "::notice::No config changes in Doxyfile detected."
else
echo "::error::Config changes in Doxyfile detected! Please update the file by running 'doxygen -u Doxyfile'."
echo ""
git diff --color=always Doxyfile
exit 1
fi
- name: Generate Documentation
if: always()
run: doxygen Doxyfile
- name: Deploy to cockatrice.github.io
if: github.event_name != 'pull_request'
uses: peaceiris/actions-gh-pages@v4
with:
deploy_key: ${{ secrets.DOCS_DEPLOY_KEY }}
external_repository: Cockatrice/cockatrice.github.io
publish_branch: master
publish_dir: ./docs/html
destination_dir: docs # Docs will live under https://cockatrice.github.io/docs/

View File

@@ -7,7 +7,6 @@ on:
- cron: '0 0 15 1,4,7,10 *' - cron: '0 0 15 1,4,7,10 *'
pull_request: pull_request:
paths: paths:
- '.tx/**'
- '.github/workflows/translations-pull.yml' - '.github/workflows/translations-pull.yml'
jobs: jobs:
@@ -20,7 +19,7 @@ jobs:
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Pull translated strings from Transifex - name: Pull translated strings from Transifex
uses: transifex/cli-action@v2 uses: transifex/cli-action@v2
@@ -33,7 +32,7 @@ jobs:
- name: Create pull request - name: Create pull request
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
id: create_pr id: create_pr
uses: peter-evans/create-pull-request@v8 uses: peter-evans/create-pull-request@v7
with: with:
add-paths: | add-paths: |
cockatrice/translations/*.ts cockatrice/translations/*.ts
@@ -52,7 +51,7 @@ jobs:
*This PR is automatically generated and updated by the workflow at `.github/workflows/translations-pull.yml`. Review [action runs][2].*<br> *This PR is automatically generated and updated by the workflow at `.github/workflows/translations-pull.yml`. Review [action runs][2].*<br>
*After merging, all new languages and translations are available in the next build.* *After merging, all new languages and translations are available in the next build.*
[1]: https://explore.transifex.com/cockatrice/cockatrice/ [1]: https://app.transifex.com/cockatrice/cockatrice/
[2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-pull.yml?query=branch%3Amaster [2]: https://github.com/Cockatrice/Cockatrice/actions/workflows/translations-pull.yml?query=branch%3Amaster
labels: | labels: |
CI CI

View File

@@ -7,7 +7,6 @@ on:
- cron: '0 0 1 1,4,7,10 *' - cron: '0 0 1 1,4,7,10 *'
pull_request: pull_request:
paths: paths:
- '.ci/update_translation_source_strings.sh'
- '.github/workflows/translations-push.yml' - '.github/workflows/translations-push.yml'
jobs: jobs:
@@ -20,7 +19,7 @@ jobs:
steps: steps:
- name: Checkout repo - name: Checkout repo
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Install lupdate - name: Install lupdate
shell: bash shell: bash
@@ -31,10 +30,10 @@ jobs:
- name: Update Cockatrice translation source - name: Update Cockatrice translation source
id: cockatrice id: cockatrice
shell: bash shell: bash
run: | env:
FILE="cockatrice/cockatrice_en@source.ts" FILE: 'cockatrice/cockatrice_en@source.ts'
export DIRS="cockatrice/src $(find . -maxdepth 1 -type d -name 'libcockatrice_*')" DIRS: 'cockatrice/src common'
FILE="$FILE" DIRS="$DIRS" .ci/update_translation_source_strings.sh run: .ci/update_translation_source_strings.sh
- name: Update Oracle translation source - name: Update Oracle translation source
id: oracle id: oracle
@@ -57,7 +56,7 @@ jobs:
- name: Create pull request - name: Create pull request
if: github.event_name != 'pull_request' if: github.event_name != 'pull_request'
id: create_pr id: create_pr
uses: peter-evans/create-pull-request@v8 uses: peter-evans/create-pull-request@v7
with: with:
add-paths: | add-paths: |
cockatrice/cockatrice_en@source.ts cockatrice/cockatrice_en@source.ts

View File

@@ -5,16 +5,14 @@ on:
branches: branches:
- master - master
paths: paths:
- '.husky/**' - '.github/workflows/web-*.yml'
- 'webclient/**' - 'webclient/**'
- '!**.md' - '!**.md'
- '.github/workflows/web-build.yml'
pull_request: pull_request:
paths: paths:
- '.husky/**' - '.github/workflows/web-*.yml'
- 'webclient/**' - 'webclient/**'
- '!**.md' - '!**.md'
- '.github/workflows/web-build.yml'
jobs: jobs:
build-web: build-web:
@@ -35,10 +33,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
node-version: ${{matrix.node_version}} node-version: ${{matrix.node_version}}
cache: 'npm' cache: 'npm'

View File

@@ -1,12 +1,11 @@
name: Code Style (TypeScript) name: Code Style (TypeScript)
on: on:
# push trigger not needed for linting, we do not allow direct pushes to master
pull_request: pull_request:
paths: paths:
- '.github/workflows/web-*.yml'
- 'webclient/**' - 'webclient/**'
- '!**.md' - '!**.md'
- '.github/workflows/web-lint.yml'
jobs: jobs:
ESLint: ESLint:
@@ -18,10 +17,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v6 uses: actions/setup-node@v4
with: with:
cache: 'npm' cache: 'npm'
cache-dependency-path: 'webclient/package-lock.json' cache-dependency-path: 'webclient/package-lock.json'

1
.gitignore vendored
View File

@@ -14,4 +14,3 @@ compile_commands.json
.cache .cache
.gdb_history .gdb_history
cockatrice/resources/config/qtlogging.ini cockatrice/resources/config/qtlogging.ini
docs/

4
.gitmodules vendored
View File

@@ -1,7 +1,3 @@
[submodule "vcpkg"] [submodule "vcpkg"]
path = vcpkg path = vcpkg
url = https://github.com/microsoft/vcpkg.git url = https://github.com/microsoft/vcpkg.git
[submodule "doxygen-awesome-css"]
path = doc/doxygen/theme
url = https://github.com/jothepro/doxygen-awesome-css.git

View File

@@ -24,8 +24,6 @@ option(WITH_ORACLE "build oracle" ON)
option(WITH_DBCONVERTER "build dbconverter" ON) option(WITH_DBCONVERTER "build dbconverter" ON)
# Compile tests # Compile tests
option(TEST "build tests" OFF) option(TEST "build tests" OFF)
# Use vcpkg regardless of OS
option(USE_VCPKG "Use vcpkg regardless of OS" OFF)
# Default to "Release" build type # Default to "Release" build type
# User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call # User-provided value for CMAKE_BUILD_TYPE must be checked before the PROJECT() call
@@ -50,8 +48,8 @@ if(USE_CCACHE)
endif() endif()
endif() endif()
if(WIN32 OR USE_VCPKG) if(WIN32)
# Use vcpkg toolchain on Windows (and on macOS in CI) # Use vcpkg toolchain on Windows
set(CMAKE_TOOLCHAIN_FILE set(CMAKE_TOOLCHAIN_FILE
${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake
CACHE STRING "Vcpkg toolchain file" CACHE STRING "Vcpkg toolchain file"
@@ -76,11 +74,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 2.11.0) project("Cockatrice" VERSION 2.10.0)
# 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 "Omenpath") set(GIT_TAG_RELEASENAME "Rings of the Wild")
endif() endif()
# Use c++20 for all targets # Use c++20 for all targets
@@ -303,7 +301,6 @@ if(UNIX)
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice") set(CPACK_DEBIAN_PACKAGE_HOMEPAGE "http://github.com/Cockatrice/Cockatrice")
if(Qt6_FOUND) if(Qt6_FOUND)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins, qt6-image-formats-plugins") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt6multimedia6, libqt6svg6, qt6-qpa-plugins, qt6-image-formats-plugins")
set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libqt6sql6-mysql") # for connecting servatrice to a mysql db
elseif(Qt5_FOUND) elseif(Qt5_FOUND)
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5") set(CPACK_DEBIAN_PACKAGE_DEPENDS "libqt5multimedia5-plugins, libqt5svg5")
endif() endif()
@@ -328,19 +325,7 @@ endif()
include(CPack) include(CPack)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_interfaces ${CMAKE_BINARY_DIR}/libcockatrice_interfaces) add_subdirectory(common)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_protocol ${CMAKE_BINARY_DIR}/libcockatrice_protocol)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_network ${CMAKE_BINARY_DIR}/libcockatrice_network)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_deck_list ${CMAKE_BINARY_DIR}/libcockatrice_deck_list)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_rng ${CMAKE_BINARY_DIR}/libcockatrice_rng)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_card ${CMAKE_BINARY_DIR}/libcockatrice_card)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_utility ${CMAKE_BINARY_DIR}/libcockatrice_utility)
if(WITH_ORACLE OR WITH_CLIENT)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_settings ${CMAKE_BINARY_DIR}/libcockatrice_settings)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_models ${CMAKE_BINARY_DIR}/libcockatrice_models)
add_subdirectory(${CMAKE_SOURCE_DIR}/libcockatrice_filters ${CMAKE_BINARY_DIR}/libcockatrice_filters)
endif()
if(WITH_SERVER) if(WITH_SERVER)
add_subdirectory(servatrice) add_subdirectory(servatrice)
set(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS}) set(CPACK_INSTALL_CMAKE_PROJECTS "Servatrice;Servatrice;ALL;/" ${CPACK_INSTALL_CMAKE_PROJECTS})

View File

@@ -1,9 +1,8 @@
# -------- Build Stage -------- FROM ubuntu:24.04
FROM ubuntu:24.04 AS build
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y\
build-essential \ build-essential \
cmake \ cmake \
file \ file \
@@ -17,28 +16,16 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
qt6-tools-dev \ qt6-tools-dev \
qt6-tools-dev-tools qt6-tools-dev-tools
WORKDIR /src COPY . /home/servatrice/code/
COPY . . WORKDIR /home/servatrice/code
RUN mkdir build && cd build && \
cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 -DWITH_DBCONVERTER=0 && \ WORKDIR build
make -j$(nproc) && \ RUN cmake .. -DWITH_SERVER=1 -DWITH_CLIENT=0 -DWITH_ORACLE=0 -DWITH_DBCONVERTER=0 &&\
make &&\
make install make install
# -------- Runtime Stage (clean) --------
FROM ubuntu:24.04
RUN apt-get update && apt-get install -y --no-install-recommends \
libprotobuf32t64 \
libqt6sql6-mysql \
libqt6websockets6 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# Only copy installed binaries, not source
COPY --from=build /usr/local /usr/local
WORKDIR /home/servatrice WORKDIR /home/servatrice
EXPOSE 4748 EXPOSE 4747 4748
ENTRYPOINT [ "servatrice", "--log-to-console" ] ENTRYPOINT [ "servatrice", "--log-to-console" ]

2965
Doxyfile

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@
Version 2, June 1991 Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
<https://fsf.org/> 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@@ -304,7 +304,8 @@ the "copyright" line and a pointer to where the full notice is found.
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License along
with this program; if not, see <https://www.gnu.org/licenses/>. with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
@@ -328,8 +329,8 @@ necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker. `Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Moe Ghoul>, 1 April 1989 <signature of Ty Coon>, 1 April 1989
Moe Ghoul, President of Vice Ty Coon, President of Vice
This General Public License does not permit incorporating your program into This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may proprietary programs. If your program is a subroutine library, you may

210
README.md
View File

@@ -5,162 +5,154 @@
<p align='center'> <p align='center'>
<a href="#cockatrice"><b>Cockatrice</b></a> <b>|</b> <a href="#cockatrice"><b>Cockatrice</b></a> <b>|</b>
<a href="#download-">Download</a> <b>|</b> <a href="#download-">Download</a> <b>|</b>
<a href="#related-repositories">Related</a> <b>|</b> <a href="#get-involved-">Get Involved</a> <b>|</b>
<a href="#community-resources-">Community</a> <b>|</b> <a href="#community-resources">Community</a> <b>|</b>
<a href="#contribute">Contribute</a> <b>|</b> <a href="#translations-">Translations</a> <b>|</b>
<a href="#build---">Build</a> <b>|</b> <a href="#build--">Build</a> <b>|</b>
<a href="#run">Run</a> <a href="#run">Run</a> <b>|</b>
<a href="#license-">License</a>
</p> </p>
--- ---
<br><pre><p align='center'> <br><pre>
<b>To get started with Cockatrice &#8674; [view our webpage](https://cockatrice.github.io/)</b><br> <b>To get started, &#8674; [view our webpage](https://cockatrice.github.io/)</b><br>
<b>To get support, or suggest changes to the app &#8674; [file an issue](https://github.com/Cockatrice/Cockatrice/issues) ([How?](https://github.com/Cockatrice/Cockatrice/wiki/How-to-Create-a-GitHub-Ticket-Regarding-Cockatrice))</b> <b>To get support or suggest changes &#8674; [file an issue](https://github.com/Cockatrice/Cockatrice/issues) ([How?](https://github.com/Cockatrice/Cockatrice/wiki/How-to-Create-a-GitHub-Ticket-Regarding-Cockatrice))</b>
<b>To help with development &#8674; learn [how to contribute](#contribute-)</b> <b>To help with development, see how to [get involved](#get-involved-)</b>
</pre><p><br> </pre><br>
# Cockatrice # Cockatrice
Cockatrice is an open-source, multiplatform application for playing tabletop card games over a network. The program's server design prevents users from manipulating the game for unfair advantage. The client also provides a single-player mode, which allows users to brew while offline.<br><br> Cockatrice is an open-source, multiplatform program for playing tabletop card games over a network. The program's server design prevents users from manipulating the game for unfair advantage. The client also provides a single-player mode, which allows users to brew while offline. This project uses C++ and the Qt5 libraries.<br>
This project uses <kbd>C++</kbd> and the <kbd>Qt</kbd> libraries.<br>
First work on a webclient with <kbd>Typescript</kbd> was started as well.<br>
# Download [![Cockatrice Eternal Download Count](https://img.shields.io/github/downloads/cockatrice/cockatrice/total.svg)](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice&search=0) # Download [![Cockatrice Eternal Download Count](https://img.shields.io/github/downloads/cockatrice/cockatrice/total.svg)](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)
Downloads are available for **stable releases** and the current **beta version** in development. Downloads are available for full releases and the current beta version in development. There is no strict release schedule for either of them.
There is no strict release schedule for either of them.
<br><pre>
Latest <kbd>stable</kbd> release:
[![Download Stable Release](https://img.shields.io/github/release/cockatrice/cockatrice.svg?label=version&colorB=0d7ebf "Download Latest Stable Release")](https://github.com/cockatrice/cockatrice/releases/latest) ![](https://img.shields.io/github/release-date/Cockatrice/Cockatrice.svg?label=released&colorB=0d7ebf "Release Date") [![](https://img.shields.io/github/downloads/cockatrice/cockatrice/latest/total.svg?label=downloads&colorB=0d7ebf "Number of Downloads")](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice&search=0)
</pre><pre>
Latest <kbd>beta</kbd> version:
[![Download Beta Release](https://img.shields.io/github/release/cockatrice/cockatrice/all.svg?label=version&colorB=f37f40 "Download Latest Beta Release")](https://github.com/cockatrice/cockatrice/releases) ![](https://img.shields.io/github/release-date-pre/Cockatrice/Cockatrice.svg?label=released&colorB=f37f40 "Release Date") [![](https://img.shields.io/github/downloads-pre/cockatrice/cockatrice/latest/total.svg?label=downloads&colorB=f37f40 "Number of Downloads")](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice&search=0) [![](https://img.shields.io/github/commits-since/Cockatrice/Cockatrice/latest.svg?label=changes&colorB=f37f40 "Changes over Stable Release")](https://github.com/Cockatrice/Cockatrice/pulls?q=is%3Apr+is%3Aclosed)
<sub><i>While incorporating the latest fixes and features, beta builds may not be stable or contain new bugs!</i></sub>
<sub><b><i>Please report any findings and open new issues when testing them!</i></b></sub>
</pre>
# Related Repositories - Latest `stable` release: [![Download from GitHub Releases](https://img.shields.io/github/release/cockatrice/cockatrice.svg)](https://github.com/cockatrice/cockatrice/releases/latest) [![DL Count on Latest Release](https://img.shields.io/github/downloads/cockatrice/cockatrice/latest/total.svg?label=downloads)](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)<br>
- Stable versions are checkpoints featuring major feature and UI enhancements.
- **Recommended for most users!**
- [Magic-Token](https://github.com/Cockatrice/Magic-Token): MtG token data to use in Cockatrice - Latest `beta` release: [![Download from GitHub Pre-Releases](https://img.shields.io/github/release/cockatrice/cockatrice/all.svg)](https://github.com/cockatrice/cockatrice/releases) [![DL Count on Latest Pre-Release](https://img.shields.io/github/downloads-pre/cockatrice/cockatrice/latest/total.svg?label=downloads)](https://tooomm.github.io/github-release-stats/?username=Cockatrice&repository=Cockatrice)
- [Magic-Spoiler](https://github.com/Cockatrice/Magic-Spoiler): Script to generate MtG spoiler data from [MTGJSON](https://github.com/mtgjson/mtgjson) to use in Cockatrice - Beta versions include the most recently added features and bugfixes, but can be unstable.
- [cockatrice.github.io](https://github.com/Cockatrice/cockatrice.github.io): Code of the official Cockatrice webpage - To be a Cockatrice Beta Tester, use this version. Find more information [here](https://github.com/Cockatrice/Cockatrice/wiki/Release-Channels)!
- [Cockatrice @Flathub](https://github.com/flathub/io.github.Cockatrice.cockatrice): Configuration for our Linux `flatpak` package
# Community Resources [![Discord](https://img.shields.io/discord/314987288398659595?label=Discord&logo=discord&logoColor=white)](https://discord.gg/3Z9yzmA) # Get Involved [![Discord](https://img.shields.io/discord/314987288398659595?label=Discord&logo=discord&logoColor=white)](https://discord.gg/3Z9yzmA)
Join our [Discord community](https://discord.gg/3Z9yzmA) to connect with other projet contributors (`#dev` channel) or fellow users of the app. Come here to talk about the application, features, or just to hang out. Join our [Discord community](https://discord.gg/3Z9yzmA) to connect with the project, contributors or fellow users of the app. Come here to talk about the application, features, or just to hang out.<br>
- [Official Website](https://cockatrice.github.io) For support regarding specific servers, please contact that server's admin or forum for support rather than asking here.<br>
- [Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki)
- [Official Code Documentation](https://cockatrice.github.io/docs) To contribute code to the project, please review [the guidelines](https://github.com/Cockatrice/Cockatrice/blob/master/.github/CONTRIBUTING.md).
- [Official Discord](https://discord.gg/3Z9yzmA) We maintain two tags for contributors to find issues to work on:
- [Good first issue](https://github.com/Cockatrice/Cockatrice/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22Good%20first%20issue%22%20): issues tagged in this way provide a simple way to get started. They don't require much experience to be worked on.
- [Help wanted](https://github.com/Cockatrice/Cockatrice/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22Help%20Wanted%22%20): This tag is used for issues that we are looking for a contributor to work on. Often this is for feature suggestions we are willing to accept, but don't have the time to work on ourselves.
For both tags, we're willing to provide help to contributors in showing them where and how they can make changes, as well as code review for changes they submit.
We try to be responsive to new issues. We'll provide advice on how best to implement a feature; alternately, we can show you where the codebase is doing something similar before you get too far along.
Cockatrice uses 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.
# Community Resources
- [Cockatrice Official Site](https://cockatrice.github.io)
- [Cockatrice Official Wiki](https://github.com/Cockatrice/Cockatrice/wiki)
- [Cockatrice Official Discord](https://discord.gg/3Z9yzmA)
- [reddit r/Cockatrice](https://reddit.com/r/cockatrice) - [reddit r/Cockatrice](https://reddit.com/r/cockatrice)
>[!IMPORTANT]
>For support regarding specific servers, please contact that server's admin/mods and use their dedicated communication channels rather than contacting the team building the software. # Translations [![Transifex Project](https://img.shields.io/badge/translate-on%20transifex-brightgreen)](https://transifex.com/cockatrice/cockatrice/)
Cockatrice uses Transifex for translations. You can help us bring Cockatrice, Oracle and Webatrice to your language or just adjust single wordings right from within your browser by visiting our [Transifex project page](https://transifex.com/cockatrice/cockatrice/).<br>
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about contributing!<br>
# Contribute # Build [![CI Desktop](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml/badge.svg?branch=master&event=push)](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml?query=branch%3Amaster+event%3Apush) [![CI Web](https://github.com/Cockatrice/Cockatrice/actions/workflows/web-build.yml/badge.svg?branch=master&event=push)](https://github.com/Cockatrice/Cockatrice/actions/workflows/web-build.yml?query=branch%3Amaster+event%3Apush)
### Code **Detailed compiling instructions can be found on the Cockatrice wiki under [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)**
To contribute code to the project, please review our [guidelines](https://github.com/Cockatrice/Cockatrice/blob/master/.github/CONTRIBUTING.md) first.<br> Dependencies: *(for minimum requirements search our [CMake file](https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt))*
We maintain two tags for contributors to easier find issues to potentially work on:
- [![Good first issue](https://img.shields.io/github/issues/cockatrice/cockatrice/Good%20First%20Issue)](https://github.com/Cockatrice/Cockatrice/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22Good%20first%20issue%22%20)<br>
Issues tagged in this way provide a simple way to get started. They don't require much experience to be worked on.
- [![Help wanted](https://img.shields.io/github/issues/cockatrice/cockatrice/Help%20Wanted)](https://github.com/Cockatrice/Cockatrice/issues?utf8=%E2%9C%93&q=is%3Aopen%20is%3Aissue%20label%3A%22Help%20Wanted%22%20)<br>
This tag is used for issues that we are looking for somebody to pick up. Often this is for feature suggestions we support, but don't have the time to work on ourselves.
For both tags, we're willing to provide help to contributors in showing them where and how they can make changes, as well as code reviews for submitted changes.<br>
We'll happily advice on how best to implement a feature, or we can show you where the codebase is doing something similar before you get too far along - put a note on an issue you want to discuss more on!
You can also have a look at our `Todo List` in our [Code Documentation](https://cockatrice.github.io/docs) or search the repo for [`\todo` comments](https://github.com/search?q=repo%3ACockatrice%2FCockatrice%20%5Ctodo&type=code).
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.
#### Repository Activity
![Cockatrice Repo Analytics](https://repobeats.axiom.co/api/embed/c7cec938789a5bbaeb4182a028b4dbb96db8f181.svg "Cockatrice Repo Analytics by Repobeats")
<details>
<summary><b>Kudos to all our amazing contributors ❤️</b></summary>
<br>
<a href="https://github.com/Cockatrice/Cockatrice/graphs/contributors">
<img src="https://contrib.rocks/image?repo=Cockatrice/Cockatrice" />
</a><br>
<sub><i>Made with <a href="https://contrib.rocks">contrib.rocks</a></i></sub>
</details>
### Translations [![Transifex Project](https://img.shields.io/badge/translate-on%20transifex-brightgreen)](https://explore.transifex.com/cockatrice/cockatrice/)
Cockatrice uses Transifex to manage translations. You can help us bring <kbd>Cockatrice</kbd>, <kbd>Oracle</kbd> and <kbd>Webatrice</kbd> to your language and just adjust single wordings right from within your browser by visiting our [Transifex project page](https://explore.transifex.com/cockatrice/cockatrice/).<br>
Check out our [Translator FAQ](https://github.com/Cockatrice/Cockatrice/wiki/Translation-FAQ) for more information about getting invovled, and join a group of hundreds of others!<br>
# Build [![CI Desktop](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml/badge.svg?branch=master&event=push)](https://github.com/Cockatrice/Cockatrice/actions/workflows/desktop-build.yml?query=branch%3Amaster+event%3Apush) [![CI Docker](https://github.com/Cockatrice/Cockatrice/actions/workflows/docker-release.yml/badge.svg?branch=master&event=push)](https://github.com/Cockatrice/Cockatrice/actions/workflows/docker-release.yml?query=branch%3Amaster+event%3Apush) [![CI Web](https://github.com/Cockatrice/Cockatrice/actions/workflows/web-build.yml/badge.svg?branch=master&event=push)](https://github.com/Cockatrice/Cockatrice/actions/workflows/web-build.yml?query=branch%3Amaster+event%3Apush)
Dependencies: *(for minimum versions search our [CMake file](https://github.com/Cockatrice/Cockatrice/blob/master/CMakeLists.txt))*
- [Qt](https://www.qt.io/developers/) - [Qt](https://www.qt.io/developers/)
- [protobuf](https://github.com/protocolbuffers/protobuf) - [protobuf](https://github.com/protocolbuffers/protobuf)
- [CMake](https://www.cmake.org/) - [CMake](https://www.cmake.org/)
Oracle can *optionally* use some packages to load compressed card files: Oracle can optionally use zlib and xz to load compressed files:
- [xz](https://tukaani.org/xz/) - [xz](https://tukaani.org/xz/)
- [zlib](https://www.zlib.net/) - [zlib](https://www.zlib.net/)
<br> To compile:
**Basic compilation steps:**
```bash
mkdir build mkdir build
cd build cd build
cmake .. cmake ..
make make
```
You can then You can then run
- Create a Cockatrice installation inside the `release` folder:
```bash
make install make install
```
- Or make an installation package specific to your system: to get a cockatrice installation inside the `release` folder, or:
```bash
make package make package
```
>[!NOTE] to create a system-specific installation package.
>Detailed compiling instructions can be found in the Cockatrice wiki at [Compiling Cockatrice](https://github.com/Cockatrice/Cockatrice/wiki/Compiling-Cockatrice)
<br> The following flags can be passed to `cmake`:
The following flags (with their non-default values) can be passed to `cmake`: - `-DWITH_SERVER=1` Whether to build the server (default 0 = no).
| Flag | Description | - `-DWITH_CLIENT=0` Whether to build the client (default 1 = yes).
| --- | --- | - `-DWITH_ORACLE=0` Whether to build oracle (default 1 = yes).
| `-DWITH_SERVER=1` | Build <kbd>Servatrice</kbd> server | - `-DCMAKE_BUILD_TYPE=Debug` Compile in debug mode. Enables extra logging output, debug symbols, and much more verbose compiler warnings (default `Release`).
| `-DWITH_CLIENT=0` | Don't build <kbd>Cockatrice</kbd> client | - `-DWARNING_AS_ERROR=0` Whether to treat compilation warnings as errors in debug mode (default 1 = yes).
| `-DWITH_ORACLE=0` | Don't build <kbd>Oracle</kbd> card database tool | - `-DUPDATE_TRANSLATIONS=1` Configure `make` to update the translation .ts files for new strings in the source code. Note: Running `make clean` will remove the .ts files (default 0 = no).
| `-DCMAKE_BUILD_TYPE=Debug` | Compile in debug mode<br> Enables extra logging output, debug symbols, and much more verbose compiler warnings | - `-DTEST=1` Enable regression tests (default 0 = no). Note: needs googletest, will be downloaded on the fly if unavailable. To run tests: ```make test```.
| `-DWARNING_AS_ERROR=0` | Don't treat compilation warnings as errors in debug mode | - `-DFORCE_USE_QT5=1` Skip looking for Qt6 before trying to find Qt5
| `-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 |
| `-DFORCE_USE_QT5=1` | Skip looking for Qt6 before trying to find Qt5 |
# Run # Run
<kbd>Cockatrice</kbd> is the game client<br> `Cockatrice` is the game client<br>
<kbd>Oracle</kbd> fetches card data<br> `Oracle` fetches card data<br>
<kbd>Servatrice</kbd> is the server<br> `Servatrice` is the server<br>
#### Docker **Servatrice Docker container**
You can build an image & deploy a <kbd>Servatrice</kbd> (Cockatrice server) container using [Docker](https://www.docker.com/resources/what-container/) and our Dockerfile yourself.<br> You can run an instance of Servatrice (the Cockatrice server) using [Docker](https://www.docker.com/what-docker) and the Cockatrice Dockerfile.<br>
For more details, look into our wiki section on [Setting up Servatrice](https://github.com/Cockatrice/Cockatrice/wiki/Setting-up-Servatrice#using-docker).<br> First, create an image from the Dockerfile<br>
You'll also find more hints on our **pre-build image** there, or the **docker-compose** file which will configure and run both a MySQL server and Servatrice. `cd /path/to/Cockatrice-Repo/`
`docker build -t servatrice .`<br>
And then run it<br>
`docker run -i -p 4747:4747/tcp -t servatrice:latest`<br>
>Note: Running this command exposes the TCP port 4747 of the docker container<br>
to permit connections to the server.
Find more information on how to use Servatrice with Docker in our [wiki](https://github.com/Cockatrice/Cockatrice/wiki/Setting-up-Servatrice#using-docker).
**Docker compose**
There is also a docker-compose file available which will configure and run both a MySQL server and Servatrice. The docker-compose setup scripts can be found in the `servatrice/docker` folder and vary only slightly from the default sql and server .ini files. The setup scripts can either be modified in place, or docker-compose can mount alternative files into the images, as you prefer.
To run Servatrice via docker-compose, first install docker-compose following the [install instructions](https://docs.docker.com/compose/install/). Once installed, run the following from the root of the repository:
```bash
docker-compose build # Build the Servatrice image using the same Dockerfile as above.
docker-compose up # Setup and run both the MySQL server and Servatrice.
```
>Note: Similar to the above Docker setup, this will expose TCP ports 4747 and 4748.
>Note: The first time running the docker-compose setup, the MySQL server will take a little time to run the initial setup scripts. Due to this, the Servatrice instance may fail the first few attempts to connect to the database. Servatrice is set to `restart: always` in the docker-compose.yml, which will allow it to continue attempting to start up. Once the MySQL scripts have completed, Servatrice should then connect automatically on the next attempt.
**Docker compose in Windows**
A out of box working docker-compose file has been added to help setup in Windows.
Docker in Windows requires additional steps in form of using Docker Desktop to allow resource sharing from the drive the volumes are mapped from, as well as potential workarounds needed to get file sharing working in Windows. This [StackOverflow discussion sheds some light on it](https://stackoverflow.com/questions/42203488/settings-to-windows-firewall-to-allow-docker-for-windows-to-share-drive)
# License [![GPLv2 License](https://img.shields.io/github/license/Cockatrice/Cockatrice.svg)](https://github.com/Cockatrice/Cockatrice/blob/master/LICENSE) # License [![GPLv2 License](https://img.shields.io/github/license/Cockatrice/Cockatrice.svg)](https://github.com/Cockatrice/Cockatrice/blob/master/LICENSE)

View File

@@ -115,7 +115,4 @@ string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" ORACLE_QT_MO
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" DB_CONVERTER_QT_MODULES "${_DBCONVERTER_NEEDED}") string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" DB_CONVERTER_QT_MODULES "${_DBCONVERTER_NEEDED}")
string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" TEST_QT_MODULES "${_TEST_NEEDED}") string(REGEX REPLACE "([^;]+)" "${COCKATRICE_QT_VERSION_NAME}::\\1" TEST_QT_MODULES "${_TEST_NEEDED}")
# Core-only export (useful for headless libs)
set(QT_CORE_MODULE "${COCKATRICE_QT_VERSION_NAME}::Core")
message(STATUS "Found Qt ${${COCKATRICE_QT_VERSION_NAME}_VERSION} at: ${${COCKATRICE_QT_VERSION_NAME}_DIR}") message(STATUS "Found Qt ${${COCKATRICE_QT_VERSION_NAME}_VERSION} at: ${${COCKATRICE_QT_VERSION_NAME}_DIR}")

View File

@@ -5,288 +5,194 @@
project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") project(Cockatrice VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(cockatrice_SOURCES set(cockatrice_SOURCES
${VERSION_STRING_CPP} src/game/cards/abstract_card_drag_item.cpp
# sort by alphabetical order, so that there is no debate about where to add new sources to the list src/game/cards/abstract_card_item.cpp
src/client/network/update/client/update_downloader.cpp src/client/game_logic/abstract_client.cpp
src/client/network/interfaces/deck_stats_interface.cpp
src/client/network/interfaces/tapped_out_interface.cpp
src/client/network/parsers/deck_link_to_api_transformer.cpp
src/client/network/update/client/client_update_checker.cpp
src/client/network/update/client/release_channel.cpp
src/client/network/update/card_spoiler/spoiler_background_updater.cpp
src/client/sound_engine.cpp
src/client/settings/cache_settings.cpp
src/client/settings/card_counter_settings.cpp
src/client/settings/shortcut_treeview.cpp
src/client/settings/shortcuts_settings.cpp
src/interface/deck_loader/card_node_function.cpp
src/interface/deck_loader/deck_file_format.cpp
src/interface/deck_loader/deck_loader.cpp
src/interface/deck_loader/loaded_deck.cpp
src/interface/widgets/dialogs/dlg_connect.cpp
src/interface/widgets/dialogs/dlg_convert_deck_to_cod_format.cpp
src/interface/widgets/dialogs/dlg_create_game.cpp
src/interface/widgets/dialogs/dlg_default_tags_editor.cpp
src/interface/widgets/dialogs/dlg_edit_avatar.cpp
src/interface/widgets/dialogs/dlg_edit_password.cpp
src/interface/widgets/dialogs/dlg_edit_tokens.cpp
src/interface/widgets/dialogs/dlg_edit_user.cpp
src/interface/widgets/dialogs/dlg_filter_games.cpp
src/interface/widgets/dialogs/dlg_forgot_password_challenge.cpp
src/interface/widgets/dialogs/dlg_forgot_password_request.cpp
src/interface/widgets/dialogs/dlg_forgot_password_reset.cpp
src/interface/widgets/dialogs/dlg_load_deck.cpp
src/interface/widgets/dialogs/dlg_load_deck_from_clipboard.cpp
src/interface/widgets/dialogs/dlg_load_deck_from_website.cpp
src/interface/widgets/dialogs/dlg_load_remote_deck.cpp
src/interface/widgets/dialogs/dlg_manage_sets.cpp
src/interface/widgets/dialogs/dlg_register.cpp
src/interface/widgets/dialogs/dlg_select_set_for_cards.cpp
src/interface/widgets/dialogs/dlg_settings.cpp
src/interface/widgets/dialogs/dlg_startup_card_check.cpp
src/interface/widgets/dialogs/dlg_tip_of_the_day.cpp
src/interface/widgets/dialogs/dlg_update.cpp
src/interface/widgets/dialogs/dlg_view_log.cpp
src/interface/widgets/dialogs/tip_of_the_day.cpp
src/filters/deck_filter_string.cpp
src/filters/filter_builder.cpp
src/filters/filter_tree_model.cpp
src/filters/syntax_help.cpp
src/game/abstract_game.cpp
src/game/board/abstract_card_drag_item.cpp
src/game/board/abstract_card_item.cpp
src/game/board/abstract_counter.cpp src/game/board/abstract_counter.cpp
src/game/board/abstract_graphics_item.cpp
src/game/board/arrow_item.cpp src/game/board/arrow_item.cpp
src/game/board/arrow_target.cpp src/game/board/arrow_target.cpp
src/game/board/card_drag_item.cpp src/game/cards/card_database.cpp
src/game/board/card_item.cpp src/game/cards/card_database_manager.cpp
src/game/board/card_list.cpp src/game/cards/card_database_model.cpp
src/game/cards/card_database_parser/card_database_parser.cpp
src/game/cards/card_database_parser/cockatrice_xml_3.cpp
src/game/cards/card_database_parser/cockatrice_xml_4.cpp
src/game/cards/card_drag_item.cpp
src/game/filters/filter_card.cpp
src/client/ui/widgets/cards/card_info_frame_widget.cpp
src/client/ui/widgets/cards/card_info_picture_widget.cpp
src/client/ui/widgets/cards/card_info_text_widget.cpp
src/client/ui/widgets/cards/card_info_display_widget.cpp
src/client/ui/widgets/cards/card_size_widget.cpp
src/game/cards/card_item.cpp
src/game/cards/card_list.cpp
src/game/zones/card_zone.cpp
src/server/chat_view/chat_view.cpp
src/game/board/counter_general.cpp src/game/board/counter_general.cpp
src/game/board/translate_counter_name.cpp src/deck/custom_line_edit.cpp
src/deck/deck_loader.cpp
src/deck/deck_list_model.cpp
src/deck/deck_stats_interface.cpp
src/dialogs/dlg_connect.cpp
src/dialogs/dlg_convert_deck_to_cod_format.cpp
src/dialogs/dlg_create_token.cpp
src/dialogs/dlg_create_game.cpp
src/dialogs/dlg_edit_avatar.cpp
src/dialogs/dlg_edit_password.cpp
src/dialogs/dlg_edit_tokens.cpp
src/dialogs/dlg_edit_user.cpp
src/dialogs/dlg_filter_games.cpp
src/dialogs/dlg_forgot_password_challenge.cpp
src/dialogs/dlg_forgot_password_request.cpp
src/dialogs/dlg_forgot_password_reset.cpp
src/dialogs/dlg_load_deck_from_clipboard.cpp
src/dialogs/dlg_load_remote_deck.cpp
src/dialogs/dlg_manage_sets.cpp
src/dialogs/dlg_move_top_cards_until.cpp
src/dialogs/dlg_register.cpp
src/dialogs/dlg_roll_dice.cpp
src/dialogs/dlg_settings.cpp
src/dialogs/dlg_tip_of_the_day.cpp
src/dialogs/dlg_update.cpp
src/dialogs/dlg_view_log.cpp
src/dialogs/dlg_load_deck.cpp
src/game/deckview/deck_view.cpp src/game/deckview/deck_view.cpp
src/game/deckview/deck_view_container.cpp src/game/deckview/deck_view_container.cpp
src/game/deckview/tabbed_deck_view_container.cpp src/game/filters/filter_string.cpp
src/game/dialogs/dlg_create_token.cpp src/game/filters/filter_builder.cpp
src/game/dialogs/dlg_move_top_cards_until.cpp src/game/filters/filter_tree.cpp
src/game/dialogs/dlg_roll_dice.cpp src/game/filters/filter_tree_model.cpp
src/game/game.cpp src/client/ui/layouts/flow_layout.cpp
src/game/game_event_handler.cpp src/client/ui/widgets/general/layout_containers/flow_widget.cpp
src/game/game_meta_info.cpp
src/game/game_scene.cpp src/game/game_scene.cpp
src/game/game_state.cpp src/game/game_selector.cpp
src/game/games_model.cpp
src/game/game_view.cpp src/game/game_view.cpp
src/client/get_text_with_max.cpp
src/game/hand_counter.cpp src/game/hand_counter.cpp
src/game/log/message_log_widget.cpp src/server/handle_public_servers.cpp
src/game/phase.cpp
src/game/phases_toolbar.cpp
src/game/player/menu/card_menu.cpp
src/game/player/menu/custom_zone_menu.cpp
src/game/player/menu/grave_menu.cpp
src/game/player/menu/hand_menu.cpp
src/game/player/menu/library_menu.cpp
src/game/player/menu/move_menu.cpp
src/game/player/menu/player_menu.cpp
src/game/player/menu/pt_menu.cpp
src/game/player/menu/rfg_menu.cpp
src/game/player/menu/say_menu.cpp
src/game/player/menu/sideboard_menu.cpp
src/game/player/menu/utility_menu.cpp
src/game/player/player.cpp
src/game/player/player_actions.cpp
src/game/player/player_area.cpp
src/game/player/player_event_handler.cpp
src/game/player/player_graphics_item.cpp
src/game/player/player_info.cpp
src/game/player/player_list_widget.cpp
src/game/player/player_manager.cpp
src/game/player/player_target.cpp
src/game/replay.cpp
src/game/zones/card_zone.cpp
src/game/zones/hand_zone.cpp src/game/zones/hand_zone.cpp
src/game/zones/logic/card_zone_logic.cpp src/client/game_logic/key_signals.cpp
src/game/zones/logic/hand_zone_logic.cpp src/client/ui/line_edit_completer.cpp
src/game/zones/logic/pile_zone_logic.cpp src/server/local_client.cpp
src/game/zones/logic/stack_zone_logic.cpp src/server/local_server.cpp
src/game/zones/logic/table_zone_logic.cpp src/server/local_server_interface.cpp
src/game/zones/logic/view_zone_logic.cpp src/utility/logger.cpp
src/game/zones/pile_zone.cpp src/client/ui/widgets/cards/card_info_picture_enlarged_widget.cpp
src/game/zones/select_zone.cpp src/client/ui/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
src/game/zones/stack_zone.cpp src/client/ui/widgets/general/display/banner_widget.cpp
src/game/zones/table_zone.cpp src/client/ui/widgets/general/display/labeled_input.cpp
src/game/zones/view_zone.cpp src/client/ui/widgets/general/display/dynamic_font_size_label.cpp
src/game/zones/view_zone_widget.cpp src/client/ui/widgets/general/display/dynamic_font_size_push_button.cpp
src/game_graphics/board/abstract_graphics_item.cpp src/client/ui/widgets/general/display/shadow_background_label.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_request_status_display_widget.cpp
src/interface/card_picture_loader/card_picture_loader_status_bar.cpp
src/interface/card_picture_loader/card_picture_loader_worker.cpp
src/interface/card_picture_loader/card_picture_loader_worker_work.cpp
src/interface/card_picture_loader/card_picture_to_load.cpp
src/interface/layouts/flow_layout.cpp
src/interface/layouts/overlap_layout.cpp
src/interface/widgets/utility/line_edit_completer.cpp
src/interface/pixel_map_generator.cpp
src/interface/theme_manager.cpp
src/interface/widgets/cards/additional_info/color_identity_widget.cpp
src/interface/widgets/cards/additional_info/mana_cost_widget.cpp
src/interface/widgets/cards/additional_info/mana_symbol_widget.cpp
src/interface/widgets/cards/card_group_display_widgets/card_group_display_widget.cpp
src/interface/widgets/cards/card_group_display_widgets/flat_card_group_display_widget.cpp
src/interface/widgets/cards/card_group_display_widgets/overlapped_card_group_display_widget.cpp
src/interface/widgets/cards/card_info_display_widget.cpp
src/interface/widgets/cards/card_info_frame_widget.cpp
src/interface/widgets/cards/card_info_picture_art_crop_widget.cpp
src/interface/widgets/cards/card_info_picture_enlarged_widget.cpp
src/interface/widgets/cards/card_info_picture_widget.cpp
src/interface/widgets/cards/card_info_picture_with_text_overlay_widget.cpp
src/interface/widgets/cards/card_info_text_widget.cpp
src/interface/widgets/cards/card_size_widget.cpp
src/interface/widgets/cards/deck_card_zone_display_widget.cpp
src/interface/widgets/cards/deck_preview_card_picture_widget.cpp
src/interface/widgets/deck_analytics/deck_analytics_widget.cpp
src/interface/widgets/deck_analytics/deck_list_statistics_analyzer.cpp
src/interface/widgets/deck_analytics/mana_base_widget.cpp
src/interface/widgets/deck_analytics/mana_curve_widget.cpp
src/interface/widgets/deck_analytics/mana_devotion_widget.cpp
src/interface/widgets/deck_editor/deck_list_history_manager_widget.cpp
src/interface/widgets/deck_editor/deck_editor_card_info_dock_widget.cpp
src/interface/widgets/deck_editor/deck_editor_database_display_widget.cpp
src/interface/widgets/deck_editor/deck_editor_deck_dock_widget.cpp
src/interface/widgets/deck_editor/deck_editor_filter_dock_widget.cpp
src/interface/widgets/deck_editor/deck_editor_printing_selector_dock_widget.cpp
src/interface/widgets/deck_editor/deck_list_style_proxy.cpp
src/interface/widgets/general/background_sources.cpp
src/interface/widgets/general/display/background_plate_widget.cpp
src/interface/widgets/general/display/banner_widget.cpp
src/interface/widgets/general/display/bar_widget.cpp
src/interface/widgets/general/display/color_bar.cpp
src/interface/widgets/general/display/dynamic_font_size_label.cpp
src/interface/widgets/general/display/dynamic_font_size_push_button.cpp
src/interface/widgets/general/display/labeled_input.cpp
src/interface/widgets/general/display/percent_bar_widget.cpp
src/interface/widgets/general/display/shadow_background_label.cpp
src/interface/widgets/general/home_styled_button.cpp
src/interface/widgets/general/home_widget.cpp
src/interface/widgets/general/layout_containers/flow_widget.cpp
src/interface/widgets/general/layout_containers/overlap_control_widget.cpp
src/interface/widgets/general/layout_containers/overlap_widget.cpp
src/interface/widgets/menus/deck_editor_menu.cpp
src/interface/widgets/printing_selector/all_zones_card_amount_widget.cpp
src/interface/widgets/printing_selector/card_amount_widget.cpp
src/interface/widgets/printing_selector/printing_selector.cpp
src/interface/widgets/printing_selector/printing_selector_card_display_widget.cpp
src/interface/widgets/printing_selector/printing_selector_card_overlay_widget.cpp
src/interface/widgets/printing_selector/printing_selector_card_search_widget.cpp
src/interface/widgets/printing_selector/printing_selector_card_selection_widget.cpp
src/interface/widgets/printing_selector/printing_selector_card_sorting_widget.cpp
src/interface/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp
src/interface/widgets/quick_settings/settings_button_widget.cpp
src/interface/widgets/quick_settings/settings_popup_widget.cpp
src/interface/widgets/replay/replay_manager.cpp
src/interface/widgets/replay/replay_timeline_widget.cpp
src/interface/widgets/server/chat_view/chat_view.cpp
src/interface/widgets/server/game_selector.cpp
src/interface/widgets/server/game_selector_quick_filter_toolbar.cpp
src/interface/widgets/server/games_model.cpp
src/interface/widgets/server/handle_public_servers.cpp
src/interface/widgets/server/remote/remote_decklist_tree_widget.cpp
src/interface/widgets/server/remote/remote_replay_list_tree_widget.cpp
src/interface/widgets/server/user/user_context_menu.cpp
src/interface/widgets/server/user/user_info_box.cpp
src/interface/widgets/server/user/user_info_connection.cpp
src/interface/widgets/server/user/user_list_manager.cpp
src/interface/widgets/server/user/user_list_widget.cpp
src/interface/widgets/utility/custom_line_edit.cpp
src/interface/widgets/utility/get_text_with_max.cpp
src/interface/widgets/utility/sequence_edit.cpp
src/interface/widgets/visual_database_display/visual_database_display_color_filter_widget.cpp
src/interface/widgets/visual_database_display/visual_database_display_filter_save_load_widget.cpp
src/interface/widgets/visual_database_display/visual_database_display_format_legality_filter_widget.cpp
src/interface/widgets/visual_database_display/visual_database_display_main_type_filter_widget.cpp
src/interface/widgets/visual_database_display/visual_database_display_name_filter_widget.cpp
src/interface/widgets/visual_database_display/visual_database_display_set_filter_widget.cpp
src/interface/widgets/visual_database_display/visual_database_display_sub_type_filter_widget.cpp
src/interface/widgets/visual_database_display/visual_database_display_widget.cpp
src/interface/widgets/visual_database_display/visual_database_filter_display_widget.cpp
src/interface/widgets/visual_deck_editor/visual_deck_display_options_widget.cpp
src/interface/widgets/visual_deck_editor/visual_deck_editor_sample_hand_widget.cpp
src/interface/widgets/visual_deck_editor/visual_deck_editor_widget.cpp
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.cpp
src/interface/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp
src/interface/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp
src/interface/widgets/visual_deck_storage/visual_deck_storage_quick_settings_widget.cpp
src/interface/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp
src/interface/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp
src/interface/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp
src/interface/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
src/interface/window_main.cpp
src/main.cpp src/main.cpp
src/interface/widgets/tabs/abstract_tab_deck_editor.cpp src/server/message_log_widget.cpp
src/interface/widgets/tabs/api/archidekt/tab_archidekt.cpp src/client/ui/layouts/overlap_layout.cpp
src/interface/widgets/tabs/api/archidekt/api_response/archidekt_deck_listing_api_response.cpp src/client/ui/widgets/general/layout_containers/overlap_widget.cpp
src/interface/widgets/tabs/api/archidekt/api_response/archidekt_formats.h src/client/ui/widgets/general/layout_containers/overlap_control_widget.cpp
src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card.cpp src/server/pending_command.cpp
src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_card_entry.cpp src/game/phase.cpp
src/interface/widgets/tabs/api/archidekt/api_response/card/archidekt_api_response_edition.cpp src/client/ui/phases_toolbar.cpp
src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck.cpp src/client/ui/picture_loader/picture_loader.cpp
src/interface/widgets/tabs/api/archidekt/api_response/deck/archidekt_api_response_deck_category.cpp src/client/ui/picture_loader/picture_loader_worker.cpp
src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_listing_container.cpp src/client/ui/picture_loader/picture_to_load.cpp
src/interface/widgets/tabs/api/archidekt/api_response/deck_listings/archidekt_api_response_deck_owner.cpp src/game/zones/pile_zone.cpp
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_display_widget.cpp src/client/ui/pixel_map_generator.cpp
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_entry_display_widget.cpp src/game/player/player.cpp
src/interface/widgets/tabs/api/archidekt/display/archidekt_api_response_deck_listings_display_widget.cpp src/game/player/player_list_widget.cpp
src/interface/widgets/tabs/api/archidekt/display/archidekt_deck_preview_image_display_widget.cpp src/game/player/player_target.cpp
src/interface/widgets/tabs/api/edhrec/api_response/archidekt_links/edhrec_api_response_archidekt_links.cpp src/client/ui/widgets/printing_selector/all_zones_card_amount_widget.cpp
src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_average_deck_api_response.cpp src/client/ui/widgets/printing_selector/card_amount_widget.cpp
src/interface/widgets/tabs/api/edhrec/api_response/average_deck/edhrec_deck_api_response.cpp src/client/ui/widgets/printing_selector/printing_selector.cpp
src/interface/widgets/tabs/api/edhrec/api_response/card_prices/edhrec_api_response_card_prices.cpp src/client/ui/widgets/printing_selector/printing_selector_card_display_widget.cpp
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_container.cpp src/client/ui/widgets/printing_selector/printing_selector_card_overlay_widget.cpp
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_details.cpp src/client/ui/widgets/printing_selector/printing_selector_card_search_widget.cpp
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_api_response_card_list.cpp src/client/ui/widgets/printing_selector/printing_selector_card_selection_widget.cpp
src/interface/widgets/tabs/api/edhrec/api_response/cards/edhrec_commander_api_response_commander_details.cpp src/client/ui/widgets/printing_selector/printing_selector_card_sorting_widget.cpp
src/interface/widgets/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response.cpp src/client/ui/widgets/printing_selector/printing_selector_view_options_toolbar_widget.cpp
src/interface/widgets/tabs/api/edhrec/api_response/commander/edhrec_commander_api_response_average_deck_statistics.cpp src/client/ui/widgets/printing_selector/printing_selector_view_options_widget.cpp
src/interface/widgets/tabs/api/edhrec/api_response/top_cards/edhrec_top_cards_api_response.cpp src/client/ui/widgets/printing_selector/set_name_and_collectors_number_display_widget.cpp
src/interface/widgets/tabs/api/edhrec/api_response/top_commanders/edhrec_top_commanders_api_response.cpp src/client/network/release_channel.cpp
src/interface/widgets/tabs/api/edhrec/api_response/top_tags/edhrec_top_tags_api_response.cpp src/client/network/client_update_checker.cpp
src/interface/widgets/tabs/api/edhrec/display/card_prices/edhrec_api_response_card_prices_display_widget.cpp src/server/remote/remote_client.cpp
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_details_display_widget.cpp src/server/remote/remote_decklist_tree_widget.cpp
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_inclusion_display_widget.cpp src/server/remote/remote_replay_list_tree_widget.cpp
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_list_display_widget.cpp src/client/network/replay_timeline_widget.cpp
src/interface/widgets/tabs/api/edhrec/display/cards/edhrec_api_response_card_synergy_display_widget.cpp src/game/zones/select_zone.cpp
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_api_response_commander_details_display_widget.cpp src/utility/sequence_edit.cpp
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_display_widget.cpp src/client/network/sets_model.cpp
src/interface/widgets/tabs/api/edhrec/display/commander/edhrec_commander_api_response_navigation_widget.cpp src/settings/card_database_settings.cpp
src/interface/widgets/tabs/api/edhrec/display/top_cards/edhrec_top_cards_api_response_display_widget.cpp src/settings/download_settings.cpp
src/interface/widgets/tabs/api/edhrec/display/top_commander/edhrec_top_commanders_api_response_display_widget.cpp src/settings/game_filters_settings.cpp
src/interface/widgets/tabs/api/edhrec/display/top_tags/edhrec_top_tags_api_response_display_widget.cpp src/settings/layouts_settings.cpp
src/interface/widgets/tabs/api/edhrec/tab_edhrec.cpp src/settings/message_settings.cpp
src/interface/widgets/tabs/api/edhrec/tab_edhrec_main.cpp src/settings/recents_settings.cpp
src/interface/widgets/tabs/tab.cpp src/settings/servers_settings.cpp
src/interface/widgets/tabs/tab_account.cpp src/settings/settings_manager.cpp
src/interface/widgets/tabs/tab_admin.cpp src/settings/cache_settings.cpp
src/interface/widgets/tabs/tab_deck_editor.cpp src/settings/shortcuts_settings.cpp
src/interface/widgets/tabs/tab_deck_storage.cpp src/settings/shortcut_treeview.cpp
src/interface/widgets/tabs/tab_game.cpp src/settings/card_override_settings.cpp
src/interface/widgets/tabs/tab_home.cpp src/settings/debug_settings.cpp
src/interface/widgets/tabs/tab_logs.cpp src/client/sound_engine.cpp
src/interface/widgets/tabs/tab_message.cpp src/client/network/spoiler_background_updater.cpp
src/interface/widgets/tabs/tab_replays.cpp src/game/zones/stack_zone.cpp
src/interface/widgets/tabs/tab_room.cpp src/client/tabs/tab.cpp
src/interface/widgets/tabs/tab_server.cpp src/client/tabs/tab_account.cpp
src/interface/widgets/tabs/tab_supervisor.cpp src/client/tabs/tab_admin.cpp
src/interface/widgets/tabs/tab_visual_database_display.cpp src/client/tabs/tab_deck_editor.cpp
src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual.cpp src/client/tabs/tab_deck_storage.cpp
src/interface/widgets/tabs/visual_deck_editor/tab_deck_editor_visual_tab_widget.cpp src/client/tabs/tab_game.cpp
src/interface/widgets/tabs/visual_deck_storage/tab_deck_storage_visual.cpp src/client/tabs/tab_logs.cpp
src/interface/key_signals.cpp src/client/tabs/tab_message.cpp
src/interface/logger.cpp src/client/tabs/tab_replays.cpp
src/client/tabs/tab_room.cpp
src/client/tabs/tab_server.cpp
src/client/tabs/tab_supervisor.cpp
src/client/tabs/api/edhrec/tab_edhrec.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_display_widget.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_card_details_display_widget.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_card_list_display_widget.cpp
src/client/tabs/api/edhrec/edhrec_commander_api_response_commander_details_display_widget.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_archidekt_links.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_average_deck_statistics.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_details.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_list.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_container.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_card_prices.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response_commander_details.cpp
src/client/tabs/api/edhrec/api_response/edhrec_commander_api_response.cpp
src/game/zones/table_zone.cpp
src/client/tapped_out_interface.cpp
src/client/ui/theme_manager.cpp
src/client/ui/tip_of_the_day.cpp
src/client/translate_counter_name.cpp
src/client/update_downloader.cpp
src/server/user/user_context_menu.cpp
src/server/user/user_info_connection.cpp
src/server/user/user_info_box.cpp
src/server/user/user_list_manager.cpp
src/server/user/user_list_widget.cpp
src/client/ui/window_main.cpp
src/game/zones/view_zone_widget.cpp
src/game/zones/view_zone.cpp
src/client/tabs/visual_deck_storage/tab_deck_storage_visual.cpp
src/client/ui/widgets/cards/deck_preview_card_picture_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_color_identity_filter_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_addition_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_display_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_dialog.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_tag_item_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_deck_tags_display_widget.cpp
src/client/ui/widgets/visual_deck_storage/deck_preview/deck_preview_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_folder_display_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_search_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_sort_widget.cpp
src/client/ui/widgets/visual_deck_storage/visual_deck_storage_tag_filter_widget.cpp
${VERSION_STRING_CPP}
) )
add_subdirectory(sounds) add_subdirectory(sounds)
@@ -298,23 +204,15 @@ configure_file(
set(cockatrice_RESOURCES cockatrice.qrc) set(cockatrice_RESOURCES cockatrice.qrc)
if(UPDATE_TRANSLATIONS) if(UPDATE_TRANSLATIONS)
# Cockatrice main sources
file(GLOB_RECURSE translate_cockatrice_SRCS ${CMAKE_SOURCE_DIR}/cockatrice/src/*.cpp file(GLOB_RECURSE translate_cockatrice_SRCS ${CMAKE_SOURCE_DIR}/cockatrice/src/*.cpp
${CMAKE_SOURCE_DIR}/cockatrice/src/*.h ${CMAKE_SOURCE_DIR}/cockatrice/src/*.h
) )
file(GLOB_RECURSE translate_common_SRCS ${CMAKE_SOURCE_DIR}/common/*.cpp ${CMAKE_SOURCE_DIR}/common/*.h)
# All libcockatrice_* libraries (recursively) set(translate_SRCS ${translate_cockatrice_SRCS} ${translate_common_SRCS})
file(GLOB_RECURSE translate_lib_SRCS ${CMAKE_SOURCE_DIR}/libcockatrice_*/**/*.cpp
${CMAKE_SOURCE_DIR}/libcockatrice_*/**/*.h
)
# Combine all sources for translation
set(translate_SRCS ${translate_cockatrice_SRCS} ${translate_lib_SRCS})
set(cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice_en@source.ts") set(cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/cockatrice_en@source.ts")
else() else()
file(GLOB cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts") file(GLOB cockatrice_TS "${CMAKE_CURRENT_SOURCE_DIR}/translations/*.ts")
endif() endif(UPDATE_TRANSLATIONS)
if(WIN32) if(WIN32)
set(cockatrice_SOURCES ${cockatrice_SOURCES} cockatrice.rc) set(cockatrice_SOURCES ${cockatrice_SOURCES} cockatrice.rc)
@@ -344,6 +242,12 @@ set(DESKTOPDIR
CACHE STRING "desktop file destination" CACHE STRING "desktop file destination"
) )
# Include directories
include_directories(../common)
include_directories(${PROTOBUF_INCLUDE_DIR})
include_directories(${CMAKE_BINARY_DIR}/common)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
set(COCKATRICE_MAC_QM_INSTALL_DIR "cockatrice.app/Contents/Resources/translations") set(COCKATRICE_MAC_QM_INSTALL_DIR "cockatrice.app/Contents/Resources/translations")
set(COCKATRICE_UNIX_QM_INSTALL_DIR "share/cockatrice/translations") set(COCKATRICE_UNIX_QM_INSTALL_DIR "share/cockatrice/translations")
set(COCKATRICE_WIN32_QM_INSTALL_DIR "translations") set(COCKATRICE_WIN32_QM_INSTALL_DIR "translations")
@@ -383,31 +287,9 @@ elseif(Qt5_FOUND)
endif() endif()
if(Qt5_FOUND) if(Qt5_FOUND)
target_link_libraries( target_link_libraries(cockatrice cockatrice_common ${COCKATRICE_QT_MODULES})
cockatrice
libcockatrice_card
libcockatrice_deck_list
libcockatrice_filters
libcockatrice_utility
libcockatrice_network
libcockatrice_models
libcockatrice_rng
libcockatrice_settings
${COCKATRICE_QT_MODULES}
)
else() else()
target_link_libraries( target_link_libraries(cockatrice PUBLIC cockatrice_common ${COCKATRICE_QT_MODULES})
cockatrice
PUBLIC libcockatrice_card
libcockatrice_deck_list
libcockatrice_filters
libcockatrice_utility
libcockatrice_network
libcockatrice_models
libcockatrice_rng
libcockatrice_settings
${COCKATRICE_QT_MODULES}
)
endif() endif()
if(UNIX) if(UNIX)
@@ -456,13 +338,6 @@ if(APPLE)
PATTERN "tls/*.dylib" PATTERN "tls/*.dylib"
) )
install(
DIRECTORY "${CMAKE_BINARY_DIR}/cockatrice/"
DESTINATION ${qtconf_dest_dir}/
FILES_MATCHING
PATTERN "*.ini"
)
install( install(
CODE " CODE "
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths] file(WRITE \"\${CMAKE_INSTALL_PREFIX}/${qtconf_dest_dir}/qt.conf\" \"[Paths]

View File

@@ -7,37 +7,27 @@
<file>resources/icons/arrow_bottom_green.svg</file> <file>resources/icons/arrow_bottom_green.svg</file>
<file>resources/icons/arrow_down_green.svg</file> <file>resources/icons/arrow_down_green.svg</file>
<file>resources/icons/arrow_history.svg</file>
<file>resources/icons/arrow_left_green.svg</file> <file>resources/icons/arrow_left_green.svg</file>
<file>resources/icons/arrow_redo.svg</file>
<file>resources/icons/arrow_right_blue.svg</file> <file>resources/icons/arrow_right_blue.svg</file>
<file>resources/icons/arrow_right_green.svg</file> <file>resources/icons/arrow_right_green.svg</file>
<file>resources/icons/arrow_top_green.svg</file> <file>resources/icons/arrow_top_green.svg</file>
<file>resources/icons/arrow_up_green.svg</file> <file>resources/icons/arrow_up_green.svg</file>
<file>resources/icons/arrow_undo.svg</file>
<file>resources/icons/clearsearch.svg</file> <file>resources/icons/clearsearch.svg</file>
<file>resources/icons/cogwheel.svg</file>
<file>resources/icons/conceded.svg</file> <file>resources/icons/conceded.svg</file>
<file>resources/icons/decrement.svg</file> <file>resources/icons/decrement.svg</file>
<file>resources/icons/delete.svg</file> <file>resources/icons/delete.svg</file>
<file>resources/icons/dropdown_collapsed.svg</file>
<file>resources/icons/dropdown_expanded.svg</file>
<file>resources/icons/forgot_password.svg</file> <file>resources/icons/forgot_password.svg</file>
<file>resources/icons/increment.svg</file> <file>resources/icons/increment.svg</file>
<file>resources/icons/info.svg</file> <file>resources/icons/info.svg</file>
<file>resources/icons/lock.svg</file> <file>resources/icons/lock.svg</file>
<file>resources/icons/not_ready_start.svg</file> <file>resources/icons/not_ready_start.svg</file>
<file>resources/icons/pencil.svg</file> <file>resources/icons/pencil.svg</file>
<file>resources/icons/pin.svg</file>
<file>resources/icons/player.svg</file> <file>resources/icons/player.svg</file>
<file>resources/icons/ready_start.svg</file> <file>resources/icons/ready_start.svg</file>
<file>resources/icons/reload.svg</file>
<file>resources/icons/remove_row.svg</file> <file>resources/icons/remove_row.svg</file>
<file>resources/icons/rename.svg</file>
<file>resources/icons/scales.svg</file> <file>resources/icons/scales.svg</file>
<file>resources/icons/search.svg</file> <file>resources/icons/search.svg</file>
<file>resources/icons/settings.svg</file> <file>resources/icons/settings.svg</file>
<file>resources/icons/share.svg</file>
<file>resources/icons/spectator.svg</file> <file>resources/icons/spectator.svg</file>
<file>resources/icons/swap.svg</file> <file>resources/icons/swap.svg</file>
<file>resources/icons/sync.svg</file> <file>resources/icons/sync.svg</file>
@@ -45,14 +35,6 @@
<file>resources/icons/update.png</file> <file>resources/icons/update.png</file>
<file>resources/icons/view.svg</file> <file>resources/icons/view.svg</file>
<file>resources/icons/mana/B.svg</file>
<file>resources/icons/mana/G.svg</file>
<file>resources/icons/mana/R.svg</file>
<file>resources/icons/mana/U.svg</file>
<file>resources/icons/mana/W.svg</file>
<file>resources/backgrounds/home.png</file>
<file>resources/config/general.svg</file> <file>resources/config/general.svg</file>
<file>resources/config/appearance.svg</file> <file>resources/config/appearance.svg</file>
<file>resources/config/interface.svg</file> <file>resources/config/interface.svg</file>
@@ -360,32 +342,21 @@
<!-- ADD TIP OF THE DAY IMAGES HERE --> <!-- ADD TIP OF THE DAY IMAGES HERE -->
<file>resources/tips/images/accounts_tab.png</file> <file>resources/tips/images/accounts_tab.png</file>
<file>resources/tips/images/add_card.png</file>
<file>resources/tips/images/arrows.png</file> <file>resources/tips/images/arrows.png</file>
<file>resources/tips/images/card_select.png</file>
<file>resources/tips/images/cockatrice_register.png</file> <file>resources/tips/images/cockatrice_register.png</file>
<file>resources/tips/images/cockatrice_wiki.png</file> <file>resources/tips/images/cockatrice_wiki.png</file>
<file>resources/tips/images/coin_flip.png</file> <file>resources/tips/images/coin_flip.png</file>
<file>resources/tips/images/counter_expression.png</file> <file>resources/tips/images/counter_expression.png</file>
<file>resources/tips/images/discord.png</file> <file>resources/tips/images/discord.png</file>
<file>resources/tips/images/edhrec.png</file>
<file>resources/tips/images/expand_card_view.png</file>
<file>resources/tips/images/face_down.png</file> <file>resources/tips/images/face_down.png</file>
<file>resources/tips/images/filter_games.png</file> <file>resources/tips/images/filter_games.png</file>
<file>resources/tips/images/github_logo.png</file> <file>resources/tips/images/github_logo.png</file>
<file>resources/tips/images/highlight_cards.png</file>
<file>resources/tips/images/pawns.png</file>
<file>resources/tips/images/setpt.png</file> <file>resources/tips/images/setpt.png</file>
<file>resources/tips/images/shortcuts.png</file> <file>resources/tips/images/shortcuts.png</file>
<file>resources/tips/images/syntax_help.png</file>
<file>resources/tips/images/themes.png</file> <file>resources/tips/images/themes.png</file>
<file>resources/tips/images/tip_of_the_day.png</file> <file>resources/tips/images/tip_of_the_day.png</file>
<file>resources/tips/images/token.png</file>
<file>resources/tips/images/updates.png</file>
<file>resources/tips/images/visual_deck_tags.png</file>
<file>resources/tips/tips_of_the_day.xml</file> <file>resources/tips/tips_of_the_day.xml</file>
<file>resources/help/search.md</file> <file>resources/help/search.md</file>
<file>resources/help/deck_search.md</file>
</qresource> </qresource>
</RCC> </RCC>

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 MiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

@@ -1,72 +1,55 @@
[Rules] [Rules]
# The default log level is info # Uncomment a rule to disable logging for that category
*.debug = false
#*.info = true
#*.warning = true
#*.critical = true
#*.fatal = true
# Uncomment a rule to see debug level logs for that category, # main = false
# or set <category> = false to disable logging # qt_translator = false
# window_main.* = false
# release_channel = false
# spoiler_background_updater = false
# theme_manager = false
# sound_engine = false
# tapped_out_interface = false
#main = true # tab_game = false
#qt_translator = true # tab_message = false
#window_main.* = true # tab_supervisor = false
#release_channel = true
#spoiler_background_updater = true
#theme_manager = true
#sound_engine = true
#tapped_out_interface = true
#tab_game = true # dlg_edit_avatar = false
#tab_message = true # dlg_settings = false
#tab_supervisor = true # dlg_tip_of_the_day = false
# dlg_update = false
#dlg_edit_avatar = true # settings_cache = false
#dlg_load_deck_from_website = true # servers_settings = false
#dlg_settings = true # shortcuts_settings = false
#dlg_tip_of_the_day = true
#dlg_update = true
#settings_cache = true # remote_client = false
#servers_settings = true
#shortcuts_settings = true
#local_client = true # player = false
#remote_client = true # game_scene = false
# game_scene.player_addition_removal = false
# card_zone = false
# view_zone = false
#player = true # user_info_connection = false
#game_scene = true
#game_scene.player_addition_removal = true
#card_zone = true
#view_zone = true
#game_event_handler = true # picture_loader = false
# picture_loader.worker = false
# picture_loader.card_back_cache_fail = false
# picture_loader.picture_to_load = false
# deck_loader = false
# card_database = false
# card_database.loading = false
# card_database.loading.success_or_failure = false
# cockatrice_xml.* = false
# cockatrice_xml.xml_3_parser = false
# cockatrice_xml.xml_4_parser = false
# card_list = false
#user_info_connection = true flow_layout.debug = false
flow_widget.debug = false
flow_widget.size.debug = false
#card_picture_loader = true # pixel_map_generator = false
#card_picture_loader.worker = true
#card_picture_loader.card_back_cache_fail = true
#card_picture_loader.picture_to_load = true
#deck_loader = true
#card_database = true
#card_database.loading = true
#card_database.loading.success_or_failure = true
#cockatrice_xml.* = true
#cockatrice_xml.xml_3_parser = true
#cockatrice_xml.xml_4_parser = true
#card_info = true
#card_list = true
#flow_layout = true # filter_string = false
#flow_widget = true
#flow_widget.size = true
#card_info_picture_widget = true
#pixel_map_generator = true
#deck_filter_string = true
#filter_string = true
#syntax_help = true

View File

@@ -1,45 +0,0 @@
@page deck_search_syntax_help Deck Search Syntax Help
## Deck Search Syntax Help
-----
The search bar recognizes a set of special commands.<br>
In this list of examples below, each entry has an explanation and can be clicked to test the query. Note that all
searches are case insensitive.
<dl>
<dt>Display Name (The deck name, or the filename if the deck name isn't set):</dt>
<dd>[red deck wins](#red deck wins) <small>(Any deck with a display name containing the words red, deck, and wins)</small></dd>
<dd>["red deck wins"](#%22red deck wins%22) <small>(Any deck with a display name containing the exact phrase "red deck wins")</small></dd>
<dt>Deck <u>N</u>ame:</dt>
<dd>[n:aggro](#n:aggro) <small>(Any deck with a name containing the word aggro)</small></dd>
<dd>[n:red n:deck n:wins](#n:red n:deck n:wins) <small>(Any deck with a name containing the words red, deck, and wins)</small></dd>
<dd>[n:"red deck wins"](#n:%22red deck wins%22) <small>(Any deck with a name containing the exact phrase "red deck wins")</small></dd>
<dt><u>F</u>ile <u>N</u>ame:</dt>
<dd>[fn:aggro](#fn:aggro) <small>(Any deck with a filename containing the word aggro)</small></dd>
<dd>[fn:red fn:deck fn:wins](#fn:red fn:deck fn:wins) <small>(Any deck with a filename containing the words red, deck, and wins)</small></dd>
<dd>[fn:"red deck wins"](#fn:%22red deck wins%22) <small>(Any deck with a filename containing the exact phrase "red deck wins")</small></dd>
<dt>Relative <u>P</u>ath (starting from the deck folder):</dt>
<dd>[p:aggro](#p:aggro) <small>(Any deck that has "aggro" somewhere in its relative path)</small></dd>
<dd>[p:edh/](#p:edh/) <small>(Any deck with "edh/" in its relative path, A.K.A. decks in the "edh" folder)</small></dd>
<dt><u>F</u>ormat:</dt>
<dd>[f:standard](#f:standard) <small>(Any deck with format set to standard)</small></dd>
<dt>Deck Contents (Uses [card search expressions](#cardSearchSyntaxHelp)):</dt>
<dd><a href="#[[plains]]">[[plains]]</a> <small>(Any deck that contains at least one card with "plains" in its name)</small></dd>
<dd><a href="#[[t:legendary]]">[[t:legendary]]</a> <small>(Any deck that contains at least one legendary)</small></dd>
<dd><a href="#[[t:legendary]]>5">[[t:legendary]]>5</a> <small>(Any card that contains at least 5 legendaries)</small></dd>
<dd><a href="#[[]]:100">[[]]:100</a> <small>(Any deck that contains exactly 100 cards)</small></dd>
<dt>Negate:</dt>
<dd>[soldier -aggro](#soldier -aggro) <small>(Any deck filename that contains "soldier", but not "aggro")</small></dd>
<dt>Branching:</dt>
<dd>[t:aggro OR o:control](#t:aggro OR o:control) <small>(Any deck filename that contains either aggro or control)</small></dd>
<dt>Grouping:</dt>
<dd><a href="#red -([[]]:100 or aggro)">red -([[]]:100 or aggro)</a> <small>(Any deck that has red in its filename but is not 100 cards or has aggro in its filename)</small></dd>
</dl>

View File

@@ -1,5 +1,3 @@
@page search_syntax_help Search Syntax Help
## Search Syntax Help ## Search Syntax Help
----- -----
The search bar recognizes a set of special commands similar to some other card databases.<br> The search bar recognizes a set of special commands similar to some other card databases.<br>
@@ -60,9 +58,4 @@ In this list of examples below, each entry has an explanation and can be clicked
<dt>Grouping:</dt> <dt>Grouping:</dt>
<dd><a href="#t:angel -(angel or c:w)">t:angel -(angel or c:w)</a> <small>(Any angel that doesn't have angel in its name and isn't white)</small></dd> <dd><a href="#t:angel -(angel or c:w)">t:angel -(angel or c:w)</a> <small>(Any angel that doesn't have angel in its name and isn't white)</small></dd>
<dt>Regular Expression:</dt>
<dd>[/^fell/](#/^fell/) <small>(Any card name that begins with "fell")</small></dd>
<dd>[o:/counter target .* spell/](#o:/counter target .* spell/) <small>(Any card text with "counter target *something* spell")</small></dd>
<dd>[o:/for each .* and\/or .*/](#o:/for each .* and\/or .*/) <small>(/'s can be escaped with a \)</small></dd>
</dl> </dl>

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<title>
history
</title>
<path d="M9 6v5h.06l2.48 2.47 1.41-1.41L11 10.11V6H9z"/>
<path d="M10 1a9 9 0 0 0-7.85 13.35L.5 16H6v-5.5l-2.38 2.38A7 7 0 1 1 10 17v2a9 9 0 0 0 0-18z"/>
</svg>

Before

Width:  |  Height:  |  Size: 332 B

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="windows-1252"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" x="0px"
y="0px" width="485.212px" height="485.212px" viewBox="0 0 485.212 485.212"
style="enable-background:new 0 0 485.212 485.212;" xml:space="preserve">
<g>
<path d="M242.607,424.559c-75.252,0-136.468-61.209-136.468-136.465c0-75.252,61.216-136.466,136.468-136.466v90.978 l151.629-121.302L242.607,0v90.978c-108.687,0-197.117,88.432-197.117,197.117c0,108.691,88.43,197.118,197.117,197.118 c108.687,0,197.114-88.427,197.114-197.118h-60.645C379.077,363.35,317.859,424.559,242.607,424.559z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1018 B

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="windows-1252"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" x="0px"
y="0px" width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;"
xml:space="preserve">
<g>
<path d="M256,448c79.406,0,144-64.594,144-144s-64.594-144-144-144v96L96,128L256,0v96c114.688,0,208,93.313,208,208 c0,114.688-93.312,208-208,208c-114.687,0-208-93.312-208-208h64C112,383.406,176.594,448,256,448z"/>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 874 B

View File

@@ -1,29 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="102.5024mm" height="102.24421mm"
viewBox="0 0 102.5024 102.24421" version="1.1"
id="svg1"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)" sodipodi:docname="cog_wheel.svg"
xmlns="http://www.w3.org/2000/svg">
<sodipodi:namedview id="namedview1" pagecolor="#ffffff" bordercolor="#000000" borderopacity="0.25"
inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" inkscape:zoom="0.66101291"
inkscape:cx="146.74449" inkscape:cy="193.64221" inkscape:window-width="1829"
inkscape:window-height="951" inkscape:window-x="0" inkscape:window-y="0"
inkscape:window-maximized="1" inkscape:current-layer="layer1"/>
<defs id="defs1"/>
<g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(-66.148059,-97.377896)">
<g id="g1" transform="translate(-165.09777,-82.009607)">
<g id="g2" transform="matrix(0.26458333,0,0,0.26458333,64.983323,161.37858)">
<path style="fill:#333333;stroke-width:94.4882"
d="m 721.34301,94.413051 40.00966,29.763289 29.51933,-9.27053 14.63768,-46.840589 36.83817,0.48792 13.41787,46.108699 28.29952,9.5145 40.74155,-28.299519 29.0314,21.468599 -15.85748,47.08454 16.58937,23.66426 48.30432,-2.68358 12.93,34.88648 -41.71741,27.07971 -0.48792,29.27536 40.49763,26.10387 -10.2464,34.15459 -48.54834,-0.97584 -18.78502,23.42029 15.85749,45.37681 -28.29952,21.71256 -41.22947,-29.27536 -28.54348,9.75846 -13.66184,47.57246 -38.30194,-0.73188 -14.63768,-48.30435 -27.07971,-9.27054 -40.00966,29.27537 -30.25121,-20.49276 17.32125,-46.35266 -17.80918,-24.64009 -49.76812,3.17149 -11.22222,-34.64251 40.74155,-27.07971 0.48792,-30.00725 -41.71739,-27.32367 12.19807,-32.93479 48.30435,2.68358 20.24879,-24.6401 -17.32126,-47.08455 z"
id="path1"/>
<circle style="fill:#f9f9f9;stroke-width:72.1317" id="path2" cx="822.09906" cy="261.28262"
r="83.434792"/>
<circle style="fill:#4d4d4d;stroke-width:40.5147" id="circle2" cx="822.09906" cy="261.28262"
r="46.863361"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.1" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="460.5" height="531.74"
viewBox="0 0 460.5 531.74" overflow="visible" enable-background="new 0 0 460.5 531.74" xml:space="preserve">
<polygon fill="#918d8d" points="0.5,0.866 459.5,265.87 0.5,530.874 "/>
</svg>

Before

Width:  |  Height:  |  Size: 657 B

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 12.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 51448) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg version="1.1" id="Layer_1" xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" width="531.74" height="460.5"
viewBox="0 0 531.74 460.5" overflow="visible" enable-background="new 0 0 531.74 460.5" xml:space="preserve">
<polygon fill="#918d8d" points="530.874,0.5 265.87,459.5 0.866,0.5 "/>
</svg>

Before

Width:  |  Height:  |  Size: 657 B

View File

@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="169.34801mm"
height="169.34801mm"
viewBox="0 0 600 600"
version="1.1"
id="svg1"
sodipodi:docname="B.svg"
inkscape:export-filename="B.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1"/>
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm">
<inkscape:page
x="0"
y="0"
width="600"
height="600"
id="page2"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<path
id="Selection"
fill="none"
stroke="#000000"
stroke-width="1"
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
style="display:inline;fill:#ababab;fill-opacity:1"/>
<path
d="m 299.67889,84.945431 c -118.26949,0 -214.122988,83.892719 -214.122988,187.357619 0,58.63289 30.863828,110.90901 79.041488,145.28579 8.02961,5.77129 12.71356,15.13917 11.29165,25.0089 l -7.86234,55.37086 c -1.17098,8.02962 5.01851,15.22281 13.13176,15.22281 h 64.98968 v -46.83939 c 0,-3.68025 3.01111,-6.69135 6.69135,-6.69135 h 13.38268 c 3.68024,0 6.69135,3.0111 6.69135,6.69135 v 46.83939 h 53.53075 v -46.83939 c 0,-3.68025 3.01111,-6.69135 6.69134,-6.69135 h 13.38269 c 3.68023,0 6.69134,3.0111 6.69134,6.69135 v 46.83939 h 64.98967 c 8.11327,0 14.30275,-7.19319 13.13177,-15.22281 l -7.86234,-55.37086 c -1.4219,-9.78609 3.1784,-19.23761 11.29165,-25.0089 48.17767,-34.37678 79.0415,-86.6529 79.0415,-145.28579 0,-103.4649 -95.8535,-187.357619 -214.123,-187.357619 z M 219.38277,352.59917 c -29.52555,0 -53.53075,-24.0052 -53.53075,-53.53075 0,-29.52555 24.0052,-53.53075 53.53075,-53.53075 29.52555,0 53.53075,24.0052 53.53075,53.53075 0,29.52555 -24.0052,53.53075 -53.53075,53.53075 z m 160.59225,0 c -29.52555,0 -53.53075,-24.0052 -53.53075,-53.53075 0,-29.52555 24.0052,-53.53075 53.53075,-53.53075 29.52555,0 53.53075,24.0052 53.53075,53.53075 0,29.52555 -24.0052,53.53075 -53.53075,53.53075 z"
id="path1"
style="fill:#4d4d4d;fill-opacity:1;stroke:#000000;stroke-width:0.836419;stroke-opacity:1"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
width="169.34801mm"
height="169.34801mm"
viewBox="0 0 600 600"
version="1.1"
id="svg1"
sodipodi:docname="B.svg"
inkscape:export-filename="U.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1"/>
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm">
<inkscape:page
x="0"
y="0"
width="600"
height="600"
id="page2"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<path
id="Selection"
fill="none"
stroke="#000000"
stroke-width="1"
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
style="display:inline;fill:#5f9f56;fill-opacity:1"/>
<path
d="m 488.52401,428.04591 -80.36527,-83.50228 h 30.81218 c 9.06362,0 17.08104,-4.61393 20.90363,-12.05153 3.82262,-7.41912 2.56521,-15.92714 -3.29949,-22.19282 l -78.59482,-83.87142 h 29.06188 c 9.15413,0 17.40291,-4.93688 20.98411,-12.55902 3.54092,-7.50219 1.87106,-16.23169 -4.26525,-22.22053 L 312.83499,83.240199 c -6.06588,-5.951919 -17.38282,-5.951919 -23.45873,0 L 178.44019,191.64831 c -6.13629,5.98884 -7.79612,14.71834 -4.26523,22.22053 3.58119,7.62214 11.84001,12.55902 20.99414,12.55902 h 29.06189 l -78.60489,83.88987 c -5.84454,6.25645 -7.10199,14.75525 -3.28944,22.18361 3.82262,7.42836 11.82996,12.04229 20.90363,12.04229 h 30.81222 l -80.36527,83.50228 c -6.03569,6.26567 -7.40379,14.84754 -3.58117,22.38663 3.7723,7.42839 12.07138,12.22682 21.13497,12.22682 h 129.63669 c 0,0 -36.12127,66.38546 0,62.75824 h 80.45578 c 33.50708,5.78651 0,-62.75824 0,-62.75824 h 129.63668 c 9.06361,0 17.36266,-4.79843 21.13499,-12.22682 3.82262,-7.53909 2.45452,-16.12096 -3.58117,-22.38663 z"
id="ENVIR"
style="fill:#3f6e3a;fill-opacity:1;stroke:#000000;stroke-width:1.09833;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
width="169.34801mm"
height="169.34801mm"
viewBox="0 0 600 600"
version="1.1"
id="svg1"
sodipodi:docname="B.svg"
inkscape:export-filename="B.svg"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1"/>
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm">
<inkscape:page
x="0"
y="0"
width="600"
height="600"
id="page2"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<path
id="Selection"
fill="none"
stroke="#000000"
stroke-width="1"
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
style="display:inline;fill:#c95e46;fill-opacity:1"/>
<path
style="display:inline;fill:#7e3525;fill-opacity:1;stroke:#000000;stroke-width:0.999129;stroke-dasharray:none;stroke-opacity:1"
d="m 278.25473,537.27772 c -22.36635,-1.29637 -48.78648,-8.31223 -69.74195,-18.51997 -47.30139,-23.04123 -75.19872,-59.72004 -85.45343,-112.35234 -2.77041,-14.21911 -2.51753,-48.32296 0.4755,-64.1246 4.84373,-25.57244 17.23939,-55.03329 30.65191,-72.85059 3.74877,-4.97991 16.33133,-18.11906 30.23479,-31.57223 13.09764,-12.67346 26.64745,-26.67202 30.11069,-31.10792 16.66894,-21.35045 26.46602,-44.71272 29.68313,-70.78286 1.93489,-15.67951 0.37962,-45.867231 -3.5802,-69.491071 -0.58906,-3.51428 0.36584,-3.52724 11.47726,-0.15583 36.51454,11.0792 67.37028,34.791071 89.32423,68.643431 9.96686,15.36862 20.07787,39.31263 24.78919,58.70364 2.23257,9.18886 2.53252,44.73878 0.46396,54.98571 -0.75708,3.75024 -1.10086,7.09425 -0.76396,7.43114 1.5021,1.5021 14.63666,-6.65479 21.98002,-13.65016 10.59844,-10.09621 14.32693,-17.61354 15.94714,-32.15254 l 1.16788,-10.47988 3.4626,3.95724 c 26.80954,30.6392 41.75268,56.11528 54.11775,92.26358 11.02075,32.21825 14.93902,62.79297 12.47422,97.33768 -1.88493,26.41774 -10.16486,50.6958 -24.95555,73.17369 -6.31625,9.59901 -30.86306,34.05172 -40.40914,40.25423 -23.44452,15.23295 -50.15355,25.25695 -77.26806,28.99903 -12.48732,1.72336 -38.04339,2.42637 -54.18798,1.49062 z m 48.34948,-30.34196 c 30.78066,-8.0491 53.53846,-30.12825 59.69792,-57.9177 2.48916,-11.23027 2.26087,-34.25269 -0.43747,-44.11787 -5.3998,-19.74181 -9.72931,-26.61651 -30.6237,-48.62658 -16.92925,-17.8332 -21.73398,-24.64464 -25.45673,-36.0889 -2.38622,-7.33554 -2.63126,-9.53814 -2.57644,-23.15876 0.0334,-8.27872 0.486,-17.4607 1.00593,-20.40441 0.75887,-4.29636 0.66928,-5.45812 -0.45409,-5.88919 -2.12997,-0.81736 -16.25071,4.45522 -21.90917,8.1807 -25.69349,16.91641 -42.62753,52.30879 -40.22917,84.07948 0.39046,5.17228 0.2831,8.79277 -0.26071,8.79277 -1.78935,0 -13.49435,-13.46378 -15.34792,-17.65406 -1.03171,-2.33236 -2.15967,-6.42651 -2.50657,-9.09812 -1.00143,-7.71233 -1.60778,-8.14619 -5.46339,-3.90915 -13.31687,14.63425 -24.58113,35.69359 -29.53283,55.21379 -11.75615,46.34414 2.14731,84.38956 37.55813,102.77397 16.56338,8.59931 29.2427,11.25369 51.26679,10.73261 12.58064,-0.29766 17.41119,-0.85366 25.26942,-2.90858 z"
id="path8"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
width="169.34801mm"
height="169.34801mm"
viewBox="0 0 600 600"
version="1.1"
id="svg1"
sodipodi:docname="U.svg"
inkscape:export-filename="U.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1"/>
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm">
<inkscape:page
x="0"
y="0"
width="600"
height="600"
id="page2"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<path
id="Selection"
fill="none"
stroke="#000000"
stroke-width="1"
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
style="display:inline;fill:#4a8fd8;fill-opacity:1"/>
<path
style="display:inline;fill:#3266af;fill-opacity:1;stroke:#000000;stroke-width:1.06525;stroke-opacity:1"
d="m 275.20608,536.5693 c -58.69596,-9.5447 -107.01545,-50.69962 -125.66779,-107.0344 -9.25532,-27.95342 -10.39669,-58.82111 -3.22092,-87.1088 5.31307,-20.94475 9.06296,-28.00552 81.87785,-154.17 38.54798,-66.79109 70.40461,-121.77997 70.79251,-122.19751 1.00535,-1.08215 140.3595,240.63696 145.26785,251.97682 8.6735,20.03855 12.6923,39.82747 12.6923,62.49805 0,44.25387 -16.70161,83.24077 -48.85852,114.0514 -21.46938,20.57055 -45.69209,33.39124 -76.46586,40.47213 -12.83139,2.95245 -42.64639,3.75165 -56.41742,1.51231 z"
id="path2"
sodipodi:nodetypes="ssssssssss"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="169.34801mm"
height="169.34801mm"
viewBox="0 0 600 600"
version="1.1"
id="svg1"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
sodipodi:docname="W.svg"
inkscape:export-filename="W.png"
xmlns="http://www.w3.org/2000/svg">
<defs
id="defs1"/>
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm">
<inkscape:page
x="0"
y="0"
width="600"
height="600"
id="page2"
margin="0"
bleed="0"/>
</sodipodi:namedview>
<path
id="Selection"
fill="none"
stroke="#000000"
stroke-width="1"
d="m 275,0.21 c 0,0 42,0 42,0 0,0 19,1.51 19,1.51 29.13,3.58 56.99,10.83 84,22.43 33.64,14.45 59.89,32.91 86.91,57.41 17.38,15.76 34.67,37.56 47.14,57.44 22.78,36.31 37.1,74.56 43.22,117 1.28,8.88 2.72,19.08 2.73,28 0,0 0,34 0,34 0,0 -0.91,10 -0.91,10 -2.36,32.29 -11.93,67.59 -25.4,97 -27.01,58.98 -70.49,105.42 -126.69,137.57 -34.3,19.63 -79.56,33.64 -119,36.52 0,0 -12,0.91 -12,0.91 0,0 -34,0 -34,0 0,0 -10,-0.91 -10,-0.91 -26.57,-1.94 -53.09,-8.27 -78,-17.67 C 163.49,569.9 134.12,553.46 109,532.57 79.87,508.33 54.41,478.39 36.31,445 -5.08,368.65 -11.86,276.57 18.05,195 47.85,113.75 113.21,48.92 194,18.42 213.55,11.04 236.32,5.43 257,2.43 Z"
style="display:inline;fill:#ffefb3;fill-opacity:1"/>
<path
id="circle8"
d="M 387.28106,302.711 A 85.962512,85.962512 0 0 1 301.31852,388.67353 85.962512,85.962512 0 0 1 215.35597,302.711 85.962512,85.962512 0 0 1 301.31852,216.74844 85.962512,85.962512 0 0 1 387.28106,302.711 Z M 191.75349,358.6114 143.05798,460.97151 245.4181,412.27601 A 121.73882,121.73882 0 0 1 191.75349,358.6114 Z M 178.33753,302.711 c 0,-13.16763 2.23687,-25.83857 5.96271,-38.01232 L 77.71657,302.711 184.30024,340.7233 a 119.25435,119.25435 0 0 1 -5.96271,-38.0123 z m 178.8814,109.56501 102.36011,48.6955 -48.6955,-102.36011 a 121.73882,121.73882 0 0 1 -53.66461,53.66461 z m -55.90041,13.41595 c -13.16762,0 -26.0869,-2.23687 -38.01232,-5.9627 l 38.01232,106.58368 38.01231,-106.58368 a 119.25435,119.25435 0 0 1 -38.01231,5.9627 z m 109.56502,-178.88139 48.6955,-102.36012 -102.36011,48.69551 a 122.98106,122.98106 0 0 1 53.66461,53.66461 z M 245.66643,193.14596 143.30658,144.45045 192.00209,246.81057 a 121.73882,121.73882 0 0 1 53.66434,-53.66461 z M 524.92046,302.711 418.33679,264.69868 a 119.25435,119.25435 0 0 1 0,76.02462 z M 301.31852,179.73 c 13.16761,0 26.0869,2.23688 38.01231,5.96271 L 301.31852,79.109036 263.3062,185.69271 A 119.25435,119.25435 0 0 1 301.31852,179.73 Z"
style="fill:#b4a35e;fill-opacity:1;stroke:#000000;stroke-width:1.09833;stroke-dasharray:none;stroke-opacity:1"/>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="64" height="64">
<g transform="matrix(0 1 -1 0 99.465813 0)" opacity="0.7">
<path fill="#000000" fill-rule="evenodd" clip-rule="evenodd"
stroke="#ffffff"
stroke-width="4"
stroke-linejoin="round"
stroke-linecap="round"
d="M65.5 62
L78 49
C73.5 44.5 69.5 42 63 44
L45 31 C47 25 46 22 41.5 18
L19 41.5
C23 45.5 25 46.5 31 45
L44 62.5
C42.3 69 45 73.5 49 78
L61.5 65.5
L84 87
L87 87
L87.5 86.5
L87.5 83.5 Z" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 736 B

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"
viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
<metadata> Svg Vector Icons : http://www.onlinewebfonts.com/icon </metadata>
<g><path d="M586.9,373.6l95.6-84.4c-49.6-39.2-129.4-79.1-198.2-79.1c-134.9,0-248.2,90.5-280.2,212.8L10.6,374.5C64.4,168.3,255.2,15.8,482.5,15.8c126.7,0,258.8,63.7,345.4,141.4l90.8-80.1L990,479.6L586.9,373.6z M317.5,710.8c49.6,39.2,129.4,79.1,198.2,79.1c134.9,0,248.2-90.5,280.2-212.8l193.5,48.5c-53.7,206.2-244.6,358.7-471.9,358.7c-126.7,0-258.8-63.7-345.4-141.4l-90.8,80.1L10,520.4l403.1,106L317.5,710.8z"/></g>
</svg>

Before

Width:  |  Height:  |  Size: 797 B

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1200pt" height="1200pt" version="1.1" viewBox="0 0 1200 1200" xmlns="http://www.w3.org/2000/svg">
<path transform="scale(50)" d="m17 16h4v-8h-4" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="2"/>
<path transform="scale(50)" d="m12 8h-9v8h9" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="2"/>
<path transform="scale(50)" d="m6 12h5" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="2"/>
<path transform="scale(50)" d="m20 4h-2c-1.1 0-2 0.9-2 2v12c0 1.1 0.9 2 2 2h2" fill="none" stroke="#000"
stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
<path transform="scale(50)" d="m12 20h2c1.1 0 2-0.9 2-2v-12c0-1.1-0.9-2-2-2h-2" fill="none" stroke="#000"
stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2"/>
</svg>

Before

Width:  |  Height:  |  Size: 875 B

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg height="800"
width="800"
version="1.1"
id="_x32_"
viewBox="0 0 512 512"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs id="defs1"/>
<style type="text/css"
id="style1">
.st0{fill:#64C0FF;stroke:black;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1}
</style>
<g id="g1"
transform="matrix(0.87097097,0,0,1.0008579,38.609049,-0.21963163)"
style="stroke-width:3.42738;stroke-dasharray:none">
<path class="st0"
d="M 512,255.995 277.045,65.394 v 103.574 c -17.255,0 -36.408,0 -57.542,0 -208.59,0 -249.35,153.44 -201.394,266.128 9.586,-103.098 142.053,-100.701 237.358,-100.701 7.247,0 14.446,0 21.578,0 v 112.211 z"
id="path1"
style="stroke-width:20;stroke:#000000;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

View File

@@ -1,27 +1,25 @@
<tips> <tips>
<tip> <tip>
<title>Tip of the Day</title> <title>Tip of the Day</title>
<text>Tip of the Day is a feature to Cockatrice that allows users to get information about the newest features of the program and some of the most commonly asked questions! <text>Tip of the Day is a new feature to Cockatrice that allows users to get information about the newest features of the program and some of the most commonly asked questions!</text>
Check back in with major updates for new tips to be added or old tips to be updated as features are added or expanded upon!
</text>
<image>tip_of_the_day.png</image> <image>tip_of_the_day.png</image>
<date>2025-02-10</date> <date>2018-03-01</date>
</tip> </tip>
<tip> <tip>
<title>Join the Community</title> <title>Suggesting New Tips</title>
<text>You can join the community to find games, interact with other players, suggest new 'Tips of the Day' and provide user feedback to the development or support teams on &lt;a href="https://discord.gg/3Z9yzmA"&gt;Discord&lt;/a&gt;!</text> <text>You can suggest new Tips of the Day by reaching out to the development team on &lt;a href="https://discord.gg/3Z9yzmA"&gt;Discord&lt;/a&gt;!</text>
<image>discord.png</image> <image>discord.png</image>
<date>2025-02-09</date> <date>2023-10-18</date>
</tip> </tip>
<tip> <tip>
<title>Reporting Bugs and Requesting Features</title> <title>Reporting Bugs</title>
<text>If you encounter a bug while using Cockatrice, you can report the bug to and request the feature from the development team via &lt;a href="https://github.com/cockatrice/cockatrice/issues"&gt;GitHub&lt;a&gt;</text> <text>If you encounter a bug while using Cockatrice, you can report the bug to the development team via &lt;a href="https://github.com/cockatrice/cockatrice/issues"&gt;GitHub&lt;a&gt;</text>
<image>github_logo.png</image> <image>github_logo.png</image>
<date>2025-02-09</date> <date>2018-03-01</date>
</tip> </tip>
<tip> <tip>
<title>FAQ/Troubleshooting Wiki</title> <title>FAQ/Troubleshooting Wiki</title>
<text>You can find answers to the most common questions and some helpful Cockatrice troubleshooting over on the &lt;a href="https://github.com/cockatrice/cockatrice/wiki"&gt;GitHub wiki&lt;a&gt;</text> <text>You can find answers to the most common questions and some helpful Cockatrice toubleshooting over on the &lt;a href="https://github.com/cockatrice/cockatrice/wiki"&gt;GitHub wiki&lt;a&gt;</text>
<image>cockatrice_wiki.png</image> <image>cockatrice_wiki.png</image>
<date>2018-03-01</date> <date>2018-03-01</date>
</tip> </tip>
@@ -31,79 +29,21 @@ Check back in with major updates for new tips to be added or old tips to be upda
<image>cockatrice_register.png</image> <image>cockatrice_register.png</image>
<date>2018-03-01</date> <date>2018-03-01</date>
</tip> </tip>
<tip>
<title>Filtering Games</title>
<text>Don't see an open game or want to see a smaller selection? Use the Game Filters to change your horizon!</text>
<image>filter_games.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Common Shortcuts</title>
<text>You can find a full list of default shortcuts &lt;a href="https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts"&gt;on the wiki&lt;/a&gt; or in Settings -> Shortcuts, but a short list:
&lt;ul&gt;
&lt;li&gt;Roll a die: CMD/CTRL + I&lt;/li&gt;
&lt;li&gt;Mulligan: CMD/CTRL + M&lt;/li&gt;
&lt;li&gt;Draw 1 / X card(s): CMD/CTRL + D / E&lt;/li&gt;
&lt;li&gt;Undo a draw: CMD/CTRL + SHIFT + D&lt;/li&gt;
&lt;li&gt;View Library / Sideboard: F3 / CMD/CTRL + F3&lt;/li&gt;
&lt;li&gt;Change Life: CMD/CTRL + L&lt;/li&gt;
&lt;li&gt;Show Card Info: Middle Mouse Click&lt;/li&gt;
&lt;/ul&gt;
All shortcuts can be customized via Cockatrice -> Settings -> Shortcuts!
</text>
<image>shortcuts.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Power and Toughness</title>
<text>You can add and subtract to a creature's stats.
With a card selected, with the following keybindings:
&lt;ul&gt;
&lt;li&gt;Set P/T to any value: CTRL + P&lt;/li&gt;
&lt;li&gt;+1 or -1 to both to P/T: CMD/CTRL + ALT + '+' or '-'&lt;/li&gt;
&lt;li&gt;+1 or -1 to Power Only: CMD/CTRL + '+' or '-'&lt;/li&gt;
&lt;li&gt;+1 or -1 to Toughness Only: ALT + '+' or '-'&lt;/li&gt;
&lt;li&gt;Set P/T to Default: CMD/CTRL + ALT + 0&lt;/li&gt;
&lt;/ul&gt;
All shortcuts can be customized via Cockatrice -> Settings -> Shortcuts!
</text>
<image>setpt.png</image>
<date>2025-02-09</date>
</tip>
<tip> <tip>
<title>Drawing Arrows</title> <title>Drawing Arrows</title>
<text>You can draw arrows of different color by holding a combination of keys! <text>You can draw arrows of different color by holding a combination of keys!
Right Click: Red Arrow
&lt;ul&gt; Shift + Right Click: Green Arrow
&lt;li&gt;Right Click: Red Arrow&lt;/li&gt; Alt + Right Click: Blue Arrow
&lt;li&gt;SHIFT + Right Click: Green Arrow&lt;/li&gt; Cmd + Right Click: Yellow Arrow
&lt;li&gt;ALT + Right Click: Blue Arrow&lt;/li&gt;
&lt;li&gt;CMD/CTRL + Right Click: Yellow Arrow&lt;/li&gt;
&lt;/ul&gt;
</text> </text>
<image>arrows.png</image> <image>arrows.png</image>
<date>2018-03-01</date> <date>2018-03-01</date>
</tip> </tip>
<tip> <tip>
<title>General Etiquette</title> <title>Filtering Games</title>
<text>When playing on Cockatrice there are general "rules of engagement" for a better play experience for all players. <text>Don't see all the active games? Want to see a smaller selection? Use the Game Filters to change your horizon</text>
The following are some of the expectations a player should reasonably expect for how to operate smooth and enjoyable games: <image>filter_games.png</image>
&lt;ul&gt;
&lt;li&gt;Have a "Rule 0" conversation pre-game with your fellow players on the expectations of the game including deck strength, house rules (e.g. no take backs and "may is not must"), etc.&lt;/li&gt;
&lt;li&gt;When rolling your die for turn order, it is often best to create a token with the text of your roll (using CTRL + T and typing the number into "Name") and then tap this token when created to show that you have resolved your mulligans and are ready to start the game.&lt;/li&gt;
&lt;li&gt;Use the phases and steps trackers on the left of the client to show others where in the turn you are and announce when moving between them. (Double Click for the action of this button)&lt;/li&gt;
&lt;li&gt;When your turn is over leave it on your end step and DO NOT HIT PASS. Allow other players to respond if they can, and then if not, let the next player pass to themselves.&lt;/li&gt;
&lt;li&gt;Please treat others kindly and respect as per &lt;a href="https://cockatrice.us/terms.php"&gt;our Terms of Service&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
</text>
<image>token.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>Flip of the Coin</title>
<text>You can flip a coin instead of rolling a die by rolling a 2 sided die instead!</text>
<image>coin_flip.png</image>
<date>2018-03-01</date> <date>2018-03-01</date>
</tip> </tip>
<tip> <tip>
@@ -113,33 +53,36 @@ The following are some of the expectations a player should reasonably expect for
<date>2018-03-01</date> <date>2018-03-01</date>
</tip> </tip>
<tip> <tip>
<title>Player Icon Key</title> <title>Common Shortcuts</title>
<text>Besides your name is a player icon, this is a key for what they mean: <text>You can find a full list of shortcuts &lt;a href="https://github.com/Cockatrice/Cockatrice/wiki/Custom-Keyboard-Shortcuts"&gt;on the wiki&lt;/a&gt;, but a short list:
&lt;ul&gt; &lt;br&gt;Roll a die: CTRL + I
&lt;li&gt;Flag: Country of Origin Player Selected&lt;/li&gt; &lt;br&gt;Mulligan: CTRL + M
&lt;li&gt;Purple Heart: Donator (&lt;a href="https://cockatrice.us/donate"&gt;Help support us and donate here!&lt;/a&gt;)&lt;/li&gt; &lt;br&gt;Draw a card: CTRL + D
&lt;li&gt;Gold Star: VIP (Special Admin Given Role)&lt;/li&gt; &lt;br&gt;Undo a draw: CTRL + SHIFT + D
&lt;li&gt;Brown Gavel (Hammer): Judge / Rule's Lawyer&lt;/li&gt; &lt;br&gt;View Sideboard: CTRL + F3
&lt;li&gt;Black/White Pawn: Moderator (Support for Client Issues)&lt;/li&gt; &lt;br&gt;Change Life: CTRL + L
&lt;li&gt;Red: Administrator (Sever Operators)&lt;/li&gt; &lt;br&gt;All shortcuts can be customized via Settings->Shortcuts!
&lt;/ul&gt;
</text> </text>
<image>pawns.png</image> <image>shortcuts.png</image>
<date>2025-02-09</date> <date>2018-03-01</date>
</tip> </tip>
<tip> <tip>
<title>Changing Themes</title> <title>Changing Themes</title>
<text>Did you know Cockatrice has custom themes? You can either &lt;a href="https://github.com/Cockatrice/Cockatrice/wiki/Themes"&gt;create one yourself&lt;/a&gt; or use one of the several preloaded ones! Go to Settings->Appearance and try them out!</text> <text>Did you know Cockatrice has custom themes? You can either &lt;a href="https://github.com/Cockatrice/Cockatrice/wiki/Themes"&gt;create one yourself&lt;/a&gt; or use one of the several pre-loaded ones! Go to Settings->Appearance and try them out!</text>
<image>themes.png</image> <image>themes.png</image>
<date>2018-03-01</date> <date>2018-03-01</date>
</tip> </tip>
<tip>
<title>Flip of the Coin</title>
<text>You can flip a coin instead of rolling a die by rolling a 2 sided die instead!</text>
<image>coin_flip.png</image>
<date>2018-03-01</date>
</tip>
<tip> <tip>
<title>Face Down Cards</title> <title>Face Down Cards</title>
<text>You can hold Shift while dragging or clicking on a card to have it enter play face down. <text>You can hold Shift while dragging or clicking on a card to have it enter play face down</text>
You can also hold CTRL + SHIFT and click and drag from your library to move bottom card face down as well!
</text>
<image>face_down.png</image> <image>face_down.png</image>
<date>2025-02-09</date> <date>2018-03-01</date>
</tip> </tip>
<tip> <tip>
<title>Counter expressions</title> <title>Counter expressions</title>
@@ -148,75 +91,9 @@ You can also hold CTRL + SHIFT and click and drag from your library to move bott
<date>2019-02-02</date> <date>2019-02-02</date>
</tip> </tip>
<tip> <tip>
<title>Select Multiple Cards</title> <title>Power and Toughness</title>
<text>You can click and drag in any zone in order to highlight all cards within the created box. <text>You can add and subtract to a creature's stats.&lt;br&gt;With a card selected, set the power and toughness ( default: ctrl + p ) and enter +3/-1 to increase power by three while decreasing toughness by one.&lt;br&gt;You can also reset it to the original value ( default: ctrl + alt + 0 ).</text>
You can also hold CMD/CTRL and clik or click and drag to maintain other previously selected cards while adding others! <image>setpt.png</image>
You can move, alter and attach multiple highlighted cards at the same time! <date>2019-03-02</date>
Other useful multi-select keybindings:
&lt;ul&gt;
&lt;li&gt;Select All Cards in Zone: CMD/CTRL + A&lt;/li&gt;
&lt;li&gt;Select All Cards in Column: CMD/CTRL + SHIFT + C&lt;/li&gt;
&lt;li&gt;Select All Cards in Row: CMD/CTRL + SHIFT + X&lt;/li&gt;
&lt;/ul&gt;
</text>
<image>highlight_cards.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Auto Cascade and Search Parameters</title>
<text>You can use the default keybind of CMD/CTRL + SHIFT + Y in order to perform auto cascade or similar effects from your library using Scryfall search syntax.
If you are unfamiliar with the syntax you may find it by opening a deck in deck editor and clicking the "i" next to the search bar in order to pull up a list of syntax commands.
This same syntax can be used in the deck editor search bar as well to help you find the best cards for your decks!
</text>
<image>syntax_help.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Visual Deck Storage and Tags</title>
<text>You can now view your saved decks visually with integrated folder,tags and filter support!
Pro Tip: If you want to use emoji's press WinKey + '.' or CTRL + CMD + SPACE on Windows or Mac respectively!
</text>
<image>visual_deck_tags.png</image>
<date>2025-02-09</date>
</tip>
<tip>
<title>Card Selector And Card Preferences</title>
<text>Cockatrice's deck editor now has the ability for players to bling out their decks by selecting the arts for cards on a per-card basis!
You can also have multiple printings of the same card in your deck if you so choose!
Not only that, other players will see the arts you have chosen by default!
If you want to disable this feature for other players: Settings -> Appearance -> Select "Override all card art with personal set preference"
</text>
<image>card_select.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>EDHREC Integration</title>
<text>We now have in-client integration for EDHREC, which allows you to right-click on any card name in the deck editor in order to bring up the contextual menu for the card.</text>
<image>edhrec.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>Add Cards to Deck</title>
<text>You can now right-click anywhere on a card in any card info view in order to add it to any decks you have open in your tabs.</text>
<image>add_card.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>Update Client and Card Database</title>
<text>You can update your client by going to Help and selecting whichever you wish to update.
Client Update: Updates the client (if available) for new features, fixes and changes.
Card Update: Updates card sources for spoilers and new card printings.
Updating your card sources can often fix issues of cards not working or displaying properly, if not, go to Cockatrice -> Settings -> Card Sources -> Update Spoilers
</text>
<image>updates.png</image>
<date>2025-02-10</date>
</tip>
<tip>
<title>Expand Card View Window</title>
<text>Double click on the title bar of the card view window to expand it! Double click again to shrink it back down.
You can configure the initial and expanded heights of the window in the settings, under "Appearance".
</text>
<image>expand_card_view.png</image>
<date>2025-02-27</date>
</tip> </tip>
</tips> </tips>

View File

@@ -350,11 +350,11 @@
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z " d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
transform="translate(0,952.36218)" transform="translate(0,952.36218)"
id="left" /> id="right" />
<path <path
style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z" d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z"
id="right" id="left"
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="display:inline;fill:url(#linearGradient3);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.77952756;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" style="display:inline;fill:url(#linearGradient3);fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.77952756;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -321,11 +321,11 @@
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z " d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
transform="translate(0,952.36218)" transform="translate(0,952.36218)"
id="left" /> id="right" />
<path <path
style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z" d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z"
id="right" id="left"
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
d="m 46.656521,12.167234 18.055171,18.054184 a 6.6081919,6.6078288 0 0 1 -0.126303,9.352065 6.6804126,6.6800456 0 0 1 -8.233169,1.011048 l -7.944268,7.943843 6.463762,6.445343 a 6.9331851,6.9328042 0 0 1 5.741536,2.022073 l 28.057729,28.092294 a 6.9962797,6.9958953 0 0 1 -9.894222,9.893685 L 50.719018,66.907526 A 7.0595711,7.0591833 0 0 1 49.18433,59.270613 l -5.741527,-5.741238 -7.944298,7.943843 A 6.716523,6.7161541 0 0 1 25.134866,69.832263 L 7.079684,51.778091 a 6.716523,6.7161541 0 0 1 8.39566,-10.345064 L 36.31101,20.59853 a 6.716523,6.7161541 0 0 1 10.345612,-8.431329 z" d="m 46.656521,12.167234 18.055171,18.054184 a 6.6081919,6.6078288 0 0 1 -0.126303,9.352065 6.6804126,6.6800456 0 0 1 -8.233169,1.011048 l -7.944268,7.943843 6.463762,6.445343 a 6.9331851,6.9328042 0 0 1 5.741536,2.022073 l 28.057729,28.092294 a 6.9962797,6.9958953 0 0 1 -9.894222,9.893685 L 50.719018,66.907526 A 7.0595711,7.0591833 0 0 1 49.18433,59.270613 l -5.741527,-5.741238 -7.944298,7.943843 A 6.716523,6.7161541 0 0 1 25.134866,69.832263 L 7.079684,51.778091 a 6.716523,6.7161541 0 0 1 8.39566,-10.345064 L 36.31101,20.59853 a 6.716523,6.7161541 0 0 1 10.345612,-8.431329 z"

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -340,11 +340,11 @@
style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" style="fill-opacity:1;stroke:black;stroke-width:2.78220296;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z " d="M 49.84375 1.71875 C 36.719738 1.71875 26.0625 12.375988 26.0625 25.5 C 26.0625 32.977454 29.538325 39.612734 34.9375 43.96875 C 24.439951 49.943698 17.919149 62.196126 14.3125 75.65625 C 9.0380874 95.34065 30.224013 98.21875 49.84375 98.21875 C 69.463486 98.21875 90.549327 94.96715 85.375 75.65625 C 81.693381 61.916246 75.224585 49.827177 64.8125 43.9375 C 70.181573 39.580662 73.59375 32.953205 73.59375 25.5 C 73.59375 12.375988 62.967762 1.71875 49.84375 1.71875 z "
transform="translate(0,952.36218)" transform="translate(0,952.36218)"
id="left" /> id="right" />
<path <path
style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" style="opacity:1;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.73577702;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z" d="m 51.28696,1001.834 0,-46.98372 1.434151,0.16768 c 5.155008,0.60274 9.462857,2.72154 12.938257,6.36366 4.74393,4.9715 6.87913,11.35611 6.16464,18.43328 -0.53702,5.31935 -3.09008,10.59498 -6.83833,14.13074 l -1.94072,1.83069 3.04083,2.20427 c 3.58084,2.5957 7.18975,6.4912 9.55296,10.3116 4.89572,7.9144 9.23593,21.4918 8.50487,26.6055 -0.81312,5.6877 -5.43872,9.6977 -13.62216,11.8093 -3.80822,0.9826 -7.68056,1.4713 -14.763321,1.8633 l -4.471177,0.2474 0,-46.9837 z"
id="right" id="left"
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
sodipodi:type="star" sodipodi:type="star"
@@ -363,6 +363,6 @@
d="m 38.011063,984.77381 -10.143601,-5.23583 -10.063711,5.38779 1.845023,-11.2651 -8.233948,-7.90624 11.283888,-1.72639 4.974851,-10.27411 5.128803,10.19813 11.308575,1.55649 -8.114112,8.02918 z" d="m 38.011063,984.77381 -10.143601,-5.23583 -10.063711,5.38779 1.845023,-11.2651 -8.233948,-7.90624 11.283888,-1.72639 4.974851,-10.27411 5.128803,10.19813 11.308575,1.55649 -8.114112,8.02918 z"
inkscape:transform-center-x="0.094945927" inkscape:transform-center-x="0.094945927"
inkscape:transform-center-y="-3.9764964" inkscape:transform-center-y="-3.9764964"
transform="matrix(-2.3768784,0,0,2.4799382,115.920285,-1400.1716)" /> transform="matrix(2.3768784,0,0,2.4799382,-15.920285,-1400.1716)" />
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,24 +1,25 @@
#include "abstract_client.h" #include "abstract_client.h"
#include "../../server/pending_command.h"
#include "featureset.h"
#include "get_pb_extension.h"
#include "pb/commands.pb.h"
#include "pb/event_add_to_list.pb.h"
#include "pb/event_connection_closed.pb.h"
#include "pb/event_game_joined.pb.h"
#include "pb/event_list_rooms.pb.h"
#include "pb/event_notify_user.pb.h"
#include "pb/event_remove_from_list.pb.h"
#include "pb/event_replay_added.pb.h"
#include "pb/event_server_identification.pb.h"
#include "pb/event_server_message.pb.h"
#include "pb/event_server_shutdown.pb.h"
#include "pb/event_user_joined.pb.h"
#include "pb/event_user_left.pb.h"
#include "pb/event_user_message.pb.h"
#include "pb/server_message.pb.h"
#include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.h>
#include <libcockatrice/protocol/featureset.h>
#include <libcockatrice/protocol/get_pb_extension.h>
#include <libcockatrice/protocol/pb/commands.pb.h>
#include <libcockatrice/protocol/pb/event_add_to_list.pb.h>
#include <libcockatrice/protocol/pb/event_connection_closed.pb.h>
#include <libcockatrice/protocol/pb/event_game_joined.pb.h>
#include <libcockatrice/protocol/pb/event_list_rooms.pb.h>
#include <libcockatrice/protocol/pb/event_notify_user.pb.h>
#include <libcockatrice/protocol/pb/event_remove_from_list.pb.h>
#include <libcockatrice/protocol/pb/event_replay_added.pb.h>
#include <libcockatrice/protocol/pb/event_server_identification.pb.h>
#include <libcockatrice/protocol/pb/event_server_message.pb.h>
#include <libcockatrice/protocol/pb/event_server_shutdown.pb.h>
#include <libcockatrice/protocol/pb/event_user_joined.pb.h>
#include <libcockatrice/protocol/pb/event_user_left.pb.h>
#include <libcockatrice/protocol/pb/event_user_message.pb.h>
#include <libcockatrice/protocol/pb/server_message.pb.h>
#include <libcockatrice/protocol/pending_command.h>
AbstractClient::AbstractClient(QObject *parent) AbstractClient::AbstractClient(QObject *parent)
: QObject(parent), nextCmdId(0), status(StatusDisconnected), serverSupportsPasswordHash(false) : QObject(parent), nextCmdId(0), status(StatusDisconnected), serverSupportsPasswordHash(false)

View File

@@ -1,16 +1,12 @@
/**
* @file abstract_client.h
* @ingroup Client
* @brief TODO: Document this.
*/
#ifndef ABSTRACTCLIENT_H #ifndef ABSTRACTCLIENT_H
#define ABSTRACTCLIENT_H #define ABSTRACTCLIENT_H
#include "pb/response.pb.h"
#include "pb/serverinfo_user.pb.h"
#include <QMutex> #include <QMutex>
#include <QObject>
#include <QVariant> #include <QVariant>
#include <libcockatrice/protocol/pb/response.pb.h>
#include <libcockatrice/protocol/pb/serverinfo_user.pb.h>
class PendingCommand; class PendingCommand;
class CommandContainer; class CommandContainer;

View File

@@ -1,10 +1,3 @@
/**
* @file key_signals.h
* @ingroup Core
* @ingroup UI
* @brief TODO: Document this.
*/
#ifndef KEYSIGNALS_H #ifndef KEYSIGNALS_H
#define KEYSIGNALS_H #define KEYSIGNALS_H

View File

@@ -1,7 +1,5 @@
#include "get_text_with_max.h" #include "get_text_with_max.h"
#include <QInputDialog>
QString getTextWithMax(QWidget *parent, QString getTextWithMax(QWidget *parent,
const QString &title, const QString &title,
const QString &label, const QString &label,

View File

@@ -1,15 +1,10 @@
/** // custom QInputDialog::getText implementation that allows configuration of the max length
* @file get_text_with_max.h
* @ingroup UI
* @brief Custom QInputDialog::getText implementation that allows configuration of the max length
*/
#ifndef GETTEXTWITHMAX_H #ifndef GETTEXTWITHMAX_H
#define GETTEXTWITHMAX_H #define GETTEXTWITHMAX_H
#include <QLineEdit> #include "trice_limits.h"
#include <QWidget>
#include <libcockatrice/utility/trice_limits.h> #include <QInputDialog>
QString getTextWithMax(QWidget *parent, QString getTextWithMax(QWidget *parent,
const QString &title, const QString &title,

View File

@@ -1,6 +1,6 @@
#include "client_update_checker.h" #include "client_update_checker.h"
#include "../../../settings/cache_settings.h" #include "../../settings/cache_settings.h"
#include "release_channel.h" #include "release_channel.h"
ClientUpdateChecker::ClientUpdateChecker(QObject *parent) : QObject(parent) ClientUpdateChecker::ClientUpdateChecker(QObject *parent) : QObject(parent)

View File

@@ -1,9 +1,3 @@
/**
* @file client_update_checker.h
* @ingroup ClientUpdate
* @brief TODO: Document this.
*/
#ifndef CLIENT_UPDATE_CHECKER_H #ifndef CLIENT_UPDATE_CHECKER_H
#define CLIENT_UPDATE_CHECKER_H #define CLIENT_UPDATE_CHECKER_H
#include <QObject> #include <QObject>

View File

@@ -1,61 +0,0 @@
#include "deck_link_to_api_transformer.h"
#include <QRegularExpression>
namespace DeckLinkToApiTransformer
{
static const QString TAPPEDOUT_BASE = "https://tappedout.net/mtg-decks/";
static const QString TAPPEDOUT_SUFFIX = "/?fmt=txt";
static const QString ARCHIDEKT_BASE = "https://archidekt.com/api/decks/";
static const QString ARCHIDEKT_SUFFIX = "/?format=json";
static const QString MOXFIELD_BASE = "https://api.moxfield.com/v2/decks/all/";
static const QString MOXFIELD_SUFFIX = "/";
static const QString DECKSTATS_SUFFIX = "?include_comments=1&export_mtgarena=1";
bool parseDeckUrl(const QString &url, ParsedDeckInfo &outInfo)
{
static QRegularExpression rxTappedOut("tappedout\\.net/(?:mtg-decks/)?([^/?#]+)");
static QRegularExpression rxArchidekt("archidekt\\.com/decks/(\\d+)");
static QRegularExpression rxMoxfield("moxfield\\.com/decks/([a-zA-Z0-9_-]+)");
static QRegularExpression rxDeckstats("deckstats\\.net/decks/(\\d+/[a-zA-Z0-9_-]+)");
QRegularExpressionMatch match;
if ((match = rxTappedOut.match(url)).hasMatch()) {
QString slug = match.captured(1);
outInfo = ParsedDeckInfo{.baseUrl = TAPPEDOUT_BASE,
.deckID = slug,
.fullUrl = TAPPEDOUT_BASE + slug + TAPPEDOUT_SUFFIX,
.provider = DeckProvider::TappedOut};
return true;
} else if ((match = rxArchidekt.match(url)).hasMatch()) {
QString deckID = match.captured(1);
outInfo = ParsedDeckInfo{.baseUrl = ARCHIDEKT_BASE,
.deckID = deckID,
.fullUrl = ARCHIDEKT_BASE + deckID + ARCHIDEKT_SUFFIX,
.provider = DeckProvider::Archidekt};
return true;
} else if ((match = rxMoxfield.match(url)).hasMatch()) {
QString deckID = match.captured(1);
outInfo = ParsedDeckInfo{.baseUrl = MOXFIELD_BASE,
.deckID = deckID,
.fullUrl = MOXFIELD_BASE + deckID + MOXFIELD_SUFFIX,
.provider = DeckProvider::Moxfield};
return true;
} else if ((match = rxDeckstats.match(url)).hasMatch()) {
QString deckPath = match.captured(1);
outInfo = ParsedDeckInfo{.baseUrl = "https://deckstats.net/decks/",
.deckID = deckPath,
.fullUrl = "https://deckstats.net/decks/" + deckPath + DECKSTATS_SUFFIX,
.provider = DeckProvider::Deckstats};
return true;
}
return false;
}
} // namespace DeckLinkToApiTransformer

View File

@@ -1,37 +0,0 @@
/**
* @file deck_link_to_api_transformer.h
* @ingroup ApiInterfaces
* @brief TODO: Document this.
*/
#ifndef DECK_LINK_TO_API_TRANSFORMER_H
#define DECK_LINK_TO_API_TRANSFORMER_H
#include <QString>
enum class DeckProvider
{
TappedOut,
Archidekt,
Moxfield,
Deckstats,
Unknown
};
struct ParsedDeckInfo
{
QString baseUrl;
QString deckID;
QString fullUrl;
DeckProvider provider;
};
namespace DeckLinkToApiTransformer
{
// Returns true if the input URL is recognized and fills outInfo.
bool parseDeckUrl(const QString &url, ParsedDeckInfo &outInfo);
} // namespace DeckLinkToApiTransformer
#endif // DECK_LINK_TO_API_TRANSFORMER_H

View File

@@ -1,120 +0,0 @@
/**
* @file interface_json_deck_parser.h
* @ingroup ApiInterfaces
* @brief TODO: Document this.
*/
#ifndef INTERFACE_JSON_DECK_PARSER_H
#define INTERFACE_JSON_DECK_PARSER_H
#include "../../../interface/deck_loader/card_node_function.h"
#include "../../../interface/deck_loader/deck_loader.h"
#include <QJsonArray>
#include <QJsonObject>
class IJsonDeckParser
{
public:
virtual ~IJsonDeckParser() = default;
virtual DeckList parse(const QJsonObject &obj) = 0;
};
class ArchidektJsonParser : public IJsonDeckParser
{
public:
DeckList parse(const QJsonObject &obj) override
{
DeckList deckList;
QString deckName = obj.value("name").toString();
QString deckDescription = obj.value("description").toString();
deckList.setName(deckName);
deckList.setComments(deckDescription);
QString outputText;
QTextStream outStream(&outputText);
for (auto entry : obj.value("cards").toArray()) {
auto quantity = entry.toObject().value("quantity").toInt();
auto card = entry.toObject().value("card").toObject();
auto oracleCard = card.value("oracleCard").toObject();
QString cardName = oracleCard.value("name").toString();
QString setName = card.value("edition").toObject().value("editioncode").toString().toUpper();
QString collectorNumber = card.value("collectorNumber").toString();
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
}
deckList.loadFromStream_Plain(outStream, false);
deckList.forEachCard(CardNodeFunction::ResolveProviderId());
return deckList;
}
};
class MoxfieldJsonParser : public IJsonDeckParser
{
public:
DeckList parse(const QJsonObject &obj) override
{
DeckList deckList;
QString deckName = obj.value("name").toString();
QString deckDescription = obj.value("description").toString();
deckList.setName(deckName);
deckList.setComments(deckDescription);
QString outputText;
QTextStream outStream(&outputText);
for (auto entry : obj.value("mainboard").toObject()) {
auto quantity = entry.toObject().value("quantity").toInt();
auto card = entry.toObject().value("card").toObject();
QString cardName = card.value("name").toString();
QString setName = card.value("set").toString().toUpper();
QString collectorNumber = card.value("cn").toString();
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
}
outStream << '\n';
for (auto entry : obj.value("sideboard").toObject()) {
auto quantity = entry.toObject().value("quantity").toInt();
auto card = entry.toObject().value("card").toObject();
QString cardName = card.value("name").toString();
QString setName = card.value("set").toString().toUpper();
QString collectorNumber = card.value("cn").toString();
outStream << quantity << ' ' << cardName << " (" << setName << ") " << collectorNumber << '\n';
}
deckList.loadFromStream_Plain(outStream, false);
deckList.forEachCard(CardNodeFunction::ResolveProviderId());
QJsonObject commandersObj = obj.value("commanders").toObject();
if (!commandersObj.isEmpty()) {
for (auto it = commandersObj.begin(); it != commandersObj.end(); ++it) {
QJsonObject cardData = it.value().toObject().value("card").toObject();
QString commanderName = cardData.value("name").toString();
QString setName = cardData.value("set").toString().toUpper();
QString collectorNumber = cardData.value("cn").toString();
QString providerId = cardData.value("scryfall_id").toString();
deckList.setBannerCard({commanderName, providerId});
deckList.addCard(commanderName, DECK_ZONE_MAIN, -1, setName, collectorNumber, providerId);
}
}
return deckList;
}
};
#endif // INTERFACE_JSON_DECK_PARSER_H

View File

@@ -11,11 +11,6 @@
#include <QSysInfo> #include <QSysInfo>
#include <QtGlobal> #include <QtGlobal>
#if defined(Q_OS_MACOS)
#include <sys/sysctl.h>
#include <sys/types.h>
#endif
#define STABLERELEASE_URL "https://api.github.com/repos/Cockatrice/Cockatrice/releases/latest" #define STABLERELEASE_URL "https://api.github.com/repos/Cockatrice/Cockatrice/releases/latest"
#define STABLEMANUALDOWNLOAD_URL "https://github.com/Cockatrice/Cockatrice/releases/latest" #define STABLEMANUALDOWNLOAD_URL "https://github.com/Cockatrice/Cockatrice/releases/latest"
#define STABLETAG_URL "https://api.github.com/repos/Cockatrice/Cockatrice/git/refs/tags/" #define STABLETAG_URL "https://api.github.com/repos/Cockatrice/Cockatrice/git/refs/tags/"
@@ -38,42 +33,31 @@ ReleaseChannel::~ReleaseChannel()
void ReleaseChannel::checkForUpdates() void ReleaseChannel::checkForUpdates()
{ {
QString releaseChannelUrl = getReleaseChannelUrl(); QString releaseChannelUrl = getReleaseChannelUrl();
qCInfo(ReleaseChannelLog) << "Searching for updates on the channel: " << releaseChannelUrl; qCDebug(ReleaseChannelLog) << "Searching for updates on the channel: " << releaseChannelUrl;
response = netMan->get(QNetworkRequest(releaseChannelUrl)); response = netMan->get(QNetworkRequest(releaseChannelUrl));
connect(response, &QNetworkReply::finished, this, &ReleaseChannel::releaseListFinished); connect(response, &QNetworkReply::finished, this, &ReleaseChannel::releaseListFinished);
} }
// Different release channel checking functions for different operating systems // Different release channel checking functions for different operating systems
#if defined(Q_OS_MACOS)
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName) bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
{ {
#if defined(Q_OS_MACOS) static QRegularExpression version_regex("macOS-(\\d+)\\.(\\d+)");
static QRegularExpression version_regex("macOS(\\d+)");
auto match = version_regex.match(fileName); auto match = version_regex.match(fileName);
if (!match.hasMatch()) { if (!match.hasMatch()) {
return false; return false;
} }
auto getSystemVersion = [] {
// QSysInfo does not go through translation layers
// We need to use sysctl to reliably detect the underlying architecture
char arch[255];
size_t len = sizeof(arch);
if (sysctlbyname("machdep.cpu.brand_string", arch, &len, nullptr, 0) == 0) {
// Intel mac is only supported on macOS 13 versions
if (QString::fromUtf8(arch).contains("Intel")) {
return 13;
}
}
return QSysInfo::productVersion().split(".")[0].toInt();
};
// older(smaller) releases are compatible with a newer or the same system version // older(smaller) releases are compatible with a newer or the same system version
int sys_maj = getSystemVersion(); int sys_maj = QSysInfo::productVersion().split(".")[0].toInt();
int sys_min = QSysInfo::productVersion().split(".")[1].toInt();
int rel_maj = match.captured(1).toInt(); int rel_maj = match.captured(1).toInt();
return rel_maj == sys_maj; int rel_min = match.captured(2).toInt();
return rel_maj < sys_maj || (rel_maj == sys_maj && rel_min <= sys_min);
}
#elif defined(Q_OS_WIN) #elif defined(Q_OS_WIN)
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
{
#if Q_PROCESSOR_WORDSIZE == 4 #if Q_PROCESSOR_WORDSIZE == 4
return fileName.contains("32bit"); return fileName.contains("32bit");
#elif Q_PROCESSOR_WORDSIZE == 8 #elif Q_PROCESSOR_WORDSIZE == 8
@@ -84,15 +68,16 @@ bool ReleaseChannel::downloadMatchesCurrentOS(const QString &fileName)
return fileName.contains("Win10"); return fileName.contains("Win10");
} }
#else #else
Q_UNUSED(fileName);
return false;
#endif
#else // If the OS doesn't fit one of the above #defines, then it will never match
Q_UNUSED(fileName);
return false; return false;
#endif #endif
} }
#else
bool ReleaseChannel::downloadMatchesCurrentOS(const QString &)
{
// If the OS doesn't fit one of the above #defines, then it will never match
return false;
}
#endif
QString StableReleaseChannel::getManualDownloadUrl() const QString StableReleaseChannel::getManualDownloadUrl() const
{ {
@@ -116,7 +101,7 @@ void StableReleaseChannel::releaseListFinished()
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError); QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
reply->deleteLater(); reply->deleteLater();
if (parseError.error != QJsonParseError::NoError) { if (parseError.error != QJsonParseError::NoError) {
qCWarning(ReleaseChannelLog) << "No reply received from the release update server."; qWarning() << "No reply received from the release update server.";
emit error(tr("No reply received from the release update server.")); emit error(tr("No reply received from the release update server."));
return; return;
} }
@@ -124,7 +109,7 @@ void StableReleaseChannel::releaseListFinished()
QVariantMap resultMap = jsonResponse.toVariant().toMap(); QVariantMap resultMap = jsonResponse.toVariant().toMap();
if (!(resultMap.contains("name") && resultMap.contains("html_url") && resultMap.contains("tag_name") && if (!(resultMap.contains("name") && resultMap.contains("html_url") && resultMap.contains("tag_name") &&
resultMap.contains("published_at"))) { resultMap.contains("published_at"))) {
qCWarning(ReleaseChannelLog) << "Invalid received from the release update server:" << resultMap; qWarning() << "Invalid received from the release update server:" << resultMap;
emit error(tr("Invalid reply received from the release update server.")); emit error(tr("Invalid reply received from the release update server."));
return; return;
} }
@@ -138,29 +123,37 @@ void StableReleaseChannel::releaseListFinished()
if (resultMap.contains("assets")) { if (resultMap.contains("assets")) {
auto rawAssets = resultMap["assets"].toList(); auto rawAssets = resultMap["assets"].toList();
for (const auto &rawAsset : rawAssets) { // [(name, url)]
QVariantMap asset = rawAsset.toMap(); QVector<std::pair<QString, QString>> assets;
std::transform(rawAssets.begin(), rawAssets.end(), std::back_inserter(assets), [](QVariant _asset) {
QVariantMap asset = _asset.toMap();
QString name = asset["name"].toString(); QString name = asset["name"].toString();
QString url = asset["browser_download_url"].toString(); QString url = asset["browser_download_url"].toString();
return std::make_pair(name, url);
});
if (downloadMatchesCurrentOS(name)) { auto _releaseAsset = std::find_if(assets.begin(), assets.end(), [](std::pair<QString, QString> nameAndUrl) {
lastRelease->setDownloadUrl(url); return downloadMatchesCurrentOS(nameAndUrl.first);
break; });
}
if (_releaseAsset != assets.end()) {
std::pair<QString, QString> releaseAsset = *_releaseAsset;
auto releaseUrl = releaseAsset.second;
lastRelease->setDownloadUrl(releaseUrl);
} }
} }
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN); QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
QString myHash = QString(VERSION_COMMIT); QString myHash = QString(VERSION_COMMIT);
qCInfo(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash; qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
qCInfo(ReleaseChannelLog) << "Got reply from release server, name=" << lastRelease->getName() qCDebug(ReleaseChannelLog) << "Got reply from release server, name=" << lastRelease->getName()
<< "desc=" << lastRelease->getDescriptionUrl() << "date=" << lastRelease->getPublishDate() << "desc=" << lastRelease->getDescriptionUrl()
<< "url=" << lastRelease->getDownloadUrl(); << "date=" << lastRelease->getPublishDate() << "url=" << lastRelease->getDownloadUrl();
const QString &tagName = resultMap["tag_name"].toString(); const QString &tagName = resultMap["tag_name"].toString();
QString url = QString(STABLETAG_URL) + tagName; QString url = QString(STABLETAG_URL) + tagName;
qCInfo(ReleaseChannelLog) << "Searching for commit hash corresponding to stable channel tag: " << tagName; qCDebug(ReleaseChannelLog) << "Searching for commit hash corresponding to stable channel tag: " << tagName;
response = netMan->get(QNetworkRequest(url)); response = netMan->get(QNetworkRequest(url));
connect(response, &QNetworkReply::finished, this, &StableReleaseChannel::tagListFinished); connect(response, &QNetworkReply::finished, this, &StableReleaseChannel::tagListFinished);
} }
@@ -172,24 +165,24 @@ void StableReleaseChannel::tagListFinished()
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError); QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
reply->deleteLater(); reply->deleteLater();
if (parseError.error != QJsonParseError::NoError) { if (parseError.error != QJsonParseError::NoError) {
qCWarning(ReleaseChannelLog) << "No reply received from the tag update server."; qWarning() << "No reply received from the tag update server.";
emit error(tr("No reply received from the tag update server.")); emit error(tr("No reply received from the tag update server."));
return; return;
} }
QVariantMap resultMap = jsonResponse.toVariant().toMap(); QVariantMap resultMap = jsonResponse.toVariant().toMap();
if (!(resultMap.contains("object") && resultMap["object"].toMap().contains("sha"))) { if (!(resultMap.contains("object") && resultMap["object"].toMap().contains("sha"))) {
qCWarning(ReleaseChannelLog) << "Invalid received from the tag update server."; qWarning() << "Invalid received from the tag update server.";
emit error(tr("Invalid reply received from the tag update server.")); emit error(tr("Invalid reply received from the tag update server."));
return; return;
} }
lastRelease->setCommitHash(resultMap["object"].toMap()["sha"].toString()); lastRelease->setCommitHash(resultMap["object"].toMap()["sha"].toString());
qCInfo(ReleaseChannelLog) << "Got reply from tag server, commit=" << lastRelease->getCommitHash(); qCDebug(ReleaseChannelLog) << "Got reply from tag server, commit=" << lastRelease->getCommitHash();
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN); QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
QString myHash = QString(VERSION_COMMIT); QString myHash = QString(VERSION_COMMIT);
qCInfo(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash; qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
const bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0); const bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0);
emit finishedCheck(needToUpdate, lastRelease->isCompatibleVersionFound(), lastRelease); emit finishedCheck(needToUpdate, lastRelease->isCompatibleVersionFound(), lastRelease);
@@ -232,7 +225,7 @@ void BetaReleaseChannel::releaseListFinished()
QVariantMap resultMap = array.at(0).toObject().toVariantMap(); QVariantMap resultMap = array.at(0).toObject().toVariantMap();
if (array.empty() || resultMap.empty()) { if (array.empty() || resultMap.empty()) {
qCWarning(ReleaseChannelLog) << "No reply received from the release update server:" << QString(jsonData); qWarning() << "No reply received from the release update server:" << QString(jsonData);
emit error(tr("No reply received from the release update server.")); emit error(tr("No reply received from the release update server."));
return; return;
} }
@@ -241,7 +234,7 @@ void BetaReleaseChannel::releaseListFinished()
if (!resultMap.contains("assets") || !resultMap.contains("author") || !resultMap.contains("tag_name") || if (!resultMap.contains("assets") || !resultMap.contains("author") || !resultMap.contains("tag_name") ||
!resultMap.contains("target_commitish") || !resultMap.contains("assets_url") || !resultMap.contains("target_commitish") || !resultMap.contains("assets_url") ||
!resultMap.contains("published_at")) { !resultMap.contains("published_at")) {
qCWarning(ReleaseChannelLog) << "Invalid received from the release update server:" << resultMap; qWarning() << "Invalid received from the release update server:" << resultMap;
emit error(tr("Invalid reply received from the release update server.")); emit error(tr("Invalid reply received from the release update server."));
return; return;
} }
@@ -256,13 +249,13 @@ void BetaReleaseChannel::releaseListFinished()
lastRelease->setName(QString("%1 (%2)").arg(resultMap["tag_name"].toString()).arg(shortHash)); lastRelease->setName(QString("%1 (%2)").arg(resultMap["tag_name"].toString()).arg(shortHash));
lastRelease->setDescriptionUrl(QString(BETARELEASE_CHANGESURL).arg(VERSION_COMMIT, shortHash)); lastRelease->setDescriptionUrl(QString(BETARELEASE_CHANGESURL).arg(VERSION_COMMIT, shortHash));
qCInfo(ReleaseChannelLog) << "Got reply from release server, size=" << resultMap.size() qCDebug(ReleaseChannelLog) << "Got reply from release server, size=" << resultMap.size()
<< "name=" << lastRelease->getName() << "desc=" << lastRelease->getDescriptionUrl() << "name=" << lastRelease->getName() << "desc=" << lastRelease->getDescriptionUrl()
<< "commit=" << lastRelease->getCommitHash() << "date=" << lastRelease->getPublishDate(); << "commit=" << lastRelease->getCommitHash() << "date=" << lastRelease->getPublishDate();
QString betaBuildDownloadUrl = resultMap["assets_url"].toString(); QString betaBuildDownloadUrl = resultMap["assets_url"].toString();
qCInfo(ReleaseChannelLog) << "Searching for a corresponding file on the beta channel: " << betaBuildDownloadUrl; qCDebug(ReleaseChannelLog) << "Searching for a corresponding file on the beta channel: " << betaBuildDownloadUrl;
response = netMan->get(QNetworkRequest(betaBuildDownloadUrl)); response = netMan->get(QNetworkRequest(betaBuildDownloadUrl));
connect(response, &QNetworkReply::finished, this, &BetaReleaseChannel::fileListFinished); connect(response, &QNetworkReply::finished, this, &BetaReleaseChannel::fileListFinished);
} }
@@ -274,7 +267,7 @@ void BetaReleaseChannel::fileListFinished()
QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError); QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll(), &parseError);
reply->deleteLater(); reply->deleteLater();
if (parseError.error != QJsonParseError::NoError) { if (parseError.error != QJsonParseError::NoError) {
qCWarning(ReleaseChannelLog) << "No reply received from the file update server."; qWarning() << "No reply received from the file update server.";
emit error(tr("No reply received from the file update server.")); emit error(tr("No reply received from the file update server."));
return; return;
} }
@@ -282,7 +275,7 @@ void BetaReleaseChannel::fileListFinished()
QVariantList resultList = jsonResponse.toVariant().toList(); QVariantList resultList = jsonResponse.toVariant().toList();
QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN); QString shortHash = lastRelease->getCommitHash().left(GIT_SHORT_HASH_LEN);
QString myHash = QString(VERSION_COMMIT); QString myHash = QString(VERSION_COMMIT);
qCInfo(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash; qCDebug(ReleaseChannelLog) << "Current hash=" << myHash << "update hash=" << shortHash;
bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0); bool needToUpdate = (QString::compare(shortHash, myHash, Qt::CaseInsensitive) != 0);
bool compatibleVersion = false; bool compatibleVersion = false;
@@ -299,7 +292,7 @@ void BetaReleaseChannel::fileListFinished()
if (downloadMatchesCurrentOS(*url)) { if (downloadMatchesCurrentOS(*url)) {
compatibleVersion = true; compatibleVersion = true;
lastRelease->setDownloadUrl(*url); lastRelease->setDownloadUrl(*url);
qCInfo(ReleaseChannelLog) << "Found compatible version url=" << *url; qCDebug(ReleaseChannelLog) << "Found compatible version url=" << *url;
break; break;
} }
} }

View File

@@ -1,9 +1,3 @@
/**
* @file release_channel.h
* @ingroup ClientUpdate
* @brief TODO: Document this.
*/
#ifndef RELEASECHANNEL_H #ifndef RELEASECHANNEL_H
#define RELEASECHANNEL_H #define RELEASECHANNEL_H
@@ -57,27 +51,27 @@ protected:
} }
public: public:
[[nodiscard]] QString getName() const QString getName() const
{ {
return name; return name;
} }
[[nodiscard]] QString getDescriptionUrl() const QString getDescriptionUrl() const
{ {
return descriptionUrl; return descriptionUrl;
} }
[[nodiscard]] QString getDownloadUrl() const QString getDownloadUrl() const
{ {
return downloadUrl; return downloadUrl;
} }
[[nodiscard]] QString getCommitHash() const QString getCommitHash() const
{ {
return commitHash; return commitHash;
} }
[[nodiscard]] QDate getPublishDate() const QDate getPublishDate() const
{ {
return publishDate; return publishDate;
} }
[[nodiscard]] bool isCompatibleVersionFound() const bool isCompatibleVersionFound() const
{ {
return compatibleVersionFound; return compatibleVersionFound;
} }
@@ -97,15 +91,15 @@ protected:
protected: protected:
static bool downloadMatchesCurrentOS(const QString &fileName); static bool downloadMatchesCurrentOS(const QString &fileName);
[[nodiscard]] virtual QString getReleaseChannelUrl() const = 0; virtual QString getReleaseChannelUrl() const = 0;
public: public:
Release *getLastRelease() Release *getLastRelease()
{ {
return lastRelease; return lastRelease;
} }
[[nodiscard]] virtual QString getManualDownloadUrl() const = 0; virtual QString getManualDownloadUrl() const = 0;
[[nodiscard]] virtual QString getName() const = 0; virtual QString getName() const = 0;
void checkForUpdates(); void checkForUpdates();
signals: signals:
void finishedCheck(bool needToUpdate, bool isCompatible, Release *release); void finishedCheck(bool needToUpdate, bool isCompatible, Release *release);
@@ -122,12 +116,12 @@ public:
explicit StableReleaseChannel() = default; explicit StableReleaseChannel() = default;
~StableReleaseChannel() override = default; ~StableReleaseChannel() override = default;
[[nodiscard]] QString getManualDownloadUrl() const override; QString getManualDownloadUrl() const override;
[[nodiscard]] QString getName() const override; QString getName() const override;
protected: protected:
[[nodiscard]] QString getReleaseChannelUrl() const override; QString getReleaseChannelUrl() const override;
protected slots: protected slots:
void releaseListFinished() override; void releaseListFinished() override;
@@ -143,12 +137,12 @@ public:
BetaReleaseChannel() = default; BetaReleaseChannel() = default;
~BetaReleaseChannel() override = default; ~BetaReleaseChannel() override = default;
[[nodiscard]] QString getManualDownloadUrl() const override; QString getManualDownloadUrl() const override;
[[nodiscard]] QString getName() const override; QString getName() const override;
protected: protected:
[[nodiscard]] QString getReleaseChannelUrl() const override; QString getReleaseChannelUrl() const override;
protected slots: protected slots:
void releaseListFinished() override; void releaseListFinished() override;

View File

@@ -1,9 +1,8 @@
#include "replay_timeline_widget.h" #include "replay_timeline_widget.h"
#include "../../../client/settings/cache_settings.h"
#include <QPainter> #include <QPainter>
#include <QPainterPath> #include <QPainterPath>
#include <QPalette>
#include <QTimer> #include <QTimer>
ReplayTimelineWidget::ReplayTimelineWidget(QWidget *parent) ReplayTimelineWidget::ReplayTimelineWidget(QWidget *parent)
@@ -152,16 +151,16 @@ void ReplayTimelineWidget::processNewEvents(PlaybackMode playbackMode)
currentProcessedTime = currentVisualTime; currentProcessedTime = currentVisualTime;
while ((currentEvent < replayTimeline.size()) && (replayTimeline[currentEvent] < currentProcessedTime)) { while ((currentEvent < replayTimeline.size()) && (replayTimeline[currentEvent] < currentProcessedTime)) {
EventProcessingOptions options; Player::EventProcessingOptions options;
// backwards skip => always skip reveal windows // backwards skip => always skip reveal windows
// forwards skip => skip reveal windows that don't happen within a big skip of the target // forwards skip => skip reveal windows that don't happen within a big skip of the target
if (playbackMode == BACKWARD_SKIP || currentProcessedTime - replayTimeline[currentEvent] > BIG_SKIP_MS) if (playbackMode == BACKWARD_SKIP || currentProcessedTime - replayTimeline[currentEvent] > BIG_SKIP_MS)
options |= SKIP_REVEAL_WINDOW; options |= Player::EventProcessingOption::SKIP_REVEAL_WINDOW;
// backwards skip => always skip tap animation // backwards skip => always skip tap animation
if (playbackMode == BACKWARD_SKIP) if (playbackMode == BACKWARD_SKIP)
options |= SKIP_TAP_ANIMATION; options |= Player::EventProcessingOption::SKIP_TAP_ANIMATION;
emit processNextEvent(options); emit processNextEvent(options);
++currentEvent; ++currentEvent;

View File

@@ -1,14 +1,9 @@
/**
* @file replay_timeline_widget.h
* @ingroup Replay
* @brief TODO: Document this.
*/
#ifndef REPLAY_TIMELINE_WIDGET #ifndef REPLAY_TIMELINE_WIDGET
#define REPLAY_TIMELINE_WIDGET #define REPLAY_TIMELINE_WIDGET
#include "../../../game/player/event_processing_options.h" #include "../../game/player/player.h"
#include <QList>
#include <QMouseEvent> #include <QMouseEvent>
#include <QWidget> #include <QWidget>
@@ -19,7 +14,7 @@ class ReplayTimelineWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
signals: signals:
void processNextEvent(EventProcessingOptions options); void processNextEvent(Player::EventProcessingOptions options);
void replayFinished(); void replayFinished();
void rewound(); void rewound();
@@ -59,10 +54,10 @@ public:
explicit ReplayTimelineWidget(QWidget *parent = nullptr); explicit ReplayTimelineWidget(QWidget *parent = nullptr);
void setTimeline(const QList<int> &_replayTimeline); void setTimeline(const QList<int> &_replayTimeline);
[[nodiscard]] QSize sizeHint() const override; QSize sizeHint() const override;
[[nodiscard]] QSize minimumSizeHint() const override; QSize minimumSizeHint() const override;
void setTimeScaleFactor(qreal _timeScaleFactor); void setTimeScaleFactor(qreal _timeScaleFactor);
[[nodiscard]] int getCurrentEvent() const int getCurrentEvent() const
{ {
return currentEvent; return currentEvent;
} }

View File

@@ -1,4 +1,4 @@
#include "card_sets_model.h" #include "sets_model.h"
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>

View File

@@ -1,17 +1,12 @@
/**
* @file sets_model.h
* @ingroup CardDatabaseModels
* @brief TODO: Document this.
*/
#ifndef SETSMODEL_H #ifndef SETSMODEL_H
#define SETSMODEL_H #define SETSMODEL_H
#include "../../game/cards/card_database.h"
#include <QAbstractTableModel> #include <QAbstractTableModel>
#include <QMimeData> #include <QMimeData>
#include <QSet> #include <QSet>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <libcockatrice/card/database/card_database.h>
class SetsProxyModel; class SetsProxyModel;
@@ -25,11 +20,11 @@ public:
SetsMimeData(int _oldRow) : oldRow(_oldRow) SetsMimeData(int _oldRow) : oldRow(_oldRow)
{ {
} }
[[nodiscard]] int getOldRow() const int getOldRow() const
{ {
return oldRow; return oldRow;
} }
[[nodiscard]] QStringList formats() const QStringList formats() const
{ {
return QStringList() << "application/x-cockatricecardset"; return QStringList() << "application/x-cockatricecardset";
} }
@@ -42,7 +37,7 @@ class SetsModel : public QAbstractTableModel
private: private:
static const int NUM_COLS = 7; static const int NUM_COLS = 7;
CardSetList sets; SetList sets;
QSet<CardSetPtr> enabledSets; QSet<CardSetPtr> enabledSets;
public: public:
@@ -64,23 +59,22 @@ public:
explicit SetsModel(CardDatabase *_db, QObject *parent = nullptr); explicit SetsModel(CardDatabase *_db, QObject *parent = nullptr);
~SetsModel() override; ~SetsModel() override;
[[nodiscard]] int rowCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex &parent = QModelIndex()) const override;
[[nodiscard]] int columnCount(const QModelIndex &parent = QModelIndex()) const override int columnCount(const QModelIndex &parent = QModelIndex()) const override
{ {
Q_UNUSED(parent); Q_UNUSED(parent);
return NUM_COLS; return NUM_COLS;
} }
[[nodiscard]] QVariant data(const QModelIndex &index, int role) const override; QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override; bool setData(const QModelIndex &index, const QVariant &value, int role) override;
[[nodiscard]] QVariant QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; Qt::ItemFlags flags(const QModelIndex &index) const override;
[[nodiscard]] Qt::ItemFlags flags(const QModelIndex &index) const override; Qt::DropActions supportedDropActions() const override;
[[nodiscard]] Qt::DropActions supportedDropActions() const override;
[[nodiscard]] QMimeData *mimeData(const QModelIndexList &indexes) const override; QMimeData *mimeData(const QModelIndexList &indexes) const override;
bool bool
dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
[[nodiscard]] QStringList mimeTypes() const override; QStringList mimeTypes() const override;
void swapRows(int oldRow, int newRow); void swapRows(int oldRow, int newRow);
void toggleRow(int row, bool enable); void toggleRow(int row, bool enable);
void toggleRow(int row); void toggleRow(int row);
@@ -98,8 +92,8 @@ public:
explicit SetsDisplayModel(QObject *parent = nullptr); explicit SetsDisplayModel(QObject *parent = nullptr);
protected: protected:
[[nodiscard]] bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
[[nodiscard]] bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override; bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
void fetchMore(const QModelIndex &index) override; void fetchMore(const QModelIndex &index) override;
}; };

View File

@@ -1,20 +1,21 @@
#include "spoiler_background_updater.h" #include "spoiler_background_updater.h"
#include "../../../../interface/window_main.h" #include "../../game/cards/card_database.h"
#include "../../../../main.h" #include "../../game/cards/card_database_manager.h"
#include "../../../settings/cache_settings.h" #include "../../main.h"
#include "../../settings/cache_settings.h"
#include "../ui/window_main.h"
#include <QApplication>
#include <QCryptographicHash> #include <QCryptographicHash>
#include <QDateTime> #include <QDateTime>
#include <QDebug> #include <QDebug>
#include <QFile> #include <QFile>
#include <QLocale> #include <QLocale>
#include <QMessageBox>
#include <QNetworkReply> #include <QNetworkReply>
#include <QUrl> #include <QUrl>
#include <QtConcurrent> #include <QtConcurrent>
#include <libcockatrice/card/database/card_database.h>
#include <libcockatrice/card/database/card_database_manager.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"
#define SPOILERS_URL "https://raw.githubusercontent.com/Cockatrice/Magic-Spoiler/files/spoiler.xml" #define SPOILERS_URL "https://raw.githubusercontent.com/Cockatrice/Magic-Spoiler/files/spoiler.xml"
@@ -27,7 +28,7 @@ SpoilerBackgroundUpdater::SpoilerBackgroundUpdater(QObject *apParent) : QObject(
// File exists means we're in spoiler season // File exists means we're in spoiler season
startSpoilerDownloadProcess(SPOILERS_STATUS_URL, false); startSpoilerDownloadProcess(SPOILERS_STATUS_URL, false);
} else { } else {
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoilers Disabled"; qCDebug(SpoilerBackgroundUpdaterLog) << "Spoilers Disabled";
} }
} }
@@ -40,9 +41,7 @@ void SpoilerBackgroundUpdater::startSpoilerDownloadProcess(QString url, bool sav
void SpoilerBackgroundUpdater::downloadFromURL(QUrl url, bool saveResults) void SpoilerBackgroundUpdater::downloadFromURL(QUrl url, bool saveResults)
{ {
auto *nam = new QNetworkAccessManager(this); auto *nam = new QNetworkAccessManager(this);
auto request = QNetworkRequest(url); QNetworkReply *reply = nam->get(QNetworkRequest(url));
request.setHeader(QNetworkRequest::UserAgentHeader, QString("Cockatrice %1").arg(VERSION_STRING));
QNetworkReply *reply = nam->get(request);
if (saveResults) { if (saveResults) {
// This will write out to the file (used for spoiler.xml) // This will write out to the file (used for spoiler.xml)
@@ -68,7 +67,7 @@ void SpoilerBackgroundUpdater::actDownloadFinishedSpoilersFile()
reply->deleteLater(); reply->deleteLater();
emit spoilerCheckerDone(); emit spoilerCheckerDone();
} else { } else {
qCWarning(SpoilerBackgroundUpdaterLog) << "Error downloading spoilers file" << errorCode; qCDebug(SpoilerBackgroundUpdaterLog) << "Error downloading spoilers file" << errorCode;
emit spoilerCheckerDone(); emit spoilerCheckerDone();
} }
} }
@@ -82,11 +81,11 @@ bool SpoilerBackgroundUpdater::deleteSpoilerFile()
// Delete the spoiler.xml file // Delete the spoiler.xml file
if (file.exists() && file.remove()) { if (file.exists() && file.remove()) {
qCInfo(SpoilerBackgroundUpdaterLog) << "Deleting spoiler.xml"; qCDebug(SpoilerBackgroundUpdaterLog) << "Deleting spoiler.xml";
return true; return true;
} }
qCInfo(SpoilerBackgroundUpdaterLog) << "Error: Spoiler.xml not found or not deleted"; qCDebug(SpoilerBackgroundUpdaterLog) << "Error: Spoiler.xml not found or not deleted";
return false; return false;
} }
@@ -102,24 +101,24 @@ void SpoilerBackgroundUpdater::actCheckIfSpoilerSeasonEnabled()
trayIcon->showMessage(tr("Spoilers season has ended"), tr("Deleting spoiler.xml. Please run Oracle")); trayIcon->showMessage(tr("Spoilers season has ended"), tr("Deleting spoiler.xml. Please run Oracle"));
} }
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Season Offline"; qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Season Offline";
emit spoilerCheckerDone(); emit spoilerCheckerDone();
} else if (errorCode == QNetworkReply::NoError) { } else if (errorCode == QNetworkReply::NoError) {
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Service Online"; qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Online";
startSpoilerDownloadProcess(SPOILERS_URL, true); startSpoilerDownloadProcess(SPOILERS_URL, true);
} else if (errorCode == QNetworkReply::HostNotFoundError) { } else if (errorCode == QNetworkReply::HostNotFoundError) {
if (trayIcon) { if (trayIcon) {
trayIcon->showMessage(tr("Spoilers download failed"), tr("No internet connection")); trayIcon->showMessage(tr("Spoilers download failed"), tr("No internet connection"));
} }
qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler download failed due to no internet connection"; qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler download failed due to no internet connection";
emit spoilerCheckerDone(); emit spoilerCheckerDone();
} else { } else {
if (trayIcon) { if (trayIcon) {
trayIcon->showMessage(tr("Spoilers download failed"), tr("Error") + " " + (short)errorCode); trayIcon->showMessage(tr("Spoilers download failed"), tr("Error") + " " + (short)errorCode);
} }
qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler download failed with reason" << errorCode; qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler download failed with reason" << errorCode;
emit spoilerCheckerDone(); emit spoilerCheckerDone();
} }
} }
@@ -140,19 +139,19 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
trayIcon->showMessage(tr("Spoilers already up to date"), tr("No new spoilers added")); trayIcon->showMessage(tr("Spoilers already up to date"), tr("No new spoilers added"));
} }
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoilers Up to Date"; qCDebug(SpoilerBackgroundUpdaterLog) << "Spoilers Up to Date";
return false; return false;
} }
QFile file(fileName); QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) { if (!file.open(QIODevice::WriteOnly)) {
qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File open (w) failed for" << fileName; qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File open (w) failed for" << fileName;
file.close(); file.close();
return false; return false;
} }
if (file.write(data) == -1) { if (file.write(data) == -1) {
qCWarning(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File write (w) failed for" << fileName; qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Error: File write (w) failed for" << fileName;
file.close(); file.close();
return false; return false;
} }
@@ -160,7 +159,7 @@ bool SpoilerBackgroundUpdater::saveDownloadedFile(QByteArray data)
file.close(); file.close();
// Data written, so reload the card database // Data written, so reload the card database
qCInfo(SpoilerBackgroundUpdaterLog) << "Spoiler Service Data Written"; qCDebug(SpoilerBackgroundUpdaterLog) << "Spoiler Service Data Written";
const auto reloadOk = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); }); const auto reloadOk = QtConcurrent::run([] { CardDatabaseManager::getInstance()->loadCardDatabases(); });
// If the user has notifications enabled, let them know // If the user has notifications enabled, let them know
@@ -203,12 +202,12 @@ QByteArray SpoilerBackgroundUpdater::getHash(const QString fileName)
QCryptographicHash hash(QCryptographicHash::Algorithm::Md5); QCryptographicHash hash(QCryptographicHash::Algorithm::Md5);
hash.addData(bytes); hash.addData(bytes);
qCInfo(SpoilerBackgroundUpdaterLog) << "File Hash =" << hash.result(); qCDebug(SpoilerBackgroundUpdaterLog) << "File Hash =" << hash.result();
file.close(); file.close();
return hash.result(); return hash.result();
} else { } else {
qCWarning(SpoilerBackgroundUpdaterLog) << "getHash ReadOnly failed!"; qCDebug(SpoilerBackgroundUpdaterLog) << "getHash ReadOnly failed!";
file.close(); file.close();
return QByteArray(); return QByteArray();
} }
@@ -222,7 +221,7 @@ QByteArray SpoilerBackgroundUpdater::getHash(QByteArray data)
QCryptographicHash hash(QCryptographicHash::Algorithm::Md5); QCryptographicHash hash(QCryptographicHash::Algorithm::Md5);
hash.addData(bytes); hash.addData(bytes);
qCInfo(SpoilerBackgroundUpdaterLog) << "Data Hash =" << hash.result(); qCDebug(SpoilerBackgroundUpdaterLog) << "Data Hash =" << hash.result();
return hash.result(); return hash.result();
} }

View File

@@ -1,9 +1,3 @@
/**
* @file spoiler_background_updater.h
* @ingroup Client
* @brief TODO: Document this.
*/
#ifndef COCKATRICE_SPOILER_DOWNLOADER_H #ifndef COCKATRICE_SPOILER_DOWNLOADER_H
#define COCKATRICE_SPOILER_DOWNLOADER_H #define COCKATRICE_SPOILER_DOWNLOADER_H
@@ -22,7 +16,7 @@ public:
inline QString getCardUpdaterBinaryName() inline QString getCardUpdaterBinaryName()
{ {
return "oracle"; return "oracle";
} };
QByteArray getHash(const QString fileName); QByteArray getHash(const QString fileName);
QByteArray getHash(QByteArray data); QByteArray getHash(QByteArray data);
static bool deleteSpoilerFile(); static bool deleteSpoilerFile();

View File

@@ -1,56 +0,0 @@
#include "card_counter_settings.h"
#include <QColor>
#include <QSettings>
#include <QtMath>
CardCounterSettings::CardCounterSettings(const QString &settingsPath, QObject *parent)
: SettingsManager(settingsPath + "global.ini", "cards", "counters", parent)
{
}
void CardCounterSettings::setColor(int counterId, const QColor &color)
{
QString key = QString("cards/counters/%1/color").arg(counterId);
if (settings.value(key).value<QColor>() == color)
return;
settings.setValue(key, color);
emit colorChanged(counterId, color);
}
QColor CardCounterSettings::color(int counterId) const
{
QColor defaultColor;
if (counterId < 6) {
// Preserve legacy colors
defaultColor = QColor::fromHsv(counterId * 60, 150, 255);
} else {
// Future-proof support for more counters with pseudo-random colors
int h = (counterId * 37) % 360;
int s = 128 + 64 * qSin((counterId * 97) * 0.1); // 64-192
int v = 196 + 32 * qSin((counterId * 101) * 0.07); // 164-228
defaultColor = QColor::fromHsv(h, s, v);
}
return settings.value(QString("cards/counters/%1/color").arg(counterId), defaultColor).value<QColor>();
}
QString CardCounterSettings::displayName(int counterId) const
{
// Currently, card counters name are fixed to A, B, ..., Z, AA, AB, ...
auto nChars = 1 + counterId / 26;
QString str;
str.resize(nChars);
for (auto it = str.rbegin(); it != str.rend(); ++it) {
*it = QChar('A' + (counterId) % 26);
counterId /= 26;
}
return str;
}

View File

@@ -1,33 +0,0 @@
/**
* @file card_counter_settings.h
* @ingroup GameSettings
* @brief TODO: Document this.
*/
#ifndef CARD_COUNTER_SETTINGS_H
#define CARD_COUNTER_SETTINGS_H
#include <libcockatrice/settings/settings_manager.h>
class QSettings;
class QColor;
class CardCounterSettings : public SettingsManager
{
Q_OBJECT
public:
CardCounterSettings(const QString &settingsPath, QObject *parent = nullptr);
[[nodiscard]] QColor color(int counterId) const;
[[nodiscard]] QString displayName(int counterId) const;
public slots:
void setColor(int counterId, const QColor &color);
signals:
void colorChanged(int counterId, const QColor &color);
};
#endif // CARD_COUNTER_SETTINGS_H

View File

@@ -1,6 +1,6 @@
#include "sound_engine.h" #include "sound_engine.h"
#include "settings/cache_settings.h" #include "../settings/cache_settings.h"
#include <QDir> #include <QDir>
#include <QMediaPlayer> #include <QMediaPlayer>
@@ -37,7 +37,7 @@ SoundEngine::~SoundEngine()
void SoundEngine::soundEnabledChanged() void SoundEngine::soundEnabledChanged()
{ {
if (SettingsCache::instance().getSoundEnabled()) { if (SettingsCache::instance().getSoundEnabled()) {
qCInfo(SoundEngineLog) << "SoundEngine: enabling sound with" << audioData.size() << "sounds"; qCDebug(SoundEngineLog) << "SoundEngine: enabling sound with" << audioData.size() << "sounds";
if (!player) { if (!player) {
player = new QMediaPlayer; player = new QMediaPlayer;
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
@@ -46,7 +46,7 @@ void SoundEngine::soundEnabledChanged()
#endif #endif
} }
} else { } else {
qCInfo(SoundEngineLog) << "SoundEngine: disabling sound"; qCDebug(SoundEngineLog) << "SoundEngine: disabling sound";
if (player) { if (player) {
player->stop(); player->stop();
player->deleteLater(); player->deleteLater();
@@ -90,7 +90,7 @@ void SoundEngine::ensureThemeDirectoryExists()
{ {
if (SettingsCache::instance().getSoundThemeName().isEmpty() || if (SettingsCache::instance().getSoundThemeName().isEmpty() ||
!getAvailableThemes().contains(SettingsCache::instance().getSoundThemeName())) { !getAvailableThemes().contains(SettingsCache::instance().getSoundThemeName())) {
qCInfo(SoundEngineLog) << "Sounds theme name not set, setting default value"; qCDebug(SoundEngineLog) << "Sounds theme name not set, setting default value";
SettingsCache::instance().setSoundThemeName(DEFAULT_THEME_NAME); SettingsCache::instance().setSoundThemeName(DEFAULT_THEME_NAME);
} }
} }
@@ -131,7 +131,7 @@ QStringMap &SoundEngine::getAvailableThemes()
void SoundEngine::themeChangedSlot() void SoundEngine::themeChangedSlot()
{ {
QString themeName = SettingsCache::instance().getSoundThemeName(); QString themeName = SettingsCache::instance().getSoundThemeName();
qCInfo(SoundEngineLog) << "Sound theme changed:" << themeName; qCDebug(SoundEngineLog) << "Sound theme changed:" << themeName;
QDir dir = getAvailableThemes().value(themeName); QDir dir = getAvailableThemes().value(themeName);

View File

@@ -1,9 +1,3 @@
/**
* @file sound_engine.h
* @ingroup Core
* @brief TODO: Document this.
*/
#ifndef SOUNDENGINE_H #ifndef SOUNDENGINE_H
#define SOUNDENGINE_H #define SOUNDENGINE_H

View File

@@ -1,18 +1,15 @@
#ifndef DECKDATA_H #ifndef DECKDATA_H
#define DECKDATA_H #define DECKDATA_H
#include "../archidekt_links/edhrec_api_response_archidekt_links.h" #include "edhrec_commander_api_response_archidekt_links.h"
#include "../cards/edhrec_api_response_card_container.h"
#include "edhrec_commander_api_response_average_deck_statistics.h" #include "edhrec_commander_api_response_average_deck_statistics.h"
#include "edhrec_commander_api_response_card_container.h"
#include <QDebug>
#include <QJsonObject> #include <QJsonObject>
#include <QString> #include <QString>
/** // Represents the main structure of the JSON
* @class EdhrecCommanderApiResponse
* @ingroup ApiResponses
* @brief Represents the main structure of the JSON
*/
class EdhrecCommanderApiResponse class EdhrecCommanderApiResponse
{ {
public: public:
@@ -22,7 +19,7 @@ public:
QString header; QString header;
QJsonObject panels; QJsonObject panels;
QString description; QString description;
EdhrecApiResponseCardContainer container; EdhrecCommanderApiResponseCardContainer container;
void fromJson(const QJsonObject &json); void fromJson(const QJsonObject &json);
void debugPrint() const; void debugPrint() const;

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