Commit 668b0639 authored by nanahira's avatar nanahira

Merge branch 'server' into develop

parents 54e1d3dc 8d90911f
# data files
/beta
/expansions
/specials
# build files
/bin
build
/obj
# dependencies
/event
/freetype
/sqlite3
/irrklang
/irrlicht*
# gframe additionals
/gframe/ygopro.ico
/gframe/ygopro.rc
/gframe/ygopro.aps
/gframe/ygopro.icns
/gframe/dirent.h
# git repos
/CustomTools
/DataEditorX
/Magic*
/pics
/Printer
/ygopro-*
/*-Cards
# libs
/*.dll
/*.so
/*.dylib
# windbot related files
/[Bb]ot
/[Bb]ot.conf
/[Bb]ot.exe
/[Bb]ot.sh
/[Ww]ind[Bb]ot
# ygopro config file
/system_user.conf
# ygopro folders
/deck
/pack
/fonts
/replay
/single
/screenshots
/sound/*.wav
/sound/custom
/sound/BGM
/sound/README.md
/sound/LICENSE
/sound/,*
/update
/update*
/locales
# ygopro main program
/ygopro
/ygopro_*
/ygopro.exe
/ygopro_*.exe
/ygopro.app
/ygopro_*.app
/premake4
/premake4.exe
/premake5
/premake5.exe
# others
*.log
.vscode
core*
/bak/
/.vs
/bug.txt
/output
/temp
[Tt]humbs.cdb
/PrinterData.txt
/*.bat
/*.sh
/*.sql
/patch.exe.manifest
/patch.exe
/diff.exe
Dockerfile
.dockerignore
/ocgcore
/script
/skin
/sound
/textures
/premake
/ikpmp3
/cards.cdb
/LICENSE
/README.md
/.gitignore
/strings.conf
/system.conf
...@@ -20,14 +20,14 @@ mat_common: ...@@ -20,14 +20,14 @@ mat_common:
- wget -O - https://cdn01.moecube.com/ygopro-build-materials/sqlite-autoconf-3390300.tar.gz | tar zfx - - wget -O - https://cdn01.moecube.com/ygopro-build-materials/sqlite-autoconf-3390300.tar.gz | tar zfx -
- mv sqlite-autoconf-3390300 sqlite3 - mv sqlite-autoconf-3390300 sqlite3
# freetype # freetype
- wget -O - https://cdn01.moecube.com/ygopro-build-materials/freetype-2.11.1.tar.gz | tar zfx - #- wget -O - https://cdn01.moecube.com/ygopro-build-materials/freetype-2.11.1.tar.gz | tar zfx -
- mv freetype-2.11.1 freetype #- mv freetype-2.11.1 freetype
# premake # premake
- cp -rf premake/* .; - cp -rf premake/* .;
artifacts: artifacts:
paths: paths:
- lua - lua
- freetype #- freetype
- sqlite3 - sqlite3
mat_submodules: mat_submodules:
...@@ -44,21 +44,6 @@ mat_submodules: ...@@ -44,21 +44,6 @@ mat_submodules:
- ocgcore - ocgcore
- script - script
mat_irrklang:
stage: prepare
tags:
- linux
script:
- apt update; apt -y install git
- mkdir -p ~/.ssh; chmod 700 ~/.ssh; echo "$NANAHIRA_SSH_KEY" | base64 --decode > ~/.ssh/id_rsa; chmod 600 ~/.ssh/id_rsa
- ssh-keyscan git.mycard.moe >> ~/.ssh/known_hosts
- git clone --depth=1 git@git.mycard.moe:nanahira/irrklang
#- mv -f irrklang/plugins/ikpmp3 .
artifacts:
paths:
- irrklang
- ikpmp3
mat_linux: mat_linux:
stage: prepare stage: prepare
tags: tags:
...@@ -75,34 +60,6 @@ mat_linux: ...@@ -75,34 +60,6 @@ mat_linux:
- irrlicht - irrlicht
- libevent-stable - libevent-stable
#mat_macos_irrklang_patched:
# stage: build
# tags:
# - linux
# dependencies: []
# script:
# - wget -O - https://cdn01.moecube.com/ygopro-build-materials/libirrklang-patched-dylib.tar.gz | tar zfx -
# artifacts:
# paths:
# - libirrklang-patched.dylib
mat_macos:
stage: prepare
tags:
- linux
script:
- apt update; apt -y install wget tar
- wget -O - https://cdn01.moecube.com/ygopro-build-materials/premake-5.0.0-beta2-macosx.tar.gz | tar zfx -
# - wget -O - https://cdn01.moecube.com/ygopro-build-materials/libirrklang-patched-dylib.tar.gz | tar zfx -
- mkdir irrlicht
- cd irrlicht
- wget -O - https://cdn01.moecube.com/ygopro-build-materials/irrlicht-mycard-mac.tar.gz | tar zfx -
- cd ..
artifacts:
paths:
- premake5
- irrlicht
mat_windows: mat_windows:
stage: prepare stage: prepare
tags: tags:
...@@ -116,17 +73,17 @@ mat_windows: ...@@ -116,17 +73,17 @@ mat_windows:
- wget -O - https://cdn01.moecube.com/ygopro-build-materials/libevent-2.0.22-stable.tar.gz | tar zfx - - wget -O - https://cdn01.moecube.com/ygopro-build-materials/libevent-2.0.22-stable.tar.gz | tar zfx -
- mv libevent-2.0.22-stable event - mv libevent-2.0.22-stable event
# irrlicht # irrlicht
- git clone --depth=1 -b develop https://code.mycard.moe/mycard/irrlicht-new irrlicht # - git clone --depth=1 -b develop https://code.mycard.moe/mycard/irrlicht-new irrlicht
artifacts: artifacts:
paths: paths:
- premake5.exe - premake5.exe
- event - event
- irrlicht # - irrlicht
._exec_build: ._exec_build:
stage: build stage: build
variables: #variables:
NO_LUA_SAFE: '1' # on client no lua safe # NO_LUA_SAFE: '1' # on client no lua safe
cache: cache:
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG" key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths: paths:
...@@ -139,12 +96,11 @@ exec_windows: ...@@ -139,12 +96,11 @@ exec_windows:
- vs - vs
dependencies: dependencies:
- mat_common - mat_common
- mat_irrklang
- mat_windows - mat_windows
- mat_submodules - mat_submodules
script: script:
- bash -c 'cp -rf premake/* .' - bash -c 'cp -rf premake/* .'
- '.\premake5.exe vs2019 --irrklang-pro' - '.\premake5.exe vs2019'
- cmd /c '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\msbuild.exe" build\YGOPro.sln /m /p:Configuration=Release' - cmd /c '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\msbuild.exe" build\YGOPro.sln /m /p:Configuration=Release'
- copy bin\release\ygopro.exe . - copy bin\release\ygopro.exe .
artifacts: artifacts:
...@@ -158,518 +114,58 @@ exec_linux: ...@@ -158,518 +114,58 @@ exec_linux:
image: git-registry.mycard.moe/mycard/docker-runner-base:debian11 image: git-registry.mycard.moe/mycard/docker-runner-base:debian11
dependencies: dependencies:
- mat_common - mat_common
- mat_irrklang
- mat_linux - mat_linux
- mat_submodules - mat_submodules
script: script:
- apt update; apt -y install git build-essential libgl1-mesa-dev libglu-dev libxxf86vm-dev - apt update; apt -y install git build-essential
- mkdir lib - ./premake5 gmake --build-sqlite --server-zip-support
- cp -rf irrklang/bin/linux-gcc-64/libIrrKlang.so ./lib/
# - cp -rf irrklang/bin/linux-gcc-64/ikpMP3.so ./lib/
- export EVENT_INCLUDE_DIR=$PWD/libevent-stable/include
- export EVENT_LIB_DIR=$PWD/libevent-stable/lib
- ./premake5 gmake --build-freetype --build-sqlite --build-irrlicht --build-ikpmp3 --irrklang-pro
- cd build - cd build
- make config=release -j$(nproc) - make config=release -j$(nproc)
- cd .. - cd ..
- mv bin/release/YGOPro ./ygopro - mv bin/release/ygopro ./ygopro
- strip ygopro - strip ygopro
artifacts: artifacts:
paths: paths:
- ygopro - ygopro
- lib
._exec_macos_platform: exec_debian:
extends: ._exec_build extends: ._exec_build
tags:
- linux
dependencies: dependencies:
- mat_macos
- mat_common - mat_common
- mat_linux
- mat_submodules - mat_submodules
script: script:
- ./.ci/exec-macos-platform.sh - apt update; apt -y install git build-essential liblua5.3-dev libsqlite3-dev libevent-dev
artifacts: - ./premake5 gmake --lua-deb
paths: - cd build
- ygopro-platforms - make config=release -j$(nproc)
exec_macos_platform_x86:
extends: ._exec_macos_platform
tags:
- macos
exec_macos_platform_m1:
extends: ._exec_macos_platform
tags:
- macos-m1
variables:
MAC_ARM: 1
exec_macos:
stage: combine
tags:
- macos
dependencies:
- exec_macos_platform_x86
- exec_macos_platform_m1
#- mat_macos_irrklang_patched
script:
- mkdir -p ygopro.app/Contents/MacOS ygopro.app/Contents/Frameworks;
- lipo -create -output ygopro.app/Contents/MacOS/ygopro $(ls -1 ygopro-platforms/ygopro-platform-*);
# do some special things for irrklang
#- mv ./libirrklang-patched.dylib ygopro.app/Contents/Frameworks/libirrklang.dylib
#- install_name_tool -change /usr/local/lib/libirrklang.dylib @executable_path/../Frameworks/libirrklang.dylib ygopro.app/Contents/MacOS/ygopro
#- dylibbundler -x ygopro.app/Contents/MacOS/ygopro -b -d ygopro.app/Contents/Frameworks/ -p @executable_path/../Frameworks/ -cd -i @executable_path/../Frameworks;
#- strip ygopro.app/Contents/MacOS/ygopro;
- mkdir ygopro.app/Contents/Resources;
- mv premake/gframe/ygopro.icns ygopro.app/Contents/Resources/Icon.icns;
- defaults write "$PWD/ygopro.app/Contents/Info.plist" "CFBundleIconFile" "Icon.icns";
- defaults write "$PWD/ygopro.app/Contents/Info.plist" "CFBundleIdentifier" "moe.mycard.ygopro";
artifacts:
paths:
- ygopro.app
#exec_macos_sign:
# stage: sign
# tags:
# - macos
# dependencies:
# - exec_macos
# script: ./.ci/sign-macos.sh
# artifacts:
# paths:
# - ygopro.app
# only:
# - tags
# - master
assets:
stage: prepare
tags:
- linux
script:
- apt update; apt -y install tar wget git
# starter pack
- wget -O - https://code.mycard.moe/mycard/ygopro-starter-pack/-/archive/master/ygopro-starter-pack-master.tar.gz | tar zfx -
- mv ygopro-starter-pack-master/* .
# sound
- wget -O - https://code.mycard.moe/mycard/ygopro-sounds/-/archive/master/ygopro-sounds-master.tar.gz | tar zfx -
- mv ygopro-sounds-master/sound/* sound
# fonts
- mkdir fonts
- cd fonts
- wget -O - https://cdn01.moecube.com/ygopro-fonts.tar.gz | tar zfx -
- cd .. - cd ..
# pack - mv bin/release/ygopro ./ygopro
- git clone --depth=1 https://code.mycard.moe/mycard/ygopro-card-list - strip ygopro
- mv ygopro-card-list/pack .
# locales
- git clone --depth=1 https://code.mycard.moe/nanahira/ygopro-database
- mv ygopro-database/locales .
artifacts:
paths:
- deck
- single
- sound
- fonts
- pack
- locales
only:
- tags
- master
assets_nonwindows:
stage: prepare
tags:
- linux
script:
- apt update; apt -y install tar wget
- wget -O - https://cdn01.moecube.com/windbot/windbot.tar.gz | tar zfx -
artifacts:
paths:
- bot.conf
- windbot
- bot
only:
- tags
- master
assets_windows:
stage: prepare
tags:
- linux
script:
- wget https://cdn01.moecube.com/windbot/WindBot.7z
- 7z x -y WindBot.7z
- aws s3 --endpoint=https://minio.mycard.moe:9000 sync s3://mycard/koishipro/contents/update-koishipro/ ./update-koishipro
- rm -rf update-koishipro/.git || true
artifacts:
paths:
- bot.conf
- WindBot
- Bot.exe
- update-koishipro
only:
- tags
- master
._locale_zh-CN:
variables:
TARGET_LOCALE: zh-CN
._locale_en-US:
variables:
TARGET_LOCALE: en-US
._assets_locale:
stage: build
tags:
- linux
script: ./.ci/assets-locale.sh
artifacts:
paths:
- pics
- cards.cdb
- strings.conf
- bot.conf
only:
- tags
- master
assets_zh-CN:
extends:
- ._assets_locale
- ._locale_zh-CN
assets_en-US:
extends:
- ._assets_locale
- ._locale_en-US
._pack:
stage: pack
tags:
- linux
artifacts: artifacts:
paths: paths:
- dist - ygopro
only:
- tags
- master
._pack_format_gz:
extends: ._pack
variables:
ARCHIVE_SUFFIX: gz
._pack_format_zst:
extends: ._pack
variables:
ARCHIVE_SUFFIX: zst
._pack_dlc:
extends: ._pack_format_zst
only:
- tags
._pack_script_windows_non7z:
extends: ._pack
script: ./.ci/pack-windows.sh
._pack_script_windows_7z:
extends: ._pack
script: ./.ci/pack-windows-7z.sh
._pack_script_linux:
extends: ._pack
script: ./.ci/pack-linux.sh
._pack_script_macos:
extends: ._pack
script: ./.ci/pack-macos.sh
._pack_script_windows_dlc:
extends: ._pack_dlc
script: ./.ci/pack-windows-dlc.sh
._pack_script_linux_dlc:
extends: ._pack_dlc
script: ./.ci/pack-linux-dlc.sh
._pack_script_macos_dlc:
extends: ._pack_dlc
script: ./.ci/pack-macos-dlc.sh
._pack_assets_windows_zh-CN:
extends: ._pack
dependencies:
- assets
- assets_windows
- exec_windows
- assets_zh-CN
- mat_submodules
._pack_assets_linux_zh-CN:
extends: ._pack
dependencies:
- assets
- assets_nonwindows
- exec_linux
- assets_zh-CN
- mat_submodules
._pack_assets_macos_zh-CN:
extends: ._pack
dependencies:
- assets
- assets_nonwindows
- exec_macos
- assets_zh-CN
- mat_submodules
._pack_assets_windows_en-US:
extends: ._pack
dependencies:
- assets
- assets_windows
- exec_windows
- assets_en-US
- mat_submodules
._pack_assets_linux_en-US:
extends: ._pack
dependencies:
- assets
- assets_nonwindows
- exec_linux
- assets_en-US
- mat_submodules
._pack_assets_macos_en-US:
extends: ._pack
dependencies:
- assets
- assets_nonwindows
- exec_macos
- assets_en-US
- mat_submodules
._pack_assets_windows_dlc:
extends: ._pack
dependencies:
- assets
- exec_windows
- mat_submodules
._pack_assets_linux_dlc:
extends: ._pack
dependencies:
- assets
- exec_linux
- mat_submodules
._pack_assets_macos_dlc:
extends: ._pack
dependencies:
- assets
- exec_macos
- mat_submodules
pack_windows_dlc_zh-CN:
extends:
- ._pack_assets_windows_dlc
- ._pack_script_windows_dlc
- ._locale_zh-CN
pack_linux_dlc_zh-CN:
extends:
- ._pack_assets_linux_dlc
- ._pack_script_linux_dlc
- ._locale_zh-CN
pack_macos_dlc_zh-CN:
extends:
- ._pack_assets_macos_dlc
- ._pack_script_macos_dlc
- ._locale_zh-CN
pack_windows_dlc_en-US:
extends:
- ._pack_assets_windows_dlc
- ._pack_script_windows_dlc
- ._locale_en-US
pack_linux_dlc_en-US:
extends:
- ._pack_assets_linux_dlc
- ._pack_script_linux_dlc
- ._locale_en-US
pack_macos_dlc_en-US:
extends:
- ._pack_assets_macos_dlc
- ._pack_script_macos_dlc
- ._locale_en-US
pack_windows_zh-CN_7z:
extends:
- ._pack_assets_windows_zh-CN
- ._pack_script_windows_7z
- ._locale_zh-CN
#pack_windows_zh-CN_gz:
# extends:
# - ._pack_assets_windows_zh-CN
# - ._pack_script_windows_non7z
# - ._pack_format_gz
# - ._locale_zh-CN
#pack_windows_zh-CN_zst:
# extends:
# - ._pack_assets_windows_zh-CN
# - ._pack_script_windows_non7z
# - ._pack_format_zst
# - ._locale_zh-CN
pack_linux_zh-CN_gz:
extends:
- ._pack_assets_linux_zh-CN
- ._pack_script_linux
- ._pack_format_gz
- ._locale_zh-CN
#pack_linux_zh-CN_zst:
# extends:
# - ._pack_assets_linux_zh-CN
# - ._pack_script_linux
# - ._pack_format_zst
# - ._locale_zh-CN
pack_macos_zh-CN_gz:
extends:
- ._pack_assets_macos_zh-CN
- ._pack_script_macos
- ._pack_format_gz
- ._locale_zh-CN
#pack_macos_zh-CN_zst:
# extends:
# - ._pack_assets_macos_zh-CN
# - ._pack_script_macos
# - ._pack_format_zst
# - ._locale_zh-CN
pack_windows_en-US_7z:
extends:
- ._pack_assets_windows_en-US
- ._pack_script_windows_7z
- ._locale_en-US
#pack_windows_en-US_gz:
# extends:
# - ._pack_assets_windows_en-US
# - ._pack_script_windows_non7z
# - ._pack_format_gz
# - ._locale_en-US
#pack_windows_en-US_zst:
# extends:
# - ._pack_assets_windows_en-US
# - ._pack_script_windows_non7z
# - ._pack_format_zst
# - ._locale_en-US
pack_linux_en-US_gz:
extends:
- ._pack_assets_linux_en-US
- ._pack_script_linux
- ._pack_format_gz
- ._locale_en-US
#pack_linux_en-US_zst:
# extends:
# - ._pack_assets_linux_en-US
# - ._pack_script_linux
# - ._pack_format_zst
# - ._locale_en-US
pack_macos_en-US_gz:
extends:
- ._pack_assets_macos_en-US
- ._pack_script_macos
- ._pack_format_gz
- ._locale_en-US
#pack_macos_en-US_zst: #win_server_pack:
# extends: # stage: pack
# - ._pack_assets_macos_en-US # dependencies:
# - ._pack_script_macos # - exec_windows
# - ._pack_format_zst # tags:
# - ._locale_en-US # - linux
# script:
# - apt update; apt -y install p7zip-full wget
# - wget https://nodejs.org/dist/v14.17.0/node-v14.17.0-win-x64.7z
upload_contents:
stage: deploy
dependencies:
- pack_windows_zh-CN_7z
tags:
- linux
script:
- 7z x -y -ocontents dist/KoishiPro-$CI_COMMIT_REF_NAME-win32-zh-CN.7z
- cd contents/update-koishipro
- chmod +x *.sh
- mono update.exe -ci
- sed -i "/git/d" filelist.txt
- cd ../..
- aws s3 --endpoint=https://minio.mycard.moe:9000 sync --delete contents/ s3://mycard/koishipro/contents/
only:
- master
upload_to_minio: upload_to_minio:
stage: deploy stage: deploy
dependencies: dependencies:
- pack_windows_zh-CN_7z - exec_windows
#- pack_windows_zh-CN_gz
#- pack_windows_zh-CN_zst
- pack_linux_zh-CN_gz
#- pack_linux_zh-CN_zst
- pack_macos_zh-CN_gz
#- pack_macos_zh-CN_zst
- pack_windows_en-US_7z
#- pack_windows_en-US_gz
#- pack_windows_en-US_zst
- pack_linux_en-US_gz
#- pack_linux_en-US_zst
- pack_macos_en-US_gz
#- pack_macos_en-US_zst
- pack_windows_dlc_zh-CN
- pack_linux_dlc_zh-CN
- pack_macos_dlc_zh-CN
- pack_windows_dlc_en-US
- pack_linux_dlc_en-US
- pack_macos_dlc_en-US
tags: tags:
- linux - linux
script: script:
- aws s3 --endpoint=https://minio.mycard.moe:9000 sync dist/ s3://mycard/koishipro/archive - aws s3 --endpoint=https://minio.mycard.moe:9000 cp ygopro.exe s3://mycard/koishipro/server/ygopro.exe
only:
- tags
- master
upload_mycard:
stage: deploy
dependencies:
- pack_windows_dlc_zh-CN
- pack_linux_dlc_zh-CN
- pack_macos_dlc_zh-CN
- pack_windows_dlc_en-US
- pack_linux_dlc_en-US
- pack_macos_dlc_en-US
tags:
- linux
variables:
appVersion: $CI_COMMIT_TAG
script: ./.ci/upload-packager.sh
only: only:
- tags - server
language: cpp
dist: bionic
git:
submodules: false
addons:
ssh_known_hosts:
- github.com
apt:
# sources:
# - ubuntu-toolchain-r-test
packages:
# - gcc-6
# - g++-6
- libevent-dev
- libsqlite3-dev
- liblua5.3-dev
env:
- DATABASE_FILE=cards.cdb
before_install:
- git submodule update --init --recursive
#- sudo ln -s /usr/bin/gcc-6 /usr/local/bin/gcc
#- sudo ln -s /usr/bin/g++-6 /usr/local/bin/g++
#- g++ --version
- wget -O - https://github.com/premake/premake-core/releases/download/v5.0.0-beta1/premake-5.0.0-beta1-linux.tar.gz | tar zfx -
#- wget -O - https://www.lua.org/ftp/lua-5.3.6.tar.gz | tar zfx -; cd lua-5.3.6; sudo make linux install; cd ..
script:
- ./premake5 gmake
- cd build
- make config=release
- cd ..
- mv -f ./bin/release/ygopro .
- strip ygopro
- mkdir replay
- echo "select id from datas;" | sqlite3 $DATABASE_FILE | xargs -I {} ./ygopro {} 2>&1 | tee ./redtext.txt
- bash -c "exit $(cat ./redtext.txt | wc -l)"
FROM debian:buster-slim as git-checkout
RUN apt update && \
env DEBIAN_FRONTEND=noninteractive apt install -y git wget tar && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /usr/src/app
COPY .git ./.git
RUN git checkout -f && \
git submodule update --init && \
git submodule foreach git checkout master && \
wget -O - https://github.com/premake/premake-core/releases/download/v5.0.0-alpha14/premake-5.0.0-alpha14-linux.tar.gz | tar zfx - && \
./premake5 gmake
FROM debian:buster-slim as builder
# apt
RUN apt update && \
env DEBIAN_FRONTEND=noninteractive apt install -y build-essential libsqlite3-dev libevent-dev liblua5.3-dev && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /usr/src/app
COPY --from=git-checkout /usr/src/app/ ./
RUN cd build && \
make -j$(nproc) && \
cd .. && \
cp -rf bin/release/ygopro . && \
strip ygopro
FROM debian:buster-slim
# apt
RUN apt update && \
env DEBIAN_FRONTEND=noninteractive apt install -y libsqlite3-dev libevent-dev liblua5.3-dev && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /usr/src/app
COPY --from=builder /usr/src/app/ygopro .
COPY --from=git-checkout /usr/src/app/script ./script
COPY ./lflist.conf .
ENTRYPOINT [ "./ygopro" ]
## YGOPro ## YGOPro(Server)
A script engine for "yu-gi-oh!" and sample gui [![Build status](https://ci.appveyor.com/api/projects/status/qgkqi6o0wq7qn922/branch/server?svg=true)](https://ci.appveyor.com/project/zh99998/ygopro/branch/server)
[![Build Status](https://travis-ci.org/moecube/ygopro.svg?branch=server)](https://travis-ci.org/moecube/ygopro)
[中文说明](https://github.com/Fluorohydride/ygopro/wiki/%E4%B8%AD%E6%96%87%E8%AF%B4%E6%98%8E) 一个YGOPro的服务端版本,运行后自动建立主机,并开启端口供YGOPro客户端连接。
### Keys: 现用于[萌卡](https://mycard.moe/)[YGOPro 233服](http://mercury233.me/ygosrv233/)
* ESC: Minimize the window.
* A: Holding down this button will let the system stop at every timing.
* S: Holding down this button will let the system skip every timing.
* D: Holding down this button will let the system stop at available timing.
* R: Fix the font glitch.
* F1~F4: Show the cards in your grave, banished zone, extra deck, xyz materials.
* F5~F8: Show the cards in your opponent's grave, banished zone, extra deck, xyz materials.
### Color in card list: ### Linux下编译
#### Background: * 需要以下组件或工具
* White = your card, Grey = your opponent's card * gcc
* premake5
* libevent
* lua5.3
* sqlite3
* 可参考本项目 [.travis.yml](https://github.com/mycard/ygopro/blob/server/.travis.yml) 中的脚本
#### Text: ### Windows下编译
Cards in deck, extra deck and banished zone: * 需要以下组件或工具
* Black = face-up, Blue = face-down * Visual Studio
* premake5
* libevent
* lua5.3
* sqlite3
* 可参考本项目 [appveyor.yml](https://github.com/mycard/ygopro/blob/server/appveyor.yml) 中的脚本
Xyz materials: ### MacOS下编译
* Black = default, Blue = the owner of the xyz material is different from its controller * 需要以下组件或工具
* clang
* premake5
* libevent
* lua5.3
* sqlite3
* 参考步骤
* 安装libevent sqlite3
* 编译premake5
* wget https://www.lua.org/ftp/lua-5.4.3.tar.gz && tar xf lua-5.4.3.tar.gz && mv lua-5.4.3 lua && cp premake/lua/* lua/
* ./premake5 gmake --cc=clang
* cd build && make config=release
### Sequence: ### 运行
* Monster Zone: 1~5, starting from the left hand side. * 使用[ygopro-server](https://github.com/mycard/ygopro-server)运行
* Spell & Trap Zone: 1~5, starting from the left hand side. * 手动运行的参数是
* Field Zone: 6 * `./ygopro 0 0 0 1 F F F 8000 5 1 180 0`
* Pendulum Zone: 0~1, starting from the left hand side. * 端口(0为随机)
* The others: 1~n, starting from the bottom. * 禁卡表编号
* 卡片允许
* 决斗模式
* 决斗规则编号
* 不检查卡组
* 不洗切卡组
* 初始LP
* 初始手牌数
* 每回合抽卡
* 每回合时间
* 录像保存模式
* 特殊选项,按位选择
* 0x1: 保存录像到 `./replay` 文件夹
* 0x2: 不向观战者发送录像
### Deck edit page: ### 特殊编译参数
* All numeric textboxs: They support >, =, <, >=, <= signs. 执行`premake5 gmake`之前,可以通过设置一些环境变量,来改变一些编译参数。
* Card name: Search card names and texts by default, $foo will only search foo in card names, and @foo will search cards of "foo" archetype(due to translation, card name contains "foo" does not mean that card is "foo" card). * `YGOPRO_DEFAULT_DUEL_RULE=X` 设置默认决斗规则为大师规则X。
* `YGOPRO_NO_LUA_SAFE` 若有定义,则开启默认禁用的`os``io`库。请慎用这个参数,确保运行的卡片脚本文件是可以信任的。
### Command-line options:
* `-e foo.cdb`: Load foo.cdb as the extra database.
* `-n nickname`: Set the nickname.
* `-h 192.168.0.2`: Set the host to join in LAN mode.
* `-p 7911`: Set the port to join in LAN mode.
* `-w abc`: Set the password to join in LAN mode.
* `-d`: Enter the deck edit page.
* `-d deck`: If used along with `-j` it mean select the deck, or it will open the deck to edit.
* `-c`: Create host with default settings.
* `-j`: Join the host specified in above, or if absent, lasthost in system.conf file.
* `-r`: Enter the replay mode page.
* `-r replay.yrp`: Load the replay.yrp in replay mode.
* `-s`: Enter the single mode page.
* `-s puzzle.lua`: Load the puzzle.lua in single mode.
* `-k`: Keep when duel finished. See below.
#### Note:
* `-c` `-j` `-e` `-r` `-s` shoule be the last parameter, because any parameters after it will get ignored.
* `-d` `-c` `-j` `-e` `-r` `-s` will make YGOPro automatically exit when the duel or deck editing is finished. This is useful for some launchers. If you want to keep it, add `-k` before them.
* `-d` `-r` `-s` support full path of file, or just filename. But remember deck filename should NOT have extension when replay and single filename MUST have extension.
### Directories:
* pics: .jpg card images(177*254).
* pics\thumbnail: .jpg thumbnail images(44*64).
* script: .lua script files.
* textures: Other image files.
* deck: .ydk deck files.
* replay: .yrp replay files.
* expansions: *.cdb will be loaded as extra databases.
\ No newline at end of file
version: '{build}'
image: Visual Studio 2019
skip_tags: true
install:
- git submodule update --init --recursive
# environment and system dependency
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/premake/premake-core/releases/download/v5.0.0-beta2/premake-5.0.0-beta2-windows.zip ; exit 0"
- 7z x premake-5.0.0-beta2-windows.zip
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/libevent-2.0.22-stable.tar.gz ; exit 0"
- tar xf libevent-2.0.22-stable.tar.gz
- move libevent-2.0.22-stable event
- xcopy /E event\WIN32-Code event\include
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://www.lua.org/ftp/lua-5.4.4.tar.gz ; exit 0"
- tar xf lua-5.4.4.tar.gz
- move lua-5.4.4 lua
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://www.sqlite.org/2024/sqlite-amalgamation-3470000.zip ; exit 0"
- 7z x sqlite-amalgamation-3470000.zip
- move sqlite-amalgamation-3470000 sqlite3
before_build:
- xcopy /E premake\* .
- premake5 vs2019
configuration: Release
build:
project: build/YGOPro.sln
parallel: true
after_build:
- ps: move bin\release\ygopro.exe .
# nodejs
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://nodejs.org/dist/v16.9.1/node-v16.9.1-win-x64.7z ; exit 0"
- 7z x -y node-v16.9.1-win-x64.7z
- mv node-v16.9.1-win-x64 node
# srvpro
- git clone https://github.com/purerosefallen/ygopro-server
- cd ygopro-server
- ../node/npm ci
- bash -c "curl --retry 5 --connect-timeout 30 --location --remote-header-name --remote-name https://github.com/purerosefallen/windbot/releases/download/latest/WindBot.7z ; exit 0"
- 7z x -y WindBot.7z
- rm -rf Bot.exe bot.conf
- mv WindBot windbot_
- mv windbot_ windbot # Windows NTFS does not support case sensitive, so renaming the folder twice.
- rm -rf WindBot.7z
- cp ../cards.cdb windbot/
- mkdir ygopro decks_save
- cp -rf ../ygopro.exe ygopro/
- mv ../cards.cdb ygopro/
- mv ../lflist.conf ygopro/
- mv ../script ygopro/
- cd ygopro
- mkdir gframe
- cp -rf ../../gframe/game.cpp gframe/ # Toss game.cpp in for version detection
# - cp -rf config_build config
- cd ../..
# start script
- bash -c "echo '@echo off' >> run.bat ; echo 'cd ygopro-server/windbot' >> run.bat ; echo 'start WindBot.exe servermode=true serverport=2399' >> run.bat ; echo 'cd ..' >> run.bat ; echo 'start ../node/node.exe ygopro-server.js' >> run.bat"
- 7z a -mx9 -xr!.git* ygopro-server-win.zip node ygopro-server run.bat
test: off
artifacts:
- path: ygopro.exe
name: ygopro server mode
- path: ygopro-server-win.zip
name: Windows version of SRVPro
deploy:
release: win
description: 'Automatic build commit $(APPVEYOR_REPO_COMMIT) $(APPVEYOR_REPO_COMMIT_TIMESTAMP)'
provider: GitHub
force_update: true
auth_token:
secure: EQ9miMjfX/QAoBvgc6D+JLmHatLyxOEKZ/uo68QijxWW5Gp4MzB/pOH9+u2GlDVO
on:
branch: server
cache:
- premake-5.0.0-beta2-windows.zip
- libevent-2.0.22-stable.tar.gz
- irrlicht-1.8.5.zip
- lua-5.4.4.tar.gz
- sqlite-amalgamation-3390300.zip
...@@ -10,6 +10,7 @@ namespace ygo { ...@@ -10,6 +10,7 @@ namespace ygo {
class ClientCard { class ClientCard {
public: public:
#ifndef YGOPRO_SERVER_MODE
irr::core::matrix4 mTransform; irr::core::matrix4 mTransform;
irr::core::vector3df curPos; irr::core::vector3df curPos;
irr::core::vector3df curRot; irr::core::vector3df curRot;
...@@ -80,6 +81,7 @@ public: ...@@ -80,6 +81,7 @@ public:
void ClearTarget(); void ClearTarget();
void ClearData(); void ClearData();
static bool client_card_sort(ClientCard* c1, ClientCard* c2); static bool client_card_sort(ClientCard* c1, ClientCard* c2);
#endif //YGOPRO_SERVER_MODE
}; };
} }
......
...@@ -78,6 +78,7 @@ inline FILE* myfopen(const wchar_t* filename, const char* mode) { ...@@ -78,6 +78,7 @@ inline FILE* myfopen(const wchar_t* filename, const char* mode) {
return fp; return fp;
} }
#ifndef YGOPRO_SERVER_MODE
#include <irrlicht.h> #include <irrlicht.h>
using namespace irr; using namespace irr;
using namespace core; using namespace core;
...@@ -85,6 +86,13 @@ using namespace scene; ...@@ -85,6 +86,13 @@ using namespace scene;
using namespace video; using namespace video;
using namespace io; using namespace io;
using namespace gui; using namespace gui;
#endif //YGOPRO_SERVER_MODE
#ifdef SERVER_ZIP_SUPPORT
#include <irrlicht.h>
using namespace irr;
using namespace io;
#endif
extern unsigned short PRO_VERSION; extern unsigned short PRO_VERSION;
extern unsigned int enable_log; extern unsigned int enable_log;
......
#include "data_manager.h" #include "data_manager.h"
#include "game.h" #include "game.h"
#include <stdio.h> #include <stdio.h>
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
#include "spmemvfs/spmemvfs.h" #include "spmemvfs/spmemvfs.h"
#endif
namespace ygo { namespace ygo {
const wchar_t* DataManager::unknown_string = L"???"; const wchar_t* DataManager::unknown_string = L"???";
unsigned char DataManager::scriptBuffer[0x100000] = {}; unsigned char DataManager::scriptBuffer[0x100000] = {};
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
irr::io::IFileSystem* DataManager::FileSystem = nullptr; irr::io::IFileSystem* DataManager::FileSystem = nullptr;
#endif
DataManager dataManager; DataManager dataManager;
DataManager::DataManager() : _datas(32768), _strings(32768) { DataManager::DataManager() : _datas(32768), _strings(32768) {
...@@ -15,10 +19,16 @@ DataManager::DataManager() : _datas(32768), _strings(32768) { ...@@ -15,10 +19,16 @@ DataManager::DataManager() : _datas(32768), _strings(32768) {
} }
bool DataManager::ReadDB(sqlite3* pDB) { bool DataManager::ReadDB(sqlite3* pDB) {
sqlite3_stmt* pStmt{}; sqlite3_stmt* pStmt{};
#ifdef YGOPRO_SERVER_MODE
const char* sql = "select * from datas";
#else
const char* sql = "select * from datas,texts where datas.id=texts.id"; const char* sql = "select * from datas,texts where datas.id=texts.id";
#endif
if (sqlite3_prepare_v2(pDB, sql, -1, &pStmt, 0) != SQLITE_OK) if (sqlite3_prepare_v2(pDB, sql, -1, &pStmt, 0) != SQLITE_OK)
return Error(pDB); return Error(pDB);
#ifndef YGOPRO_SERVER_MODE
wchar_t strBuffer[4096]; wchar_t strBuffer[4096];
#endif
int step = 0; int step = 0;
do { do {
CardDataC cd; CardDataC cd;
...@@ -60,6 +70,7 @@ bool DataManager::ReadDB(sqlite3* pDB) { ...@@ -60,6 +70,7 @@ bool DataManager::ReadDB(sqlite3* pDB) {
cd.attribute = sqlite3_column_int(pStmt, 9); cd.attribute = sqlite3_column_int(pStmt, 9);
cd.category = sqlite3_column_int(pStmt, 10); cd.category = sqlite3_column_int(pStmt, 10);
_datas[cd.code] = cd; _datas[cd.code] = cd;
#ifndef YGOPRO_SERVER_MODE
if (const char* text = (const char*)sqlite3_column_text(pStmt, 12)) { if (const char* text = (const char*)sqlite3_column_text(pStmt, 12)) {
BufferIO::DecodeUTF8(text, strBuffer); BufferIO::DecodeUTF8(text, strBuffer);
cs.name = strBuffer; cs.name = strBuffer;
...@@ -76,6 +87,7 @@ bool DataManager::ReadDB(sqlite3* pDB) { ...@@ -76,6 +87,7 @@ bool DataManager::ReadDB(sqlite3* pDB) {
} }
} }
_strings[cd.code] = cs; _strings[cd.code] = cs;
#endif //YGOPRO_SERVER_MODE
} }
} while (step != SQLITE_DONE); } while (step != SQLITE_DONE);
sqlite3_finalize(pStmt); sqlite3_finalize(pStmt);
...@@ -84,6 +96,15 @@ bool DataManager::ReadDB(sqlite3* pDB) { ...@@ -84,6 +96,15 @@ bool DataManager::ReadDB(sqlite3* pDB) {
bool DataManager::LoadDB(const wchar_t* wfile) { bool DataManager::LoadDB(const wchar_t* wfile) {
char file[256]; char file[256];
BufferIO::EncodeUTF8(wfile, file); BufferIO::EncodeUTF8(wfile, file);
#if defined(YGOPRO_SERVER_MODE) && !defined(SERVER_ZIP_SUPPORT)
bool ret{};
sqlite3* pDB{};
if (sqlite3_open_v2(file, &pDB, SQLITE_OPEN_READONLY, 0) != SQLITE_OK)
ret = Error(pDB);
else
ret = ReadDB(pDB);
sqlite3_close(pDB);
#else
#ifdef _WIN32 #ifdef _WIN32
IReadFile* reader = FileSystem->createAndOpenFile(wfile); IReadFile* reader = FileSystem->createAndOpenFile(wfile);
#else #else
...@@ -106,8 +127,10 @@ bool DataManager::LoadDB(const wchar_t* wfile) { ...@@ -106,8 +127,10 @@ bool DataManager::LoadDB(const wchar_t* wfile) {
ret = ReadDB(db.handle); ret = ReadDB(db.handle);
spmemvfs_close_db(&db); spmemvfs_close_db(&db);
spmemvfs_env_fini(); spmemvfs_env_fini();
#endif //YGOPRO_SERVER_MODE
return ret; return ret;
} }
#ifndef YGOPRO_SERVER_MODE
bool DataManager::LoadStrings(const char* file) { bool DataManager::LoadStrings(const char* file) {
FILE* fp = fopen(file, "r"); FILE* fp = fopen(file, "r");
if(!fp) if(!fp)
...@@ -165,6 +188,7 @@ void DataManager::ReadStringConfLine(const char* linebuf) { ...@@ -165,6 +188,7 @@ void DataManager::ReadStringConfLine(const char* linebuf) {
_setnameStrings[value] = strBuffer; _setnameStrings[value] = strBuffer;
} }
} }
#endif //YGOPRO_SERVER_MODE
bool DataManager::Error(sqlite3* pDB, sqlite3_stmt* pStmt) { bool DataManager::Error(sqlite3* pDB, sqlite3_stmt* pStmt) {
errmsg[0] = '\0'; errmsg[0] = '\0';
std::strncat(errmsg, sqlite3_errmsg(pDB), sizeof errmsg - 1); std::strncat(errmsg, sqlite3_errmsg(pDB), sizeof errmsg - 1);
...@@ -175,6 +199,7 @@ bool DataManager::Error(sqlite3* pDB, sqlite3_stmt* pStmt) { ...@@ -175,6 +199,7 @@ bool DataManager::Error(sqlite3* pDB, sqlite3_stmt* pStmt) {
code_pointer DataManager::GetCodePointer(unsigned int code) const { code_pointer DataManager::GetCodePointer(unsigned int code) const {
return _datas.find(code); return _datas.find(code);
} }
#ifndef YGOPRO_SERVER_MODE
string_pointer DataManager::GetStringPointer(unsigned int code) const { string_pointer DataManager::GetStringPointer(unsigned int code) const {
return _strings.find(code); return _strings.find(code);
} }
...@@ -190,6 +215,7 @@ string_pointer DataManager::strings_begin() const { ...@@ -190,6 +215,7 @@ string_pointer DataManager::strings_begin() const {
string_pointer DataManager::strings_end() const { string_pointer DataManager::strings_end() const {
return _strings.cend(); return _strings.cend();
} }
#endif //YGOPRO_SERVER_MODE
bool DataManager::GetData(unsigned int code, CardData* pData) const { bool DataManager::GetData(unsigned int code, CardData* pData) const {
auto cdit = _datas.find(code); auto cdit = _datas.find(code);
if(cdit == _datas.end()) if(cdit == _datas.end())
...@@ -199,6 +225,7 @@ bool DataManager::GetData(unsigned int code, CardData* pData) const { ...@@ -199,6 +225,7 @@ bool DataManager::GetData(unsigned int code, CardData* pData) const {
} }
return true; return true;
} }
#ifndef YGOPRO_SERVER_MODE
bool DataManager::GetString(unsigned int code, CardString* pStr) const { bool DataManager::GetString(unsigned int code, CardString* pStr) const {
auto csit = _strings.find(code); auto csit = _strings.find(code);
if(csit == _strings.end()) { if(csit == _strings.end()) {
...@@ -267,10 +294,12 @@ std::vector<unsigned int> DataManager::GetSetCodes(std::wstring setname) const { ...@@ -267,10 +294,12 @@ std::vector<unsigned int> DataManager::GetSetCodes(std::wstring setname) const {
std::vector<unsigned int> matchingCodes; std::vector<unsigned int> matchingCodes;
for(auto csit = _setnameStrings.begin(); csit != _setnameStrings.end(); ++csit) { for(auto csit = _setnameStrings.begin(); csit != _setnameStrings.end(); ++csit) {
auto xpos = csit->second.find_first_of(L'|');//setname|another setname or extra info auto xpos = csit->second.find_first_of(L'|');//setname|another setname or extra info
#ifndef YGOPRO_SERVER_MODE
if (mainGame->CheckRegEx(csit->second, setname, true)) { if (mainGame->CheckRegEx(csit->second, setname, true)) {
matchingCodes.push_back(csit->first); matchingCodes.push_back(csit->first);
} } else
else if(setname.size() < 2) { #endif
if(setname.size() < 2) {
if(csit->second.compare(0, xpos, setname) == 0 if(csit->second.compare(0, xpos, setname) == 0
|| csit->second.compare(xpos + 1, csit->second.length(), setname) == 0) || csit->second.compare(xpos + 1, csit->second.length(), setname) == 0)
matchingCodes.push_back(csit->first); matchingCodes.push_back(csit->first);
...@@ -387,6 +416,7 @@ std::wstring DataManager::FormatLinkMarker(unsigned int link_marker) const { ...@@ -387,6 +416,7 @@ std::wstring DataManager::FormatLinkMarker(unsigned int link_marker) const {
buffer.append(L"[\u2198]"); buffer.append(L"[\u2198]");
return buffer; return buffer;
} }
#endif //YGOPRO_SERVER_MODE
uint32_t DataManager::CardReader(uint32_t code, card_data* pData) { uint32_t DataManager::CardReader(uint32_t code, card_data* pData) {
if (!dataManager.GetData(code, pData)) if (!dataManager.GetData(code, pData))
pData->clear(); pData->clear();
...@@ -396,30 +426,37 @@ unsigned char* DataManager::ScriptReaderEx(const char* script_name, int* slen) { ...@@ -396,30 +426,37 @@ unsigned char* DataManager::ScriptReaderEx(const char* script_name, int* slen) {
if (std::strncmp(script_name, "./script", 8) != 0) if (std::strncmp(script_name, "./script", 8) != 0)
return ReadScriptFromFile(script_name, slen); return ReadScriptFromFile(script_name, slen);
unsigned char* buffer; unsigned char* buffer;
#ifndef YGOPRO_SERVER_MODE
if(!mainGame->gameConf.prefer_expansion_script) { if(!mainGame->gameConf.prefer_expansion_script) {
buffer = ScriptReaderExSingle("", script_name, slen); buffer = ScriptReaderExSingle("", script_name, slen);
if(buffer) if(buffer)
return buffer; return buffer;
} }
#endif //YGOPRO_SERVER_MODE
buffer = ScriptReaderExSingle("specials/", script_name, slen, 9); buffer = ScriptReaderExSingle("specials/", script_name, slen, 9);
if(buffer) if(buffer)
return buffer; return buffer;
buffer = ScriptReaderExSingle("expansions/", script_name, slen); buffer = ScriptReaderExSingle("expansions/", script_name, slen);
if(buffer) if(buffer)
return buffer; return buffer;
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
buffer = ScriptReaderExSingle("", script_name, slen, 2, TRUE); buffer = ScriptReaderExSingle("", script_name, slen, 2, TRUE);
if(buffer) if(buffer)
return buffer; return buffer;
#endif
return ScriptReaderExSingle("", script_name, slen); return ScriptReaderExSingle("", script_name, slen);
} }
unsigned char* DataManager::ScriptReaderExSingle(const char* path, const char* script_name, int* slen, int pre_len, unsigned int use_irr) { unsigned char* DataManager::ScriptReaderExSingle(const char* path, const char* script_name, int* slen, int pre_len, unsigned int use_irr) {
char sname[256]; char sname[256];
snprintf(sname, sizeof sname, "%s%s", path, script_name + pre_len); //default script name: ./script/c%d.lua snprintf(sname, sizeof sname, "%s%s", path, script_name + pre_len); //default script name: ./script/c%d.lua
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
if (use_irr) { if (use_irr) {
return ReadScriptFromIrrFS(sname, slen); return ReadScriptFromIrrFS(sname, slen);
} }
#endif
return ReadScriptFromFile(sname, slen); return ReadScriptFromFile(sname, slen);
} }
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
unsigned char* DataManager::ReadScriptFromIrrFS(const char* script_name, int* slen) { unsigned char* DataManager::ReadScriptFromIrrFS(const char* script_name, int* slen) {
#ifdef _WIN32 #ifdef _WIN32
wchar_t fname[256]{}; wchar_t fname[256]{};
...@@ -437,6 +474,7 @@ unsigned char* DataManager::ReadScriptFromIrrFS(const char* script_name, int* sl ...@@ -437,6 +474,7 @@ unsigned char* DataManager::ReadScriptFromIrrFS(const char* script_name, int* sl
*slen = size; *slen = size;
return scriptBuffer; return scriptBuffer;
} }
#endif
unsigned char* DataManager::ReadScriptFromFile(const char* script_name, int* slen) { unsigned char* DataManager::ReadScriptFromFile(const char* script_name, int* slen) {
wchar_t fname[256]{}; wchar_t fname[256]{};
BufferIO::DecodeUTF8(script_name, fname); BufferIO::DecodeUTF8(script_name, fname);
...@@ -450,6 +488,7 @@ unsigned char* DataManager::ReadScriptFromFile(const char* script_name, int* sle ...@@ -450,6 +488,7 @@ unsigned char* DataManager::ReadScriptFromFile(const char* script_name, int* sle
*slen = (int)len; *slen = (int)len;
return scriptBuffer; return scriptBuffer;
} }
#ifndef YGOPRO_SERVER_MODE
bool DataManager::deck_sort_lv(code_pointer p1, code_pointer p2) { bool DataManager::deck_sort_lv(code_pointer p1, code_pointer p2) {
if ((p1->second.type & 0x7) != (p2->second.type & 0x7)) if ((p1->second.type & 0x7) != (p2->second.type & 0x7))
return (p1->second.type & 0x7) < (p2->second.type & 0x7); return (p1->second.type & 0x7) < (p2->second.type & 0x7);
...@@ -518,5 +557,6 @@ bool DataManager::deck_sort_name(code_pointer p1, code_pointer p2) { ...@@ -518,5 +557,6 @@ bool DataManager::deck_sort_name(code_pointer p1, code_pointer p2) {
return res < 0; return res < 0;
return p1->first < p2->first; return p1->first < p2->first;
} }
#endif //YGOPRO_SERVER_MODE
} }
...@@ -45,18 +45,23 @@ public: ...@@ -45,18 +45,23 @@ public:
DataManager(); DataManager();
bool ReadDB(sqlite3* pDB); bool ReadDB(sqlite3* pDB);
bool LoadDB(const wchar_t* wfile); bool LoadDB(const wchar_t* wfile);
#ifndef YGOPRO_SERVER_MODE
bool LoadStrings(const char* file); bool LoadStrings(const char* file);
bool LoadStrings(irr::io::IReadFile* reader); bool LoadStrings(irr::io::IReadFile* reader);
void ReadStringConfLine(const char* linebuf); void ReadStringConfLine(const char* linebuf);
#endif
bool Error(sqlite3* pDB, sqlite3_stmt* pStmt = nullptr); bool Error(sqlite3* pDB, sqlite3_stmt* pStmt = nullptr);
code_pointer GetCodePointer(unsigned int code) const; code_pointer GetCodePointer(unsigned int code) const;
#ifndef YGOPRO_SERVER_MODE
string_pointer GetStringPointer(unsigned int code) const; string_pointer GetStringPointer(unsigned int code) const;
code_pointer datas_begin() const; code_pointer datas_begin() const;
code_pointer datas_end() const; code_pointer datas_end() const;
string_pointer strings_begin() const; string_pointer strings_begin() const;
string_pointer strings_end() const; string_pointer strings_end() const;
#endif
bool GetData(unsigned int code, CardData* pData) const; bool GetData(unsigned int code, CardData* pData) const;
#ifndef YGOPRO_SERVER_MODE
bool GetString(unsigned int code, CardString* pStr) const; bool GetString(unsigned int code, CardString* pStr) const;
const wchar_t* GetName(unsigned int code) const; const wchar_t* GetName(unsigned int code) const;
const wchar_t* GetText(unsigned int code) const; const wchar_t* GetText(unsigned int code) const;
...@@ -78,6 +83,7 @@ public: ...@@ -78,6 +83,7 @@ public:
std::unordered_map<unsigned int, std::wstring> _victoryStrings; std::unordered_map<unsigned int, std::wstring> _victoryStrings;
std::unordered_map<unsigned int, std::wstring> _setnameStrings; std::unordered_map<unsigned int, std::wstring> _setnameStrings;
std::unordered_map<unsigned int, std::wstring> _sysStrings; std::unordered_map<unsigned int, std::wstring> _sysStrings;
#endif
char errmsg[512]{}; char errmsg[512]{};
static unsigned char scriptBuffer[0x100000]; static unsigned char scriptBuffer[0x100000];
...@@ -85,13 +91,24 @@ public: ...@@ -85,13 +91,24 @@ public:
static uint32_t CardReader(uint32_t, card_data*); static uint32_t CardReader(uint32_t, card_data*);
static unsigned char* ScriptReaderEx(const char* script_name, int* slen); static unsigned char* ScriptReaderEx(const char* script_name, int* slen);
static unsigned char* ScriptReaderExSingle(const char* path, const char* script_name, int* slen, int pre_len = 2, unsigned int use_irr = FALSE); static unsigned char* ScriptReaderExSingle(const char* path, const char* script_name, int* slen, int pre_len = 2, unsigned int use_irr = FALSE);
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
//read by IFileSystem //read by IFileSystem
static unsigned char* ReadScriptFromIrrFS(const char* script_name, int* slen); static unsigned char* ReadScriptFromIrrFS(const char* script_name, int* slen);
#endif
//read by fread //read by fread
static unsigned char* ReadScriptFromFile(const char* script_name, int* slen); static unsigned char* ReadScriptFromFile(const char* script_name, int* slen);
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_ZIP_SUPPORT)
static irr::io::IFileSystem* FileSystem; static irr::io::IFileSystem* FileSystem;
#endif
#ifndef YGOPRO_SERVER_MODE
static bool deck_sort_lv(code_pointer l1, code_pointer l2);
static bool deck_sort_atk(code_pointer l1, code_pointer l2);
static bool deck_sort_def(code_pointer l1, code_pointer l2);
static bool deck_sort_name(code_pointer l1, code_pointer l2);
#endif
static bool deck_sort_lv(code_pointer l1, code_pointer l2); static bool deck_sort_lv(code_pointer l1, code_pointer l2);
static bool deck_sort_atk(code_pointer l1, code_pointer l2); static bool deck_sort_atk(code_pointer l1, code_pointer l2);
......
...@@ -6,7 +6,9 @@ ...@@ -6,7 +6,9 @@
namespace ygo { namespace ygo {
#ifndef YGOPRO_SERVER_MODE
char DeckManager::deckBuffer[0x10000]{}; char DeckManager::deckBuffer[0x10000]{};
#endif
DeckManager deckManager; DeckManager deckManager;
void DeckManager::LoadLFListSingle(const char* path) { void DeckManager::LoadLFListSingle(const char* path) {
...@@ -50,6 +52,9 @@ void DeckManager::LoadLFListSingle(const char* path) { ...@@ -50,6 +52,9 @@ void DeckManager::LoadLFListSingle(const char* path) {
} }
} }
void DeckManager::LoadLFList() { void DeckManager::LoadLFList() {
#ifdef SERVER_PRO2_SUPPORT
LoadLFListSingle("config/lflist.conf");
#endif
LoadLFListSingle("expansions/lflist.conf"); LoadLFListSingle("expansions/lflist.conf");
LoadLFListSingle("lflist.conf"); LoadLFListSingle("lflist.conf");
LFList nolimit; LFList nolimit;
...@@ -190,6 +195,7 @@ int DeckManager::LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec, bool is_p ...@@ -190,6 +195,7 @@ int DeckManager::LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec, bool is_p
} }
return errorcode; return errorcode;
} }
#ifndef YGOPRO_SERVER_MODE
int DeckManager::LoadDeck(Deck& deck, std::istringstream& deckStream, bool is_packlist) { int DeckManager::LoadDeck(Deck& deck, std::istringstream& deckStream, bool is_packlist) {
int ct = 0, mainc = 0, sidec = 0, code = 0; int ct = 0, mainc = 0, sidec = 0, code = 0;
int cardlist[PACK_MAX_SIZE]{}; int cardlist[PACK_MAX_SIZE]{};
...@@ -211,6 +217,7 @@ int DeckManager::LoadDeck(Deck& deck, std::istringstream& deckStream, bool is_pa ...@@ -211,6 +217,7 @@ int DeckManager::LoadDeck(Deck& deck, std::istringstream& deckStream, bool is_pa
} }
return LoadDeck(current_deck, cardlist, mainc, sidec, is_packlist); return LoadDeck(current_deck, cardlist, mainc, sidec, is_packlist);
} }
#endif
bool DeckManager::LoadSide(Deck& deck, int* dbuf, int mainc, int sidec) { bool DeckManager::LoadSide(Deck& deck, int* dbuf, int mainc, int sidec) {
std::unordered_map<int, int> pcount; std::unordered_map<int, int> pcount;
std::unordered_map<int, int> ncount; std::unordered_map<int, int> ncount;
...@@ -240,6 +247,7 @@ bool DeckManager::LoadSide(Deck& deck, int* dbuf, int mainc, int sidec) { ...@@ -240,6 +247,7 @@ bool DeckManager::LoadSide(Deck& deck, int* dbuf, int mainc, int sidec) {
deck = ndeck; deck = ndeck;
return true; return true;
} }
#ifndef YGOPRO_SERVER_MODE
void DeckManager::GetCategoryPath(wchar_t* ret, int index, const wchar_t* text) { void DeckManager::GetCategoryPath(wchar_t* ret, int index, const wchar_t* text) {
wchar_t catepath[256]; wchar_t catepath[256];
switch(index) { switch(index) {
...@@ -441,4 +449,5 @@ bool DeckManager::SaveDeckBuffer(const int deckbuf[], const wchar_t* name) { ...@@ -441,4 +449,5 @@ bool DeckManager::SaveDeckBuffer(const int deckbuf[], const wchar_t* name) {
fclose(fp); fclose(fp);
return true; return true;
} }
#endif //YGOPRO_SERVER_MODE
} }
...@@ -57,7 +57,9 @@ public: ...@@ -57,7 +57,9 @@ public:
Deck current_deck; Deck current_deck;
std::vector<LFList> _lfList; std::vector<LFList> _lfList;
#ifndef YGOPRO_SERVER_MODE
static char deckBuffer[0x10000]; static char deckBuffer[0x10000];
#endif
void LoadLFListSingle(const char* path); void LoadLFListSingle(const char* path);
void LoadLFList(); void LoadLFList();
...@@ -65,8 +67,9 @@ public: ...@@ -65,8 +67,9 @@ public:
const std::unordered_map<int, int>* GetLFListContent(int lfhash); const std::unordered_map<int, int>* GetLFListContent(int lfhash);
unsigned int CheckDeck(Deck& deck, int lfhash, int rule); unsigned int CheckDeck(Deck& deck, int lfhash, int rule);
int LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec, bool is_packlist = false); int LoadDeck(Deck& deck, int* dbuf, int mainc, int sidec, bool is_packlist = false);
int LoadDeck(Deck& deck, std::istringstream& deckStream, bool is_packlist = false);
bool LoadSide(Deck& deck, int* dbuf, int mainc, int sidec); bool LoadSide(Deck& deck, int* dbuf, int mainc, int sidec);
#ifndef YGOPRO_SERVER_MODE
int LoadDeck(Deck& deck, std::istringstream& deckStream, bool is_packlist = false);
void GetCategoryPath(wchar_t* ret, int index, const wchar_t* text); void GetCategoryPath(wchar_t* ret, int index, const wchar_t* text);
void GetDeckFile(wchar_t* ret, irr::gui::IGUIComboBox* cbCategory, irr::gui::IGUIComboBox* cbDeck); void GetDeckFile(wchar_t* ret, irr::gui::IGUIComboBox* cbCategory, irr::gui::IGUIComboBox* cbDeck);
FILE* OpenDeckFile(const wchar_t* file, const char* mode); FILE* OpenDeckFile(const wchar_t* file, const char* mode);
...@@ -83,10 +86,31 @@ public: ...@@ -83,10 +86,31 @@ public:
bool RenameCategory(const wchar_t* oldname, const wchar_t* newname); bool RenameCategory(const wchar_t* oldname, const wchar_t* newname);
bool DeleteCategory(const wchar_t* name); bool DeleteCategory(const wchar_t* name);
bool SaveDeckBuffer(const int deckbuf[], const wchar_t* name); bool SaveDeckBuffer(const int deckbuf[], const wchar_t* name);
#endif //YGOPRO_SERVER_MODE
}; };
extern DeckManager deckManager; extern DeckManager deckManager;
} }
#ifdef YGOPRO_SERVER_MODE
#ifndef DECKCOUNT_MAIN_MIN
#define DECKCOUNT_MAIN_MIN 40
#endif
#ifndef DECKCOUNT_MAIN_MAX
#define DECKCOUNT_MAIN_MAX 60
#endif
#ifndef DECKCOUNT_SIDE
#define DECKCOUNT_SIDE 15
#endif
#ifndef DECKCOUNT_EXTRA
#define DECKCOUNT_EXTRA 15
#endif
#endif //YGOPRO_SERVER_MODE
#endif //DECKMANAGER_H #endif //DECKMANAGER_H
...@@ -364,7 +364,6 @@ bool ClientField::OnEvent(const irr::SEvent& event) { ...@@ -364,7 +364,6 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
if(sel == -1) if(sel == -1)
break; break;
DuelClient::SetResponseI(ancard[sel]); DuelClient::SetResponseI(ancard[sel]);
mainGame->dInfo.announce_cache.insert(mainGame->dInfo.announce_cache.begin(), ancard[sel]);
mainGame->HideElement(mainGame->wANCard, true); mainGame->HideElement(mainGame->wANCard, true);
break; break;
} }
......
#include "config.h" #include "config.h"
#include "game.h" #include "game.h"
#include "myfilesystem.h" #ifdef YGOPRO_SERVER_MODE
#include "data_manager.h"
#include "deck_manager.h"
#include "replay.h"
#ifdef SERVER_ZIP_SUPPORT
#include "CFileSystem.h"
namespace irr {
namespace core {
// taken from Irrlicht.cpp beacuse that file is not included
irr::core::stringc LOCALE_DECIMAL_POINTS(".");
}
}
#endif
#else
#include "image_manager.h" #include "image_manager.h"
#include "data_manager.h" #include "data_manager.h"
#include "deck_manager.h" #include "deck_manager.h"
...@@ -12,7 +25,9 @@ ...@@ -12,7 +25,9 @@
#include "single_mode.h" #include "single_mode.h"
#include <sstream> #include <sstream>
#include <regex> #include <regex>
#endif //YGOPRO_SERVER_MODE
#include <thread> #include <thread>
#include "myfilesystem.h"
unsigned short PRO_VERSION = 0x1361; unsigned short PRO_VERSION = 0x1361;
...@@ -20,6 +35,7 @@ namespace ygo { ...@@ -20,6 +35,7 @@ namespace ygo {
Game* mainGame; Game* mainGame;
#ifndef YGOPRO_SERVER_MODE
void DuelInfo::Clear() { void DuelInfo::Clear() {
isStarted = false; isStarted = false;
isInDuel = false; isInDuel = false;
...@@ -65,6 +81,7 @@ void DuelInfo::Clear() { ...@@ -65,6 +81,7 @@ void DuelInfo::Clear() {
total_attack_color[1] = 0; total_attack_color[1] = 0;
announce_cache.clear(); announce_cache.clear();
} }
#endif
bool IsExtension(const wchar_t* filename, const wchar_t* extension) { bool IsExtension(const wchar_t* filename, const wchar_t* extension) {
auto flen = std::wcslen(filename); auto flen = std::wcslen(filename);
...@@ -74,6 +91,41 @@ bool IsExtension(const wchar_t* filename, const wchar_t* extension) { ...@@ -74,6 +91,41 @@ bool IsExtension(const wchar_t* filename, const wchar_t* extension) {
return !mywcsncasecmp(filename + (flen - elen), extension, elen); return !mywcsncasecmp(filename + (flen - elen), extension, elen);
} }
#ifdef YGOPRO_SERVER_MODE
unsigned short server_port;
unsigned short replay_mode;
unsigned int pre_seed[3];
HostInfo game_info;
void Game::MainServerLoop() {
#ifdef SERVER_ZIP_SUPPORT
DataManager::FileSystem = new irr::io::CFileSystem();
#endif
initUtils();
deckManager.LoadLFList();
dataManager.LoadDB(L"cards.cdb");
LoadExpansions();
#ifdef SERVER_PRO2_SUPPORT
DataManager::FileSystem->addFileArchive("data/script.zip", true, false, EFAT_ZIP);
#endif
server_port = NetServer::StartServer(server_port);
NetServer::InitDuel();
printf("%u\n", server_port);
fflush(stdout);
while(NetServer::net_evbase) {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
void Game::MainTestLoop(int code) {
LoadExpansions();
dataManager.LoadDB(L"cards.cdb");
fflush(stdout);
NetServer::InitTestCard(code);
}
#else //YGOPRO_SERVER_MODE
bool Game::Initialize() { bool Game::Initialize() {
initUtils(); initUtils();
LoadConfig(); LoadConfig();
...@@ -1252,7 +1304,17 @@ std::wstring Game::SetStaticText(irr::gui::IGUIStaticText* pControl, u32 cWidth, ...@@ -1252,7 +1304,17 @@ std::wstring Game::SetStaticText(irr::gui::IGUIStaticText* pControl, u32 cWidth,
ret.assign(strBuffer); ret.assign(strBuffer);
return ret; return ret;
} }
#endif //YGOPRO_SERVER_MODE
void Game::LoadExpansions() { void Game::LoadExpansions() {
#ifdef SERVER_PRO2_SUPPORT
FileSystem::TraversalDir(L"./cdb", [](const wchar_t* name, bool isdir) {
wchar_t fpath[1024];
myswprintf(fpath, L"./cdb/%ls", name);
if(!isdir && IsExtension(name, L".cdb")) {
dataManager.LoadDB(fpath);
}
});
#endif // SERVER_PRO2_SUPPORT
FileSystem::TraversalDir(L"./expansions", [](const wchar_t* name, bool isdir) { FileSystem::TraversalDir(L"./expansions", [](const wchar_t* name, bool isdir) {
wchar_t fpath[1024]; wchar_t fpath[1024];
myswprintf(fpath, L"./expansions/%ls", name); myswprintf(fpath, L"./expansions/%ls", name);
...@@ -1260,12 +1322,15 @@ void Game::LoadExpansions() { ...@@ -1260,12 +1322,15 @@ void Game::LoadExpansions() {
dataManager.LoadDB(fpath); dataManager.LoadDB(fpath);
return; return;
} }
#ifndef YGOPRO_SERVER_MODE
if (!isdir && IsExtension(name, L".conf")) { if (!isdir && IsExtension(name, L".conf")) {
char upath[1024]; char upath[1024];
BufferIO::EncodeUTF8(fpath, upath); BufferIO::EncodeUTF8(fpath, upath);
dataManager.LoadStrings(upath); dataManager.LoadStrings(upath);
return; return;
} }
#endif // YGOPRO_SERVER_MODE
#if defined(SERVER_ZIP_SUPPORT) || !defined(YGOPRO_SERVER_MODE)
if (!isdir && (IsExtension(name, L".zip") || IsExtension(name, L".ypk"))) { if (!isdir && (IsExtension(name, L".zip") || IsExtension(name, L".ypk"))) {
#ifdef _WIN32 #ifdef _WIN32
DataManager::FileSystem->addFileArchive(fpath, true, false, EFAT_ZIP); DataManager::FileSystem->addFileArchive(fpath, true, false, EFAT_ZIP);
...@@ -1276,7 +1341,9 @@ void Game::LoadExpansions() { ...@@ -1276,7 +1341,9 @@ void Game::LoadExpansions() {
#endif #endif
return; return;
} }
#endif //SERVER_ZIP_SUPPORT
}); });
#if defined(SERVER_ZIP_SUPPORT) || !defined(YGOPRO_SERVER_MODE)
for(u32 i = 0; i < DataManager::FileSystem->getFileArchiveCount(); ++i) { for(u32 i = 0; i < DataManager::FileSystem->getFileArchiveCount(); ++i) {
const IFileList* archive = DataManager::FileSystem->getFileArchive(i)->getFileList(); const IFileList* archive = DataManager::FileSystem->getFileArchive(i)->getFileList();
for(u32 j = 0; j < archive->getFileCount(); ++j) { for(u32 j = 0; j < archive->getFileCount(); ++j) {
...@@ -1291,6 +1358,7 @@ void Game::LoadExpansions() { ...@@ -1291,6 +1358,7 @@ void Game::LoadExpansions() {
dataManager.LoadDB(fname); dataManager.LoadDB(fname);
continue; continue;
} }
#ifndef YGOPRO_SERVER_MODE
if (IsExtension(fname, L".conf")) { if (IsExtension(fname, L".conf")) {
#ifdef _WIN32 #ifdef _WIN32
IReadFile* reader = DataManager::FileSystem->createAndOpenFile(fname); IReadFile* reader = DataManager::FileSystem->createAndOpenFile(fname);
...@@ -1304,9 +1372,12 @@ void Game::LoadExpansions() { ...@@ -1304,9 +1372,12 @@ void Game::LoadExpansions() {
deckBuilder.expansionPacks.push_back(fname); deckBuilder.expansionPacks.push_back(fname);
continue; continue;
} }
#endif // YGOPRO_SERVER_MODE
} }
} }
#endif //SERVER_ZIP_SUPPORT
} }
#ifndef YGOPRO_SERVER_MODE
void Game::RefreshCategoryDeck(irr::gui::IGUIComboBox* cbCategory, irr::gui::IGUIComboBox* cbDeck, bool selectlastused) { void Game::RefreshCategoryDeck(irr::gui::IGUIComboBox* cbCategory, irr::gui::IGUIComboBox* cbDeck, bool selectlastused) {
cbCategory->clear(); cbCategory->clear();
cbCategory->addItem(dataManager.GetSysString(1450)); cbCategory->addItem(dataManager.GetSysString(1450));
...@@ -1990,7 +2061,11 @@ void Game::ClearChatMsg() { ...@@ -1990,7 +2061,11 @@ void Game::ClearChatMsg() {
chatTiming[i] = 0; chatTiming[i] = 0;
} }
} }
#endif //YGOPRO_SERVER_MODE
void Game::AddDebugMsg(const char* msg) { void Game::AddDebugMsg(const char* msg) {
#ifdef YGOPRO_SERVER_MODE
fprintf(stderr, "%s\n", msg);
#else
if (enable_log & 0x1) { if (enable_log & 0x1) {
wchar_t wbuf[1024]; wchar_t wbuf[1024];
BufferIO::DecodeUTF8(msg, wbuf); BufferIO::DecodeUTF8(msg, wbuf);
...@@ -2001,7 +2076,9 @@ void Game::AddDebugMsg(const char* msg) { ...@@ -2001,7 +2076,9 @@ void Game::AddDebugMsg(const char* msg) {
snprintf(msgbuf, sizeof msgbuf, "[Script Error]: %s", msg); snprintf(msgbuf, sizeof msgbuf, "[Script Error]: %s", msg);
ErrorLog(msgbuf); ErrorLog(msgbuf);
} }
#endif //YGOPRO_SERVER_MODE
} }
#ifndef YGOPRO_SERVER_MODE
void Game::ErrorLog(const char* msg) { void Game::ErrorLog(const char* msg) {
FILE* fp = fopen("error.log", "at"); FILE* fp = fopen("error.log", "at");
if(!fp) if(!fp)
...@@ -2013,12 +2090,17 @@ void Game::ErrorLog(const char* msg) { ...@@ -2013,12 +2090,17 @@ void Game::ErrorLog(const char* msg) {
fprintf(fp, "[%s]%s\n", timebuf, msg); fprintf(fp, "[%s]%s\n", timebuf, msg);
fclose(fp); fclose(fp);
} }
#endif //YGOPRO_SERVER_MODE
void Game::initUtils() { void Game::initUtils() {
//user files //user files
FileSystem::MakeDir("replay"); FileSystem::MakeDir("replay");
FileSystem::MakeDir("screenshots");
//cards from extra pack //cards from extra pack
FileSystem::MakeDir("expansions"); FileSystem::MakeDir("expansions");
#ifdef YGOPRO_SERVER_MODE
//special scripts
FileSystem::MakeDir("specials");
#else
FileSystem::MakeDir("screenshots");
//files in ygopro-starter-pack //files in ygopro-starter-pack
FileSystem::MakeDir("deck"); FileSystem::MakeDir("deck");
FileSystem::MakeDir("single"); FileSystem::MakeDir("single");
...@@ -2055,7 +2137,9 @@ void Game::initUtils() { ...@@ -2055,7 +2137,9 @@ void Game::initUtils() {
//pics //pics
FileSystem::MakeDir("pics"); FileSystem::MakeDir("pics");
FileSystem::MakeDir("pics/field"); FileSystem::MakeDir("pics/field");
#endif //YGOPRO_SERVER_MODE
} }
#ifndef YGOPRO_SERVER_MODE
void Game::ClearTextures() { void Game::ClearTextures() {
matManager.mCard.setTexture(0, 0); matManager.mCard.setTexture(0, 0);
ClearCardInfo(0); ClearCardInfo(0);
...@@ -2537,5 +2621,6 @@ void Game::SetCursor(ECURSOR_ICON icon) { ...@@ -2537,5 +2621,6 @@ void Game::SetCursor(ECURSOR_ICON icon) {
cursor->setActiveIcon(icon); cursor->setActiveIcon(icon);
} }
} }
#endif //YGOPRO_SERVER_MODE
} }
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define GAME_H #define GAME_H
#include "config.h" #include "config.h"
#ifndef YGOPRO_SERVER_MODE
#ifdef __APPLE__ #ifdef __APPLE__
#include <OpenGL/gl.h> #include <OpenGL/gl.h>
#include <OpenGL/glu.h> #include <OpenGL/glu.h>
...@@ -16,6 +17,9 @@ ...@@ -16,6 +17,9 @@
#include "deck_con.h" #include "deck_con.h"
#include "menu_handler.h" #include "menu_handler.h"
#include "CGUISkinSystem/CGUISkinSystem.h" #include "CGUISkinSystem/CGUISkinSystem.h"
#else
#include "netserver.h"
#endif //YGOPRO_SERVER_MODE
#include <time.h> #include <time.h>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
...@@ -26,6 +30,8 @@ ...@@ -26,6 +30,8 @@
#ifndef YGOPRO_DEFAULT_DUEL_RULE #ifndef YGOPRO_DEFAULT_DUEL_RULE
#define YGOPRO_DEFAULT_DUEL_RULE 5 #define YGOPRO_DEFAULT_DUEL_RULE 5
#endif #endif
#define DEFAULT_DUEL_RULE YGOPRO_DEFAULT_DUEL_RULE
constexpr int CONFIG_LINE_SIZE = 1024; constexpr int CONFIG_LINE_SIZE = 1024;
constexpr int TEXT_LINE_SIZE = 256; constexpr int TEXT_LINE_SIZE = 256;
...@@ -33,6 +39,7 @@ namespace ygo { ...@@ -33,6 +39,7 @@ namespace ygo {
bool IsExtension(const wchar_t* filename, const wchar_t* extension); bool IsExtension(const wchar_t* filename, const wchar_t* extension);
#ifndef YGOPRO_SERVER_MODE
struct Config { struct Config {
bool use_d3d{ false }; bool use_d3d{ false };
bool use_image_scale{ true }; bool use_image_scale{ true };
...@@ -155,11 +162,19 @@ struct FadingUnit { ...@@ -155,11 +162,19 @@ struct FadingUnit {
irr::core::vector2di fadingLR; irr::core::vector2di fadingLR;
irr::core::vector2di fadingDiff; irr::core::vector2di fadingDiff;
}; };
#endif //YGOPRO_SERVER_MODE
class Game { class Game {
public: public:
bool Initialize(); bool Initialize();
#ifdef YGOPRO_SERVER_MODE
void MainServerLoop();
void MainTestLoop(int code);
void LoadExpansions();
void AddDebugMsg(const char* msgbuf);
void initUtils();
#else
void MainLoop(); void MainLoop();
void RefreshTimeDisplay(); void RefreshTimeDisplay();
void BuildProjectionMatrix(irr::core::matrix4& mProjection, f32 left, f32 right, f32 bottom, f32 top, f32 znear, f32 zfar); void BuildProjectionMatrix(irr::core::matrix4& mProjection, f32 left, f32 right, f32 bottom, f32 top, f32 znear, f32 zfar);
...@@ -664,13 +679,24 @@ public: ...@@ -664,13 +679,24 @@ public:
irr::gui::IGUIButton* btnBigCardZoomIn; irr::gui::IGUIButton* btnBigCardZoomIn;
irr::gui::IGUIButton* btnBigCardZoomOut; irr::gui::IGUIButton* btnBigCardZoomOut;
irr::gui::IGUIButton* btnBigCardClose; irr::gui::IGUIButton* btnBigCardClose;
#endif //YGOPRO_SERVER_MODE
}; };
extern Game* mainGame; extern Game* mainGame;
#ifdef YGOPRO_SERVER_MODE
extern unsigned short server_port;
extern unsigned short replay_mode;
extern HostInfo game_info;
extern unsigned int pre_seed[3];
#endif
} }
#ifdef YGOPRO_SERVER_MODE
#define SIZE_QUERY_BUFFER 0x40000
#else
#define SIZE_QUERY_BUFFER 0x4000 #define SIZE_QUERY_BUFFER 0x4000
#endif
#define CARD_IMG_WIDTH 177 #define CARD_IMG_WIDTH 177
#define CARD_IMG_HEIGHT 254 #define CARD_IMG_HEIGHT 254
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#endif #endif
unsigned int enable_log = 0x3; unsigned int enable_log = 0x3;
#ifndef YGOPRO_SERVER_MODE
bool exit_on_return = false; bool exit_on_return = false;
bool auto_watch_mode = false; bool auto_watch_mode = false;
bool open_file = false; bool open_file = false;
...@@ -23,12 +24,13 @@ void ClickButton(irr::gui::IGUIElement* btn) { ...@@ -23,12 +24,13 @@ void ClickButton(irr::gui::IGUIElement* btn) {
event.GUIEvent.Caller = btn; event.GUIEvent.Caller = btn;
ygo::mainGame->device->postEventFromUser(event); ygo::mainGame->device->postEventFromUser(event);
} }
#endif //YGOPRO_SERVER_MODE
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
#ifndef _WIN32 #ifndef _WIN32
setlocale(LC_CTYPE, "UTF-8"); setlocale(LC_CTYPE, "UTF-8");
#endif #endif
#ifdef __APPLE__ #if defined __APPLE__ && !defined YGOPRO_SERVER_MODE
CFURLRef bundle_url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); CFURLRef bundle_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
CFURLRef bundle_base_url = CFURLCreateCopyDeletingLastPathComponent(nullptr, bundle_url); CFURLRef bundle_base_url = CFURLCreateCopyDeletingLastPathComponent(nullptr, bundle_url);
CFRelease(bundle_url); CFRelease(bundle_url);
...@@ -60,6 +62,72 @@ int main(int argc, char* argv[]) { ...@@ -60,6 +62,72 @@ int main(int argc, char* argv[]) {
evthread_use_pthreads(); evthread_use_pthreads();
#endif //_WIN32 #endif //_WIN32
ygo::Game _game; ygo::Game _game;
#ifdef YGOPRO_SERVER_MODE
enable_log = 1;
ygo::server_port = 7911;
ygo::replay_mode = 0;
ygo::game_info.lflist = 0;
ygo::game_info.rule = 0;
ygo::game_info.mode = 0;
ygo::game_info.start_hand = 5;
ygo::game_info.start_lp = 8000;
ygo::game_info.draw_count = 1;
ygo::game_info.no_check_deck = false;
ygo::game_info.no_shuffle_deck = false;
ygo::game_info.duel_rule = YGOPRO_DEFAULT_DUEL_RULE;
ygo::game_info.time_limit = 180;
for (int i = 0; i < 3; ++i)
ygo::pre_seed[i] = (unsigned int)0;
if (argc == 2) {
int code = atoi(argv[1]);
ygo::mainGame = &_game;
ygo::mainGame->MainTestLoop(code);
return 0;
} else
if(argc > 2) {
ygo::server_port = atoi(argv[1]);
int lflist = atoi(argv[2]);
if(lflist < 0)
lflist = 999;
ygo::game_info.lflist = lflist;
ygo::game_info.rule = atoi(argv[3]);
int mode = atoi(argv[4]);
if(mode > 2)
mode = 0;
ygo::game_info.mode = mode;
if(argv[5][0] == 'T')
ygo::game_info.duel_rule = YGOPRO_DEFAULT_DUEL_RULE - 1;
else if(argv[5][0] == 'F')
ygo::game_info.duel_rule = YGOPRO_DEFAULT_DUEL_RULE;
else {
int master_rule = atoi(argv[5]);
if(master_rule)
ygo::game_info.duel_rule = master_rule;
else
ygo::game_info.duel_rule = YGOPRO_DEFAULT_DUEL_RULE;
}
if(argv[6][0] == 'T')
ygo::game_info.no_check_deck = true;
else
ygo::game_info.no_check_deck = false;
if(argv[7][0] == 'T')
ygo::game_info.no_shuffle_deck = true;
else
ygo::game_info.no_shuffle_deck = false;
ygo::game_info.start_lp = atoi(argv[8]);
ygo::game_info.start_hand = atoi(argv[9]);
ygo::game_info.draw_count = atoi(argv[10]);
ygo::game_info.time_limit = atoi(argv[11]);
ygo::replay_mode = atoi(argv[12]);
for (int i = 13; (i < argc && i <= 15) ; ++i)
{
ygo::pre_seed[i - 13] = (unsigned int)atol(argv[i]);
}
}
ygo::mainGame = &_game;
ygo::mainGame->MainServerLoop();
return 0;
#else //YGOPRO_SERVER_MODE
ygo::mainGame = &_game; ygo::mainGame = &_game;
if(!ygo::mainGame->Initialize()) if(!ygo::mainGame->Initialize())
return 0; return 0;
...@@ -215,5 +283,6 @@ int main(int argc, char* argv[]) { ...@@ -215,5 +283,6 @@ int main(int argc, char* argv[]) {
#else #else
#endif //_WIN32 #endif //_WIN32
#endif //YGOPRO_SERVER_MODE
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
...@@ -195,10 +195,12 @@ public: ...@@ -195,10 +195,12 @@ public:
return success; return success;
} }
#ifndef YGOPRO_SERVER_MODE
struct file_unit { struct file_unit {
std::string filename; std::string filename;
bool is_dir; bool is_dir;
}; };
#endif
static void TraversalDir(const char* path, const std::function<void(const char*, bool)>& cb) { static void TraversalDir(const char* path, const std::function<void(const char*, bool)>& cb) {
DIR* dir = nullptr; DIR* dir = nullptr;
...@@ -206,26 +208,40 @@ public: ...@@ -206,26 +208,40 @@ public:
if((dir = opendir(path)) == nullptr) if((dir = opendir(path)) == nullptr)
return; return;
struct stat fileStat; struct stat fileStat;
#ifndef YGOPRO_SERVER_MODE
std::vector<file_unit> file_list; std::vector<file_unit> file_list;
#endif
while((dirp = readdir(dir)) != nullptr) { while((dirp = readdir(dir)) != nullptr) {
#ifndef YGOPRO_SERVER_MODE
file_unit funit; file_unit funit;
#endif
char fname[1024]; char fname[1024];
int len = std::snprintf(fname, sizeof fname, "%s/%s", path, dirp->d_name); int len = std::snprintf(fname, sizeof fname, "%s/%s", path, dirp->d_name);
if (len < 0 || len >= (int)(sizeof fname)) if (len < 0 || len >= (int)(sizeof fname))
continue; continue;
stat(fname, &fileStat); stat(fname, &fileStat);
#ifdef YGOPRO_SERVER_MODE
bool is_dir = S_ISDIR(fileStat.st_mode);
if (is_dir && (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) || strcmp(dirp->d_name, ".git") == 0)
continue;
cb(dirp->d_name, is_dir);
#else
funit.filename = std::string(dirp->d_name); funit.filename = std::string(dirp->d_name);
funit.is_dir = S_ISDIR(fileStat.st_mode); funit.is_dir = S_ISDIR(fileStat.st_mode);
if(funit.is_dir && (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) || strcmp(dirp->d_name, ".git") == 0) if(funit.is_dir && (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) || strcmp(dirp->d_name, ".git") == 0)
continue; continue;
file_list.push_back(funit); file_list.push_back(funit);
#endif
} }
closedir(dir); closedir(dir);
#ifndef YGOPRO_SERVER_MODE
std::sort(file_list.begin(), file_list.end(), TraversalDirSort); std::sort(file_list.begin(), file_list.end(), TraversalDirSort);
for (file_unit funit : file_list) for (file_unit funit : file_list)
cb(funit.filename.c_str(), funit.is_dir); cb(funit.filename.c_str(), funit.is_dir);
#endif
} }
#ifndef YGOPRO_SERVER_MODE
static bool TraversalDirSort(file_unit file1, file_unit file2) { static bool TraversalDirSort(file_unit file1, file_unit file2) {
if(file1.is_dir != file2.is_dir) { if(file1.is_dir != file2.is_dir) {
return file2.is_dir; return file2.is_dir;
...@@ -233,6 +249,7 @@ public: ...@@ -233,6 +249,7 @@ public:
return file1.filename < file2.filename; return file1.filename < file2.filename;
} }
} }
#endif
static void TraversalDir(const wchar_t* wpath, const std::function<void(const wchar_t*, bool)>& cb) { static void TraversalDir(const wchar_t* wpath, const std::function<void(const wchar_t*, bool)>& cb) {
char path[1024]; char path[1024];
......
...@@ -15,7 +15,77 @@ DuelMode* NetServer::duel_mode = 0; ...@@ -15,7 +15,77 @@ DuelMode* NetServer::duel_mode = 0;
unsigned char NetServer::net_server_write[SIZE_NETWORK_BUFFER]; unsigned char NetServer::net_server_write[SIZE_NETWORK_BUFFER];
size_t NetServer::last_sent = 0; size_t NetServer::last_sent = 0;
#ifdef YGOPRO_SERVER_MODE
extern unsigned short replay_mode;
extern HostInfo game_info;
void NetServer::InitDuel()
{
if(game_info.mode == MODE_SINGLE) {
duel_mode = new SingleDuel(false);
duel_mode->etimer = event_new(net_evbase, 0, EV_TIMEOUT | EV_PERSIST, SingleDuel::SingleTimer, duel_mode);
} else if(game_info.mode == MODE_MATCH) {
duel_mode = new SingleDuel(true);
duel_mode->etimer = event_new(net_evbase, 0, EV_TIMEOUT | EV_PERSIST, SingleDuel::SingleTimer, duel_mode);
} else if(game_info.mode == MODE_TAG) {
duel_mode = new TagDuel();
duel_mode->etimer = event_new(net_evbase, 0, EV_TIMEOUT | EV_PERSIST, TagDuel::TagTimer, duel_mode);
}
CTOS_CreateGame* pkt = new CTOS_CreateGame;
pkt->info.mode = game_info.mode;
pkt->info.start_hand = game_info.start_hand;
pkt->info.start_lp = game_info.start_lp;
pkt->info.draw_count = game_info.draw_count;
pkt->info.no_check_deck = game_info.no_check_deck;
pkt->info.no_shuffle_deck = game_info.no_shuffle_deck;
pkt->info.duel_rule = game_info.duel_rule;
pkt->info.rule = game_info.rule;
pkt->info.time_limit = game_info.time_limit;
if(game_info.lflist == 999)
pkt->info.lflist = 0;
else if(game_info.lflist >= deckManager._lfList.size())
pkt->info.lflist = deckManager._lfList[0].hash;
else
pkt->info.lflist = deckManager._lfList[game_info.lflist].hash;
duel_mode->host_info = pkt->info;
BufferIO::CopyWStr(pkt->name, duel_mode->name, 20);
BufferIO::CopyWStr(pkt->pass, duel_mode->pass, 20);
}
void NetServer::InitTestCard(int code) {
DuelMode* test_duel = new SingleDuel(false);
test_duel->TestCard(code);
}
bool NetServer::IsCanIncreaseTime(unsigned short gameMsg, void *pdata, unsigned int len) {
int32_t* ivalue = (int32_t*)pdata;
switch(gameMsg) {
case MSG_RETRY:
case MSG_SELECT_UNSELECT_CARD:
return false;
case MSG_SELECT_CHAIN:
return ivalue[0] != -1;
case MSG_SELECT_IDLECMD: {
int32_t idleChoice = ivalue[0] & 0xffff;
return idleChoice <= 5; // no shuffle hand, enter other phases
}
case MSG_SELECT_BATTLECMD: {
int32_t battleChoice = ivalue[0] & 0xffff;
return battleChoice <= 1; // attack only
}
default:
return true;
}
}
unsigned short NetServer::StartServer(unsigned short port) {
#else
bool NetServer::StartServer(unsigned short port) { bool NetServer::StartServer(unsigned short port) {
#endif //YGOPRO_SERVER_MODE
if(net_evbase) if(net_evbase)
return false; return false;
net_evbase = event_base_new(); net_evbase = event_base_new();
...@@ -25,7 +95,11 @@ bool NetServer::StartServer(unsigned short port) { ...@@ -25,7 +95,11 @@ bool NetServer::StartServer(unsigned short port) {
std::memset(&sin, 0, sizeof sin); std::memset(&sin, 0, sizeof sin);
server_port = port; server_port = port;
sin.sin_family = AF_INET; sin.sin_family = AF_INET;
#ifdef SERVER_PRO2_SUPPORT
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
#else
sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
sin.sin_port = htons(port); sin.sin_port = htons(port);
listener = evconnlistener_new_bind(net_evbase, ServerAccept, nullptr, listener = evconnlistener_new_bind(net_evbase, ServerAccept, nullptr,
LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, (sockaddr*)&sin, sizeof(sin)); LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, -1, (sockaddr*)&sin, sizeof(sin));
...@@ -36,7 +110,15 @@ bool NetServer::StartServer(unsigned short port) { ...@@ -36,7 +110,15 @@ bool NetServer::StartServer(unsigned short port) {
} }
evconnlistener_set_error_cb(listener, ServerAcceptError); evconnlistener_set_error_cb(listener, ServerAcceptError);
std::thread(ServerThread).detach(); std::thread(ServerThread).detach();
#ifdef YGOPRO_SERVER_MODE
evutil_socket_t fd = evconnlistener_get_fd(listener);
socklen_t addrlen = sizeof(sockaddr);
sockaddr_in addr;
getsockname(fd, (sockaddr*)&addr, &addrlen);
return ntohs(addr.sin_port);
#else
return true; return true;
#endif //YGOPRO_SERVER_MODE
} }
bool NetServer::StartBroadcast() { bool NetServer::StartBroadcast() {
if(!net_evbase) if(!net_evbase)
...@@ -63,7 +145,12 @@ void NetServer::StopServer() { ...@@ -63,7 +145,12 @@ void NetServer::StopServer() {
return; return;
if(duel_mode) if(duel_mode)
duel_mode->EndDuel(); duel_mode->EndDuel();
#ifdef YGOPRO_SERVER_MODE // For solving the problem of connection lost after duel. See https://github.com/Fluorohydride/ygopro/issues/2067 for details.
timeval etv = { 0, 1 };
event_base_loopexit(net_evbase, &etv);
#else
event_base_loopexit(net_evbase, 0); event_base_loopexit(net_evbase, 0);
#endif
} }
void NetServer::StopBroadcast() { void NetServer::StopBroadcast() {
if(!net_evbase || !broadcast_ev) if(!net_evbase || !broadcast_ev)
...@@ -186,7 +273,11 @@ void NetServer::DisconnectPlayer(DuelPlayer* dp) { ...@@ -186,7 +273,11 @@ void NetServer::DisconnectPlayer(DuelPlayer* dp) {
void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) { void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) {
auto pdata = data; auto pdata = data;
unsigned char pktType = BufferIO::ReadUInt8(pdata); unsigned char pktType = BufferIO::ReadUInt8(pdata);
#ifdef YGOPRO_SERVER_MODE
if((pktType != CTOS_SURRENDER) && (pktType != CTOS_CHAT) && (pktType != CTOS_REQUEST_FIELD) && (dp->state == 0xff || (dp->state && dp->state != pktType)))
#else
if((pktType != CTOS_SURRENDER) && (pktType != CTOS_CHAT) && (dp->state == 0xff || (dp->state && dp->state != pktType))) if((pktType != CTOS_SURRENDER) && (pktType != CTOS_CHAT) && (dp->state == 0xff || (dp->state && dp->state != pktType)))
#endif
return; return;
switch(pktType) { switch(pktType) {
case CTOS_RESPONSE: { case CTOS_RESPONSE: {
...@@ -357,6 +448,14 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) { ...@@ -357,6 +448,14 @@ void NetServer::HandleCTOSPacket(DuelPlayer* dp, unsigned char* data, int len) {
duel_mode->StartDuel(dp); duel_mode->StartDuel(dp);
break; break;
} }
#ifdef YGOPRO_SERVER_MODE
case CTOS_REQUEST_FIELD: {
if(!dp->game || !duel_mode->pduel)
break;
duel_mode->RequestField(dp);
break;
}
#endif
} }
} }
size_t NetServer::CreateChatPacket(unsigned char* src, int src_size, unsigned char* dst, uint16_t dst_player_type) { size_t NetServer::CreateChatPacket(unsigned char* src, int src_size, unsigned char* dst, uint16_t dst_player_type) {
......
...@@ -10,7 +10,9 @@ class NetServer { ...@@ -10,7 +10,9 @@ class NetServer {
private: private:
static std::unordered_map<bufferevent*, DuelPlayer> users; static std::unordered_map<bufferevent*, DuelPlayer> users;
static unsigned short server_port; static unsigned short server_port;
#ifndef YGOPRO_SERVER_MODE
static event_base* net_evbase; static event_base* net_evbase;
#endif
static event* broadcast_ev; static event* broadcast_ev;
static evconnlistener* listener; static evconnlistener* listener;
static DuelMode* duel_mode; static DuelMode* duel_mode;
...@@ -18,7 +20,15 @@ private: ...@@ -18,7 +20,15 @@ private:
static size_t last_sent; static size_t last_sent;
public: public:
#ifdef YGOPRO_SERVER_MODE
static event_base* net_evbase;
static void InitDuel();
static void InitTestCard(int code);
static unsigned short StartServer(unsigned short port);
static bool IsCanIncreaseTime(unsigned short gameMsg, void *pdata, unsigned int len);
#else
static bool StartServer(unsigned short port); static bool StartServer(unsigned short port);
#endif //YGOPRO_SERVER_MODE
static bool StartBroadcast(); static bool StartBroadcast();
static void StopServer(); static void StopServer();
static void StopBroadcast(); static void StopBroadcast();
...@@ -67,6 +77,14 @@ public: ...@@ -67,6 +77,14 @@ public:
if(dp) if(dp)
bufferevent_write(dp->bev, net_server_write, last_sent); bufferevent_write(dp->bev, net_server_write, last_sent);
} }
#ifdef YGOPRO_SERVER_MODE
static void ReSendToPlayers(DuelPlayer* dp1, DuelPlayer* dp2) {
if(dp1)
bufferevent_write(dp1->bev, net_server_write, last_sent);
if(dp2)
bufferevent_write(dp2->bev, net_server_write, last_sent);
}
#endif //YGOPRO_SERVER_MODE
}; };
} }
......
...@@ -233,7 +233,13 @@ public: ...@@ -233,7 +233,13 @@ public:
virtual void Surrender(DuelPlayer* dp) = 0; virtual void Surrender(DuelPlayer* dp) = 0;
virtual void GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len) = 0; virtual void GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len) = 0;
virtual void TimeConfirm(DuelPlayer* dp) = 0; virtual void TimeConfirm(DuelPlayer* dp) = 0;
#ifdef YGOPRO_SERVER_MODE
virtual void RequestField(DuelPlayer* dp) = 0;
#endif
virtual void EndDuel() = 0; virtual void EndDuel() = 0;
#ifdef YGOPRO_SERVER_MODE
virtual void TestCard(int code) = 0;
#endif
public: public:
event* etimer { nullptr }; event* etimer { nullptr };
......
include "lzma/." include "lzma/."
if (SERVER_ZIP_SUPPORT or not SERVER_MODE) then
include "spmemvfs/." include "spmemvfs/."
end
project "YGOPro" project "ygopro"
if SERVER_MODE then
kind "ConsoleApp"
defines { "YGOPRO_SERVER_MODE" }
files { "gframe.cpp", "config.h",
"game.cpp", "game.h", "myfilesystem.h",
"deck_manager.cpp", "deck_manager.h",
"data_manager.cpp", "data_manager.h",
"replay.cpp", "replay.h",
"netserver.cpp", "netserver.h",
"single_duel.cpp", "single_duel.h",
"tag_duel.cpp", "tag_duel.h" }
includedirs { "../ocgcore" }
links { "ocgcore", "clzma", LUA_LIB_NAME, "sqlite3", "event" }
if SERVER_ZIP_SUPPORT then
defines { "SERVER_ZIP_SUPPORT" }
links { "irrlicht", "cspmemvfs" }
if BUILD_IRRLICHT then
includedirs { "../irrlicht/source/Irrlicht" }
end
end
if SERVER_PRO2_SUPPORT then
defines { "SERVER_PRO2_SUPPORT" }
end
if SERVER_TAG_SURRENDER_CONFIRM then
defines { "SERVER_TAG_SURRENDER_CONFIRM" }
end
else
kind "WindowedApp" kind "WindowedApp"
files { "*.cpp", "*.h", "CGUISkinSystem/*.cpp", "CGUISkinSystem/*.h", "CXMLRegistry/*.cpp", "CXMLRegistry/*.h" } files { "*.cpp", "*.h" }
includedirs { "../ocgcore" } includedirs { "../ocgcore" }
links { "ocgcore", "clzma", "cspmemvfs", LUA_LIB_NAME, "sqlite3", "irrlicht", "freetype", "event" } links { "ocgcore", "clzma", "cspmemvfs", LUA_LIB_NAME, "sqlite3", "irrlicht", "freetype", "event" }
end
if BUILD_IKPMP3 then if BUILD_IKPMP3 then
links { "ikpmp3" } links { "ikpmp3" }
end end
...@@ -54,7 +86,12 @@ project "YGOPro" ...@@ -54,7 +86,12 @@ project "YGOPro"
filter "system:windows" filter "system:windows"
defines { "_IRR_WCHAR_FILESYSTEM" } defines { "_IRR_WCHAR_FILESYSTEM" }
files "ygopro.rc" files "ygopro.rc"
if not SERVER_MODE then
libdirs { "$(DXSDK_DIR)Lib/x86" } libdirs { "$(DXSDK_DIR)Lib/x86" }
end
if SERVER_PRO2_SUPPORT then
targetname ("AI.Server")
end
if USE_IRRKLANG then if USE_IRRKLANG then
links { "irrKlang" } links { "irrKlang" }
if IRRKLANG_PRO then if IRRKLANG_PRO then
...@@ -66,14 +103,20 @@ project "YGOPro" ...@@ -66,14 +103,20 @@ project "YGOPro"
filter {} filter {}
end end
end end
if SERVER_MODE then
links { "ws2_32" }
else
links { "opengl32", "ws2_32", "winmm", "gdi32", "kernel32", "user32", "imm32", "Dnsapi" } links { "opengl32", "ws2_32", "winmm", "gdi32", "kernel32", "user32", "imm32", "Dnsapi" }
end
filter "not action:vs*" filter "not action:vs*"
buildoptions { "-std=c++14", "-fno-rtti" } buildoptions { "-std=c++14", "-fno-rtti" }
filter "not system:windows" filter "not system:windows"
links { "event_pthreads", "dl", "pthread", "resolv" } links { "event_pthreads", "dl", "pthread", "resolv" }
filter "system:macosx" filter "system:macosx"
if not SERVER_MODE then
links { "z" } links { "z" }
defines { "GL_SILENCE_DEPRECATION" } defines { "GL_SILENCE_DEPRECATION" }
end
if MAC_ARM then if MAC_ARM then
buildoptions { "--target=arm64-apple-macos12" } buildoptions { "--target=arm64-apple-macos12" }
linkoptions { "-arch arm64" } linkoptions { "-arch arm64" }
...@@ -82,8 +125,10 @@ project "YGOPro" ...@@ -82,8 +125,10 @@ project "YGOPro"
links { "irrklang" } links { "irrklang" }
end end
filter "system:linux" filter "system:linux"
linkoptions { "-static-libstdc++", "-static-libgcc" } linkoptions { "-static-libstdc++", "-static-libgcc" }
if not SERVER_MODE then
links { "GL", "X11", "Xxf86vm" } links { "GL", "X11", "Xxf86vm" }
end
if USE_IRRKLANG then if USE_IRRKLANG then
links { "IrrKlang" } links { "IrrKlang" }
linkoptions { IRRKLANG_LINK_RPATH } linkoptions { IRRKLANG_LINK_RPATH }
......
...@@ -3,7 +3,11 @@ ...@@ -3,7 +3,11 @@
#include "lzma/LzmaLib.h" #include "lzma/LzmaLib.h"
namespace ygo { namespace ygo {
#ifdef YGOPRO_SERVER_MODE
extern unsigned short server_port;
extern unsigned short replay_mode;
#endif
Replay::Replay() { Replay::Replay() {
replay_data = new unsigned char[MAX_REPLAY_SIZE]; replay_data = new unsigned char[MAX_REPLAY_SIZE];
comp_data = new unsigned char[MAX_COMP_SIZE]; comp_data = new unsigned char[MAX_COMP_SIZE];
...@@ -13,21 +17,47 @@ Replay::~Replay() { ...@@ -13,21 +17,47 @@ Replay::~Replay() {
delete[] comp_data; delete[] comp_data;
} }
void Replay::BeginRecord() { void Replay::BeginRecord() {
#ifdef YGOPRO_SERVER_MODE
if(replay_mode & REPLAY_MODE_SAVE_IN_SERVER) {
#endif
if(!FileSystem::IsDirExists(L"./replay") && !FileSystem::MakeDir(L"./replay")) if(!FileSystem::IsDirExists(L"./replay") && !FileSystem::MakeDir(L"./replay"))
return; return;
#ifdef _WIN32 #ifdef _WIN32
if(is_recording) if(is_recording)
CloseHandle(recording_fp); CloseHandle(recording_fp);
#ifdef YGOPRO_SERVER_MODE
time_t nowtime = time(nullptr);
struct tm *localedtime = localtime(&nowtime);
wchar_t tmppath[80];
wcsftime(tmppath, 80, L"./replay/%Y-%m-%d %H-%M-%S %%u.yrp", localedtime);
wchar_t path[80];
myswprintf(path, tmppath, server_port);
recording_fp = CreateFileW(path, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, nullptr);
#else
recording_fp = CreateFileW(L"./replay/_LastReplay.yrp", GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, nullptr); recording_fp = CreateFileW(L"./replay/_LastReplay.yrp", GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_FLAG_WRITE_THROUGH, nullptr);
#endif //YGOPRO_SERVER_MODE
if(recording_fp == INVALID_HANDLE_VALUE) if(recording_fp == INVALID_HANDLE_VALUE)
return; return;
#else #else
if(is_recording) if(is_recording)
fclose(fp); fclose(fp);
#ifdef YGOPRO_SERVER_MODE
time_t nowtime = time(nullptr);
struct tm *localedtime = localtime(&nowtime);
char tmppath[40];
strftime(tmppath, 40, "./replay/%Y-%m-%d %H-%M-%S %%u.yrp", localedtime);
char path[40];
sprintf(path, tmppath, server_port);
fp = fopen(path, "wb");
#else
fp = fopen("./replay/_LastReplay.yrp", "wb"); fp = fopen("./replay/_LastReplay.yrp", "wb");
#endif //YGOPRO_SERVER_MODE
if(!fp) if(!fp)
return; return;
#endif #endif
#ifdef YGOPRO_SERVER_MODE
}
#endif //YGOPRO_SERVER_MODE
replay_size = 0; replay_size = 0;
comp_size = 0; comp_size = 0;
is_replaying = false; is_replaying = false;
...@@ -35,6 +65,9 @@ void Replay::BeginRecord() { ...@@ -35,6 +65,9 @@ void Replay::BeginRecord() {
} }
void Replay::WriteHeader(ReplayHeader& header) { void Replay::WriteHeader(ReplayHeader& header) {
pheader = header; pheader = header;
#ifdef YGOPRO_SERVER_MODE
if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return;
#endif
#ifdef _WIN32 #ifdef _WIN32
DWORD size; DWORD size;
WriteFile(recording_fp, &header, sizeof(header), &size, nullptr); WriteFile(recording_fp, &header, sizeof(header), &size, nullptr);
...@@ -50,6 +83,9 @@ void Replay::WriteData(const void* data, size_t length, bool flush) { ...@@ -50,6 +83,9 @@ void Replay::WriteData(const void* data, size_t length, bool flush) {
return; return;
std::memcpy(replay_data + replay_size, data, length); std::memcpy(replay_data + replay_size, data, length);
replay_size += length; replay_size += length;
#ifdef YGOPRO_SERVER_MODE
if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return;
#endif
#ifdef _WIN32 #ifdef _WIN32
DWORD size; DWORD size;
WriteFile(recording_fp, data, length, &size, nullptr); WriteFile(recording_fp, data, length, &size, nullptr);
...@@ -65,6 +101,9 @@ void Replay::WriteInt32(int32_t data, bool flush) { ...@@ -65,6 +101,9 @@ void Replay::WriteInt32(int32_t data, bool flush) {
void Replay::Flush() { void Replay::Flush() {
if(!is_recording) if(!is_recording)
return; return;
#ifdef YGOPRO_SERVER_MODE
if(!(replay_mode & REPLAY_MODE_SAVE_IN_SERVER)) return;
#endif
#ifdef _WIN32 #ifdef _WIN32
#else #else
fflush(fp); fflush(fp);
...@@ -73,10 +112,16 @@ void Replay::Flush() { ...@@ -73,10 +112,16 @@ void Replay::Flush() {
void Replay::EndRecord() { void Replay::EndRecord() {
if(!is_recording) if(!is_recording)
return; return;
#ifdef YGOPRO_SERVER_MODE
if(replay_mode & REPLAY_MODE_SAVE_IN_SERVER) {
#endif
#ifdef _WIN32 #ifdef _WIN32
CloseHandle(recording_fp); CloseHandle(recording_fp);
#else #else
fclose(fp); fclose(fp);
#endif
#ifdef YGOPRO_SERVER_MODE
}
#endif #endif
pheader.datasize = replay_size; pheader.datasize = replay_size;
pheader.flag |= REPLAY_COMPRESSED; pheader.flag |= REPLAY_COMPRESSED;
......
...@@ -16,6 +16,12 @@ namespace ygo { ...@@ -16,6 +16,12 @@ namespace ygo {
constexpr int MAX_REPLAY_SIZE = 0x20000; constexpr int MAX_REPLAY_SIZE = 0x20000;
constexpr int MAX_COMP_SIZE = UINT16_MAX + 1; constexpr int MAX_COMP_SIZE = UINT16_MAX + 1;
#ifdef YGOPRO_SERVER_MODE
#define REPLAY_MODE_SAVE_IN_SERVER 0x1
#define REPLAY_MODE_WATCHER_NO_SEND 0x2
#define REPLAY_MODE_INCLUDE_CHAT 0x4
#endif // YGOPRO_SERVER_MODE
struct ReplayHeader { struct ReplayHeader {
unsigned int id{}; unsigned int id{};
unsigned int version{}; unsigned int version{};
......
...@@ -282,7 +282,6 @@ void ReplayMode::EndDuel() { ...@@ -282,7 +282,6 @@ void ReplayMode::EndDuel() {
} }
void ReplayMode::Restart(bool refresh) { void ReplayMode::Restart(bool refresh) {
end_duel(pduel); end_duel(pduel);
mainGame->dInfo.isInDuel = false;
mainGame->dInfo.isStarted = false; mainGame->dInfo.isStarted = false;
mainGame->dInfo.isInDuel = false; mainGame->dInfo.isInDuel = false;
mainGame->dInfo.isFinished = true; mainGame->dInfo.isFinished = true;
......
...@@ -7,8 +7,15 @@ ...@@ -7,8 +7,15 @@
namespace ygo { namespace ygo {
#ifdef YGOPRO_SERVER_MODE
extern unsigned short replay_mode;
#endif
SingleDuel::SingleDuel(bool is_match) { SingleDuel::SingleDuel(bool is_match) {
match_mode = is_match; match_mode = is_match;
#ifdef YGOPRO_SERVER_MODE
cache_recorder = 0;
replay_recorder = 0;
#endif
} }
SingleDuel::~SingleDuel() { SingleDuel::~SingleDuel() {
} }
...@@ -21,8 +28,17 @@ void SingleDuel::Chat(DuelPlayer* dp, unsigned char* pdata, int len) { ...@@ -21,8 +28,17 @@ void SingleDuel::Chat(DuelPlayer* dp, unsigned char* pdata, int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::ReSendToPlayer(cache_recorder);
if(replay_recorder && replay_mode & REPLAY_MODE_INCLUDE_CHAT)
NetServer::ReSendToPlayer(replay_recorder);
#endif
} }
void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) { void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {
#ifdef YGOPRO_SERVER_MODE
bool is_recorder = false;
#endif
if(!is_creater) { if(!is_creater) {
if(dp->game && dp->type != 0xff) { if(dp->game && dp->type != 0xff) {
STOC_ErrorMsg scem; STOC_ErrorMsg scem;
...@@ -48,6 +64,18 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) ...@@ -48,6 +64,18 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater)
wchar_t jpass[20]; wchar_t jpass[20];
BufferIO::NullTerminate(pkt->pass); BufferIO::NullTerminate(pkt->pass);
BufferIO::CopyCharArray(pkt->pass, jpass); BufferIO::CopyCharArray(pkt->pass, jpass);
#ifdef YGOPRO_SERVER_MODE
if(!std::wcscmp(jpass, L"the Big Brother") && !cache_recorder) {
is_recorder = true;
cache_recorder = dp;
}
#ifndef YGOPRO_SERVER_MODE_DISABLE_CLOUD_REPLAY
if(!std::wcscmp(jpass, L"Marshtomp") && !replay_recorder) {
is_recorder = true;
replay_recorder = dp;
}
#endif //YGOPRO_SERVER_MODE_DISABLE_CLOUD_REPLAY
#else
if(std::wcscmp(jpass, pass)) { if(std::wcscmp(jpass, pass)) {
STOC_ErrorMsg scem; STOC_ErrorMsg scem;
scem.msg = ERRMSG_JOINERROR; scem.msg = ERRMSG_JOINERROR;
...@@ -55,6 +83,7 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) ...@@ -55,6 +83,7 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater)
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem); NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return; return;
} }
#endif //YGOPRO_SERVER_MODE
} }
dp->game = this; dp->game = this;
if(!players[0] && !players[1] && observers.size() == 0) if(!players[0] && !players[1] && observers.size() == 0)
...@@ -63,6 +92,13 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) ...@@ -63,6 +92,13 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater)
scjg.info = host_info; scjg.info = host_info;
STOC_TypeChange sctc; STOC_TypeChange sctc;
sctc.type = (host_player == dp) ? 0x10 : 0; sctc.type = (host_player == dp) ? 0x10 : 0;
#ifdef YGOPRO_SERVER_MODE
if(is_recorder) {
dp->type = 9;
sctc.type = NETPLAYER_TYPE_OBSERVER;
}
else
#endif
if(!players[0] || !players[1]) { if(!players[0] || !players[1]) {
STOC_HS_PlayerEnter scpe; STOC_HS_PlayerEnter scpe;
BufferIO::CopyCharArray(dp->name, scpe.name); BufferIO::CopyCharArray(dp->name, scpe.name);
...@@ -78,6 +114,12 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) ...@@ -78,6 +114,12 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater)
} }
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_ENTER, scpe);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_ENTER, scpe);
#endif
if(!players[0]) { if(!players[0]) {
players[0] = dp; players[0] = dp;
dp->type = NETPLAYER_TYPE_PLAYER1; dp->type = NETPLAYER_TYPE_PLAYER1;
...@@ -99,6 +141,12 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) ...@@ -99,6 +141,12 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater)
NetServer::SendPacketToPlayer(players[1], STOC_HS_WATCH_CHANGE, scwc); NetServer::SendPacketToPlayer(players[1], STOC_HS_WATCH_CHANGE, scwc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc); NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_WATCH_CHANGE, scwc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_WATCH_CHANGE, scwc);
#endif
} }
NetServer::SendPacketToPlayer(dp, STOC_JOIN_GAME, scjg); NetServer::SendPacketToPlayer(dp, STOC_JOIN_GAME, scjg);
NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc); NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc);
...@@ -132,9 +180,32 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) ...@@ -132,9 +180,32 @@ void SingleDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater)
} }
void SingleDuel::LeaveGame(DuelPlayer* dp) { void SingleDuel::LeaveGame(DuelPlayer* dp) {
if(dp == host_player) { if(dp == host_player) {
#ifdef YGOPRO_SERVER_MODE
int host_pos;
if(players[0] && dp->type != 0) {
host_pos = 0;
host_player = players[0];
} else if(players[1] && dp->type != 1) {
host_pos = 1;
host_player = players[1];
} else {
EndDuel();
NetServer::StopServer();
return;
}
if(duel_stage == DUEL_STAGE_BEGIN) {
ready[host_pos] = false;
STOC_TypeChange sctc;
sctc.type = 0x10 | host_pos;
NetServer::SendPacketToPlayer(players[host_pos], STOC_TYPE_CHANGE, sctc);
}
}
if(dp->type == NETPLAYER_TYPE_OBSERVER) {
#else
EndDuel(); EndDuel();
NetServer::StopServer(); NetServer::StopServer();
} else if(dp->type == NETPLAYER_TYPE_OBSERVER) { } else if(dp->type == NETPLAYER_TYPE_OBSERVER) {
#endif //YGOPRO_SERVER_MODE
observers.erase(dp); observers.erase(dp);
if(duel_stage == DUEL_STAGE_BEGIN) { if(duel_stage == DUEL_STAGE_BEGIN) {
STOC_HS_WatchChange scwc; STOC_HS_WatchChange scwc;
...@@ -145,6 +216,12 @@ void SingleDuel::LeaveGame(DuelPlayer* dp) { ...@@ -145,6 +216,12 @@ void SingleDuel::LeaveGame(DuelPlayer* dp) {
NetServer::SendPacketToPlayer(players[1], STOC_HS_WATCH_CHANGE, scwc); NetServer::SendPacketToPlayer(players[1], STOC_HS_WATCH_CHANGE, scwc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc); NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_WATCH_CHANGE, scwc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_WATCH_CHANGE, scwc);
#endif
} }
NetServer::DisconnectPlayer(dp); NetServer::DisconnectPlayer(dp);
} else { } else {
...@@ -159,6 +236,12 @@ void SingleDuel::LeaveGame(DuelPlayer* dp) { ...@@ -159,6 +236,12 @@ void SingleDuel::LeaveGame(DuelPlayer* dp) {
NetServer::SendPacketToPlayer(players[1], STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(players[1], STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_CHANGE, scpc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_CHANGE, scpc);
#endif
NetServer::DisconnectPlayer(dp); NetServer::DisconnectPlayer(dp);
} else { } else {
if(duel_stage == DUEL_STAGE_SIDING) { if(duel_stage == DUEL_STAGE_SIDING) {
...@@ -176,13 +259,22 @@ void SingleDuel::LeaveGame(DuelPlayer* dp) { ...@@ -176,13 +259,22 @@ void SingleDuel::LeaveGame(DuelPlayer* dp) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
EndDuel(); EndDuel();
NetServer::SendPacketToPlayer(players[0], STOC_DUEL_END); NetServer::SendPacketToPlayer(players[0], STOC_DUEL_END);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
NetServer::StopServer();
#endif
} }
#ifndef YGOPRO_SERVER_MODE
NetServer::DisconnectPlayer(dp); NetServer::DisconnectPlayer(dp);
#endif
} }
} }
} }
...@@ -215,6 +307,16 @@ void SingleDuel::ToDuelist(DuelPlayer* dp) { ...@@ -215,6 +307,16 @@ void SingleDuel::ToDuelist(DuelPlayer* dp) {
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe);
NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc); NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc);
} }
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder) {
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_ENTER, scpe);
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_WATCH_CHANGE, scwc);
}
if(replay_recorder) {
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_ENTER, scpe);
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_WATCH_CHANGE, scwc);
}
#endif
STOC_TypeChange sctc; STOC_TypeChange sctc;
sctc.type = (dp == host_player ? 0x10 : 0) | dp->type; sctc.type = (dp == host_player ? 0x10 : 0) | dp->type;
NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc); NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc);
...@@ -230,6 +332,12 @@ void SingleDuel::ToObserver(DuelPlayer* dp) { ...@@ -230,6 +332,12 @@ void SingleDuel::ToObserver(DuelPlayer* dp) {
NetServer::SendPacketToPlayer(players[1], STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(players[1], STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_CHANGE, scpc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_CHANGE, scpc);
#endif
players[dp->type] = 0; players[dp->type] = 0;
ready[dp->type] = false; ready[dp->type] = false;
dp->type = NETPLAYER_TYPE_OBSERVER; dp->type = NETPLAYER_TYPE_OBSERVER;
...@@ -271,6 +379,12 @@ void SingleDuel::PlayerReady(DuelPlayer* dp, bool is_ready) { ...@@ -271,6 +379,12 @@ void SingleDuel::PlayerReady(DuelPlayer* dp, bool is_ready) {
NetServer::SendPacketToPlayer(players[1 - dp->type], STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(players[1 - dp->type], STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_CHANGE, scpc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_CHANGE, scpc);
#endif
} }
void SingleDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) { void SingleDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) {
if(pos > 1 || dp != host_player || dp == players[pos] || !players[pos]) if(pos > 1 || dp != host_player || dp == players[pos] || !players[pos])
...@@ -283,13 +397,19 @@ void SingleDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) { ...@@ -283,13 +397,19 @@ void SingleDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {
if (len < 8 || len > sizeof(CTOS_DeckData)) if (len < 8 || len > sizeof(CTOS_DeckData))
return; return;
bool valid = true; bool valid = true;
const int deck_size = len - 2 * sizeof(int32_t);
CTOS_DeckData deckbuf; CTOS_DeckData deckbuf;
std::memcpy(&deckbuf, pdata, len); std::memcpy(&deckbuf, pdata, len);
if (deckbuf.mainc < 0 || deckbuf.mainc > MAINC_MAX) if (deckbuf.mainc < 0 || deckbuf.mainc > MAINC_MAX)
valid = false; valid = false;
else if (deckbuf.sidec < 0 || deckbuf.sidec > SIDEC_MAX) else if (deckbuf.sidec < 0 || deckbuf.sidec > SIDEC_MAX)
valid = false; valid = false;
else if (len < (2 + deckbuf.mainc + deckbuf.sidec) * (int)sizeof(int32_t)) else if
#ifdef YGOPRO_SERVER_MODE
(deck_size < (deckbuf.mainc + deckbuf.sidec) * (int)sizeof(int32_t) || deck_size > MAINC_MAX + SIDEC_MAX)
#else
(len < (2 + deckbuf.mainc + deckbuf.sidec) * (int)sizeof(int32_t))
#endif
valid = false; valid = false;
if (!valid) { if (!valid) {
STOC_ErrorMsg scem; STOC_ErrorMsg scem;
...@@ -331,6 +451,13 @@ void SingleDuel::StartDuel(DuelPlayer* dp) { ...@@ -331,6 +451,13 @@ void SingleDuel::StartDuel(DuelPlayer* dp) {
(*oit)->state = CTOS_LEAVE_GAME; (*oit)->state = CTOS_LEAVE_GAME;
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
} }
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
cache_recorder->state = CTOS_LEAVE_GAME;
if(replay_recorder)
replay_recorder->state = CTOS_LEAVE_GAME;
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
unsigned char deckbuff[12]; unsigned char deckbuff[12];
auto pbuf = deckbuff; auto pbuf = deckbuff;
BufferIO::WriteInt16(pbuf, (short)pdeck[0].main.size()); BufferIO::WriteInt16(pbuf, (short)pdeck[0].main.size());
...@@ -366,6 +493,9 @@ void SingleDuel::HandResult(DuelPlayer* dp, unsigned char res) { ...@@ -366,6 +493,9 @@ void SingleDuel::HandResult(DuelPlayer* dp, unsigned char res) {
NetServer::SendPacketToPlayer(players[0], STOC_HAND_RESULT, schr); NetServer::SendPacketToPlayer(players[0], STOC_HAND_RESULT, schr);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
schr.res1 = hand_result[1]; schr.res1 = hand_result[1];
schr.res2 = hand_result[0]; schr.res2 = hand_result[0];
NetServer::SendPacketToPlayer(players[1], STOC_HAND_RESULT, schr); NetServer::SendPacketToPlayer(players[1], STOC_HAND_RESULT, schr);
...@@ -414,6 +544,11 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -414,6 +544,11 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
dp->state = CTOS_RESPONSE; dp->state = CTOS_RESPONSE;
std::random_device rd; std::random_device rd;
unsigned int seed = rd(); unsigned int seed = rd();
#ifdef YGOPRO_SERVER_MODE
if(pre_seed[duel_count] > 0) {
seed = pre_seed[duel_count];
}
#endif
mt19937 rnd((uint_fast32_t)seed); mt19937 rnd((uint_fast32_t)seed);
auto duel_seed = rnd.rand(); auto duel_seed = rnd.rand();
ReplayHeader rh; ReplayHeader rh;
...@@ -480,11 +615,26 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -480,11 +615,26 @@ void SingleDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
startbuf[1] = 0x11; startbuf[1] = 0x11;
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::SendBufferToPlayer(*oit, STOC_GAME_MSG, startbuf, 19); NetServer::SendBufferToPlayer(*oit, STOC_GAME_MSG, startbuf, 19);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendBufferToPlayer(cache_recorder, STOC_GAME_MSG, startbuf, 19);
if(replay_recorder)
NetServer::SendBufferToPlayer(replay_recorder, STOC_GAME_MSG, startbuf, 19);
turn_player = 0;
phase = 1;
#endif
RefreshExtra(0); RefreshExtra(0);
RefreshExtra(1); RefreshExtra(1);
start_duel(pduel, opt); start_duel(pduel, opt);
if(host_info.time_limit) { if(host_info.time_limit) {
time_elapsed = 0; time_elapsed = 0;
#ifdef YGOPRO_SERVER_MODE
time_compensator[0] = host_info.time_limit;
time_compensator[1] = host_info.time_limit;
time_backed[0] = host_info.time_limit;
time_backed[1] = host_info.time_limit;
last_game_msg = 0;
#endif
timeval timeout = { 1, 0 }; timeval timeout = { 1, 0 };
event_add(etimer, &timeout); event_add(etimer, &timeout);
} }
...@@ -518,7 +668,12 @@ void SingleDuel::DuelEndProc() { ...@@ -518,7 +668,12 @@ void SingleDuel::DuelEndProc() {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
NetServer::StopServer();
#else
duel_stage = DUEL_STAGE_END; duel_stage = DUEL_STAGE_END;
#endif
} else { } else {
int winc[3] = {0, 0, 0}; int winc[3] = {0, 0, 0};
for(int i = 0; i < duel_count; ++i) for(int i = 0; i < duel_count; ++i)
...@@ -531,7 +686,12 @@ void SingleDuel::DuelEndProc() { ...@@ -531,7 +686,12 @@ void SingleDuel::DuelEndProc() {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
NetServer::StopServer();
#else
duel_stage = DUEL_STAGE_END; duel_stage = DUEL_STAGE_END;
#endif
} else { } else {
if(players[0] != pplayer[0]) { if(players[0] != pplayer[0]) {
players[0] = pplayer[0]; players[0] = pplayer[0];
...@@ -550,6 +710,12 @@ void SingleDuel::DuelEndProc() { ...@@ -550,6 +710,12 @@ void SingleDuel::DuelEndProc() {
NetServer::SendPacketToPlayer(players[1], STOC_CHANGE_SIDE); NetServer::SendPacketToPlayer(players[1], STOC_CHANGE_SIDE);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::SendPacketToPlayer(*oit, STOC_WAITING_SIDE); NetServer::SendPacketToPlayer(*oit, STOC_WAITING_SIDE);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_WAITING_SIDE);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_WAITING_SIDE);
#endif
duel_stage = DUEL_STAGE_SIDING; duel_stage = DUEL_STAGE_SIDING;
} }
} }
...@@ -566,6 +732,9 @@ void SingleDuel::Surrender(DuelPlayer* dp) { ...@@ -566,6 +732,9 @@ void SingleDuel::Surrender(DuelPlayer* dp) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
if(players[player] == pplayer[player]) { if(players[player] == pplayer[player]) {
match_result[duel_count++] = 1 - player; match_result[duel_count++] = 1 - player;
tp_player = player; tp_player = player;
...@@ -584,6 +753,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -584,6 +753,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
while (pbuf - msgbuffer < (int)len) { while (pbuf - msgbuffer < (int)len) {
offset = pbuf; offset = pbuf;
unsigned char engType = BufferIO::ReadUInt8(pbuf); unsigned char engType = BufferIO::ReadUInt8(pbuf);
#ifdef YGOPRO_SERVER_MODE
last_game_msg = engType;
#endif
switch (engType) { switch (engType) {
case MSG_RESET_TIME: { case MSG_RESET_TIME: {
player = BufferIO::ReadInt8(pbuf); player = BufferIO::ReadInt8(pbuf);
...@@ -632,6 +804,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -632,6 +804,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case 10: case 10:
...@@ -643,6 +818,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -643,6 +818,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[1], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[1], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
} }
...@@ -655,6 +833,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -655,6 +833,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
if(player > 1) { if(player > 1) {
match_result[duel_count++] = 2; match_result[duel_count++] = 2;
tp_player = 1 - tp_player; tp_player = 1 - tp_player;
...@@ -837,6 +1018,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -837,6 +1018,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CONFIRM_EXTRATOP: { case MSG_CONFIRM_EXTRATOP: {
...@@ -847,6 +1031,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -847,6 +1031,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for (auto oit = observers.begin(); oit != observers.end(); ++oit) for (auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CONFIRM_CARDS: { case MSG_CONFIRM_CARDS: {
...@@ -858,6 +1045,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -858,6 +1045,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1 - player]); NetServer::ReSendToPlayer(players[1 - player]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
} else { } else {
pbuf += count * 7; pbuf += count * 7;
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, offset, pbuf - offset);
...@@ -870,17 +1060,26 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -870,17 +1060,26 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SHUFFLE_HAND: { case MSG_SHUFFLE_HAND: {
player = BufferIO::ReadUInt8(pbuf); player = BufferIO::ReadUInt8(pbuf);
count = BufferIO::ReadUInt8(pbuf); count = BufferIO::ReadUInt8(pbuf);
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, offset, (pbuf - offset) + count * 4); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, offset, (pbuf - offset) + count * 4);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(replay_recorder);
#endif
for(int i = 0; i < count; ++i) for(int i = 0; i < count; ++i)
BufferIO::WriteInt32(pbuf, 0); BufferIO::WriteInt32(pbuf, 0);
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(cache_recorder);
#endif
RefreshHand(player, 0x781fff, 0); RefreshHand(player, 0x781fff, 0);
break; break;
} }
...@@ -888,11 +1087,17 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -888,11 +1087,17 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
player = BufferIO::ReadUInt8(pbuf); player = BufferIO::ReadUInt8(pbuf);
count = BufferIO::ReadUInt8(pbuf); count = BufferIO::ReadUInt8(pbuf);
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, offset, (pbuf - offset) + count * 4); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, offset, (pbuf - offset) + count * 4);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(replay_recorder);
#endif
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
BufferIO::WriteInt32(pbuf, 0); BufferIO::WriteInt32(pbuf, 0);
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, offset, pbuf - offset);
for (auto oit = observers.begin(); oit != observers.end(); ++oit) for (auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(cache_recorder);
#endif
RefreshExtra(player); RefreshExtra(player);
break; break;
} }
...@@ -902,6 +1107,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -902,6 +1107,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SWAP_GRAVE_DECK: { case MSG_SWAP_GRAVE_DECK: {
...@@ -910,6 +1118,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -910,6 +1118,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshGrave(player); RefreshGrave(player);
break; break;
} }
...@@ -918,6 +1129,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -918,6 +1129,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_DECK_TOP: { case MSG_DECK_TOP: {
...@@ -926,6 +1140,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -926,6 +1140,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SHUFFLE_SET_CARD: { case MSG_SHUFFLE_SET_CARD: {
...@@ -936,6 +1153,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -936,6 +1153,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
if(loc == LOCATION_MZONE) { if(loc == LOCATION_MZONE) {
RefreshMzone(0, 0x181fff, 0); RefreshMzone(0, 0x181fff, 0);
RefreshMzone(1, 0x181fff, 0); RefreshMzone(1, 0x181fff, 0);
...@@ -953,21 +1173,41 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -953,21 +1173,41 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
RefreshSzone(1); RefreshSzone(1);
RefreshHand(0); RefreshHand(0);
RefreshHand(1); RefreshHand(1);
#ifdef YGOPRO_SERVER_MODE
turn_player = BufferIO::ReadInt8(pbuf) & 0x1;
#else
pbuf++; pbuf++;
#endif
time_limit[0] = host_info.time_limit; time_limit[0] = host_info.time_limit;
time_limit[1] = host_info.time_limit; time_limit[1] = host_info.time_limit;
#ifdef YGOPRO_SERVER_MODE
time_compensator[0] = host_info.time_limit;
time_compensator[1] = host_info.time_limit;
time_backed[0] = host_info.time_limit;
time_backed[1] = host_info.time_limit;
#endif
NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, offset, pbuf - offset);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_NEW_PHASE: { case MSG_NEW_PHASE: {
#ifdef YGOPRO_SERVER_MODE
phase = BufferIO::ReadInt16(pbuf);
#else
pbuf += 2; pbuf += 2;
#endif
NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, offset, pbuf - offset);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -993,6 +1233,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -993,6 +1233,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[1 - cc], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[1 - cc], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
if (cl != 0 && (cl & LOCATION_OVERLAY) == 0 && (cl != pl || pc != cc)) if (cl != 0 && (cl & LOCATION_OVERLAY) == 0 && (cl != pl || pc != cc))
RefreshSingle(cc, cl, cs); RefreshSingle(cc, cl, cs);
break; break;
...@@ -1008,6 +1251,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1008,6 +1251,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
if((pp & POS_FACEDOWN) && (cp & POS_FACEUP)) if((pp & POS_FACEDOWN) && (cp & POS_FACEUP))
RefreshSingle(cc, cl, cs); RefreshSingle(cc, cl, cs);
break; break;
...@@ -1019,6 +1265,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1019,6 +1265,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SWAP: { case MSG_SWAP: {
...@@ -1033,6 +1282,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1033,6 +1282,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshSingle(c1, l1, s1); RefreshSingle(c1, l1, s1);
RefreshSingle(c2, l2, s2); RefreshSingle(c2, l2, s2);
break; break;
...@@ -1043,6 +1295,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1043,6 +1295,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SUMMONING: { case MSG_SUMMONING: {
...@@ -1051,6 +1306,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1051,6 +1306,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SUMMONED: { case MSG_SUMMONED: {
...@@ -1058,6 +1316,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1058,6 +1316,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1070,6 +1331,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1070,6 +1331,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SPSUMMONED: { case MSG_SPSUMMONED: {
...@@ -1077,6 +1341,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1077,6 +1341,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1090,6 +1357,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1090,6 +1357,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_FLIPSUMMONED: { case MSG_FLIPSUMMONED: {
...@@ -1097,6 +1367,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1097,6 +1367,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1109,6 +1382,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1109,6 +1382,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CHAINED: { case MSG_CHAINED: {
...@@ -1117,6 +1393,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1117,6 +1393,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1131,6 +1410,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1131,6 +1410,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CHAIN_SOLVED: { case MSG_CHAIN_SOLVED: {
...@@ -1139,6 +1421,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1139,6 +1421,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1152,6 +1437,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1152,6 +1437,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1166,6 +1454,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1166,6 +1454,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CHAIN_DISABLED: { case MSG_CHAIN_DISABLED: {
...@@ -1174,6 +1465,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1174,6 +1465,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CARD_SELECTED: { case MSG_CARD_SELECTED: {
...@@ -1190,6 +1484,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1190,6 +1484,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_BECOME_TARGET: { case MSG_BECOME_TARGET: {
...@@ -1199,6 +1496,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1199,6 +1496,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_DRAW: { case MSG_DRAW: {
...@@ -1207,6 +1507,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1207,6 +1507,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
pbufw = pbuf; pbufw = pbuf;
pbuf += count * 4; pbuf += count * 4;
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, offset, pbuf - offset);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(replay_recorder);
#endif
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
if(!(pbufw[3] & 0x80)) if(!(pbufw[3] & 0x80))
BufferIO::WriteInt32(pbufw, 0); BufferIO::WriteInt32(pbufw, 0);
...@@ -1216,6 +1519,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1216,6 +1519,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(cache_recorder);
#endif
break; break;
} }
case MSG_DAMAGE: { case MSG_DAMAGE: {
...@@ -1224,6 +1530,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1224,6 +1530,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_RECOVER: { case MSG_RECOVER: {
...@@ -1232,6 +1541,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1232,6 +1541,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_EQUIP: { case MSG_EQUIP: {
...@@ -1240,6 +1552,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1240,6 +1552,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_LPUPDATE: { case MSG_LPUPDATE: {
...@@ -1248,6 +1563,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1248,6 +1563,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_UNEQUIP: { case MSG_UNEQUIP: {
...@@ -1256,6 +1574,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1256,6 +1574,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CARD_TARGET: { case MSG_CARD_TARGET: {
...@@ -1264,6 +1585,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1264,6 +1585,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CANCEL_TARGET: { case MSG_CANCEL_TARGET: {
...@@ -1272,6 +1596,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1272,6 +1596,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_PAY_LPCOST: { case MSG_PAY_LPCOST: {
...@@ -1280,6 +1607,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1280,6 +1607,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_ADD_COUNTER: { case MSG_ADD_COUNTER: {
...@@ -1288,6 +1618,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1288,6 +1618,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_REMOVE_COUNTER: { case MSG_REMOVE_COUNTER: {
...@@ -1296,6 +1629,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1296,6 +1629,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_ATTACK: { case MSG_ATTACK: {
...@@ -1304,6 +1640,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1304,6 +1640,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_BATTLE: { case MSG_BATTLE: {
...@@ -1312,6 +1651,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1312,6 +1651,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_ATTACK_DISABLED: { case MSG_ATTACK_DISABLED: {
...@@ -1319,6 +1661,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1319,6 +1661,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_DAMAGE_STEP_START: { case MSG_DAMAGE_STEP_START: {
...@@ -1326,6 +1671,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1326,6 +1671,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
break; break;
...@@ -1335,6 +1683,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1335,6 +1683,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
break; break;
...@@ -1353,6 +1704,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1353,6 +1704,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_TOSS_DICE: { case MSG_TOSS_DICE: {
...@@ -1363,6 +1717,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1363,6 +1717,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_ROCK_PAPER_SCISSORS: { case MSG_ROCK_PAPER_SCISSORS: {
...@@ -1408,6 +1765,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1408,6 +1765,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_PLAYER_HINT: { case MSG_PLAYER_HINT: {
...@@ -1416,6 +1776,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1416,6 +1776,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_MATCH_KILL: { case MSG_MATCH_KILL: {
...@@ -1426,6 +1789,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1426,6 +1789,9 @@ int SingleDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
} }
break; break;
} }
...@@ -1447,6 +1813,13 @@ void SingleDuel::GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int ...@@ -1447,6 +1813,13 @@ void SingleDuel::GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int
time_limit[dp->type] -= time_elapsed; time_limit[dp->type] -= time_elapsed;
else time_limit[dp->type] = 0; else time_limit[dp->type] = 0;
time_elapsed = 0; time_elapsed = 0;
#ifdef YGOPRO_SERVER_MODE
if(time_backed[dp->type] > 0 && time_limit[dp->type] < host_info.time_limit && NetServer::IsCanIncreaseTime(last_game_msg, pdata, len)) {
++time_limit[dp->type];
++time_compensator[dp->type];
--time_backed[dp->type];
}
#endif
} }
Process(); Process();
} }
...@@ -1460,8 +1833,16 @@ void SingleDuel::EndDuel() { ...@@ -1460,8 +1833,16 @@ void SingleDuel::EndDuel() {
std::memcpy(pbuf, last_replay.comp_data, last_replay.comp_size); std::memcpy(pbuf, last_replay.comp_data, last_replay.comp_size);
NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size); NetServer::SendBufferToPlayer(players[0], STOC_REPLAY, replaybuf, sizeof(ReplayHeader) + last_replay.comp_size);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
#ifdef YGOPRO_SERVER_MODE
if(!(replay_mode & REPLAY_MODE_WATCHER_NO_SEND)) {
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
}
#else
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#endif //YGOPRO_SERVER_MODE
end_duel(pduel); end_duel(pduel);
event_del(etimer); event_del(etimer);
pduel = 0; pduel = 0;
...@@ -1480,14 +1861,89 @@ void SingleDuel::WaitforResponse(int playerid) { ...@@ -1480,14 +1861,89 @@ void SingleDuel::WaitforResponse(int playerid) {
} else } else
players[playerid]->state = CTOS_RESPONSE; players[playerid]->state = CTOS_RESPONSE;
} }
#ifdef YGOPRO_SERVER_MODE
void SingleDuel::RequestField(DuelPlayer* dp) {
if(dp->type > 1)
return;
int player = dp->type;
NetServer::SendPacketToPlayer(dp, STOC_DUEL_START);
unsigned char startbuf[32], *pbuf = startbuf;
BufferIO::WriteInt8(pbuf, MSG_START);
BufferIO::WriteInt8(pbuf, player);
BufferIO::WriteInt8(pbuf, host_info.duel_rule);
BufferIO::WriteInt32(pbuf, host_info.start_lp);
BufferIO::WriteInt32(pbuf, host_info.start_lp);
BufferIO::WriteInt16(pbuf, 0);
BufferIO::WriteInt16(pbuf, 0);
BufferIO::WriteInt16(pbuf, 0);
BufferIO::WriteInt16(pbuf, 0);
NetServer::SendBufferToPlayer(dp, STOC_GAME_MSG, startbuf, 19);
int newturn_count = 1;
if(turn_player == 1)
newturn_count = 2;
for(int i = 0; i < newturn_count; i++) {
unsigned char turnbuf[2], *pbuf_t = turnbuf;
BufferIO::WriteInt8(pbuf_t, MSG_NEW_TURN);
BufferIO::WriteInt8(pbuf_t, i);
NetServer::SendBufferToPlayer(dp, STOC_GAME_MSG, turnbuf, 2);
}
unsigned char phasebuf[4], *pbuf_p = phasebuf;
BufferIO::WriteInt8(pbuf_p, MSG_NEW_PHASE);
BufferIO::WriteInt16(pbuf_p, phase);
NetServer::SendBufferToPlayer(dp, STOC_GAME_MSG, phasebuf, 3);
unsigned char query_buffer[1024];
int length = query_field_info(pduel, (unsigned char*)query_buffer);
NetServer::SendBufferToPlayer(dp, STOC_GAME_MSG, query_buffer, length);
RefreshMzone(1 - player, 0xefffff, 0, dp);
RefreshMzone(player, 0xefffff, 0, dp);
RefreshSzone(1 - player, 0xefffff, 0, dp);
RefreshSzone(player, 0xefffff, 0, dp);
RefreshHand(1 - player, 0xefffff, 0, dp);
RefreshHand(player, 0xefffff, 0, dp);
RefreshGrave(1 - player, 0xefffff, 0, dp);
RefreshGrave(player, 0xefffff, 0, dp);
RefreshExtra(1 - player, 0xefffff, 0, dp);
RefreshExtra(player, 0xefffff, 0, dp);
RefreshRemoved(1 - player, 0xefffff, 0, dp);
RefreshRemoved(player, 0xefffff, 0, dp);
/*
if(dp == players[last_response])
WaitforResponse(last_response);
*/
STOC_TimeLimit sctl;
sctl.player = 1 - last_response;
sctl.left_time = time_limit[1 - last_response];
NetServer::SendPacketToPlayer(dp, STOC_TIME_LIMIT, sctl);
sctl.player = last_response;
sctl.left_time = time_limit[last_response] - time_elapsed;
NetServer::SendPacketToPlayer(dp, STOC_TIME_LIMIT, sctl);
NetServer::SendPacketToPlayer(dp, STOC_FIELD_FINISH);
}
#endif //YGOPRO_SERVER_MODE
void SingleDuel::TimeConfirm(DuelPlayer* dp) { void SingleDuel::TimeConfirm(DuelPlayer* dp) {
if(host_info.time_limit == 0) if(host_info.time_limit == 0)
return; return;
if(dp->type != last_response) if(dp->type != last_response)
return; return;
players[last_response]->state = CTOS_RESPONSE; players[last_response]->state = CTOS_RESPONSE;
#ifdef YGOPRO_SERVER_MODE
if(time_elapsed < 10 && time_elapsed <= time_compensator[dp->type]){
time_compensator[dp->type] -= time_elapsed;
time_elapsed = 0;
}
else {
time_limit[dp->type] -= time_elapsed;
time_elapsed = 0;
}
#else
if(time_elapsed < 10) if(time_elapsed < 10)
time_elapsed = 0; time_elapsed = 0;
#endif //YGOPRO_SERVER_MODE
} }
inline int SingleDuel::WriteUpdateData(int& player, int location, int& flag, unsigned char*& qbuf, int& use_cache) { inline int SingleDuel::WriteUpdateData(int& player, int location, int& flag, unsigned char*& qbuf, int& use_cache) {
flag |= (QUERY_CODE | QUERY_POSITION); flag |= (QUERY_CODE | QUERY_POSITION);
...@@ -1497,12 +1953,24 @@ inline int SingleDuel::WriteUpdateData(int& player, int location, int& flag, uns ...@@ -1497,12 +1953,24 @@ inline int SingleDuel::WriteUpdateData(int& player, int location, int& flag, uns
int len = query_field_card(pduel, player, location, flag, qbuf, use_cache); int len = query_field_card(pduel, player, location, flag, qbuf, use_cache);
return len; return len;
} }
void SingleDuel::RefreshMzone(int player, int flag, int use_cache) { #ifdef YGOPRO_SERVER_MODE
void SingleDuel::RefreshMzone(int player, int flag, int use_cache, DuelPlayer* dp)
#else
void SingleDuel::RefreshMzone(int player, int flag, int use_cache)
#endif //YGOPRO_SERVER_MODE
{
std::vector<unsigned char> query_buffer; std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER); query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data(); auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_MZONE, flag, qbuf, use_cache); auto len = WriteUpdateData(player, LOCATION_MZONE, flag, qbuf, use_cache);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[player])
#endif
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(replay_recorder);
#endif
int qlen = 0; int qlen = 0;
while(qlen < len) { while(qlen < len) {
const int clen = BufferIO::ReadInt32(qbuf); const int clen = BufferIO::ReadInt32(qbuf);
...@@ -1514,16 +1982,38 @@ void SingleDuel::RefreshMzone(int player, int flag, int use_cache) { ...@@ -1514,16 +1982,38 @@ void SingleDuel::RefreshMzone(int player, int flag, int use_cache) {
std::memset(qbuf, 0, clen - 4); std::memset(qbuf, 0, clen - 4);
qbuf += clen - 4; qbuf += clen - 4;
} }
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[1 - player])
#endif
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
#endif
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(cache_recorder);
#endif
} }
void SingleDuel::RefreshSzone(int player, int flag, int use_cache) { #ifdef YGOPRO_SERVER_MODE
void SingleDuel::RefreshSzone(int player, int flag, int use_cache, DuelPlayer* dp)
#else
void SingleDuel::RefreshSzone(int player, int flag, int use_cache)
#endif //YGOPRO_SERVER_MODE
{
std::vector<unsigned char> query_buffer; std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER); query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data(); auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_SZONE, flag, qbuf, use_cache); auto len = WriteUpdateData(player, LOCATION_SZONE, flag, qbuf, use_cache);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[player])
#endif
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(replay_recorder);
#endif
int qlen = 0; int qlen = 0;
while(qlen < len) { while(qlen < len) {
const int clen = BufferIO::ReadInt32(qbuf); const int clen = BufferIO::ReadInt32(qbuf);
...@@ -1535,16 +2025,38 @@ void SingleDuel::RefreshSzone(int player, int flag, int use_cache) { ...@@ -1535,16 +2025,38 @@ void SingleDuel::RefreshSzone(int player, int flag, int use_cache) {
std::memset(qbuf, 0, clen - 4); std::memset(qbuf, 0, clen - 4);
qbuf += clen - 4; qbuf += clen - 4;
} }
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[1 - player])
#endif
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
#endif
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(cache_recorder);
#endif
} }
void SingleDuel::RefreshHand(int player, int flag, int use_cache) { #ifdef YGOPRO_SERVER_MODE
void SingleDuel::RefreshHand(int player, int flag, int use_cache, DuelPlayer* dp)
#else
void SingleDuel::RefreshHand(int player, int flag, int use_cache)
#endif //YGOPRO_SERVER_MODE
{
std::vector<unsigned char> query_buffer; std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER); query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data(); auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_HAND, flag, qbuf, use_cache); auto len = WriteUpdateData(player, LOCATION_HAND, flag, qbuf, use_cache);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[player])
#endif
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(replay_recorder);
#endif
int qlen = 0; int qlen = 0;
while(qlen < len) { while(qlen < len) {
const int slen = BufferIO::ReadInt32(qbuf); const int slen = BufferIO::ReadInt32(qbuf);
...@@ -1556,27 +2068,115 @@ void SingleDuel::RefreshHand(int player, int flag, int use_cache) { ...@@ -1556,27 +2068,115 @@ void SingleDuel::RefreshHand(int player, int flag, int use_cache) {
std::memset(qbuf, 0, slen - 4); std::memset(qbuf, 0, slen - 4);
qbuf += slen - 4; qbuf += slen - 4;
} }
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[1 - player])
#endif
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
#endif
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(cache_recorder);
#endif
} }
void SingleDuel::RefreshGrave(int player, int flag, int use_cache) { #ifdef YGOPRO_SERVER_MODE
void SingleDuel::RefreshGrave(int player, int flag, int use_cache, DuelPlayer* dp)
#else
void SingleDuel::RefreshGrave(int player, int flag, int use_cache)
#endif //YGOPRO_SERVER_MODE
{
std::vector<unsigned char> query_buffer; std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER); query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data(); auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_GRAVE, flag, qbuf, use_cache); auto len = WriteUpdateData(player, LOCATION_GRAVE, flag, qbuf, use_cache);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[0])
#endif
NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[1])
NetServer::SendBufferToPlayer(players[1], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
#else
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
#endif
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
} }
void SingleDuel::RefreshExtra(int player, int flag, int use_cache) { #ifdef YGOPRO_SERVER_MODE
void SingleDuel::RefreshExtra(int player, int flag, int use_cache, DuelPlayer* dp)
#else
void SingleDuel::RefreshExtra(int player, int flag, int use_cache)
#endif //YGOPRO_SERVER_MODE
{
std::vector<unsigned char> query_buffer; std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER); query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data(); auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_EXTRA, flag, qbuf, use_cache); auto len = WriteUpdateData(player, LOCATION_EXTRA, flag, qbuf, use_cache);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[player])
#endif
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(replay_recorder);
int qlen = 0;
while(qlen < len) {
int clen = BufferIO::ReadInt32(qbuf);
qlen += clen;
if (clen <= LEN_HEADER)
continue;
auto position = GetPosition(qbuf, 8);
if (position & POS_FACEDOWN)
memset(qbuf, 0, clen - 4);
qbuf += clen - 4;
}
if(!dp || dp == players[1 - player])
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
if(!dp)
NetServer::ReSendToPlayer(cache_recorder);
#endif //YGOPRO_SERVER_MODE
}
#ifdef YGOPRO_SERVER_MODE
void SingleDuel::RefreshRemoved(int player, int flag, int use_cache, DuelPlayer* dp) {
std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_REMOVED, flag, qbuf, use_cache);
if(!dp || dp == players[player])
NetServer::SendBufferToPlayer(players[player], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
NetServer::ReSendToPlayer(replay_recorder);
int qlen = 0;
while(qlen < len) {
int clen = BufferIO::ReadInt32(qbuf);
qlen += clen;
if (clen <= LEN_HEADER)
continue;
auto position = GetPosition(qbuf, 8);
if (position & POS_FACEDOWN)
memset(qbuf, 0, clen - 4);
qbuf += clen - 4;
}
if(!dp || dp == players[1 - player])
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
if(!dp)
NetServer::ReSendToPlayer(cache_recorder);
} }
#endif
void SingleDuel::RefreshSingle(int player, int location, int sequence, int flag) { void SingleDuel::RefreshSingle(int player, int location, int sequence, int flag) {
flag |= (QUERY_CODE | QUERY_POSITION); flag |= (QUERY_CODE | QUERY_POSITION);
unsigned char query_buffer[0x1000]; unsigned char query_buffer[0x1000];
...@@ -1599,6 +2199,9 @@ void SingleDuel::RefreshSingle(int player, int location, int sequence, int flag) ...@@ -1599,6 +2199,9 @@ void SingleDuel::RefreshSingle(int player, int location, int sequence, int flag)
NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer, len + 4); NetServer::SendBufferToPlayer(players[1 - player], STOC_GAME_MSG, query_buffer, len + 4);
for (auto pit = observers.begin(); pit != observers.end(); ++pit) for (auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
} }
uint32_t SingleDuel::MessageHandler(intptr_t fduel, uint32_t type) { uint32_t SingleDuel::MessageHandler(intptr_t fduel, uint32_t type) {
if(!enable_log) if(!enable_log)
...@@ -1621,6 +2224,9 @@ void SingleDuel::SingleTimer(evutil_socket_t fd, short events, void* arg) { ...@@ -1621,6 +2224,9 @@ void SingleDuel::SingleTimer(evutil_socket_t fd, short events, void* arg) {
NetServer::ReSendToPlayer(sd->players[1]); NetServer::ReSendToPlayer(sd->players[1]);
for(auto oit = sd->observers.begin(); oit != sd->observers.end(); ++oit) for(auto oit = sd->observers.begin(); oit != sd->observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(sd->cache_recorder, sd->replay_recorder);
#endif
if(sd->players[player] == sd->pplayer[player]) { if(sd->players[player] == sd->pplayer[player]) {
sd->match_result[sd->duel_count++] = 1 - player; sd->match_result[sd->duel_count++] = 1 - player;
sd->tp_player = player; sd->tp_player = player;
...@@ -1636,5 +2242,24 @@ void SingleDuel::SingleTimer(evutil_socket_t fd, short events, void* arg) { ...@@ -1636,5 +2242,24 @@ void SingleDuel::SingleTimer(evutil_socket_t fd, short events, void* arg) {
timeval timeout = { 1, 0 }; timeval timeout = { 1, 0 };
event_add(sd->etimer, &timeout); event_add(sd->etimer, &timeout);
} }
#ifdef YGOPRO_SERVER_MODE
void SingleDuel::TestCard(int code) {
std::random_device rd;
unsigned int seed = rd();
mt19937 rnd(seed);
unsigned int duel_seed = rnd.rand();
set_script_reader((script_reader)DataManager::ScriptReaderEx);
set_card_reader((card_reader)DataManager::CardReader);
set_message_handler((message_handler)SingleDuel::MessageHandler);
rnd.reset(seed);
unsigned long tduel = create_duel(duel_seed);
preload_script(tduel, "./script/special.lua");
preload_script(tduel, "./script/init.lua");
set_player_info(tduel, 0, 8000, 5, 1);
set_player_info(tduel, 1, 8000, 5, 1);
new_card(tduel, code, 0, 0, LOCATION_DECK, 0, POS_FACEUP_ATTACK);
end_duel(tduel);
}
#endif
} }
...@@ -28,15 +28,30 @@ public: ...@@ -28,15 +28,30 @@ public:
int Analyze(unsigned char* msgbuffer, unsigned int len) override; int Analyze(unsigned char* msgbuffer, unsigned int len) override;
void GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len) override; void GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len) override;
void TimeConfirm(DuelPlayer* dp) override; void TimeConfirm(DuelPlayer* dp) override;
#ifdef YGOPRO_SERVER_MODE
void RequestField(DuelPlayer* dp) override;
#endif
void EndDuel() override; void EndDuel() override;
#ifdef YGOPRO_SERVER_MODE
void TestCard(int code) override;
#endif
void DuelEndProc(); void DuelEndProc();
void WaitforResponse(int playerid); void WaitforResponse(int playerid);
#ifdef YGOPRO_SERVER_MODE
void RefreshMzone(int player, int flag = 0x881fff, int use_cache = 1, DuelPlayer* dp = 0);
void RefreshSzone(int player, int flag = 0xe81fff, int use_cache = 1, DuelPlayer* dp = 0);
void RefreshHand(int player, int flag = 0x681fff, int use_cache = 1, DuelPlayer* dp = 0);
void RefreshGrave(int player, int flag = 0x81fff, int use_cache = 1, DuelPlayer* dp = 0);
void RefreshExtra(int player, int flag = 0xe81fff, int use_cache = 1, DuelPlayer* dp = 0);
void RefreshRemoved(int player, int flag = 0x81fff, int use_cache = 1, DuelPlayer* dp = 0);
#else
void RefreshMzone(int player, int flag = 0x881fff, int use_cache = 1); void RefreshMzone(int player, int flag = 0x881fff, int use_cache = 1);
void RefreshSzone(int player, int flag = 0xe81fff, int use_cache = 1); void RefreshSzone(int player, int flag = 0xe81fff, int use_cache = 1);
void RefreshHand(int player, int flag = 0x681fff, int use_cache = 1); void RefreshHand(int player, int flag = 0x681fff, int use_cache = 1);
void RefreshGrave(int player, int flag = 0x81fff, int use_cache = 1); void RefreshGrave(int player, int flag = 0x81fff, int use_cache = 1);
void RefreshExtra(int player, int flag = 0xe81fff, int use_cache = 1); void RefreshExtra(int player, int flag = 0xe81fff, int use_cache = 1);
#endif
void RefreshSingle(int player, int location, int sequence, int flag = 0xf81fff); void RefreshSingle(int player, int location, int sequence, int flag = 0xf81fff);
static uint32_t MessageHandler(intptr_t fduel, uint32_t type); static uint32_t MessageHandler(intptr_t fduel, uint32_t type);
...@@ -54,6 +69,12 @@ protected: ...@@ -54,6 +69,12 @@ protected:
unsigned char hand_result[2]{}; unsigned char hand_result[2]{};
unsigned char last_response{ 0 }; unsigned char last_response{ 0 };
std::set<DuelPlayer*> observers; std::set<DuelPlayer*> observers;
#ifdef YGOPRO_SERVER_MODE
DuelPlayer* cache_recorder;
DuelPlayer* replay_recorder;
unsigned char turn_player;
unsigned short phase;
#endif
Replay last_replay; Replay last_replay;
bool match_mode{ false }; bool match_mode{ false };
int match_kill{ 0 }; int match_kill{ 0 };
...@@ -62,8 +83,14 @@ protected: ...@@ -62,8 +83,14 @@ protected:
unsigned char match_result[3]{}; unsigned char match_result[3]{};
short time_limit[2]{}; short time_limit[2]{};
short time_elapsed{ 0 }; short time_elapsed{ 0 };
#ifdef YGOPRO_SERVER_MODE
short time_compensator[2];
short time_backed[2];
unsigned char last_game_msg;
#endif
}; };
} }
#endif //SINGLE_DUEL_H #endif //SINGLE_DUEL_H
...@@ -7,12 +7,19 @@ ...@@ -7,12 +7,19 @@
namespace ygo { namespace ygo {
#ifdef YGOPRO_SERVER_MODE
extern unsigned short replay_mode;
#endif
TagDuel::TagDuel() { TagDuel::TagDuel() {
for(int i = 0; i < 4; ++i) { for(int i = 0; i < 4; ++i) {
players[i] = 0; players[i] = 0;
ready[i] = false; ready[i] = false;
surrender[i] = false; surrender[i] = false;
} }
#ifdef YGOPRO_SERVER_MODE
cache_recorder = 0;
replay_recorder = 0;
#endif
} }
TagDuel::~TagDuel() { TagDuel::~TagDuel() {
} }
...@@ -25,8 +32,17 @@ void TagDuel::Chat(DuelPlayer* dp, unsigned char* pdata, int len) { ...@@ -25,8 +32,17 @@ void TagDuel::Chat(DuelPlayer* dp, unsigned char* pdata, int len) {
NetServer::SendBufferToPlayer(players[i], STOC_CHAT, scc, scc_size); NetServer::SendBufferToPlayer(players[i], STOC_CHAT, scc, scc_size);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::ReSendToPlayer(cache_recorder);
if(replay_recorder && replay_mode & REPLAY_MODE_INCLUDE_CHAT)
NetServer::ReSendToPlayer(replay_recorder);
#endif
} }
void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) { void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {
#ifdef YGOPRO_SERVER_MODE
bool is_recorder = false;
#endif
if(!is_creater) { if(!is_creater) {
if(dp->game && dp->type != 0xff) { if(dp->game && dp->type != 0xff) {
STOC_ErrorMsg scem; STOC_ErrorMsg scem;
...@@ -52,6 +68,18 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) { ...@@ -52,6 +68,18 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {
wchar_t jpass[20]; wchar_t jpass[20];
BufferIO::NullTerminate(pkt->pass); BufferIO::NullTerminate(pkt->pass);
BufferIO::CopyCharArray(pkt->pass, jpass); BufferIO::CopyCharArray(pkt->pass, jpass);
#ifdef YGOPRO_SERVER_MODE
if(!std::wcscmp(jpass, L"the Big Brother") && !cache_recorder) {
is_recorder = true;
cache_recorder = dp;
}
#ifndef YGOPRO_SERVER_MODE_DISABLE_CLOUD_REPLAY
if(!std::wcscmp(jpass, L"Marshtomp") && !replay_recorder) {
is_recorder = true;
replay_recorder = dp;
}
#endif //YGOPRO_SERVER_MODE_DISABLE_CLOUD_REPLAY
#else
if(std::wcscmp(jpass, pass)) { if(std::wcscmp(jpass, pass)) {
STOC_ErrorMsg scem; STOC_ErrorMsg scem;
scem.msg = ERRMSG_JOINERROR; scem.msg = ERRMSG_JOINERROR;
...@@ -59,6 +87,7 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) { ...@@ -59,6 +87,7 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {
NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem); NetServer::SendPacketToPlayer(dp, STOC_ERROR_MSG, scem);
return; return;
} }
#endif //YGOPRO_SERVER_MODE
} }
dp->game = this; dp->game = this;
if(!players[0] && !players[1] && !players[2] && !players[3] && observers.size() == 0) if(!players[0] && !players[1] && !players[2] && !players[3] && observers.size() == 0)
...@@ -67,6 +96,13 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) { ...@@ -67,6 +96,13 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {
scjg.info = host_info; scjg.info = host_info;
STOC_TypeChange sctc; STOC_TypeChange sctc;
sctc.type = (host_player == dp) ? 0x10 : 0; sctc.type = (host_player == dp) ? 0x10 : 0;
#ifdef YGOPRO_SERVER_MODE
if(is_recorder) {
dp->type = 9;
sctc.type = NETPLAYER_TYPE_OBSERVER;
}
else
#endif
if(!players[0] || !players[1] || !players[2] || !players[3]) { if(!players[0] || !players[1] || !players[2] || !players[3]) {
STOC_HS_PlayerEnter scpe; STOC_HS_PlayerEnter scpe;
BufferIO::CopyCharArray(dp->name, scpe.name); BufferIO::CopyCharArray(dp->name, scpe.name);
...@@ -83,6 +119,12 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) { ...@@ -83,6 +119,12 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {
NetServer::SendPacketToPlayer(players[i], STOC_HS_PLAYER_ENTER, scpe); NetServer::SendPacketToPlayer(players[i], STOC_HS_PLAYER_ENTER, scpe);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_ENTER, scpe);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_ENTER, scpe);
#endif
players[scpe.pos] = dp; players[scpe.pos] = dp;
dp->type = scpe.pos; dp->type = scpe.pos;
sctc.type |= scpe.pos; sctc.type |= scpe.pos;
...@@ -97,6 +139,12 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) { ...@@ -97,6 +139,12 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {
NetServer::SendPacketToPlayer(players[i], STOC_HS_WATCH_CHANGE, scwc); NetServer::SendPacketToPlayer(players[i], STOC_HS_WATCH_CHANGE, scwc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc); NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_WATCH_CHANGE, scwc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_WATCH_CHANGE, scwc);
#endif
} }
NetServer::SendPacketToPlayer(dp, STOC_JOIN_GAME, scjg); NetServer::SendPacketToPlayer(dp, STOC_JOIN_GAME, scjg);
NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc); NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc);
...@@ -120,9 +168,38 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) { ...@@ -120,9 +168,38 @@ void TagDuel::JoinGame(DuelPlayer* dp, unsigned char* pdata, bool is_creater) {
} }
void TagDuel::LeaveGame(DuelPlayer* dp) { void TagDuel::LeaveGame(DuelPlayer* dp) {
if(dp == host_player) { if(dp == host_player) {
#ifdef YGOPRO_SERVER_MODE
int host_pos;
if(players[0] && dp->type != 0) {
host_pos = 0;
host_player = players[0];
} else if(players[1] && dp->type != 1) {
host_pos = 1;
host_player = players[1];
} else if(players[2] && dp->type != 2) {
host_pos = 2;
host_player = players[2];
} else if(players[3] && dp->type != 3) {
host_pos = 3;
host_player = players[3];
} else {
EndDuel();
NetServer::StopServer();
return;
}
if(duel_stage == DUEL_STAGE_BEGIN) {
ready[host_pos] = false;
STOC_TypeChange sctc;
sctc.type = 0x10 | host_pos;
NetServer::SendPacketToPlayer(players[host_pos], STOC_TYPE_CHANGE, sctc);
}
}
if(dp->type == NETPLAYER_TYPE_OBSERVER) {
#else
EndDuel(); EndDuel();
NetServer::StopServer(); NetServer::StopServer();
} else if(dp->type == NETPLAYER_TYPE_OBSERVER) { } else if(dp->type == NETPLAYER_TYPE_OBSERVER) {
#endif //YGOPRO_SERVER_MODE
observers.erase(dp); observers.erase(dp);
if(duel_stage == DUEL_STAGE_BEGIN) { if(duel_stage == DUEL_STAGE_BEGIN) {
STOC_HS_WatchChange scwc; STOC_HS_WatchChange scwc;
...@@ -132,6 +209,12 @@ void TagDuel::LeaveGame(DuelPlayer* dp) { ...@@ -132,6 +209,12 @@ void TagDuel::LeaveGame(DuelPlayer* dp) {
NetServer::SendPacketToPlayer(players[i], STOC_HS_WATCH_CHANGE, scwc); NetServer::SendPacketToPlayer(players[i], STOC_HS_WATCH_CHANGE, scwc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc); NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_WATCH_CHANGE, scwc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_WATCH_CHANGE, scwc);
#endif
} }
NetServer::DisconnectPlayer(dp); NetServer::DisconnectPlayer(dp);
} else { } else {
...@@ -145,6 +228,12 @@ void TagDuel::LeaveGame(DuelPlayer* dp) { ...@@ -145,6 +228,12 @@ void TagDuel::LeaveGame(DuelPlayer* dp) {
NetServer::SendPacketToPlayer(players[i], STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(players[i], STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_CHANGE, scpc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_CHANGE, scpc);
#endif
NetServer::DisconnectPlayer(dp); NetServer::DisconnectPlayer(dp);
} else if(duel_stage != DUEL_STAGE_END) { } else if(duel_stage != DUEL_STAGE_END) {
EndDuel(); EndDuel();
...@@ -181,6 +270,16 @@ void TagDuel::ToDuelist(DuelPlayer* dp) { ...@@ -181,6 +270,16 @@ void TagDuel::ToDuelist(DuelPlayer* dp) {
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_ENTER, scpe);
NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc); NetServer::SendPacketToPlayer(*pit, STOC_HS_WATCH_CHANGE, scwc);
} }
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder) {
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_ENTER, scpe);
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_WATCH_CHANGE, scwc);
}
if(replay_recorder) {
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_ENTER, scpe);
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_WATCH_CHANGE, scwc);
}
#endif
STOC_TypeChange sctc; STOC_TypeChange sctc;
sctc.type = (dp == host_player ? 0x10 : 0) | dp->type; sctc.type = (dp == host_player ? 0x10 : 0) | dp->type;
NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc); NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc);
...@@ -197,6 +296,12 @@ void TagDuel::ToDuelist(DuelPlayer* dp) { ...@@ -197,6 +296,12 @@ void TagDuel::ToDuelist(DuelPlayer* dp) {
NetServer::SendPacketToPlayer(players[i], STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(players[i], STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_CHANGE, scpc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_CHANGE, scpc);
#endif
STOC_TypeChange sctc; STOC_TypeChange sctc;
sctc.type = (dp == host_player ? 0x10 : 0) | dptype; sctc.type = (dp == host_player ? 0x10 : 0) | dptype;
NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc); NetServer::SendPacketToPlayer(dp, STOC_TYPE_CHANGE, sctc);
...@@ -215,6 +320,12 @@ void TagDuel::ToObserver(DuelPlayer* dp) { ...@@ -215,6 +320,12 @@ void TagDuel::ToObserver(DuelPlayer* dp) {
NetServer::SendPacketToPlayer(players[i], STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(players[i], STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_CHANGE, scpc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_CHANGE, scpc);
#endif
players[dp->type] = 0; players[dp->type] = 0;
ready[dp->type] = false; ready[dp->type] = false;
dp->type = NETPLAYER_TYPE_OBSERVER; dp->type = NETPLAYER_TYPE_OBSERVER;
...@@ -254,6 +365,12 @@ void TagDuel::PlayerReady(DuelPlayer* dp, bool is_ready) { ...@@ -254,6 +365,12 @@ void TagDuel::PlayerReady(DuelPlayer* dp, bool is_ready) {
NetServer::SendPacketToPlayer(players[i], STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(players[i], STOC_HS_PLAYER_CHANGE, scpc);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc); NetServer::SendPacketToPlayer(*pit, STOC_HS_PLAYER_CHANGE, scpc);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendPacketToPlayer(cache_recorder, STOC_HS_PLAYER_CHANGE, scpc);
if(replay_recorder)
NetServer::SendPacketToPlayer(replay_recorder, STOC_HS_PLAYER_CHANGE, scpc);
#endif
} }
void TagDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) { void TagDuel::PlayerKick(DuelPlayer* dp, unsigned char pos) {
if(pos > 3 || dp != host_player || dp == players[pos] || !players[pos]) if(pos > 3 || dp != host_player || dp == players[pos] || !players[pos])
...@@ -266,13 +383,19 @@ void TagDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) { ...@@ -266,13 +383,19 @@ void TagDuel::UpdateDeck(DuelPlayer* dp, unsigned char* pdata, int len) {
if (len < 8 || len > sizeof(CTOS_DeckData)) if (len < 8 || len > sizeof(CTOS_DeckData))
return; return;
bool valid = true; bool valid = true;
const int deck_size = len - 2 * sizeof(int32_t);
CTOS_DeckData deckbuf; CTOS_DeckData deckbuf;
std::memcpy(&deckbuf, pdata, len); std::memcpy(&deckbuf, pdata, len);
if (deckbuf.mainc < 0 || deckbuf.mainc > MAINC_MAX) if (deckbuf.mainc < 0 || deckbuf.mainc > MAINC_MAX)
valid = false; valid = false;
else if (deckbuf.sidec < 0 || deckbuf.sidec > SIDEC_MAX) else if (deckbuf.sidec < 0 || deckbuf.sidec > SIDEC_MAX)
valid = false; valid = false;
else if (len < (2 + deckbuf.mainc + deckbuf.sidec) * (int)sizeof(int32_t)) else if
#ifdef YGOPRO_SERVER_MODE
(deck_size < (deckbuf.mainc + deckbuf.sidec) * (int)sizeof(int32_t) || deck_size > MAINC_MAX + SIDEC_MAX)
#else
(len < (2 + deckbuf.mainc + deckbuf.sidec) * (int)sizeof(int32_t))
#endif
valid = false; valid = false;
if (!valid) { if (!valid) {
STOC_ErrorMsg scem; STOC_ErrorMsg scem;
...@@ -296,6 +419,13 @@ void TagDuel::StartDuel(DuelPlayer* dp) { ...@@ -296,6 +419,13 @@ void TagDuel::StartDuel(DuelPlayer* dp) {
(*oit)->state = CTOS_LEAVE_GAME; (*oit)->state = CTOS_LEAVE_GAME;
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
} }
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
cache_recorder->state = CTOS_LEAVE_GAME;
if(replay_recorder)
replay_recorder->state = CTOS_LEAVE_GAME;
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
unsigned char deckbuff[12]; unsigned char deckbuff[12];
auto pbuf = deckbuff; auto pbuf = deckbuff;
BufferIO::WriteInt16(pbuf, (short)pdeck[0].main.size()); BufferIO::WriteInt16(pbuf, (short)pdeck[0].main.size());
...@@ -335,6 +465,9 @@ void TagDuel::HandResult(DuelPlayer* dp, unsigned char res) { ...@@ -335,6 +465,9 @@ void TagDuel::HandResult(DuelPlayer* dp, unsigned char res) {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
schr.res1 = hand_result[1]; schr.res1 = hand_result[1];
schr.res2 = hand_result[0]; schr.res2 = hand_result[0];
NetServer::SendPacketToPlayer(players[2], STOC_HAND_RESULT, schr); NetServer::SendPacketToPlayer(players[2], STOC_HAND_RESULT, schr);
...@@ -387,6 +520,11 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -387,6 +520,11 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
dp->state = CTOS_RESPONSE; dp->state = CTOS_RESPONSE;
std::random_device rd; std::random_device rd;
unsigned int seed = rd(); unsigned int seed = rd();
#ifdef YGOPRO_SERVER_MODE
if(pre_seed[0] > 0) {
seed = pre_seed[0];
}
#endif
mt19937 rnd((uint_fast32_t)seed); mt19937 rnd((uint_fast32_t)seed);
auto duel_seed = rnd.rand(); auto duel_seed = rnd.rand();
ReplayHeader rh; ReplayHeader rh;
...@@ -470,11 +608,26 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) { ...@@ -470,11 +608,26 @@ void TagDuel::TPResult(DuelPlayer* dp, unsigned char tp) {
else startbuf[1] = 0x11; else startbuf[1] = 0x11;
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::SendBufferToPlayer(*oit, STOC_GAME_MSG, startbuf, 19); NetServer::SendBufferToPlayer(*oit, STOC_GAME_MSG, startbuf, 19);
#ifdef YGOPRO_SERVER_MODE
if(cache_recorder)
NetServer::SendBufferToPlayer(cache_recorder, STOC_GAME_MSG, startbuf, 19);
if(replay_recorder)
NetServer::SendBufferToPlayer(replay_recorder, STOC_GAME_MSG, startbuf, 19);
turn_player = 0;
phase = 1;
#endif
RefreshExtra(0); RefreshExtra(0);
RefreshExtra(1); RefreshExtra(1);
start_duel(pduel, opt); start_duel(pduel, opt);
if(host_info.time_limit) { if(host_info.time_limit) {
time_elapsed = 0; time_elapsed = 0;
#ifdef YGOPRO_SERVER_MODE
time_compensator[0] = host_info.time_limit;
time_compensator[1] = host_info.time_limit;
time_backed[0] = host_info.time_limit;
time_backed[1] = host_info.time_limit;
last_game_msg = 0;
#endif
timeval timeout = { 1, 0 }; timeval timeout = { 1, 0 };
event_add(etimer, &timeout); event_add(etimer, &timeout);
} }
...@@ -509,12 +662,18 @@ void TagDuel::DuelEndProc() { ...@@ -509,12 +662,18 @@ void TagDuel::DuelEndProc() {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
NetServer::StopServer();
#else
duel_stage = DUEL_STAGE_END; duel_stage = DUEL_STAGE_END;
#endif
} }
void TagDuel::Surrender(DuelPlayer* dp) { void TagDuel::Surrender(DuelPlayer* dp) {
if(dp->type > 3 || !pduel) if(dp->type > 3 || !pduel)
return; return;
uint32_t player = dp->type; uint32_t player = dp->type;
#if !defined(YGOPRO_SERVER_MODE) || defined(SERVER_TAG_SURRENDER_CONFIRM)
if(surrender[player]) if(surrender[player])
return; return;
static const uint32_t teammatemap[] = { 1, 0, 3, 2 }; static const uint32_t teammatemap[] = { 1, 0, 3, 2 };
...@@ -525,6 +684,7 @@ void TagDuel::Surrender(DuelPlayer* dp) { ...@@ -525,6 +684,7 @@ void TagDuel::Surrender(DuelPlayer* dp) {
NetServer::SendPacketToPlayer(players[teammate], STOC_TEAMMATE_SURRENDER); NetServer::SendPacketToPlayer(players[teammate], STOC_TEAMMATE_SURRENDER);
return; return;
} }
#endif
static const uint32_t winplayermap[] = { 1, 1, 0, 0 }; static const uint32_t winplayermap[] = { 1, 1, 0, 0 };
unsigned char wbuf[3]; unsigned char wbuf[3];
wbuf[0] = MSG_WIN; wbuf[0] = MSG_WIN;
...@@ -536,6 +696,9 @@ void TagDuel::Surrender(DuelPlayer* dp) { ...@@ -536,6 +696,9 @@ void TagDuel::Surrender(DuelPlayer* dp) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
EndDuel(); EndDuel();
DuelEndProc(); DuelEndProc();
event_del(etimer); event_del(etimer);
...@@ -546,6 +709,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -546,6 +709,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
while (pbuf - msgbuffer < (int)len) { while (pbuf - msgbuffer < (int)len) {
offset = pbuf; offset = pbuf;
unsigned char engType = BufferIO::ReadUInt8(pbuf); unsigned char engType = BufferIO::ReadUInt8(pbuf);
#ifdef YGOPRO_SERVER_MODE
last_game_msg = engType;
#endif
switch (engType) { switch (engType) {
case MSG_RESET_TIME: { case MSG_RESET_TIME: {
player = BufferIO::ReadInt8(pbuf); player = BufferIO::ReadInt8(pbuf);
...@@ -596,6 +762,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -596,6 +762,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case 10: case 10:
...@@ -607,6 +776,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -607,6 +776,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
} }
...@@ -621,6 +793,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -621,6 +793,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
EndDuel(); EndDuel();
return 2; return 2;
} }
...@@ -795,6 +970,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -795,6 +970,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CONFIRM_EXTRATOP: { case MSG_CONFIRM_EXTRATOP: {
...@@ -807,6 +985,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -807,6 +985,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for (auto oit = observers.begin(); oit != observers.end(); ++oit) for (auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CONFIRM_CARDS: { case MSG_CONFIRM_CARDS: {
...@@ -820,6 +1001,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -820,6 +1001,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
} else { } else {
pbuf += count * 7; pbuf += count * 7;
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
...@@ -834,12 +1018,18 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -834,12 +1018,18 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SHUFFLE_HAND: { case MSG_SHUFFLE_HAND: {
player = BufferIO::ReadUInt8(pbuf); player = BufferIO::ReadUInt8(pbuf);
count = BufferIO::ReadUInt8(pbuf); count = BufferIO::ReadUInt8(pbuf);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, (pbuf - offset) + count * 4); NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, (pbuf - offset) + count * 4);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(replay_recorder);
#endif
for(int i = 0; i < count; ++i) for(int i = 0; i < count; ++i)
BufferIO::WriteInt32(pbuf, 0); BufferIO::WriteInt32(pbuf, 0);
for(int i = 0; i < 4; ++i) for(int i = 0; i < 4; ++i)
...@@ -847,6 +1037,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -847,6 +1037,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(cache_recorder);
#endif
RefreshHand(player, 0x781fff, 0); RefreshHand(player, 0x781fff, 0);
break; break;
} }
...@@ -854,6 +1047,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -854,6 +1047,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
player = BufferIO::ReadUInt8(pbuf); player = BufferIO::ReadUInt8(pbuf);
count = BufferIO::ReadUInt8(pbuf); count = BufferIO::ReadUInt8(pbuf);
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, (pbuf - offset) + count * 4); NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, (pbuf - offset) + count * 4);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(replay_recorder);
#endif
for(int i = 0; i < count; ++i) for(int i = 0; i < count; ++i)
BufferIO::WriteInt32(pbuf, 0); BufferIO::WriteInt32(pbuf, 0);
for(int i = 0; i < 4; ++i) for(int i = 0; i < 4; ++i)
...@@ -861,6 +1057,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -861,6 +1057,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(cache_recorder);
#endif
RefreshExtra(player); RefreshExtra(player);
break; break;
} }
...@@ -872,6 +1071,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -872,6 +1071,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SWAP_GRAVE_DECK: { case MSG_SWAP_GRAVE_DECK: {
...@@ -882,6 +1084,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -882,6 +1084,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshGrave(player); RefreshGrave(player);
break; break;
} }
...@@ -892,6 +1097,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -892,6 +1097,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_DECK_TOP: { case MSG_DECK_TOP: {
...@@ -902,6 +1110,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -902,6 +1110,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SHUFFLE_SET_CARD: { case MSG_SHUFFLE_SET_CARD: {
...@@ -914,6 +1125,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -914,6 +1125,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
if(loc == LOCATION_MZONE) { if(loc == LOCATION_MZONE) {
RefreshMzone(0, 0x181fff, 0); RefreshMzone(0, 0x181fff, 0);
RefreshMzone(1, 0x181fff, 0); RefreshMzone(1, 0x181fff, 0);
...@@ -925,14 +1139,26 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -925,14 +1139,26 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
} }
case MSG_NEW_TURN: { case MSG_NEW_TURN: {
int r_player = BufferIO::ReadInt8(pbuf); int r_player = BufferIO::ReadInt8(pbuf);
#ifdef YGOPRO_SERVER_MODE
turn_player = r_player & 0x1;
#endif
time_limit[0] = host_info.time_limit; time_limit[0] = host_info.time_limit;
time_limit[1] = host_info.time_limit; time_limit[1] = host_info.time_limit;
#ifdef YGOPRO_SERVER_MODE
time_compensator[0] = host_info.time_limit;
time_compensator[1] = host_info.time_limit;
time_backed[0] = host_info.time_limit;
time_backed[1] = host_info.time_limit;
#endif
NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, offset, pbuf - offset);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
NetServer::ReSendToPlayer(players[2]); NetServer::ReSendToPlayer(players[2]);
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
if(!(r_player & 0x2)) { if(!(r_player & 0x2)) {
if(turn_count > 0) { if(turn_count > 0) {
if(turn_count % 2 == 0) { if(turn_count % 2 == 0) {
...@@ -955,13 +1181,20 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -955,13 +1181,20 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
break; break;
} }
case MSG_NEW_PHASE: { case MSG_NEW_PHASE: {
#ifdef YGOPRO_SERVER_MODE
phase = BufferIO::ReadInt16(pbuf);
#else
pbuf += 2; pbuf += 2;
#endif
NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, offset, pbuf - offset);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
NetServer::ReSendToPlayer(players[2]); NetServer::ReSendToPlayer(players[2]);
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -989,6 +1222,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -989,6 +1222,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
if (cl != 0 && (cl & LOCATION_OVERLAY) == 0 && (cl != pl || pc != cc)) if (cl != 0 && (cl & LOCATION_OVERLAY) == 0 && (cl != pl || pc != cc))
RefreshSingle(cc, cl, cs); RefreshSingle(cc, cl, cs);
break; break;
...@@ -1006,6 +1242,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1006,6 +1242,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
if((pp & POS_FACEDOWN) && (cp & POS_FACEUP)) if((pp & POS_FACEDOWN) && (cp & POS_FACEUP))
RefreshSingle(cc, cl, cs); RefreshSingle(cc, cl, cs);
break; break;
...@@ -1019,6 +1258,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1019,6 +1258,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SWAP: { case MSG_SWAP: {
...@@ -1035,6 +1277,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1035,6 +1277,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshSingle(c1, l1, s1); RefreshSingle(c1, l1, s1);
RefreshSingle(c2, l2, s2); RefreshSingle(c2, l2, s2);
break; break;
...@@ -1047,6 +1292,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1047,6 +1292,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SUMMONING: { case MSG_SUMMONING: {
...@@ -1057,6 +1305,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1057,6 +1305,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SUMMONED: { case MSG_SUMMONED: {
...@@ -1066,6 +1317,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1066,6 +1317,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1080,6 +1334,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1080,6 +1334,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_SPSUMMONED: { case MSG_SPSUMMONED: {
...@@ -1089,6 +1346,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1089,6 +1346,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1104,6 +1364,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1104,6 +1364,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_FLIPSUMMONED: { case MSG_FLIPSUMMONED: {
...@@ -1113,6 +1376,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1113,6 +1376,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1127,6 +1393,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1127,6 +1393,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CHAINED: { case MSG_CHAINED: {
...@@ -1137,6 +1406,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1137,6 +1406,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1153,6 +1425,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1153,6 +1425,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CHAIN_SOLVED: { case MSG_CHAIN_SOLVED: {
...@@ -1163,6 +1438,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1163,6 +1438,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1178,6 +1456,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1178,6 +1456,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
RefreshSzone(0); RefreshSzone(0);
...@@ -1194,6 +1475,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1194,6 +1475,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CHAIN_DISABLED: { case MSG_CHAIN_DISABLED: {
...@@ -1204,6 +1488,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1204,6 +1488,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CARD_SELECTED: { case MSG_CARD_SELECTED: {
...@@ -1222,6 +1509,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1222,6 +1509,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_BECOME_TARGET: { case MSG_BECOME_TARGET: {
...@@ -1233,6 +1523,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1233,6 +1523,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_DRAW: { case MSG_DRAW: {
...@@ -1241,6 +1534,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1241,6 +1534,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
pbufw = pbuf; pbufw = pbuf;
pbuf += count * 4; pbuf += count * 4;
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, offset, pbuf - offset);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(replay_recorder);
#endif
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
if(!(pbufw[3] & 0x80)) if(!(pbufw[3] & 0x80))
BufferIO::WriteInt32(pbufw, 0); BufferIO::WriteInt32(pbufw, 0);
...@@ -1252,6 +1548,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1252,6 +1548,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(cache_recorder);
#endif
break; break;
} }
case MSG_DAMAGE: { case MSG_DAMAGE: {
...@@ -1262,6 +1561,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1262,6 +1561,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_RECOVER: { case MSG_RECOVER: {
...@@ -1272,6 +1574,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1272,6 +1574,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_EQUIP: { case MSG_EQUIP: {
...@@ -1282,6 +1587,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1282,6 +1587,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_LPUPDATE: { case MSG_LPUPDATE: {
...@@ -1292,6 +1600,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1292,6 +1600,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_UNEQUIP: { case MSG_UNEQUIP: {
...@@ -1302,6 +1613,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1302,6 +1613,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CARD_TARGET: { case MSG_CARD_TARGET: {
...@@ -1312,6 +1626,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1312,6 +1626,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_CANCEL_TARGET: { case MSG_CANCEL_TARGET: {
...@@ -1322,6 +1639,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1322,6 +1639,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_PAY_LPCOST: { case MSG_PAY_LPCOST: {
...@@ -1332,6 +1652,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1332,6 +1652,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_ADD_COUNTER: { case MSG_ADD_COUNTER: {
...@@ -1342,6 +1665,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1342,6 +1665,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_REMOVE_COUNTER: { case MSG_REMOVE_COUNTER: {
...@@ -1352,6 +1678,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1352,6 +1678,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_ATTACK: { case MSG_ATTACK: {
...@@ -1362,6 +1691,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1362,6 +1691,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_BATTLE: { case MSG_BATTLE: {
...@@ -1372,6 +1704,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1372,6 +1704,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_ATTACK_DISABLED: { case MSG_ATTACK_DISABLED: {
...@@ -1381,6 +1716,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1381,6 +1716,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_DAMAGE_STEP_START: { case MSG_DAMAGE_STEP_START: {
...@@ -1390,6 +1728,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1390,6 +1728,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
break; break;
...@@ -1401,6 +1742,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1401,6 +1742,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshMzone(0); RefreshMzone(0);
RefreshMzone(1); RefreshMzone(1);
break; break;
...@@ -1421,6 +1765,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1421,6 +1765,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_TOSS_DICE: { case MSG_TOSS_DICE: {
...@@ -1433,6 +1780,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1433,6 +1780,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_ROCK_PAPER_SCISSORS: { case MSG_ROCK_PAPER_SCISSORS: {
...@@ -1482,6 +1832,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1482,6 +1832,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_PLAYER_HINT: { case MSG_PLAYER_HINT: {
...@@ -1492,6 +1845,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1492,6 +1845,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
break; break;
} }
case MSG_TAG_SWAP: { case MSG_TAG_SWAP: {
...@@ -1520,6 +1876,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) { ...@@ -1520,6 +1876,9 @@ int TagDuel::Analyze(unsigned char* msgbuffer, unsigned int len) {
NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset); NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, offset, pbuf - offset);
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
RefreshExtra(player); RefreshExtra(player);
RefreshMzone(0, 0x81fff, 0); RefreshMzone(0, 0x81fff, 0);
RefreshMzone(1, 0x81fff, 0); RefreshMzone(1, 0x81fff, 0);
...@@ -1552,6 +1911,13 @@ void TagDuel::GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len ...@@ -1552,6 +1911,13 @@ void TagDuel::GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len
time_limit[resp_type] -= time_elapsed; time_limit[resp_type] -= time_elapsed;
else time_limit[resp_type] = 0; else time_limit[resp_type] = 0;
time_elapsed = 0; time_elapsed = 0;
#ifdef YGOPRO_SERVER_MODE
if(time_backed[resp_type] > 0 && time_limit[resp_type] < host_info.time_limit && NetServer::IsCanIncreaseTime(last_game_msg, pdata, len)) {
++time_limit[resp_type];
++time_compensator[resp_type];
--time_backed[resp_type];
}
#endif
} }
Process(); Process();
} }
...@@ -1567,8 +1933,16 @@ void TagDuel::EndDuel() { ...@@ -1567,8 +1933,16 @@ void TagDuel::EndDuel() {
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
NetServer::ReSendToPlayer(players[2]); NetServer::ReSendToPlayer(players[2]);
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
#ifdef YGOPRO_SERVER_MODE
if(!(replay_mode & REPLAY_MODE_WATCHER_NO_SEND)) {
for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit);
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
}
#else
for(auto oit = observers.begin(); oit != observers.end(); ++oit) for(auto oit = observers.begin(); oit != observers.end(); ++oit)
NetServer::ReSendToPlayer(*oit); NetServer::ReSendToPlayer(*oit);
#endif
end_duel(pduel); end_duel(pduel);
event_del(etimer); event_del(etimer);
pduel = 0; pduel = 0;
...@@ -1591,14 +1965,89 @@ void TagDuel::WaitforResponse(int playerid) { ...@@ -1591,14 +1965,89 @@ void TagDuel::WaitforResponse(int playerid) {
} else } else
cur_player[playerid]->state = CTOS_RESPONSE; cur_player[playerid]->state = CTOS_RESPONSE;
} }
#ifdef YGOPRO_SERVER_MODE
void TagDuel::RequestField(DuelPlayer* dp) {
if(dp->type > 3)
return;
int player = (dp->type > 1) ? 1 : 0;
NetServer::SendPacketToPlayer(dp, STOC_DUEL_START);
unsigned char startbuf[32], *pbuf = startbuf;
BufferIO::WriteInt8(pbuf, MSG_START);
BufferIO::WriteInt8(pbuf, player);
BufferIO::WriteInt8(pbuf, host_info.duel_rule);
BufferIO::WriteInt32(pbuf, host_info.start_lp);
BufferIO::WriteInt32(pbuf, host_info.start_lp);
BufferIO::WriteInt16(pbuf, 0);
BufferIO::WriteInt16(pbuf, 0);
BufferIO::WriteInt16(pbuf, 0);
BufferIO::WriteInt16(pbuf, 0);
NetServer::SendBufferToPlayer(dp, STOC_GAME_MSG, startbuf, 19);
int newturn_count = turn_count % 4;
if(newturn_count == 0)
newturn_count = 4;
for(int i = 0; i < newturn_count; i++) {
unsigned char turnbuf[2], *pbuf_t = turnbuf;
BufferIO::WriteInt8(pbuf_t, MSG_NEW_TURN);
BufferIO::WriteInt8(pbuf_t, i % 2);
NetServer::SendBufferToPlayer(dp, STOC_GAME_MSG, turnbuf, 2);
}
unsigned char phasebuf[4], *pbuf_p = phasebuf;
BufferIO::WriteInt8(pbuf_p, MSG_NEW_PHASE);
BufferIO::WriteInt16(pbuf_p, phase);
NetServer::SendBufferToPlayer(dp, STOC_GAME_MSG, phasebuf, 3);
unsigned char query_buffer[1024];
int length = query_field_info(pduel, (unsigned char*)query_buffer);
NetServer::SendBufferToPlayer(dp, STOC_GAME_MSG, query_buffer, length);
RefreshMzone(1 - player, 0xefffff, 0, dp);
RefreshMzone(player, 0xefffff, 0, dp);
RefreshSzone(1 - player, 0xefffff, 0, dp);
RefreshSzone(player, 0xefffff, 0, dp);
RefreshHand(1 - player, 0xefffff, 0, dp);
RefreshHand(player, 0xefffff, 0, dp);
RefreshGrave(1 - player, 0xefffff, 0, dp);
RefreshGrave(player, 0xefffff, 0, dp);
RefreshExtra(1 - player, 0xefffff, 0, dp);
RefreshExtra(player, 0xefffff, 0, dp);
RefreshRemoved(1 - player, 0xefffff, 0, dp);
RefreshRemoved(player, 0xefffff, 0, dp);
/*
if(dp == cur_player[last_response])
WaitforResponse(last_response);
*/
STOC_TimeLimit sctl;
sctl.player = 1 - last_response;
sctl.left_time = time_limit[1 - last_response];
NetServer::SendPacketToPlayer(dp, STOC_TIME_LIMIT, sctl);
sctl.player = last_response;
sctl.left_time = time_limit[last_response] - time_elapsed;
NetServer::SendPacketToPlayer(dp, STOC_TIME_LIMIT, sctl);
NetServer::SendPacketToPlayer(dp, STOC_FIELD_FINISH);
}
#endif //YGOPRO_SERVER_MODE
void TagDuel::TimeConfirm(DuelPlayer* dp) { void TagDuel::TimeConfirm(DuelPlayer* dp) {
if(host_info.time_limit == 0) if(host_info.time_limit == 0)
return; return;
if(dp != cur_player[last_response]) if(dp != cur_player[last_response])
return; return;
cur_player[last_response]->state = CTOS_RESPONSE; cur_player[last_response]->state = CTOS_RESPONSE;
#ifdef YGOPRO_SERVER_MODE
if(time_elapsed < 10 && time_elapsed <= time_compensator[dp->type]){
time_compensator[dp->type] -= time_elapsed;
time_elapsed = 0;
}
else {
time_limit[dp->type] -= time_elapsed;
time_elapsed = 0;
}
#else
if(time_elapsed < 10) if(time_elapsed < 10)
time_elapsed = 0; time_elapsed = 0;
#endif //YGOPRO_SERVER_MODE
} }
inline int TagDuel::WriteUpdateData(int& player, int location, int& flag, unsigned char*& qbuf, int& use_cache) { inline int TagDuel::WriteUpdateData(int& player, int location, int& flag, unsigned char*& qbuf, int& use_cache) {
flag |= (QUERY_CODE | QUERY_POSITION); flag |= (QUERY_CODE | QUERY_POSITION);
...@@ -1608,14 +2057,29 @@ inline int TagDuel::WriteUpdateData(int& player, int location, int& flag, unsign ...@@ -1608,14 +2057,29 @@ inline int TagDuel::WriteUpdateData(int& player, int location, int& flag, unsign
int len = query_field_card(pduel, player, location, flag, qbuf, use_cache); int len = query_field_card(pduel, player, location, flag, qbuf, use_cache);
return len; return len;
} }
void TagDuel::RefreshMzone(int player, int flag, int use_cache) { #ifdef YGOPRO_SERVER_MODE
void TagDuel::RefreshMzone(int player, int flag, int use_cache, DuelPlayer* dp)
#else
void TagDuel::RefreshMzone(int player, int flag, int use_cache)
#endif //YGOPRO_SERVER_MODE
{
std::vector<unsigned char> query_buffer; std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER); query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data(); auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_MZONE, flag, qbuf, use_cache); auto len = WriteUpdateData(player, LOCATION_MZONE, flag, qbuf, use_cache);
int pid = (player == 0) ? 0 : 2; int pid = (player == 0) ? 0 : 2;
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[pid])
#endif
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[pid + 1])
NetServer::SendBufferToPlayer(players[pid + 1], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
NetServer::ReSendToPlayer(replay_recorder);
#else
NetServer::ReSendToPlayer(players[pid + 1]); NetServer::ReSendToPlayer(players[pid + 1]);
#endif
int qlen = 0; int qlen = 0;
while(qlen < len) { while(qlen < len) {
int clen = BufferIO::ReadInt32(qbuf); int clen = BufferIO::ReadInt32(qbuf);
...@@ -1628,19 +2092,47 @@ void TagDuel::RefreshMzone(int player, int flag, int use_cache) { ...@@ -1628,19 +2092,47 @@ void TagDuel::RefreshMzone(int player, int flag, int use_cache) {
qbuf += clen - 4; qbuf += clen - 4;
} }
pid = 2 - pid; pid = 2 - pid;
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[pid])
#endif
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[pid + 1])
NetServer::SendBufferToPlayer(players[pid + 1], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
#else
NetServer::ReSendToPlayer(players[pid + 1]); NetServer::ReSendToPlayer(players[pid + 1]);
#endif
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(cache_recorder);
#endif
} }
void TagDuel::RefreshSzone(int player, int flag, int use_cache) { #ifdef YGOPRO_SERVER_MODE
void TagDuel::RefreshSzone(int player, int flag, int use_cache, DuelPlayer* dp)
#else
void TagDuel::RefreshSzone(int player, int flag, int use_cache)
#endif //YGOPRO_SERVER_MODE
{
std::vector<unsigned char> query_buffer; std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER); query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data(); auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_SZONE, flag, qbuf, use_cache); auto len = WriteUpdateData(player, LOCATION_SZONE, flag, qbuf, use_cache);
int pid = (player == 0) ? 0 : 2; int pid = (player == 0) ? 0 : 2;
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[pid])
#endif
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[pid + 1])
NetServer::SendBufferToPlayer(players[pid + 1], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
NetServer::ReSendToPlayer(replay_recorder);
#else
NetServer::ReSendToPlayer(players[pid + 1]); NetServer::ReSendToPlayer(players[pid + 1]);
#endif
int qlen = 0; int qlen = 0;
while(qlen < len) { while(qlen < len) {
int clen = BufferIO::ReadInt32(qbuf); int clen = BufferIO::ReadInt32(qbuf);
...@@ -1653,17 +2145,42 @@ void TagDuel::RefreshSzone(int player, int flag, int use_cache) { ...@@ -1653,17 +2145,42 @@ void TagDuel::RefreshSzone(int player, int flag, int use_cache) {
qbuf += clen - 4; qbuf += clen - 4;
} }
pid = 2 - pid; pid = 2 - pid;
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[pid])
#endif
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[pid + 1])
NetServer::SendBufferToPlayer(players[pid + 1], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
#else
NetServer::ReSendToPlayer(players[pid + 1]); NetServer::ReSendToPlayer(players[pid + 1]);
#endif
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(cache_recorder);
#endif
} }
void TagDuel::RefreshHand(int player, int flag, int use_cache) { #ifdef YGOPRO_SERVER_MODE
void TagDuel::RefreshHand(int player, int flag, int use_cache, DuelPlayer* dp)
#else
void TagDuel::RefreshHand(int player, int flag, int use_cache)
#endif //YGOPRO_SERVER_MODE
{
std::vector<unsigned char> query_buffer; std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER); query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data(); auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_HAND, flag, qbuf, use_cache); auto len = WriteUpdateData(player, LOCATION_HAND, flag, qbuf, use_cache);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == cur_player[player])
#endif
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(replay_recorder);
#endif
int qlen = 0; int qlen = 0;
while(qlen < len) { while(qlen < len) {
int slen = BufferIO::ReadInt32(qbuf); int slen = BufferIO::ReadInt32(qbuf);
...@@ -1676,30 +2193,124 @@ void TagDuel::RefreshHand(int player, int flag, int use_cache) { ...@@ -1676,30 +2193,124 @@ void TagDuel::RefreshHand(int player, int flag, int use_cache) {
qbuf += slen - 4; qbuf += slen - 4;
} }
for(int i = 0; i < 4; ++i) for(int i = 0; i < 4; ++i)
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == players[i])
#endif
if(players[i] != cur_player[player]) if(players[i] != cur_player[player])
NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
#endif
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(cache_recorder);
#endif
} }
void TagDuel::RefreshGrave(int player, int flag, int use_cache) { #ifdef YGOPRO_SERVER_MODE
void TagDuel::RefreshGrave(int player, int flag, int use_cache, DuelPlayer* dp)
#else
void TagDuel::RefreshGrave(int player, int flag, int use_cache)
#endif //YGOPRO_SERVER_MODE
{
std::vector<unsigned char> query_buffer; std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER); query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data(); auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_GRAVE, flag, qbuf, use_cache); auto len = WriteUpdateData(player, LOCATION_GRAVE, flag, qbuf, use_cache);
#ifdef YGOPRO_SERVER_MODE
for(int i = 0; i < 4; ++i)
if(!dp || dp == players[i])
NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
#else
NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(players[0], STOC_GAME_MSG, query_buffer.data(), len + 3);
NetServer::ReSendToPlayer(players[1]); NetServer::ReSendToPlayer(players[1]);
NetServer::ReSendToPlayer(players[2]); NetServer::ReSendToPlayer(players[2]);
NetServer::ReSendToPlayer(players[3]); NetServer::ReSendToPlayer(players[3]);
#endif
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayers(cache_recorder, replay_recorder);
#endif
} }
void TagDuel::RefreshExtra(int player, int flag, int use_cache) { #ifdef YGOPRO_SERVER_MODE
void TagDuel::RefreshExtra(int player, int flag, int use_cache, DuelPlayer* dp)
#else
void TagDuel::RefreshExtra(int player, int flag, int use_cache)
#endif //YGOPRO_SERVER_MODE
{
std::vector<unsigned char> query_buffer; std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER); query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data(); auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_EXTRA, flag, qbuf, use_cache); auto len = WriteUpdateData(player, LOCATION_EXTRA, flag, qbuf, use_cache);
#ifdef YGOPRO_SERVER_MODE
if(!dp || dp == cur_player[player])
#endif
NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, query_buffer.data(), len + 3); NetServer::SendBufferToPlayer(cur_player[player], STOC_GAME_MSG, query_buffer.data(), len + 3);
#ifdef YGOPRO_SERVER_MODE
if(!dp)
NetServer::ReSendToPlayer(replay_recorder);
int qlen = 0;
while(qlen < len) {
int clen = BufferIO::ReadInt32(qbuf);
qlen += clen;
if (clen <= LEN_HEADER)
continue;
auto position = GetPosition(qbuf, 8);
if (position & POS_FACEDOWN)
memset(qbuf, 0, clen - 4);
qbuf += clen - 4;
}
for(int i = 0; i < 4; ++i)
if(!dp || dp == players[i])
if(players[i] != cur_player[player])
NetServer::SendBufferToPlayer(players[i], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
if(!dp)
NetServer::ReSendToPlayer(cache_recorder);
#endif
}
#ifdef YGOPRO_SERVER_MODE
void TagDuel::RefreshRemoved(int player, int flag, int use_cache, DuelPlayer* dp) {
std::vector<unsigned char> query_buffer;
query_buffer.resize(SIZE_QUERY_BUFFER);
auto qbuf = query_buffer.data();
auto len = WriteUpdateData(player, LOCATION_REMOVED, flag, qbuf, use_cache);
int pid = (player == 0) ? 0 : 2;
if(!dp || dp == players[pid])
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp || dp == players[pid + 1])
NetServer::SendBufferToPlayer(players[pid + 1], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
NetServer::ReSendToPlayer(replay_recorder);
int qlen = 0;
while(qlen < len) {
int clen = BufferIO::ReadInt32(qbuf);
qlen += clen;
if (clen <= LEN_HEADER)
continue;
auto position = GetPosition(qbuf, 8);
if (position & POS_FACEDOWN)
memset(qbuf, 0, clen - 4);
qbuf += clen - 4;
}
pid = 2 - pid;
if(!dp || dp == players[pid])
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp || dp == players[pid + 1])
NetServer::SendBufferToPlayer(players[pid + 1], STOC_GAME_MSG, query_buffer.data(), len + 3);
if(!dp)
for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit);
if(!dp)
NetServer::ReSendToPlayer(cache_recorder);
} }
#endif
void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) { void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) {
flag |= (QUERY_CODE | QUERY_POSITION); flag |= (QUERY_CODE | QUERY_POSITION);
unsigned char query_buffer[0x1000]; unsigned char query_buffer[0x1000];
...@@ -1714,17 +2325,26 @@ void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) { ...@@ -1714,17 +2325,26 @@ void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) {
int pid = (player == 0) ? 0 : 2; int pid = (player == 0) ? 0 : 2;
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 4); NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 4);
NetServer::ReSendToPlayer(players[pid + 1]); NetServer::ReSendToPlayer(players[pid + 1]);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(replay_recorder);
#endif
if(position & POS_FACEUP) { if(position & POS_FACEUP) {
pid = 2 - pid; pid = 2 - pid;
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 4); NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 4);
NetServer::ReSendToPlayer(players[pid + 1]); NetServer::ReSendToPlayer(players[pid + 1]);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(cache_recorder);
#endif
} }
} else { } else {
int pid = (player == 0) ? 0 : 2; int pid = (player == 0) ? 0 : 2;
NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 4); NetServer::SendBufferToPlayer(players[pid], STOC_GAME_MSG, query_buffer, len + 4);
NetServer::ReSendToPlayer(players[pid + 1]); NetServer::ReSendToPlayer(players[pid + 1]);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(replay_recorder);
#endif
if(location == LOCATION_REMOVED && (position & POS_FACEDOWN)) if(location == LOCATION_REMOVED && (position & POS_FACEDOWN))
return; return;
if (location & 0x90) { if (location & 0x90) {
...@@ -1733,6 +2353,9 @@ void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) { ...@@ -1733,6 +2353,9 @@ void TagDuel::RefreshSingle(int player, int location, int sequence, int flag) {
NetServer::ReSendToPlayer(players[i]); NetServer::ReSendToPlayer(players[i]);
for(auto pit = observers.begin(); pit != observers.end(); ++pit) for(auto pit = observers.begin(); pit != observers.end(); ++pit)
NetServer::ReSendToPlayer(*pit); NetServer::ReSendToPlayer(*pit);
#ifdef YGOPRO_SERVER_MODE
NetServer::ReSendToPlayer(cache_recorder);
#endif
} }
} }
} }
...@@ -1765,5 +2388,10 @@ void TagDuel::TagTimer(evutil_socket_t fd, short events, void* arg) { ...@@ -1765,5 +2388,10 @@ void TagDuel::TagTimer(evutil_socket_t fd, short events, void* arg) {
timeval timeout = { 1, 0 }; timeval timeout = { 1, 0 };
event_add(sd->etimer, &timeout); event_add(sd->etimer, &timeout);
} }
#ifdef YGOPRO_SERVER_MODE
void TagDuel::TestCard(int code) {
// not implemented
}
#endif
} }
...@@ -28,15 +28,30 @@ public: ...@@ -28,15 +28,30 @@ public:
int Analyze(unsigned char* msgbuffer, unsigned int len) override; int Analyze(unsigned char* msgbuffer, unsigned int len) override;
void GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len) override; void GetResponse(DuelPlayer* dp, unsigned char* pdata, unsigned int len) override;
void TimeConfirm(DuelPlayer* dp) override; void TimeConfirm(DuelPlayer* dp) override;
#ifdef YGOPRO_SERVER_MODE
void RequestField(DuelPlayer* dp) override;
#endif
void EndDuel() override; void EndDuel() override;
#ifdef YGOPRO_SERVER_MODE
void TestCard(int code) override;
#endif
void DuelEndProc(); void DuelEndProc();
void WaitforResponse(int playerid); void WaitforResponse(int playerid);
#ifdef YGOPRO_SERVER_MODE
void RefreshMzone(int player, int flag = 0x881fff, int use_cache = 1, DuelPlayer* dp = 0);
void RefreshSzone(int player, int flag = 0xe81fff, int use_cache = 1, DuelPlayer* dp = 0);
void RefreshHand(int player, int flag = 0x681fff, int use_cache = 1, DuelPlayer* dp = 0);
void RefreshGrave(int player, int flag = 0x81fff, int use_cache = 1, DuelPlayer* dp = 0);
void RefreshExtra(int player, int flag = 0xe81fff, int use_cache = 1, DuelPlayer* dp = 0);
void RefreshRemoved(int player, int flag = 0x81fff, int use_cache = 1, DuelPlayer* dp = 0);
#else
void RefreshMzone(int player, int flag = 0x881fff, int use_cache = 1); void RefreshMzone(int player, int flag = 0x881fff, int use_cache = 1);
void RefreshSzone(int player, int flag = 0xe81fff, int use_cache = 1); void RefreshSzone(int player, int flag = 0xe81fff, int use_cache = 1);
void RefreshHand(int player, int flag = 0x681fff, int use_cache = 1); void RefreshHand(int player, int flag = 0x681fff, int use_cache = 1);
void RefreshGrave(int player, int flag = 0x81fff, int use_cache = 1); void RefreshGrave(int player, int flag = 0x81fff, int use_cache = 1);
void RefreshExtra(int player, int flag = 0xe81fff, int use_cache = 1); void RefreshExtra(int player, int flag = 0xe81fff, int use_cache = 1);
#endif
void RefreshSingle(int player, int location, int sequence, int flag = 0xf81fff); void RefreshSingle(int player, int location, int sequence, int flag = 0xf81fff);
static uint32_t MessageHandler(intptr_t fduel, uint32_t type); static uint32_t MessageHandler(intptr_t fduel, uint32_t type);
...@@ -50,6 +65,12 @@ protected: ...@@ -50,6 +65,12 @@ protected:
DuelPlayer* pplayer[4]; DuelPlayer* pplayer[4];
DuelPlayer* cur_player[2]; DuelPlayer* cur_player[2];
std::set<DuelPlayer*> observers; std::set<DuelPlayer*> observers;
#ifdef YGOPRO_SERVER_MODE
DuelPlayer* cache_recorder;
DuelPlayer* replay_recorder;
int turn_player;
int phase;
#endif
bool ready[4]; bool ready[4];
bool surrender[4]; bool surrender[4];
Deck pdeck[4]; Deck pdeck[4];
...@@ -60,8 +81,14 @@ protected: ...@@ -60,8 +81,14 @@ protected:
unsigned char turn_count; unsigned char turn_count;
short time_limit[2]; short time_limit[2];
short time_elapsed; short time_elapsed;
#ifdef YGOPRO_SERVER_MODE
short time_compensator[2];
short time_backed[2];
unsigned char last_game_msg;
#endif
}; };
} }
#endif //TAG_DUEL_H #endif //TAG_DUEL_H
premake/gframe/ygopro.ico

159 KB | W: | H:

premake/gframe/ygopro.ico

17.1 KB | W: | H:

premake/gframe/ygopro.ico
premake/gframe/ygopro.ico
premake/gframe/ygopro.ico
premake/gframe/ygopro.ico
  • 2-up
  • Swipe
  • Onion skin
...@@ -11,13 +11,13 @@ BLOCK "StringFileInfo" ...@@ -11,13 +11,13 @@ BLOCK "StringFileInfo"
BEGIN BEGIN
BLOCK "080404b0" BLOCK "080404b0"
BEGIN BEGIN
VALUE "FileDescription", "KoishiPro" VALUE "FileDescription", "YGOPRO Server Mode ver.Koishi"
VALUE "InternalName", "KoishiPro" VALUE "InternalName", "YGOPRO Server Mode"
VALUE "LegalCopyright", "Copyright (C) 2023 Nanahira" VALUE "LegalCopyright", "Copyright (C) 2023 Nanahira"
VALUE "OriginalFilename", "ygopro.exe" VALUE "OriginalFilename", "ygopro.exe"
VALUE "ProductName", "KoishiPro" VALUE "ProductName", "YGOPRO Server Mode"
VALUE "FileVersion", "Moon" VALUE "FileVersion", "Server"
VALUE "ProductVersion", "Moon" VALUE "ProductVersion", "Server"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"
......
...@@ -37,7 +37,7 @@ index 43557cd..ffa06bc 100644 ...@@ -37,7 +37,7 @@ index 43557cd..ffa06bc 100644
} // end namespace core } // end namespace core
} // end namespace irr } // end namespace irr
diff --git a/include/irrTypes.h b/include/irrTypes.h diff --git a/include/irrTypes.h b/include/irrTypes.h
index 403f890..940e859 100644 index 403f890..bfa13f4 100644
--- a/include/irrTypes.h --- a/include/irrTypes.h
+++ b/include/irrTypes.h +++ b/include/irrTypes.h
@@ -48,6 +48,9 @@ typedef __int16 s16; @@ -48,6 +48,9 @@ typedef __int16 s16;
...@@ -50,6 +50,24 @@ index 403f890..940e859 100644 ...@@ -50,6 +50,24 @@ index 403f890..940e859 100644
//! 32 bit unsigned variable. //! 32 bit unsigned variable.
@@ -113,17 +116,6 @@ typedef double f64;
#include <wchar.h>
#ifdef _IRR_WINDOWS_API_
-//! Defines for s{w,n}printf because these methods do not match the ISO C
-//! standard on Windows platforms, but it does on all others.
-//! These should be int snprintf(char *str, size_t size, const char *format, ...);
-//! and int swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...);
-#if defined(_MSC_VER) && _MSC_VER > 1310 && !defined (_WIN32_WCE)
-#define swprintf swprintf_s
-#define snprintf sprintf_s
-#elif !defined(__CYGWIN__)
-#define swprintf _snwprintf
-#define snprintf _snprintf
-#endif
// define the wchar_t type if not already built in.
#ifdef _MSC_VER
diff --git a/source/Irrlicht/CGUIEditBox.cpp b/source/Irrlicht/CGUIEditBox.cpp diff --git a/source/Irrlicht/CGUIEditBox.cpp b/source/Irrlicht/CGUIEditBox.cpp
index 395fb69..cc6b75f 100644 index 395fb69..cc6b75f 100644
--- a/source/Irrlicht/CGUIEditBox.cpp --- a/source/Irrlicht/CGUIEditBox.cpp
......
project "irrlicht"
kind "StaticLib"
includedirs { "include", "source/Irrlicht", "source/Irrlicht/zlib" }
defines {
"_IRR_STATIC_LIB_",
"NO_IRR_COMPILE_WITH_ZIP_ENCRYPTION_",
"NO_IRR_COMPILE_WITH_BZIP2_",
"NO__IRR_COMPILE_WITH_MOUNT_ARCHIVE_LOADER_",
"NO__IRR_COMPILE_WITH_PAK_ARCHIVE_LOADER_",
"NO__IRR_COMPILE_WITH_NPK_ARCHIVE_LOADER_",
"NO__IRR_COMPILE_WITH_TAR_ARCHIVE_LOADER_",
"NO__IRR_COMPILE_WITH_WAD_ARCHIVE_LOADER_"
}
exceptionhandling "Off"
rtti "Off"
files {
"source/Irrlicht/os.cpp",
"source/Irrlicht/zlib/adler32.c",
"source/Irrlicht/zlib/crc32.c",
"source/Irrlicht/zlib/inffast.c",
"source/Irrlicht/zlib/inflate.c",
"source/Irrlicht/zlib/inftrees.c",
"source/Irrlicht/zlib/zutil.c",
"source/Irrlicht/CAttributes.cpp",
"source/Irrlicht/CFileList.cpp",
"source/Irrlicht/CFileSystem.cpp",
"source/Irrlicht/CLimitReadFile.cpp",
"source/Irrlicht/CMemoryFile.cpp",
"source/Irrlicht/CReadFile.cpp",
"source/Irrlicht/CWriteFile.cpp",
"source/Irrlicht/CXMLReader.cpp",
"source/Irrlicht/CXMLWriter.cpp",
"source/Irrlicht/CZipReader.cpp"
}
filter { "system:windows" }
defines { "_IRR_WCHAR_FILESYSTEM" }
...@@ -9,6 +9,12 @@ USE_IRRKLANG = true ...@@ -9,6 +9,12 @@ USE_IRRKLANG = true
IRRKLANG_PRO = false IRRKLANG_PRO = false
LUA_LIB_NAME = "lua" LUA_LIB_NAME = "lua"
SERVER_MODE = true
SERVER_ZIP_SUPPORT = false
SERVER_PRO2_SUPPORT = false
SERVER_TAG_SURRENDER_CONFIRM = false
USE_IRRKLANG = false
-- read settings from command line or environment variables -- read settings from command line or environment variables
newoption { trigger = "build-lua", category = "YGOPro - lua", description = "" } newoption { trigger = "build-lua", category = "YGOPro - lua", description = "" }
...@@ -52,13 +58,17 @@ newoption { trigger = 'build-ikpmp3', category = "YGOPro - irrklang - ikpmp3", d ...@@ -52,13 +58,17 @@ newoption { trigger = 'build-ikpmp3', category = "YGOPro - irrklang - ikpmp3", d
newoption { trigger = "winxp-support", category = "YGOPro", description = "" } newoption { trigger = "winxp-support", category = "YGOPro", description = "" }
newoption { trigger = "mac-arm", category = "YGOPro", description = "M1" } newoption { trigger = "mac-arm", category = "YGOPro", description = "M1" }
-- koishipro specific newoption { trigger = "server-mode", category = "YGOPro - server", description = "" }
newoption { trigger = "server-zip-support", category = "YGOPro - server", description = "" }
newoption { trigger = "server-pro2-support", category = "YGOPro - server", description = "" }
newoption { trigger = "server-tag-surrender-confirm", category = "YGOPro - server", description = "" }
boolOptions = { boolOptions = {
"compat-mycard", "compat-mycard",
"no-lua-safe", "no-lua-safe",
"message-debug", "message-debug",
"no-side-check", "no-side-check",
"enable-debug-func"
} }
for _, boolOption in ipairs(boolOptions) do for _, boolOption in ipairs(boolOptions) do
...@@ -201,6 +211,29 @@ if os.istarget("macosx") then ...@@ -201,6 +211,29 @@ if os.istarget("macosx") then
MAC_ARM = true MAC_ARM = true
end end
end end
if GetParam("server-mode") then
SERVER_MODE = true
end
if GetParam("server-zip-support") then
SERVER_ZIP_SUPPORT = true
end
if GetParam("server-pro2-support") then
SERVER_PRO2_SUPPORT = true
SERVER_ZIP_SUPPORT = true
end
if GetParam("server-tag-surrender-confirm") then
SERVER_TAG_SURRENDER_CONFIRM = true
end
if SERVER_MODE then
BUILD_FREETYPE = false
BUILD_IKPMP3 = false
USE_IRRKLANG = false
IRRKLANG_PRO = false
if not SERVER_ZIP_SUPPORT then
BUILD_IRRLICHT = false
end
end
workspace "YGOPro" workspace "YGOPro"
location "build" location "build"
...@@ -209,7 +242,6 @@ workspace "YGOPro" ...@@ -209,7 +242,6 @@ workspace "YGOPro"
configurations { "Release", "Debug" } configurations { "Release", "Debug" }
for _, numberOption in ipairs(numberOptions) do for _, numberOption in ipairs(numberOptions) do
ApplyNumber(numberOption) ApplyNumber(numberOption)
end end
...@@ -218,7 +250,6 @@ workspace "YGOPro" ...@@ -218,7 +250,6 @@ workspace "YGOPro"
ApplyBoolean(boolOption) ApplyBoolean(boolOption)
end end
filter "system:windows" filter "system:windows"
defines { "WIN32", "_WIN32" } defines { "WIN32", "_WIN32" }
entrypoint "mainCRTStartup" entrypoint "mainCRTStartup"
...@@ -237,7 +268,9 @@ workspace "YGOPro" ...@@ -237,7 +268,9 @@ workspace "YGOPro"
if MAC_ARM then if MAC_ARM then
buildoptions { "--target=arm64-apple-macos12" } buildoptions { "--target=arm64-apple-macos12" }
end end
if not SERVER_MODE then
links { "OpenGL.framework", "Cocoa.framework", "IOKit.framework" } links { "OpenGL.framework", "Cocoa.framework", "IOKit.framework" }
end
filter "system:linux" filter "system:linux"
buildoptions { "-U_FORTIFY_SOURCE" } buildoptions { "-U_FORTIFY_SOURCE" }
...@@ -284,15 +317,18 @@ workspace "YGOPro" ...@@ -284,15 +317,18 @@ workspace "YGOPro"
if BUILD_EVENT then if BUILD_EVENT then
include "event" include "event"
end end
if BUILD_FREETYPE then if BUILD_FREETYPE and not SERVER_MODE then
include "freetype" include "freetype"
end end
if BUILD_IRRLICHT then if BUILD_IRRLICHT and not SERVER_MODE then
include "irrlicht" include "irrlicht"
end end
if BUILD_IRRLICHT and SERVER_MODE and SERVER_ZIP_SUPPORT then
include "irrlicht/premake5-only-zipreader.lua"
end
if BUILD_SQLITE then if BUILD_SQLITE then
include "sqlite3" include "sqlite3"
end end
if BUILD_IKPMP3 then if BUILD_IKPMP3 and not SERVER_MODE then
include "ikpmp3" include "ikpmp3"
end end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment