Commit ada55647 authored by 苍蓝's avatar 苍蓝

update

parents 24d00885 73e95a2b
......@@ -4,8 +4,9 @@ set -o errexit
source .ci/asset-branch
# ygopro-database
apt update && apt -y install wget git libarchive-tools sqlite3
git clone --depth=1 -b "$ASSET_BRANCH_NAME" https://code.moenext.com/mycard/ygopro-database
git clone --depth=1 -b master https://code.moenext.com/nanahira/ygopro-database
cp -rf ./ygopro-database/locales/$TARGET_LOCALE/strings.conf .
cp -rf ./ygopro-database/locales/$TARGET_LOCALE/servers.conf .
rm -f cards.cdb
sqlite3 ./ygopro-database/locales/$TARGET_LOCALE/cards.cdb .dump | sqlite3 cards.cdb
# ygopro-images
......
#!/bin/bash
set -x
set -o errexit
ARCHIVE_FILES=(ygopro cards.cdb locales fonts sound textures strings.conf system.conf servers.conf pack)
if [[ -z "$TARGET_PLATFORM" ]]; then
TARGET_PLATFORM=linux
fi
#if [[ "$TARGET_PLATFORM" != "linuxarm" ]]; then
ARCHIVE_FILES+=(sound)
#fi
apt update && apt -y install tar zstd
mkdir dist replay
cp -rf locales/$TARGET_LOCALE/* .
tar -acf "dist/KoishiPro-dlc-$CI_COMMIT_REF_NAME-$TARGET_PLATFORM-$TARGET_LOCALE.tar.$ARCHIVE_SUFFIX" --exclude='.git*' "${ARCHIVE_FILES[@]}"
#!/bin/bash
set -x
set -o errexit
ARCHIVE_FILES=(ygopro LICENSE README.md lflist.conf strings.conf system.conf servers.conf cards.cdb script textures deck single pics replay windbot bot bot.conf locales fonts pack)
# TARGET_LOCALE
# ARCHIVE_SUFFIX
if [[ -z "$TARGET_PLATFORM" ]]; then
TARGET_PLATFORM=linux
fi
if [[ "$TARGET_PLATFORM" != "linuxarm" ]]; then
ARCHIVE_FILES+=(sound)
fi
apt update && apt -y install tar git zstd
mkdir dist replay
tar --zstd -cf dist/ygopro-$CI_COMMIT_REF_NAME-linux-$TARGET_LOCALE.tar.zst --exclude='.git*' ygopro LICENSE README.md lflist.conf strings.conf system.conf cards.cdb script textures deck single pics replay sound windbot bot bot.conf pack fonts
tar -acf "dist/KoishiPro-$CI_COMMIT_REF_NAME-$TARGET_PLATFORM-$TARGET_LOCALE.tar.$ARCHIVE_SUFFIX" --exclude='.git*' "${ARCHIVE_FILES[@]}"
#!/bin/bash
set -x
set -o errexit
ARCHIVE_FILES=(ygopro.app cards.cdb locales fonts sound textures strings.conf system.conf servers.conf pack)
if [[ -z "$TARGET_PLATFORM" ]]; then
TARGET_PLATFORM=darwin
fi
apt update && apt -y install tar zstd
mkdir dist replay
cp -rf locales/$TARGET_LOCALE/* .
tar -acf "dist/KoishiPro-dlc-$CI_COMMIT_REF_NAME-$TARGET_PLATFORM-$TARGET_LOCALE.tar.$ARCHIVE_SUFFIX" --exclude='.git*' "${ARCHIVE_FILES[@]}"
#!/bin/bash
set -x
set -o errexit
ARCHIVE_FILES=(ygopro.app LICENSE README.md lflist.conf strings.conf system.conf servers.conf cards.cdb script textures deck single pics replay sound windbot bot bot.conf locales fonts pack)
# TARGET_LOCALE
# ARCHIVE_SUFFIX
if [[ -z "$TARGET_PLATFORM" ]]; then
TARGET_PLATFORM=darwin
fi
apt update && apt -y install tar git zstd
mkdir dist replay
tar --zstd -cf dist/ygopro-$CI_COMMIT_REF_NAME-darwin-$TARGET_LOCALE.tar.zst --exclude='.git*' ygopro.app LICENSE README.md lflist.conf strings.conf system.conf cards.cdb script textures deck single pics replay sound windbot bot bot.conf pack fonts
tar -acf "dist/KoishiPro-$CI_COMMIT_REF_NAME-$TARGET_PLATFORM-$TARGET_LOCALE.tar.$ARCHIVE_SUFFIX" --exclude='.git*' "${ARCHIVE_FILES[@]}"
#!/bin/bash
set -x
set -o errexit
ARCHIVE_FILES=(ygopro.exe vcomp140.dll LICENSE README.md lflist.conf strings.conf system.conf servers.conf cards.cdb script textures deck single pics replay sound bot.conf Bot.exe WindBot locales fonts skin pack)
if [[ "$TARGET_LOCALE" == "zh-CN" ]]; then
ARCHIVE_FILES=("${ARCHIVE_FILES[@]}" update-koishipro)
fi
# TARGET_LOCALE
if [[ -z "$TARGET_PLATFORM" ]]; then
TARGET_PLATFORM=win32
fi
apt update && apt -y install p7zip-full git
mkdir dist replay
7z a -mx9 -xr!.git* dist/KoishiPro-$CI_COMMIT_REF_NAME-win32-$TARGET_LOCALE.7z "${ARCHIVE_FILES[@]}"
#!/bin/bash
set -x
set -o errexit
ARCHIVE_FILES=(ygopro.exe vcomp140.dll cards.cdb locales fonts sound textures strings.conf system.conf servers.conf skin pack)
if [[ -z "$TARGET_PLATFORM" ]]; then
TARGET_PLATFORM=win32
fi
apt update && apt -y install tar zstd
mkdir dist replay
cp -rf locales/$TARGET_LOCALE/* .
tar -acf "dist/KoishiPro-dlc-$CI_COMMIT_REF_NAME-$TARGET_PLATFORM-$TARGET_LOCALE.tar.$ARCHIVE_SUFFIX" --exclude='.git*' "${ARCHIVE_FILES[@]}"
#!/bin/bash
set -x
set -o errexit
ARCHIVE_FILES=(ygopro.exe vcomp140.dll LICENSE README.md lflist.conf strings.conf system.conf servers.conf cards.cdb script textures deck single pics replay sound bot.conf Bot.exe WindBot locales fonts skin pack)
if [[ "$TARGET_LOCALE" == "zh-CN" && "$ARCHIVE_SUFFIX" != "zst" ]]; then
ARCHIVE_FILES=("${ARCHIVE_FILES[@]}" update-koishipro)
fi
# TARGET_LOCALE
# ARCHIVE_SUFFIX
if [[ -z "$TARGET_PLATFORM" ]]; then
TARGET_PLATFORM=win32
fi
apt update && apt -y install tar git zstd
mkdir dist replay
tar --zstd -cf dist/ygopro-$CI_COMMIT_REF_NAME-win32-$TARGET_LOCALE.tar.zst --exclude='.git*' ygopro.exe vcomp140.dll LICENSE README.md lflist.conf strings.conf system.conf cards.cdb script textures deck single pics replay sound bot.conf Bot.exe WindBot pack fonts
tar -acf "dist/KoishiPro-$CI_COMMIT_REF_NAME-$TARGET_PLATFORM-$TARGET_LOCALE.tar.$ARCHIVE_SUFFIX" --exclude='.git*' "${ARCHIVE_FILES[@]}"
......@@ -10,7 +10,7 @@ token=$(echo $loginInfo | jq '.token' | sed 's/"//g')
header="Authorization: $token"
echo "Login succeeded."
appName="ygopro"
appName="koishipro"
handleErrorMessage() {
rawJsonInput="$1"
......@@ -25,7 +25,7 @@ handleErrorMessage() {
runForDepot() {
platform=$1
locale=$2
archivePath="./dist/$appName-$appVersion-$platform-$locale.tar.zst"
archivePath="./dist/KoishiPro-dlc-$appVersion-$platform-$locale.tar.zst"
suffix="?platform=$platform&locale=$locale&arch=generic"
echo "Uploading $archivePath"
result=$(curl -H "$header" -X POST "$apiRoot/release/api/build/$appName/${appVersion}${suffix}" -F file=@$archivePath)
......
.DS_Store
/deck
# data files
/beta
/expansions
/fonts
/icon
/pack
/pics
/replay
/single
/sound
!/sound/files.txt
/WindBot
/cards.cdb
/error.log
/bot.conf
/Bot.exe
/bot
/ygopro
/ygopro.exe
/ygopro.app
/ikpMP3.dll
/irrKlang.dll
/specials
# build files
/bin
/build
build
/obj
# dependencies
/event
/libevent*
/freetype
/irrlicht
/sqlite3
/irrklang
/ikpmp3
/irrlicht*
/lua
/miniaudio
/sqlite3
/gframe/*.ico
# gframe additionals
/gframe/ygopro.ico
/gframe/ygopro.rc
/gframe/ygopro.aps
/premake5
/premake5.exe
/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
/lib
/pack
# 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
......@@ -4,7 +4,6 @@ stages:
- combine
- pack
- deploy
- notify
variables:
GIT_DEPTH: "1"
......@@ -59,23 +58,20 @@ mat_submodules:
# stage: prepare
# tags:
# - linux
# image: git-registry.mycard.moe/mycard/docker-runner-base:debian11
# script:
# - apt update; apt -y install git wget tar
# - ./.ci/prepare-irrlicht.sh
# # - wget -O - https://cdn02.moecube.com:444/ygopro-build-materials/premake-5.0.0-beta6-linux.tar.gz | tar zfx -
# # - env PROCESSOR_COUNT=$(nproc) ./.ci/libevent-prebuild.sh
# artifacts:
# paths:
# # - premake5
# - irrlicht
# # - libevent-stable
# image: git-registry.mycard.moe/mycard/docker-runner-base:debian11
mat_macos:
stage: prepare
tags:
- linux
script:
- apt update; apt -y install wget tar
- wget -O - https://cdn02.moecube.com:444/premake5-built/premake-5.0.0-beta7-macosx.tar.gz | tar zfx -
- chmod +x premake5
artifacts:
......@@ -87,6 +83,7 @@ mat_windows:
tags:
- linux
script:
- apt update; apt -y install wget tar patch p7zip-full
# premake5.exe
- wget https://cdn02.moecube.com:444/premake5-built/premake-5.0.0-beta7-windows.zip
- 7z x -y premake-5.0.0-beta7-windows.zip
......@@ -96,6 +93,13 @@ mat_windows:
._exec_build:
stage: build
variables:
NO_LUA_SAFE: '1' # on client no lua safe
#cache:
# key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
# paths:
# - bin/
# - obj/
exec_windows:
extends: ._exec_build
......@@ -116,343 +120,4 @@ exec_windows:
- ygopro.exe
- vcomp140.dll
.exec_unix:
extends: ._exec_build
variables:
BUILD_FREETYPE: '1'
BUILD_SQLITE: '1'
BUILD_IRRLICHT: '1'
BUILD_EVENT: '1'
BUILD_OPUS_VORBIS: '1'
AUDIO_LIB: 'miniaudio'
MINIAUDIO_SUPPORT_OPUS_VORBIS: '1'
BUILD_OPUS_VORBIS: '1'
before_script:
- ./.ci/configure-libevent.sh
exec_linux:
extends: .exec_unix
tags:
- avx2
image: git-registry.moenext.com/mycard/docker-ygopro-builder:latest
dependencies:
- mat_common
#- mat_linux
- mat_submodules
script:
- ./.ci/configure-audio.sh
- premake5 gmake --build-freetype --build-sqlite
- cd build
- make config=release -j$(nproc)
- cd ..
- mv bin/release/YGOPro ./ygopro
- strip ygopro
artifacts:
paths:
- ygopro
.exec_macos_platform:
extends: .exec_unix
dependencies:
- mat_macos
- mat_common
- mat_submodules
script: ./.ci/exec-macos-platform.sh
artifacts:
paths:
- ygopro-platforms
exec_macos_platform_x86:
extends: .exec_macos_platform
tags:
- macos
exec_macos_platform_m1:
extends: .exec_macos_platform
tags:
- macos-m1
exec_macos:
stage: combine
tags:
- macos
dependencies:
- exec_macos_platform_x86
- exec_macos_platform_m1
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-*);
- mkdir ygopro.app/Contents/Resources;
- mv resource/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
# - gitlabci
assets:
stage: prepare
tags:
- linux
script:
- apt update; apt -y install tar wget git
# starter pack
- wget -O - https://code.moenext.com/mycard/ygopro-starter-pack/-/archive/master/ygopro-starter-pack-master.tar.gz | tar zfx -
- mv ygopro-starter-pack-master/* .
# sound
- wget -O - https://code.moenext.com/mycard/ygopro-sounds/-/archive/master/ygopro-sounds-master.tar.gz | tar zfx -
- mv ygopro-sounds-master/sound/* sound
# fonts
- git clone --depth=1 https://code.moenext.com/mycard/ygopro-fonts
- mv ygopro-fonts/fonts .
# pack
- git clone --depth=1 https://code.moenext.com/mycard/ygopro-card-list
- mv ygopro-card-list/pack .
artifacts:
paths:
- deck
- single
- sound
- fonts
- pack
only:
- tags
- gitlabci
assets_nonwindows:
stage: prepare
tags:
- linux
script:
- apt update; apt -y install tar wget
- wget -O - https://cdn02.moecube.com:444/windbot-mc/windbot.tar.gz | tar zfx -
artifacts:
paths:
- bot.conf
- windbot
- bot
only:
- tags
- gitlabci
assets_windows:
stage: prepare
tags:
- linux
script:
- apt update; apt -y install wget p7zip-full
- wget https://cdn02.moecube.com:444/windbot-mc/WindBot.7z
- 7z x -y WindBot.7z
artifacts:
paths:
- bot.conf
- WindBot
- Bot.exe
only:
- tags
- gitlabci
assets_zh-CN:
stage: build
tags:
- linux
script: ./.ci/assets-locale.sh
variables:
TARGET_LOCALE: zh-CN
artifacts:
paths:
- pics
- cards.cdb
- strings.conf
only:
- tags
- gitlabci
assets_en-US:
stage: build
tags:
- linux
script: ./.ci/assets-locale.sh
variables:
TARGET_LOCALE: en-US
artifacts:
paths:
- pics
- cards.cdb
- strings.conf
- mat_submodules
only:
- tags
- gitlabci
pack_windows_zh-CN:
stage: pack
tags:
- linux
dependencies:
- assets
- assets_windows
- exec_windows
- assets_zh-CN
- mat_submodules
script: ./.ci/pack-windows.sh
variables:
TARGET_LOCALE: zh-CN
artifacts:
paths:
- dist
only:
- tags
- gitlabci
pack_windows_zh-CN:
stage: pack
tags:
- linux
dependencies:
- assets
- assets_windows
- exec_windows
- assets_zh-CN
- mat_submodules
script: ./.ci/pack-windows.sh
variables:
TARGET_LOCALE: zh-CN
artifacts:
paths:
- dist
only:
- tags
- gitlabci
pack_windows_en-US:
stage: pack
tags:
- linux
dependencies:
- assets
- assets_windows
- exec_windows
- assets_en-US
- mat_submodules
script: ./.ci/pack-windows.sh
variables:
TARGET_LOCALE: en-US
artifacts:
paths:
- dist
only:
- tags
- gitlabci
pack_linux_zh-CN:
stage: pack
tags:
- linux
dependencies:
- assets
- assets_nonwindows
- exec_linux
- assets_zh-CN
- mat_submodules
script: ./.ci/pack-linux.sh
variables:
TARGET_LOCALE: zh-CN
artifacts:
paths:
- dist
only:
- tags
- gitlabci
pack_linux_en-US:
stage: pack
tags:
- linux
dependencies:
- assets
- assets_nonwindows
- exec_linux
- assets_en-US
- mat_submodules
script: ./.ci/pack-linux.sh
variables:
TARGET_LOCALE: en-US
artifacts:
paths:
- dist
only:
- tags
- gitlabci
pack_macos_zh-CN:
stage: pack
tags:
- linux
dependencies:
- assets
- assets_nonwindows
- exec_macos
- assets_zh-CN
- mat_submodules
script: ./.ci/pack-macos.sh
variables:
TARGET_LOCALE: zh-CN
artifacts:
paths:
- dist
only:
- tags
- gitlabci
pack_macos_en-US:
stage: pack
tags:
- linux
dependencies:
- assets
- assets_nonwindows
- exec_macos
- assets_en-US
- mat_submodules
script: ./.ci/pack-macos.sh
variables:
TARGET_LOCALE: en-US
artifacts:
paths:
- dist
only:
- tags
- gitlabci
upload:
stage: deploy
dependencies:
- pack_windows_zh-CN
- pack_linux_zh-CN
- pack_macos_zh-CN
- pack_windows_en-US
- pack_linux_en-US
- pack_macos_en-US
tags:
- linux
variables:
appVersion: $CI_COMMIT_TAG
script: ./.ci/upload-packager.sh
only:
- tags
......@@ -64,4 +64,4 @@ Xyz materials:
* textures: Other image files.
* deck: .ydk deck files.
* replay: .yrp replay files.
* expansions: *.cdb will be loaded as extra databases.
* expansions: *.cdb will be loaded as extra databases.
\ No newline at end of file
File added
#include "CConfigMap.h"
core::stringc CConfigMap::getConfig( const core::stringc& name )
{
core::map<core::stringc,core::stringc>::Node* node = Map.find(name);
if ( node == 0 )
return core::stringc();
return node->getValue();
}
s32 CConfigMap::getConfigAsInt( const core::stringc& name )
{
core::stringc cfg = getConfig(name);
if ( cfg.size() == 0 )
return 0;
s32 x = 0;
sscanf( cfg.c_str(), "%d", &x );
return x;
}
f32 CConfigMap::getConfigAsFloat( const core::stringc& name )
{
core::stringc cfg = getConfig(name);
if ( cfg.size() == 0 )
return 0;
f32 x = 0.0f;
sscanf( cfg.c_str(), "%f", &x );
return x;
}
core::vector2df CConfigMap::getConfigAsVector2df( const core::stringc& name )
{
core::stringc cfg = getConfig(name);
if ( cfg.size() == 0 )
return core::vector2df(0,0);
core::vector2df vec;
sscanf( cfg.c_str(), "%f , %f", &vec.X, &vec.Y );
return vec;
}
core::vector3df CConfigMap::getConfigAsVector3df( const core::stringc& name )
{
core::stringc cfg = getConfig(name);
if ( cfg.size() == 0 )
return core::vector3df(0,0,0);
core::vector3df vec;
sscanf( cfg.c_str(), "%f , %f , %f", &vec.X, &vec.Y, &vec.Z );
return vec;
}
bool CConfigMap::hasConfig( const core::stringc& name )
{
core::map<core::stringc,core::stringc>::Node* node = Map.find(name);
return ( node != 0 );
}
void CConfigMap::setConfig( const core::stringc& name, const core::stringc& value )
{
Map.set(name,value);
}
#ifndef CCONFIGMAP_H_
#define CCONFIGMAP_H_
#include <irrMap.h>
#include <irrString.h>
#include <irrTypes.h>
#include <vector2d.h>
#include <vector3d.h>
using namespace irr;
class CConfigMap
{
public:
core::stringc getConfig( const core::stringc& name );
s32 getConfigAsInt( const core::stringc& name );
f32 getConfigAsFloat( const core::stringc& name );
core::vector2df getConfigAsVector2df( const core::stringc& name );
core::vector3df getConfigAsVector3df( const core::stringc& name );
bool hasConfig( const core::stringc& name );
void setConfig( const core::stringc& name, const core::stringc& value );
private:
core::map<core::stringc,core::stringc> Map;
};
#endif
#include "CGUIProgressBar.h"
#include <IGUIEnvironment.h>
#include "CImageGUISkin.h"
#include <IGUIFont.h>
namespace irr
{
namespace gui
{
CGUIProgressBar::CGUIProgressBar( IGUIElement* parent, IGUIEnvironment* environment, const core::rect<s32>& rectangle, s32 id,bool bind )
: IGUIElement( EGUIET_ELEMENT, environment, parent, id, rectangle )
{
FilledRatio = 0.0f;
FillColor = video::SColor(255,255,0,0);
EmptyColor = video::SColor();
AutomaticTextFormat = L"%2.0f %%";
bindColorsToSkin = bind;
}
void CGUIProgressBar::setAutomaticText( const wchar_t* text )
{
AutomaticTextFormat = text? text:L"";
if ( AutomaticTextFormat != L"" )
{
wchar_t* buffer = new wchar_t[ AutomaticTextFormat.size() + 10 ];
swprintf( buffer, AutomaticTextFormat.size() + 10, AutomaticTextFormat.c_str(), 100*FilledRatio );
Text = buffer;
delete buffer;
}
}
void CGUIProgressBar::setFillColor( video::SColor fill )
{
FillColor = fill;
}
video::SColor CGUIProgressBar::getFillColor() const
{
return FillColor;
}
void CGUIProgressBar::setEmptyColor( video::SColor empty )
{
EmptyColor = empty;
}
video::SColor CGUIProgressBar::getEmptyColor() const
{
return EmptyColor;
}
void CGUIProgressBar::setProgress( f32 progress )
{
FilledRatio = progress;
if ( AutomaticTextFormat != L"" )
{
wchar_t* buffer = new wchar_t[ AutomaticTextFormat.size() + 10 ];
swprintf( buffer, AutomaticTextFormat.size() + 10, AutomaticTextFormat.c_str(), 100*FilledRatio );
Text = buffer;
delete buffer;
}
}
f32 CGUIProgressBar::getProgress() const
{
return FilledRatio;
}
void CGUIProgressBar::draw()
{
CImageGUISkin* skin = static_cast<CImageGUISkin*>( Environment->getSkin() );
// Madoc added these changes to let the progress bar get its fill colors from the skin
if(bindColorsToSkin) {
EmptyColor = ((gui::SImageGUISkinConfig)skin->getConfig()).ProgressBar.Color;
FillColor = ((gui::SImageGUISkinConfig)skin->getConfig()).ProgressBarFilled.Color;
}
// End Madoc changes
skin->drawHorizontalProgressBar( this, AbsoluteRect, &AbsoluteClippingRect, FilledRatio, FillColor, EmptyColor );
// Draw text in center
skin->getFont(EGDF_DEFAULT)->draw( Text.c_str(), AbsoluteRect, skin->getColor(EGDC_BUTTON_TEXT), true, true, &AbsoluteClippingRect );
}
}
}
#ifndef CGUIPROGRESSBAR_H_
#define CGUIPROGRESSBAR_H_
#include <IGUIElement.h>
#include <SColor.h>
namespace irr
{
namespace gui
{
/*!
* A horizontal progess bar. ONLY works with CImageGUISkin applied - will fail
* if another skin is used.
*/
class CGUIProgressBar : public IGUIElement
{
public:
// If you want your progress bar colors to be independent of the skin set bind to false -- Madoc
CGUIProgressBar( IGUIElement* parent, IGUIEnvironment* environment, const core::rect<s32>& rectangle, s32 id=-1 ,bool bind=true);
//! Automatically updates the progress bar's text every time the progress changes.
//! Set format to NULL or an empty string to disable automatic text.
void setAutomaticText( const wchar_t* format );
void setFillColor( video::SColor fill );
video::SColor getFillColor() const;
void setEmptyColor( video::SColor empty );
video::SColor getEmptyColor() const;
void setProgress( f32 progress );
f32 getProgress() const;
virtual void draw();
private:
video::SColor FillColor;
video::SColor EmptyColor;
bool bindColorsToSkin;
f32 FilledRatio;
core::stringw AutomaticTextFormat;
};
} // namespace gui
} // namespace irr
#endif
This diff is collapsed.
#ifndef __C_GUISKIN_SYSTEM_H_INCLUDED__
#define __C_GUISKIN_SYSTEM_H_INCLUDED__
#ifdef _WIN32
#include <irrlicht.h>
#endif
#include "CImageGUISkin.h"
#include "CGUIProgressBar.h"
//#include "SkinLoader.h"
#include "../CXMLRegistry/CXMLRegistry.h"
#ifndef _WIN32
// gcc dosnt do 'debug'
#ifndef _DEBUG
#define _DEBUG
#endif
#endif
#define SKINSYSTEM_SKINFILE "/skin.xml"
using namespace irr;
class CGUISkinSystem {
private :
IrrlichtDevice *device;
io::IFileSystem *fs;
io::path skinsPath;
core::array<core::stringw> skinsList;
CXMLRegistry *registry;
gui::CImageGUISkin* loadSkinFromFile(const c8 *skinfile);
void ParseGUIElementStyle(gui::SImageGUIElementStyle& elem, const core::stringc& name,bool nullcolors=false);
bool checkSkinColor(gui::EGUI_DEFAULT_COLOR colToSet,const wchar_t *context,gui::CImageGUISkin *skin);
bool checkSkinSize(gui::EGUI_DEFAULT_SIZE sizeToSet,const wchar_t *context,const wchar_t *key,gui::CImageGUISkin *skin);
bool loadProperty(core::stringw key,gui::CImageGUISkin *skin);
public:
// Constructor
// path = Path to skins
// dev = Irrlicht device
CGUISkinSystem(core::string<wchar_t> path,IrrlichtDevice *dev);
~CGUISkinSystem();
core::array<core::stringw> listSkins();
bool loadSkinList();
bool applySkin(const wchar_t *skinname);
gui::CGUIProgressBar *addProgressBar(gui::IGUIElement *parent,core::rect<s32> rect,bool bindColorsToSkin=true);
// Gets property from current skin
core::stringw getProperty(core::stringw key);
bool populateTreeView(gui::IGUITreeView *control,const core::stringc& skinname);
};
#endif
This diff is collapsed.
#ifndef CIMAGEGUISKIN_H_
#define CIMAGEGUISKIN_H_
#include <IGUISkin.h>
#include <irrString.h>
#include <irrMap.h>
#include <IGUISpriteBank.h>
namespace irr
{
namespace video
{
class IVideoDriver;
class ITexture;
}
namespace gui
{
struct SImageGUIElementStyle
{
struct SBorder
{
s32 Top, Left, Bottom, Right;
SBorder() : Top(0), Left(0), Bottom(0), Right(0) {}
};
SBorder SrcBorder;
SBorder DstBorder;
video::ITexture* Texture;
video::SColor Color;
SImageGUIElementStyle() : Texture(0), Color(255,255,255,255) {}
};
struct SImageGUISkinConfig
{
SImageGUIElementStyle SunkenPane, Window, Button, ButtonPressed, ButtonDisabled, ProgressBar, ProgressBarFilled, TabButton, TabButtonPressed, TabBody, MenuBar, MenuPane, MenuPressed, CheckBox, CheckBoxDisabled, ComboBox, ComboBoxDisabled;
video::SColor CheckBoxColor;
};
class CImageGUISkin : public IGUISkin
{
public:
CImageGUISkin( video::IVideoDriver* videoDriver, IGUISkin* fallbackSkin );
virtual ~CImageGUISkin();
void loadConfig( const SImageGUISkinConfig& config );
//! returns default color
virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const;
//! sets a default color
virtual void setColor(EGUI_DEFAULT_COLOR which, video::SColor newColor);
//! returns default color
virtual s32 getSize(EGUI_DEFAULT_SIZE size) const;
//! Returns a default text.
virtual const wchar_t* getDefaultText(EGUI_DEFAULT_TEXT text) const;
//! Sets a default text.
virtual void setDefaultText(EGUI_DEFAULT_TEXT which, const wchar_t* newText);
//! sets a default size
virtual void setSize(EGUI_DEFAULT_SIZE which, s32 size);
//! returns the default font
virtual IGUIFont* getFont(EGUI_DEFAULT_FONT defaultFont) const;
//! sets a default font
virtual void setFont(IGUIFont* font, EGUI_DEFAULT_FONT defaultFont);
//! returns the sprite bank
virtual IGUISpriteBank* getSpriteBank() const;
//! sets the sprite bank
virtual void setSpriteBank(IGUISpriteBank* bank);
virtual u32 getIcon(EGUI_DEFAULT_ICON icon) const;
virtual void setIcon(EGUI_DEFAULT_ICON icon, u32 index);
virtual void draw3DButtonPaneStandard(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
virtual void draw3DButtonPanePressed(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
virtual void draw3DSunkenPane(IGUIElement* element,
video::SColor bgcolor, bool flat, bool fillBackGround,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
/* Updates for irrlicht 1.7 by Mamnarock
virtual core::rect<s32> draw3DWindowBackground(IGUIElement* element,
bool drawTitleBar, video::SColor titleBarColor,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
*/
virtual core::rect<s32> draw3DWindowBackground(IGUIElement* element,
bool drawTitleBar, video::SColor titleBarColor,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0,
core::rect<s32>* checkClientArea=0);
virtual void draw3DMenuPane(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
virtual void draw3DToolBar(IGUIElement* element,
const core::rect<s32>& rect,
const core::rect<s32>* clip=0);
virtual void draw3DTabButton(IGUIElement* element, bool active,
const core::rect<s32>& rect, const core::rect<s32>* clip=0, EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT);
virtual void draw3DTabBody(IGUIElement* element, bool border, bool background,
const core::rect<s32>& rect, const core::rect<s32>* clip=0,s32 tabHeight=-1, gui::EGUI_ALIGNMENT alignment=EGUIA_UPPERLEFT );
virtual void drawIcon(IGUIElement* element, EGUI_DEFAULT_ICON icon,
const core::position2di position, u32 starttime=0, u32 currenttime=0,
bool loop=false, const core::rect<s32>* clip=0);
// Madoc - I had to add some things
// Exposes config so we can get the progress bar colors
virtual SImageGUISkinConfig getConfig() { return Config; }
// End Madoc adds
virtual void drawHorizontalProgressBar( IGUIElement* element, const core::rect<s32>& rectangle, const core::rect<s32>* clip,
f32 filledRatio, video::SColor fillColor, video::SColor emptyColor );
virtual void draw2DRectangle(IGUIElement* element, const video::SColor &color,
const core::rect<s32>& pos, const core::rect<s32>* clip = 0);
virtual void setProperty(core::stringw key, core::stringw value);
virtual core::stringw getProperty(core::stringw key);
private:
void drawElementStyle( const SImageGUIElementStyle& elem, const core::rect<s32>& rect, const core::rect<s32>* clip, video::SColor* color=0 );
video::IVideoDriver* VideoDriver;
IGUISkin* FallbackSkin;
SImageGUISkinConfig Config;
core::map<core::stringw,core::stringw> properties;
};
}
}
#endif
#ifndef _CLIP_RECTS_H_
#define _CLIP_RECTS_H_
#include <rect.h>
namespace irr
{
//! Workaround for a bug in IVideoDriver::draw2DImage( ITexture* tex, rect<s32> dstRect, rect<s32> srcRect, rect<s32>* clip, SColor* colors, bool alpha )
//! It modifies dstRect and srcRect so the resulting dstRect is entirely inside the clipping rect.
//! srcRect is scaled so the same part of the image is displayed.
//! Returns false if dstRect is entirely outside clip, or true if at least some of it is inside.
inline bool clipRects( core::rect<s32>& dstRect, core::rect<s32>& srcRect, const core::rect<s32>& clip )
{
// Clip left side
if ( dstRect.UpperLeftCorner.X < clip.UpperLeftCorner.X )
{
s32 w = clip.UpperLeftCorner.X - dstRect.UpperLeftCorner.X;
f32 percentRemoved = (f32)w / (f32)dstRect.getWidth();
dstRect.UpperLeftCorner.X = clip.UpperLeftCorner.X;
srcRect.UpperLeftCorner.X += (s32)(percentRemoved * srcRect.getWidth());
}
// Clip top side
if ( dstRect.UpperLeftCorner.Y < clip.UpperLeftCorner.Y )
{
s32 w = clip.UpperLeftCorner.Y - dstRect.UpperLeftCorner.Y;
f32 percentRemoved = (f32)w / (f32)dstRect.getHeight();
dstRect.UpperLeftCorner.Y = clip.UpperLeftCorner.Y;
srcRect.UpperLeftCorner.Y += (s32)(percentRemoved * srcRect.getHeight());
}
// Clip right side
if ( dstRect.LowerRightCorner.X > clip.LowerRightCorner.X )
{
s32 w = dstRect.LowerRightCorner.X - clip.LowerRightCorner.X;
f32 percentRemoved = (f32)w / (f32)dstRect.getWidth();
dstRect.LowerRightCorner.X = clip.LowerRightCorner.X;
srcRect.LowerRightCorner.X -= (s32)(percentRemoved * srcRect.getWidth());
}
// Clip bottom side
if ( dstRect.LowerRightCorner.Y > clip.LowerRightCorner.Y )
{
s32 w = dstRect.LowerRightCorner.Y - clip.LowerRightCorner.Y;
f32 percentRemoved = (f32)w / (f32)dstRect.getHeight();
dstRect.LowerRightCorner.Y = clip.LowerRightCorner.Y;
srcRect.LowerRightCorner.Y -= (s32)(percentRemoved * srcRect.getHeight());
}
return ( dstRect.getWidth() > 0 && dstRect.getHeight() > 0 );
}
} // namespace irr
#endif
#include "CXMLNode.h"
CXMLNODETYPE CXMLNode::getType() { return type; }
void CXMLNode::setType(CXMLNODETYPE newtype) { type = newtype; }
void CXMLNode::setName(const wchar_t* newname) { name = newname; }
const wchar_t* CXMLNode::getName() { return name.c_str(); }
CXMLNode *CXMLNode::getThis() { return this; }
void CXMLNode::setValue(const wchar_t* newvalue) {
value = newvalue;
}
CXMLNode *CXMLNode::getParent() {
return parent;
}
void CXMLNode::setParent(CXMLNode *newparent) {
parent = newparent;
}
/*
bool CXMLNode::getValueAsBool() {
if(!value.size()) return false;
if(value.equals_ignore_case((core::stringw)"true")) return true;
return false;
}
s32 CXMLNode::getValueAsInt() {
if(!value.size()) return 0;
return _wtoi(value.c_str());
}
const wchar_t* CXMLNode::getValueAsCStr() {
if(!value.size()) return false;
return value.c_str();
}
*/
/*
u16 CXMLNode::getChildCount() {
return children.getSize();
}
irr::core::list<CXMLNode*>::Iterator CXMLNode::getFirstChild() {
//if(children.empty()) return 0;
return children.begin();
}
irr::core::list<CXMLNode*>::Iterator CXMLNode::getLastChild() {
//if(children.empty()) return 0;
return children.getLast();
}
*/
const wchar_t* CXMLNode::getValue() {
return value.c_str();
}
void CXMLNode::addChild(CXMLNode *newchild) {
children.push_back(newchild);
}
void CXMLNode::drop() {
if(children.getSize() != 0) {
core::list<CXMLNode*>::Iterator it;
for( it = children.begin(); it != children.end(); it++ ) {
( *it )->drop();
}
children.clear();
}
}
CXMLNode *CXMLNode::findChildByName(const wchar_t *name) {
core::list<CXMLNode*>::Iterator it;
core::stringw tmp;
CXMLNode *node = NULL;
tmp = name;
for( it = children.begin(); it != children.end(); it++ ) {
if(tmp.equals_ignore_case((*it)->getName())) {
node = (*it);
break;
}
}
return node;
}
core::array<const wchar_t*> *CXMLNode::listChildrenByType(CXMLNODETYPE nodetype) {
core::array<const wchar_t*> *ret = new core::array<const wchar_t*>;
//core::stringw construct = L"";
core::list<CXMLNode*>::Iterator it;
for( it = children.begin(); it != children.end(); it++ ) {
if((*it)->getType() == nodetype) {
ret->push_front((*it)->getName());
}
}
return ret;
}
core::array<const wchar_t*> *CXMLNode::listNonNodeChildren() {
return listChildrenByType(CXMLNODETYPE_VALUE);
}
core::array<const wchar_t*> *CXMLNode::listNodeChildren() {
return listChildrenByType(CXMLNODETYPE_NODE);
}
void CXMLNode::populateTreeView(irr::gui::IGUITreeViewNode *node) {
irr::gui::IGUITreeViewNode *myNode;
irr::core::stringw myText;
core::list<CXMLNode*>::Iterator it;
// If I'm a value, I have nothing to add, my parent will do that
if(type == CXMLNODETYPE_VALUE) return;
// So I'm a node, if im not the toplevel node, write me
if(parent != NULL) {
//myText = L"(Key) ";
myText += getName();
myNode = node->addChildBack(myText.c_str());
}
else
myNode = node;
// If I dont have children, I'm done
if(children.empty()) return;
// setup my children
for( it = children.begin(); it != children.end(); it++ ) {
switch((*it)->getType()) {
case CXMLNODETYPE_NODE :
myText = L"";
myText += (core::stringw)(*it)->getName();
(*it)->populateTreeView(myNode);
break;
case CXMLNODETYPE_VALUE :
myText = L"";
myText += (core::stringw)(*it)->getName();
myText += L":";
myText += (core::stringw)(*it)->getValue();
myNode->addChildBack(myText.c_str());
}
}
}
void CXMLNode::writeOut(io::IXMLWriter* xml) {
core::array<core::stringw> names;
core::array<core::stringw> values;
core::list<CXMLNode*>::Iterator it;
bool nodeChildren = false;
// If I'm a value, I have nothing to write, I'll be written by my parent
if(type == CXMLNODETYPE_VALUE) return;
// If I'm a node with no values, which also means no children write as empty and return
if(children.empty()) {
xml->writeElement(name.c_str(),true);
xml->writeLineBreak();
return;
}
// Need to figure out myself first
for( it = children.begin(); it != children.end(); it++ ) {
// cache all my values for writing, and set a flag if I have node children, ie non empty
switch((*it)->getType()) {
case CXMLNODETYPE_VALUE:
names.push_front((core::stringw)(*it)->getName());
values.push_front((core::stringw)(*it)->getValue());
break;
case CXMLNODETYPE_NODE:
nodeChildren = true;
}
}
// At this point I just need to write myself
xml->writeElement(name.c_str(),nodeChildren?false:true,names,values);
xml->writeLineBreak();
// Now I need to see if I have to tell my node children to write
if(!nodeChildren) return;
for( it = children.begin(); it != children.end(); it++ ) {
// If I have a node child, tell it to write, recursion made easy!
if((*it)->getType() == CXMLNODETYPE_NODE) {
(*it)->writeOut(xml);
}
}
xml->writeClosingTag(name.c_str());
xml->writeLineBreak();
}
\ No newline at end of file
// Madoc 05/09
#ifndef __C_XMLNODE_H_INCLUDED__
#define __C_XMLNODE_H_INCLUDED__
#include <irrlicht.h>
using namespace irr;
enum CXMLNODETYPE {
CXMLNODETYPE_VALUE,
CXMLNODETYPE_NODE,
//CXMLNODETYPE_COMMENT
};
class CXMLNode {
public :
/* Decided to move this up to the registry object, reduce mem use.
s32 getValueAsInt();
const wchar_t* getValueAsCStr();
bool getValueAsBool();
*/
CXMLNODETYPE getType();
const wchar_t* getName();
const wchar_t* getValue();
void setType(CXMLNODETYPE newtype);
void setName(const wchar_t* newname);
void setValue(const wchar_t* newvalue);
void addChild(CXMLNode *newchild);
void writeOut(irr::io::IXMLWriter* xml);
void populateTreeView(irr::gui::IGUITreeViewNode *node);
//u16 getChildCount();
void drop();
/*
irr::core::list<CXMLNode*>::Iterator getFirstChild();
// get last is not get end point, this causes problems with iterators
// Screw it, I'll keep all pointers internal
irr::core::list<CXMLNode*>::Iterator getLastChild();
*/
// Careful with these, mem leak waiting to happen
// Maby I should steal IReferenceCounted from irrlicht, would at
// least give me autodetection of mem leaks
core::array<const wchar_t *> *listNonNodeChildren();
core::array<const wchar_t *> *listNodeChildren();
CXMLNode *getThis();
CXMLNode *findChildByName(const wchar_t *name);
CXMLNode *getParent();
void setParent(CXMLNode *newparent);
private :
CXMLNode *parent;
irr::core::stringw value;
irr::core::stringw name;
CXMLNODETYPE type;
irr::core::list<CXMLNode*> children;
irr::core::array<const wchar_t *> *listChildrenByType(CXMLNODETYPE nodetype);
};
#endif
#include "CXMLRegistry.h"
#ifndef _WIN32
inline int _wtoi(const wchar_t * str){
return (int)wcstol(str, 0, 10);
}
#endif
CXMLRegistry::CXMLRegistry(io::IFileSystem *fsys) {
fileSystem = fsys;
fileSystem->grab();
registry = NULL;
}
CXMLRegistry::~CXMLRegistry() {
if(registry != NULL) registry->drop();
fileSystem->drop();
}
bool CXMLRegistry::isTopLevelNode(const wchar_t *node) {
if(registry->findChildByName(node)) return true;
else return false;
}
CXMLNode *CXMLRegistry::resolveContext(const wchar_t* context) {
core::stringw sContext;
CXMLNode *currentNode;
u16 start;
s16 end;
if(!context) return currentContext;
sContext = context;
if(sContext.size() == 0) return 0;
// Make sure the context ends in a /
if(sContext.lastChar() != L'/')
sContext += L'/';
start = 0;
end = sContext.findFirst('/');
// Theres no values in the top level nodes
if(end == -1) return 0;
currentNode = registry;
while(end != -1) {
currentNode = currentNode->findChildByName(sContext.subString(start,end-start).c_str());
if(currentNode == NULL) return NULL;
start = end+1;
end = sContext.findNext('/',start);
}
return currentNode;
}
void CXMLRegistry::setContext(const wchar_t *context) { currentContext = resolveContext(context); }
const wchar_t *CXMLRegistry::convertBoolToText(bool boolval) {
if(boolval) return L"true";
else return L"false";
}
bool CXMLRegistry::convertTextToBool(const wchar_t *textval) {
if(((core::stringw)textval).equals_ignore_case(L"true")) return true;
return false;
}
bool CXMLRegistry::setValue(const wchar_t *index, bool boolval, const wchar_t *context) {
return setValue(index,convertBoolToText(boolval),context);
}
bool CXMLRegistry::setValue(const wchar_t *index, u16 intval, const wchar_t *context) {
return setValue(index,((core::stringw)intval).c_str(),context);
}
bool CXMLRegistry::setValue(const wchar_t *index, const wchar_t * txtval, const wchar_t *context) {
CXMLNode *targetNode;
targetNode = resolveContext(context);
if(!targetNode) return false;
targetNode = targetNode->findChildByName(index);
if(!targetNode) return false;
targetNode->setValue(txtval);
return true;
}
bool CXMLRegistry::populateTreeView(irr::gui::IGUITreeView *control, const wchar_t *context) {
CXMLNode *targetNode = NULL;
if(context == 0)
targetNode = registry;
else
targetNode = resolveContext(context);
if(!targetNode) return false;
targetNode->populateTreeView(control->getRoot());
return true;
}
bool CXMLRegistry::getValueAsBool(const wchar_t *index, const wchar_t *context) {
return convertTextToBool(getValueAsCStr(index,context));
}
// little more robust
u16 CXMLRegistry::getValueAsInt(const wchar_t *index, const wchar_t *context) {
core::stringw tmp = getValueAsCStr(index,context);
if(tmp.equals_ignore_case("")) return 0;
else return _wtoi(tmp.c_str());
}
core::array<const wchar_t*>* CXMLRegistry::listNonNodeChildren(const wchar_t *node,const wchar_t *context) {
CXMLNode *targetNode;
targetNode = resolveContext(context);
if(!targetNode) return 0;
return targetNode->listNonNodeChildren();
}
core::array<const wchar_t*>* CXMLRegistry::listNodeChildren(const wchar_t *node,const wchar_t *context) {
CXMLNode *targetNode;
targetNode = resolveContext(context);
if(!targetNode) return 0;
return targetNode->listNodeChildren();
}
//BROKEN
/*
const irr::c8 *CXMLRegistry::getValueAsCharCStr(const wchar_t *index, const wchar_t *context) {
irr::core::stringc temp;
temp = getValueAsCStr(index,context);
return (const irr::c8 *)temp.c_str();
}
*/
const wchar_t *CXMLRegistry::getValueAsCStr(const wchar_t *index, const wchar_t *context) {
CXMLNode *targetNode;
targetNode = resolveContext(context);
if(!targetNode) return 0;
targetNode = targetNode->findChildByName(index);
if(!targetNode) return 0;
return targetNode->getValue();
}
irr::core::rect<u32> CXMLRegistry::getValueAsRect(const wchar_t *context) {
CXMLNode *targetNode = resolveContext(context);
irr::u32 tx,ty,bx,by;
if(!targetNode) return irr::core::rect<u32>(0,0,0,0);
tx = _wtoi(targetNode->findChildByName(L"tlx")->getValue());
ty = _wtoi(targetNode->findChildByName(L"tly")->getValue());
bx = _wtoi(targetNode->findChildByName(L"brx")->getValue());
by = _wtoi(targetNode->findChildByName(L"bry")->getValue());
// Hrm what to return on err, cant return null, 0,0,0,0 might be a real loc
// Its u32, maby some HUGE value? maxint?
// Still takes out a value but its less likely
if(!tx || !ty || !bx || !by) return irr::core::rect<u32>(0,0,0,0);
else return irr::core::rect<u32>(tx,ty,bx,by);
}
// Made more robust
irr::video::SColor CXMLRegistry::getValueAsColor(const wchar_t *context) {
CXMLNode *targetNode = resolveContext(context);
if(!targetNode) return NULL;
irr::u32 r,g,b,a;
irr::core::stringw tmp;
tmp = targetNode->findChildByName(L"r")->getValue();
if(tmp.size()) r = _wtoi(tmp.c_str());
tmp = targetNode->findChildByName(L"g")->getValue();
if(tmp.size()) g = _wtoi(tmp.c_str());
tmp = targetNode->findChildByName(L"b")->getValue();
if(tmp.size()) b = _wtoi(tmp.c_str());
tmp = targetNode->findChildByName(L"a")->getValue();
if(tmp.size()) a = _wtoi(tmp.c_str());
return irr::video::SColor(a,r,g,b);
}
bool CXMLRegistry::writeFile(const irr::c8 *fname,const c8 *path) {
io::IXMLWriter* xml;
CXMLNode *currentnode = 0;
core::stringw wstmp;
core::stringc fileName;
wstmp = fname;
currentnode = registry->findChildByName(wstmp.c_str());
if(!currentnode) return false;
fileName = path;
fileName += fname;
fileName += ".xml";
xml = fileSystem->createXMLWriter(fileName.c_str());
xml->writeXMLHeader();
currentnode->writeOut(xml);
// Get rid of double top level end tag
//xml->writeClosingTag(currentnode->getName());
//xml->writeLineBreak();
//if(xml) xml->drop();
delete xml;
return true;
}
// check current folder, if there isnt anything in current, use default
const c8 *CXMLRegistry::resolveConfigPath(const c8 *fname) {
core::string <c8> filename;
bool useCurrent = true;
filename = "config/current/";
filename += fname;
filename += ".xml";
if(!fileSystem->existFile(filename.c_str())) {
useCurrent = false;
}
return useCurrent?"config/current/":"config/defaults/";
}
bool CXMLRegistry::loadConfigFile(const c8 *fname) {
return loadFile(fname, resolveConfigPath(fname));
}
bool CXMLRegistry::writeConfigFile(const c8 *fname) {
return writeFile(fname,"config/current/");
}
// This is tricky, we have to keep track of which nodes are 'open'
bool CXMLRegistry::loadFile(const c8 *fname, const c8 *path) {
io::IXMLReader* xml;
CXMLNode *currentNode = 0;
CXMLNode *topNode = 0;
CXMLNode *currentParent;
core::string <c8> filename;
filename = path;
filename += fname;
// If it dosnt end in .xml add it
if(!filename.subString(filename.size()-4,4).equals_ignore_case(".xml"))
filename += ".xml";
xml = fileSystem->createXMLReader(filename.c_str());
if(!registry) {
registry = new CXMLNode;
registry->setName(L"TopLevelNode");
registry->setType(CXMLNODETYPE_NODE);
}
while(xml && xml->read()) {
CXMLNode *newNode = 0;
switch(xml->getNodeType()) {
case io::EXN_ELEMENT :
u16 i;
newNode = new CXMLNode;
newNode->setName(xml->getNodeName());
newNode->setType(CXMLNODETYPE_NODE);
if(!topNode) {
newNode->setParent(NULL);
registry->addChild(newNode);
topNode = newNode;
currentParent = newNode;
}
else {
newNode->setParent(currentParent);
currentParent->addChild(newNode);
if(!xml->isEmptyElement())
currentParent = newNode;
}
currentNode = newNode;
i = xml->getAttributeCount();
while(i--) {
newNode = new CXMLNode;
newNode->setName(xml->getAttributeName(i));
newNode->setType(CXMLNODETYPE_VALUE);
newNode->setValue(xml->getAttributeValue(i));
currentNode->addChild(newNode);
}
break;
case io::EXN_ELEMENT_END :
// NEVER go back further then the topNode
// Even if the XML is screwed up
if(currentParent->getParent() != NULL)
currentParent = currentParent->getParent();
break;
/*
case io::EXN_COMMENT :
newNode = new CXMLNode;
newNode->setType(CXMLNODETYPE_COMMENT);
//newNode->setValue(xml->getNodeType
currentNode->addChild(newNode);
break;
*/
}
}
//if(xml) xml->drop();
// Documentation says delete not drop
delete xml;
// To support loading multiple files or 'hives' have to
// see if this load ADDED any to decide succcessful or not
if(topNode == 0) return false;
return true;
}
\ No newline at end of file
// Madoc 05/09
#ifndef __C_XMLREGISTRY_H_INCLUDED__
#define __C_XMLREGISTRY_H_INCLUDED__
#include <irrlicht.h>
using namespace irr;
#include "CXMLNode.h"
//File->
// Node1->
// Name1/Value
// Node2->
// Name2/Value
// Oddity: Very little error checking, crashes if you look at it funny
// Oddity: When using setValue ala setValue("someindex",100); compiler cant tell if 100 is a bool or an int, silly compiler,
// casting to u16 works ala setValue("someindex",(u16)100); I see why, but its still silly, and casts are slow
class CXMLRegistry {
public:
CXMLRegistry(io::IFileSystem *fsys);
~CXMLRegistry();
bool loadFile(const c8 *fname, const c8 *path);
bool loadConfigFile(const c8 *fname);
bool writeFile(const c8 *fname, const c8 *path);
bool writeConfigFile(const c8 *fname);
const wchar_t *getValueAsCStr(const wchar_t *index,const wchar_t *context = 0);
// Dosnt work, just declare a stringc and assign the wchar_t to it
//const irr::c8 *getValueAsCharCStr(const wchar_t *index,const wchar_t *context = 0);
bool getValueAsBool(const wchar_t *index, const wchar_t *context = 0);
u16 getValueAsInt(const wchar_t *index, const wchar_t *context = 0);
// This one only takes a context because its going to read 4 childrens values
irr::core::rect<u32> getValueAsRect(const wchar_t *context = 0);
// This one only takes a context because its going to read 4 childrens values
video::SColor getValueAsColor(const wchar_t *context = 0);
irr::core::array<const wchar_t*> *listNonNodeChildren(const wchar_t *node,const wchar_t *context = 0);
irr::core::array<const wchar_t*> *listNodeChildren(const wchar_t *node,const wchar_t *context = 0);
bool setValue(const wchar_t *index, bool boolval, const wchar_t *context = 0);
bool setValue(const wchar_t *index, u16 intval, const wchar_t *context = 0);
bool setValue(const wchar_t *index, const wchar_t *txtval,const wchar_t *context = 0);
// Speed improvement, why search if we want multiple values from the same context
void setContext(const wchar_t *context);
bool isTopLevelNode(const wchar_t *node);
bool populateTreeView(irr::gui::IGUITreeView *control,const wchar_t *context = 0);
// TODO: These are trivial to do, just dont need them yet
// renameNode(context(?),TYPE)
// deleteNode(context(?) (CAREFUL WITH CHILDREN)
// addNode(context, value, type)
// CXMLNODETYPE_COMMENT
// Loading/saving of CDATA, easiest would be just save it in the value of
// the CXMLNODETYPE_NODE their accosicated with.
// make registry inherit node instead of containing an instance of it.
// context(?) might be tricky with CXMLNODETYPE_VALUE
//
//
private:
io::IFileSystem* fileSystem;
CXMLNode* registry;
CXMLNode* currentContext;
const wchar_t *convertBoolToText(bool boolval);
bool convertTextToBool(const wchar_t* textval);
CXMLNode *resolveContext(const wchar_t* context);
const irr::c8 *resolveConfigPath(const irr::c8 *fname);
};
#endif
#ifndef BASE64_H
#define BASE64_H
#include <string>
#include <cstring>
const char kBase64Alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
class Base64 {
public:
static bool Encode(const std::string &in, std::string *out) {
int i = 0, j = 0;
size_t enc_len = 0;
unsigned char a3[3];
unsigned char a4[4];
out->resize(EncodedLength(in));
int input_len = in.size();
std::string::const_iterator input = in.begin();
while (input_len--) {
a3[i++] = *(input++);
if (i == 3) {
a3_to_a4(a4, a3);
for (i = 0; i < 4; i++) {
(*out)[enc_len++] = kBase64Alphabet[a4[i]];
}
i = 0;
}
}
if (i) {
for (j = i; j < 3; j++) {
a3[j] = '\0';
}
a3_to_a4(a4, a3);
for (j = 0; j < i + 1; j++) {
(*out)[enc_len++] = kBase64Alphabet[a4[j]];
}
while ((i++ < 3)) {
(*out)[enc_len++] = '=';
}
}
return (enc_len == out->size());
}
static bool Encode(const unsigned char *input, size_t input_length, unsigned char *out, size_t out_length) {
int i = 0, j = 0;
unsigned char *out_begin = out;
unsigned char a3[3];
unsigned char a4[4];
size_t encoded_length = EncodedLength(input_length);
if (out_length < encoded_length + 1) return false;
std::memset(out, 0, out_length);
while (input_length--) {
a3[i++] = *input++;
if (i == 3) {
a3_to_a4(a4, a3);
for (i = 0; i < 4; i++) {
*out++ = kBase64Alphabet[a4[i]];
}
i = 0;
}
}
if (i) {
for (j = i; j < 3; j++) {
a3[j] = '\0';
}
a3_to_a4(a4, a3);
for (j = 0; j < i + 1; j++) {
*out++ = kBase64Alphabet[a4[j]];
}
while ((i++ < 3)) {
*out++ = '=';
}
}
return (out == (out_begin + encoded_length));
}
static bool Decode(const std::string &in, std::string *out) {
int i = 0, j = 0;
size_t dec_len = 0;
unsigned char a3[3];
unsigned char a4[4];
int input_len = in.size();
std::string::const_iterator input = in.begin();
out->resize(DecodedLength(in));
while (input_len--) {
if (*input == '=') {
break;
}
a4[i++] = *(input++);
if (i == 4) {
for (i = 0; i <4; i++) {
a4[i] = b64_lookup(a4[i]);
}
a4_to_a3(a3,a4);
for (i = 0; i < 3; i++) {
(*out)[dec_len++] = a3[i];
}
i = 0;
}
}
if (i) {
for (j = i; j < 4; j++) {
a4[j] = '\0';
}
for (j = 0; j < 4; j++) {
a4[j] = b64_lookup(a4[j]);
}
a4_to_a3(a3,a4);
for (j = 0; j < i - 1; j++) {
(*out)[dec_len++] = a3[j];
}
}
return (dec_len == out->size());
}
static bool Decode(const unsigned char *input, size_t input_length, unsigned char *out, size_t out_length) {
int i = 0, j = 0;
unsigned char *out_begin = out;
unsigned char a3[3];
unsigned char a4[4];
size_t decoded_length = DecodedLength(input, input_length);
if (out_length < decoded_length) return false;
while (input_length--) {
if (*input == '=') {
break;
}
a4[i++] = *(input++);
if (i == 4) {
for (i = 0; i <4; i++) {
a4[i] = b64_lookup(a4[i]);
}
a4_to_a3(a3,a4);
for (i = 0; i < 3; i++) {
*out++ = a3[i];
}
i = 0;
}
}
if (i) {
for (j = i; j < 4; j++) {
a4[j] = '\0';
}
for (j = 0; j < 4; j++) {
a4[j] = b64_lookup(a4[j]);
}
a4_to_a3(a3,a4);
for (j = 0; j < i - 1; j++) {
*out++ = a3[j];
}
}
return (out == (out_begin + decoded_length));
}
static int DecodedLength(const unsigned char *in, size_t in_length) {
int numEq = 0;
const unsigned char *in_end = in + in_length;
while (*--in_end == '=') ++numEq;
return ((6 * in_length) / 8) - numEq;
}
static int DecodedLength(const std::string &in) {
int numEq = 0;
int n = in.size();
for (std::string::const_reverse_iterator it = in.rbegin(); *it == '='; ++it) {
++numEq;
}
return ((6 * n) / 8) - numEq;
}
inline static int EncodedLength(size_t length) {
return (length + 2 - ((length + 2) % 3)) / 3 * 4;
}
inline static int EncodedLength(const std::string &in) {
return EncodedLength(in.length());
}
inline static void StripPadding(std::string *in) {
while (!in->empty() && *(in->rbegin()) == '=') in->resize(in->size() - 1);
}
private:
static inline void a3_to_a4(unsigned char * a4, unsigned char * a3) {
a4[0] = (a3[0] & 0xfc) >> 2;
a4[1] = ((a3[0] & 0x03) << 4) + ((a3[1] & 0xf0) >> 4);
a4[2] = ((a3[1] & 0x0f) << 2) + ((a3[2] & 0xc0) >> 6);
a4[3] = (a3[2] & 0x3f);
}
static inline void a4_to_a3(unsigned char * a3, unsigned char * a4) {
a3[0] = (a4[0] << 2) + ((a4[1] & 0x30) >> 4);
a3[1] = ((a4[1] & 0xf) << 4) + ((a4[2] & 0x3c) >> 2);
a3[2] = ((a4[2] & 0x3) << 6) + a4[3];
}
static inline unsigned char b64_lookup(unsigned char c) {
if(c >='A' && c <='Z') return c - 'A';
if(c >='a' && c <='z') return c - 71;
if(c >='0' && c <='9') return c + 4;
if(c == '+') return 62;
if(c == '/') return 63;
return 255;
}
};
#endif // BASE64_H
......@@ -10,9 +10,15 @@ public:
static int ReadInt32(unsigned char*& p) {
return buffer_read<int32_t>(p);
}
static unsigned int ReadUInt32(unsigned char*& p) {
return buffer_read<uint32_t>(p);
}
static short ReadInt16(unsigned char*& p) {
return buffer_read<int16_t>(p);
}
static unsigned short ReadUInt16(unsigned char*& p) {
return buffer_read<uint16_t>(p);
}
static char ReadInt8(unsigned char*& p) {
return buffer_read<char>(p);
}
......
......@@ -88,6 +88,9 @@ void ClientField::Clear() {
extra_act[i] = false;
pzone_act[i] = false;
}
for(auto cit = limbo_temp.begin(); cit != limbo_temp.end(); ++cit)
delete *cit;
limbo_temp.clear();
for(auto sit = overlay_cards.begin(); sit != overlay_cards.end(); ++sit)
delete *sit;
overlay_cards.clear();
......@@ -117,6 +120,7 @@ void ClientField::Clear() {
cant_check_grave = false;
tag_surrender = false;
tag_teammate_surrender = false;
RefreshCardCountDisplay();
}
void ClientField::Initial(int player, int deckc, int extrac, int sidec) {
auto load_location = [&](std::vector<ClientCard*>& container, int count, uint8_t location) {
......@@ -135,6 +139,8 @@ void ClientField::Initial(int player, int deckc, int extrac, int sidec) {
load_location(deck[player], deckc, LOCATION_DECK);
load_location(extra[player], extrac, LOCATION_EXTRA);
load_location(remove[player], sidec, LOCATION_REMOVED);
RefreshCardCountDisplay();
}
void ClientField::ResetSequence(std::vector<ClientCard*>& list, bool reset_height) {
unsigned char seq = 0;
......@@ -243,6 +249,7 @@ void ClientField::AddCard(ClientCard* pcard, int controler, int location, int se
break;
}
}
RefreshCardCountDisplay();
}
ClientCard* ClientField::RemoveCard(int controler, int location, int sequence) {
ClientCard* pcard = nullptr;
......@@ -313,6 +320,7 @@ ClientCard* ClientField::RemoveCard(int controler, int location, int sequence) {
return nullptr;
}
pcard->location = 0;
RefreshCardCountDisplay();
return pcard;
}
void ClientField::UpdateCard(int controler, int location, int sequence, unsigned char* data) {
......@@ -320,6 +328,7 @@ void ClientField::UpdateCard(int controler, int location, int sequence, unsigned
int len = BufferIO::ReadInt32(data);
if (pcard && len > LEN_HEADER)
pcard->UpdateInfo(data);
RefreshCardCountDisplay();
}
void ClientField::UpdateFieldCard(int controler, int location, unsigned char* data) {
std::vector<ClientCard*>* lst = 0;
......@@ -355,6 +364,7 @@ void ClientField::UpdateFieldCard(int controler, int location, unsigned char* da
(*cit)->UpdateInfo(data);
data += len - 4;
}
RefreshCardCountDisplay();
}
void ClientField::ClearCommandFlag() {
for(auto cit = activatable_cards.begin(); cit != activatable_cards.end(); ++cit)
......@@ -462,6 +472,8 @@ void ClientField::ShowSelectCard(bool buttonok, bool chain) {
myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(selectable_cards[i]->overlayTarget->location, selectable_cards[i]->overlayTarget->sequence),
selectable_cards[i]->overlayTarget->sequence + 1, selectable_cards[i]->sequence + 1);
else if (selectable_cards[i]->location == 0)
myswprintf(formatBuffer, L"");
else
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i]->location, selectable_cards[i]->sequence),
selectable_cards[i]->sequence + 1);
......@@ -757,6 +769,7 @@ void ClientField::ReplaySwap() {
std::swap(mainGame->dInfo.strLP[0], mainGame->dInfo.strLP[1]);
std::swap(mainGame->dInfo.hostname, mainGame->dInfo.clientname);
std::swap(mainGame->dInfo.hostname_tag, mainGame->dInfo.clientname_tag);
RefreshCardCountDisplay();
for(auto chit = chains.begin(); chit != chains.end(); ++chit) {
chit->controler = 1 - chit->controler;
GetChainLocation(chit->controler, chit->location, chit->sequence, &chit->chain_pos);
......@@ -1059,21 +1072,22 @@ void ClientField::GetCardLocation(ClientCard* pcard, irr::core::vector3df* t, ir
break;
}
case LOCATION_OVERLAY: {
if (pcard->overlayTarget->location != LOCATION_MZONE) {
if (!(pcard->overlayTarget->location & LOCATION_ONFIELD)) {
return;
}
int oseq = pcard->overlayTarget->sequence;
int mseq = (sequence < MAX_LAYER_COUNT) ? sequence : (MAX_LAYER_COUNT - 1);
auto vFieldZone = (pcard->overlayTarget->location == LOCATION_MZONE) ? matManager.vFieldMzone[pcard->overlayTarget->controler][oseq] : matManager.vFieldSzone[pcard->overlayTarget->controler][oseq][rule];
if (pcard->overlayTarget->controler == 0) {
t->X = (matManager.vFieldMzone[0][oseq][0].Pos.X + matManager.vFieldMzone[0][oseq][1].Pos.X) / 2 - 0.12f + 0.06f * mseq;
t->Y = (matManager.vFieldMzone[0][oseq][0].Pos.Y + matManager.vFieldMzone[0][oseq][2].Pos.Y) / 2 + 0.05f;
t->X = (vFieldZone[0].Pos.X + vFieldZone[1].Pos.X) / 2 - 0.12f + 0.06f * mseq;
t->Y = (vFieldZone[0].Pos.Y + vFieldZone[2].Pos.Y) / 2 + 0.05f;
t->Z = overlay_buttom + mseq * material_height;
r->X = 0.0f;
r->Y = 0.0f;
r->Z = 0.0f;
} else {
t->X = (matManager.vFieldMzone[1][oseq][0].Pos.X + matManager.vFieldMzone[1][oseq][1].Pos.X) / 2 + 0.12f - 0.06f * mseq;
t->Y = (matManager.vFieldMzone[1][oseq][0].Pos.Y + matManager.vFieldMzone[1][oseq][2].Pos.Y) / 2 - 0.05f;
t->X = (vFieldZone[0].Pos.X + vFieldZone[1].Pos.X) / 2 + 0.12f - 0.06f * mseq;
t->Y = (vFieldZone[0].Pos.Y + vFieldZone[2].Pos.Y) / 2 - 0.05f;
t->Z = overlay_buttom + mseq * material_height;
r->X = 0.0f;
r->Y = 0.0f;
......@@ -1168,6 +1182,14 @@ bool ClientField::ShowSelectSum(bool panelmode) {
}
return false;
}
static void get_sum_params(irr::u32 opParam, int& op1, int& op2) {
op1 = opParam & 0xffff;
op2 = (opParam >> 16) & 0xffff;
if(op2 & 0x8000) {
op1 = opParam & 0x7fffffff;
op2 = 0;
}
}
bool ClientField::CheckSelectSum() {
std::set<ClientCard*> selable;
for(auto sc : selectsum_all) {
......@@ -1547,20 +1569,27 @@ void ClientField::UpdateDeclarableList() {
ancard.push_back(trycode);
return;
}
if(pname[0] == 0) {
int sel = mainGame->lstANCard->getSelected();
trycode = (sel == -1) ? 0 : ancard[sel];
}
mainGame->lstANCard->clear();
ancard.clear();
if(pname[0] == 0 && mainGame->dInfo.announce_cache.size()) {
for(int i = 0; i < mainGame->dInfo.announce_cache.size(); ++i) {
unsigned int cache_code = mainGame->dInfo.announce_cache[i];
if(dataManager.GetString(cache_code, &cstr) && dataManager.GetData(cache_code, &cd) && is_declarable(cd, declare_opcodes)) {
mainGame->lstANCard->addItem(cstr.name.c_str());
ancard.push_back(cache_code);
}
}
// if(ancard.size())
// return;
}
for(auto cit = dataManager.strings_begin(); cit != dataManager.strings_end(); ++cit) {
if(cit->second.name.find(pname) != std::wstring::npos) {
if(cit->second.name.find(pname) != std::wstring::npos || mainGame->CheckRegEx(cit->second.name, pname)) {
auto cp = dataManager.GetCodePointer(cit->first);
if (cp == dataManager.datas_end())
continue;
//datas.alias can be double card names or alias
if(is_declarable(cp->second, declare_opcodes)) {
if(pname == cit->second.name || trycode == cit->first) { //exact match or last used
if(pname == cit->second.name) { //exact match
mainGame->lstANCard->insertItem(0, cit->second.name.c_str(), -1);
ancard.insert(ancard.begin(), cit->first);
} else {
......@@ -1571,4 +1600,49 @@ void ClientField::UpdateDeclarableList() {
}
}
}
void ClientField::RefreshCardCountDisplay() {
ClientCard* pcard;
for(int p = 0; p < 2; ++p) {
mainGame->dInfo.card_count[p] = hand[p].size();
mainGame->dInfo.total_attack[p] = 0;
for(auto it = mzone[p].begin(); it != mzone[p].end(); ++it) {
pcard = *it;
if(pcard) {
//if(pcard->type & TYPE_LINK && pcard->link)
// mainGame->dInfo.card_count[p] += pcard->link;
//else
mainGame->dInfo.card_count[p]++;
if(pcard->position == POS_FACEUP_ATTACK && pcard->attack > 0 && (p == 1 || mainGame->dInfo.curMsg != MSG_SELECT_BATTLECMD || pcard->cmdFlag & COMMAND_ATTACK))
mainGame->dInfo.total_attack[p] += pcard->attack;
}
}
for(auto it = szone[p].begin(); it != szone[p].end(); ++it) {
pcard = *it;
if(pcard)
mainGame->dInfo.card_count[p]++;
}
myswprintf(mainGame->dInfo.str_card_count[p], L"%d", mainGame->dInfo.card_count[p]);
myswprintf(mainGame->dInfo.str_total_attack[p], L"%d", mainGame->dInfo.total_attack[p]);
}
if(mainGame->dInfo.card_count[0] > mainGame->dInfo.card_count[1]) {
mainGame->dInfo.card_count_color[0] = 0xffffff00;
mainGame->dInfo.card_count_color[1] = 0xffff0000;
} else if(mainGame->dInfo.card_count[1] > mainGame->dInfo.card_count[0]) {
mainGame->dInfo.card_count_color[1] = 0xffffff00;
mainGame->dInfo.card_count_color[0] = 0xffff0000;
} else {
mainGame->dInfo.card_count_color[0] = 0xffffffff;
mainGame->dInfo.card_count_color[1] = 0xffffffff;
}
if(mainGame->dInfo.total_attack[0] > mainGame->dInfo.total_attack[1]) {
mainGame->dInfo.total_attack_color[0] = 0xffffff00;
mainGame->dInfo.total_attack_color[1] = 0xffff0000;
} else if(mainGame->dInfo.total_attack[1] > mainGame->dInfo.total_attack[0]) {
mainGame->dInfo.total_attack_color[1] = 0xffffff00;
mainGame->dInfo.total_attack_color[0] = 0xffff0000;
} else {
mainGame->dInfo.total_attack_color[0] = 0xffffffff;
mainGame->dInfo.total_attack_color[1] = 0xffffffff;
}
}
}
......@@ -32,6 +32,7 @@ public:
std::vector<ClientCard*> grave[2];
std::vector<ClientCard*> remove[2];
std::vector<ClientCard*> extra[2];
std::vector<ClientCard*> limbo_temp;
std::set<ClientCard*> overlay_cards;
std::vector<ClientCard*> summonable_cards;
......@@ -68,6 +69,7 @@ public:
int announce_count{ 0 };
int select_counter_count{ 0 };
int select_counter_type{ 0 };
int current_mset_param{ 0 };
std::vector<ClientCard*> selectable_cards;
std::vector<ClientCard*> selected_cards;
std::set<ClientCard*> selectsum_cards;
......@@ -129,6 +131,7 @@ public:
bool check_sum_trib(std::set<ClientCard*>::const_iterator index, std::set<ClientCard*>::const_iterator end, int acc);
void UpdateDeclarableList();
void RefreshCardCountDisplay();
irr::gui::IGUIElement* panel{ nullptr };
std::vector<int> ancard;
......
......@@ -45,6 +45,24 @@
#define mystrncasecmp strncasecmp
#endif
#ifndef _WIN32
#include <wchar.h>
inline int _wtoi(const wchar_t * str){
return (int)wcstol(str, 0, 10);
}
#endif
// load env things
#ifdef _WIN32
#include <windows.h>
#include <string>
#else
#include <unistd.h>
#include <stdlib.h>
extern char** environ;
#endif
#include <cstdio>
#include <cstdlib>
#include <iostream>
......@@ -89,11 +107,14 @@ inline FILE* myfopen(const char* filename, const char* mode) {
#include <irrlicht.h>
extern const unsigned short PRO_VERSION;
extern unsigned short PRO_VERSION;
extern unsigned int enable_log;
extern bool exit_on_return;
extern bool auto_watch_mode;
extern bool open_file;
extern wchar_t open_file_name[256];
extern bool bot_mode;
extern bool expansions_specified;
extern std::vector<std::wstring> expansions_list;
#endif
......@@ -88,6 +88,9 @@ bool DataManager::LoadDB(const wchar_t* wfile) {
#else
auto reader = FileSystem->createAndOpenFile(file);
#endif
return LoadDB(reader);
}
bool DataManager::LoadDB(irr::io::IReadFile* reader) {
if(reader == nullptr)
return false;
spmemvfs_db_t db;
......@@ -99,7 +102,7 @@ bool DataManager::LoadDB(const wchar_t* wfile) {
reader->drop();
(mem->data)[mem->total] = '\0';
bool ret{};
if (spmemvfs_open_db(&db, file, mem) != SQLITE_OK)
if (spmemvfs_open_db(&db, "temp.db", mem) != SQLITE_OK)
ret = Error(db.handle);
else
ret = ReadDB(db.handle);
......@@ -118,6 +121,17 @@ bool DataManager::LoadStrings(const char* file) {
std::fclose(fp);
return true;
}
bool DataManager::LoadStrings(const wchar_t* file) {
FILE* fp = mywfopen(file, "r");
if(!fp)
return false;
char linebuf[TEXT_LINE_SIZE]{};
while(std::fgets(linebuf, sizeof linebuf, fp)) {
ReadStringConfLine(linebuf);
}
std::fclose(fp);
return true;
}
bool DataManager::LoadStrings(irr::io::IReadFile* reader) {
char ch{};
std::string linebuf;
......@@ -164,6 +178,159 @@ void DataManager::ReadStringConfLine(const char* linebuf) {
_setnameStrings[value] = strBuffer;
}
}
bool DataManager::LoadServerList(const char* file) {
FILE* fp = myfopen(file, "r");
if(!fp)
return false;
char linebuf[TEXT_LINE_SIZE]{};
while(std::fgets(linebuf, sizeof linebuf, fp)) {
ReadServerConfLine(linebuf);
}
std::fclose(fp);
return true;
}
bool DataManager::LoadServerList(const wchar_t* file) {
FILE* fp = mywfopen(file, "r");
if(!fp)
return false;
char linebuf[TEXT_LINE_SIZE]{};
while(std::fgets(linebuf, sizeof linebuf, fp)) {
ReadServerConfLine(linebuf);
}
std::fclose(fp);
return true;
}
bool DataManager::LoadServerList(irr::io::IReadFile* reader) {
char ch{};
std::string linebuf;
while (reader->read(&ch, 1)) {
if (ch == '\0')
break;
linebuf.push_back(ch);
if (ch == '\n' || linebuf.size() >= TEXT_LINE_SIZE - 1) {
ReadServerConfLine(linebuf.data());
linebuf.clear();
}
}
reader->drop();
return true;
}
void DataManager::ReadServerConfLine(const char* linebuf) {
char buffer[1024];
std::strncpy(buffer, linebuf, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
buffer[strcspn(buffer, "\n")] = '\0';
char* sep1 = std::strchr(buffer, '|');
if (sep1 != nullptr) {
*sep1 = '\0';
char* addrPart = sep1 + 1;
wchar_t wname[256], wip[512];
// read the server name
BufferIO::DecodeUTF8(buffer, wname);
// replace the first '|' with ':'
char* sep2 = std::strchr(addrPart, '|');
if (sep2) {
*sep2 = ':';
}
BufferIO::DecodeUTF8(addrPart, wip);
_serverStrings.emplace_back(wname, wip);
}
}
bool DataManager::LoadCorresSrvIni(const char* file) {
FILE* fp = myfopen(file, "r");
if(!fp)
return false;
char linebuf[TEXT_LINE_SIZE]{};
while(std::fgets(linebuf, sizeof linebuf, fp)) {
ReadCorresSrvIniLine(linebuf);
}
std::fclose(fp);
InsertServerList();
return true;
}
bool DataManager::LoadCorresSrvIni(const wchar_t* file) {
FILE* fp = mywfopen(file, "r");
if(!fp)
return false;
char linebuf[TEXT_LINE_SIZE]{};
while(std::fgets(linebuf, sizeof linebuf, fp)) {
ReadCorresSrvIniLine(linebuf);
}
std::fclose(fp);
InsertServerList();
return true;
}
bool DataManager::LoadCorresSrvIni(irr::io::IReadFile* reader) {
char ch{};
std::string linebuf;
while (reader->read(&ch, 1)) {
if (ch == '\0')
break;
linebuf.push_back(ch);
if (ch == '\n' || linebuf.size() >= TEXT_LINE_SIZE - 1) {
ReadCorresSrvIniLine(linebuf.data());
linebuf.clear();
}
}
reader->drop();
InsertServerList();
return true;
}
void DataManager::ReadCorresSrvIniLine(const char* linebuf) {
std::wstring name = GetINIValue(linebuf, "ServerName = ");
std::wstring host = GetINIValue(linebuf, "ServerHost = ");
std::wstring port = GetINIValue(linebuf, "ServerPort = ");
if (name != L"")
iniName = name;
if (host != L"")
iniHost = host;
if (port != L"")
iniPort = port;
}
std::wstring DataManager::GetINIValue(const char* line, const char* key) {
if (!line || !key) {
return L"";
}
const char* keyPos = strstr(line, key);
if (!keyPos) {
return L"";
}
const char* valStart = keyPos + strlen(key);
while (*valStart == ' ')
valStart++;
const char* valEnd = valStart;
while (*valEnd && *valEnd != '\n' && *valEnd != '\r')
valEnd++;
if (valStart == valEnd)
return L"";
std::string narrowStr(valStart, valEnd);
if (narrowStr.empty())
return L"";
wchar_t wbuf[1024];
BufferIO::DecodeUTF8(narrowStr.c_str(), wbuf);
return wbuf;
}
void DataManager::InsertServerList() {
if (iniName != L"" && iniHost != L"") {
std::wstring ip = iniHost;
if (iniPort != L"") {
ip += L":";
ip += iniPort;
}
_serverStrings.emplace_back(iniName, ip);
}
iniName.clear();
iniHost.clear();
iniPort.clear();
}
bool DataManager::Error(sqlite3* pDB, sqlite3_stmt* pStmt) {
std::snprintf(errmsg, sizeof errmsg, "%s", sqlite3_errmsg(pDB));
if(pStmt)
......@@ -265,7 +432,10 @@ std::vector<unsigned int> DataManager::GetSetCodes(std::wstring setname) const {
std::vector<unsigned int> matchingCodes;
for(auto csit = _setnameStrings.begin(); csit != _setnameStrings.end(); ++csit) {
auto xpos = csit->second.find_first_of(L'|');//setname|another setname or extra info
if(setname.size() < 2) {
if (mainGame->CheckRegEx(csit->second, setname, true)) {
matchingCodes.push_back(csit->first);
}
else if(setname.size() < 2) {
if(csit->second.compare(0, xpos, setname) == 0
|| csit->second.compare(xpos + 1, csit->second.length(), setname) == 0)
matchingCodes.push_back(csit->first);
......@@ -387,30 +557,35 @@ uint32_t DataManager::CardReader(uint32_t code, card_data* pData) {
pData->clear();
return 0;
}
unsigned char* DataManager::ScriptReaderEx(const char* script_path, int* slen) {
// default script name: ./script/c%d.lua
if (std::strncmp(script_path, "./script", 8) != 0) // not a card script file
return ReadScriptFromFile(script_path, slen);
const char* script_name = script_path + 2;
char expansions_path[1024]{};
std::snprintf(expansions_path, sizeof expansions_path, "./expansions/%s", script_name);
if (mainGame->gameConf.prefer_expansion_script) { // debug script with raw file in expansions
if (ReadScriptFromFile(expansions_path, slen))
return scriptBuffer;
if (ReadScriptFromIrrFS(script_name, slen))
return scriptBuffer;
if (ReadScriptFromFile(script_path, slen))
return scriptBuffer;
} else {
if (ReadScriptFromIrrFS(script_name, slen))
return scriptBuffer;
if (ReadScriptFromFile(script_path, slen))
return scriptBuffer;
if (ReadScriptFromFile(expansions_path, slen))
return scriptBuffer;
unsigned char* DataManager::ScriptReaderEx(const char* script_name, int* slen) {
if (std::strncmp(script_name, "./script", 8) != 0)
return ReadScriptFromFile(script_name, slen);
unsigned char* buffer;
if(!mainGame->gameConf.prefer_expansion_script) {
buffer = ScriptReaderExSingle("", script_name, slen);
if(buffer)
return buffer;
}
return nullptr;
buffer = ScriptReaderExSingle("specials/", script_name, slen, 9);
if(buffer)
return buffer;
for(auto ex : mainGame->GetExpansionsListU("/")) {
buffer = ScriptReaderExSingle(ex.c_str(), script_name, slen);
if(buffer)
return buffer;
}
buffer = ScriptReaderExSingle("", script_name, slen, 2, TRUE);
if(buffer)
return buffer;
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) {
char sname[256];
std::snprintf(sname, sizeof sname, "%s%s", path, script_name + pre_len); //default script name: ./script/c%d.lua
if (use_irr) {
return ReadScriptFromIrrFS(sname, slen);
}
return ReadScriptFromFile(sname, slen);
}
unsigned char* DataManager::ReadScriptFromIrrFS(const char* script_name, int* slen) {
#ifdef _WIN32
......@@ -508,5 +683,4 @@ bool DataManager::deck_sort_name(code_pointer p1, code_pointer p2) {
return res < 0;
return p1->first < p2->first;
}
}
......@@ -45,9 +45,21 @@ public:
DataManager();
bool ReadDB(sqlite3* pDB);
bool LoadDB(const wchar_t* wfile);
bool LoadDB(irr::io::IReadFile* reader);
bool LoadStrings(const char* file);
bool LoadStrings(const wchar_t* file);
bool LoadStrings(irr::io::IReadFile* reader);
void ReadStringConfLine(const char* linebuf);
bool LoadServerList(const char* file);
bool LoadServerList(const wchar_t* file);
bool LoadServerList(irr::io::IReadFile* reader);
void ReadServerConfLine(const char* linebuf);
bool LoadCorresSrvIni(const char* file);
bool LoadCorresSrvIni(const wchar_t* file);
bool LoadCorresSrvIni(irr::io::IReadFile* reader);
void ReadCorresSrvIniLine(const char* linebuf);
std::wstring GetINIValue(const char* line, const char* key);
void InsertServerList();
bool Error(sqlite3* pDB, sqlite3_stmt* pStmt = nullptr);
code_pointer GetCodePointer(unsigned int code) const;
......@@ -78,12 +90,14 @@ public:
std::unordered_map<unsigned int, std::wstring> _victoryStrings;
std::unordered_map<unsigned int, std::wstring> _setnameStrings;
std::unordered_map<unsigned int, std::wstring> _sysStrings;
std::vector<std::pair<std::wstring, std::wstring>> _serverStrings;
char errmsg[512]{};
static unsigned char scriptBuffer[0x100000];
static const wchar_t* unknown_string;
static uint32_t CardReader(uint32_t, card_data*);
static unsigned char* ScriptReaderEx(const char* script_path, 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);
//read by IFileSystem
static unsigned char* ReadScriptFromIrrFS(const char* script_name, int* slen);
......@@ -101,6 +115,9 @@ private:
std::unordered_map<unsigned int, CardDataC> _datas;
std::unordered_map<unsigned int, CardString> _strings;
std::unordered_map<unsigned int, std::vector<uint16_t>> extra_setcode;
std::wstring iniName;
std::wstring iniHost;
std::wstring iniPort;
};
extern DataManager dataManager;
......
......@@ -148,7 +148,8 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
(mainGame->wQuery->isVisible() && id != BUTTON_YES && id != BUTTON_NO) ||
(mainGame->wLinkMarks->isVisible() && id != BUTTON_MARKERS_OK) ||
(mainGame->wDMQuery->isVisible() && id != BUTTON_DM_OK && id != BUTTON_DM_CANCEL) ||
(mainGame->wDeckManage->isVisible() && !(id >= WINDOW_DECK_MANAGE && id < COMBOBOX_LFLIST)))
(mainGame->wDeckManage->isVisible() && !(id >= WINDOW_DECK_MANAGE && id < COMBOBOX_LFLIST)) ||
(mainGame->wDeckCode->isVisible() && id != BUTTON_DECK_CODE_SAVE && id != BUTTON_DECK_CODE_CANCEL))
&& event.GUIEvent.EventType != irr::gui::EGET_LISTBOX_CHANGED
&& event.GUIEvent.EventType != irr::gui::EGET_COMBO_BOX_CHANGED) {
if(mainGame->wDMQuery->isVisible())
......@@ -235,6 +236,49 @@ bool DeckBuilder::OnEvent(const irr::SEvent& event) {
}
break;
}
case BUTTON_DECK_CODE: {
int sel = mainGame->cbDBDecks->getSelected();
if(sel == -1)
break;
mainGame->gMutex.lock();
mainGame->wDeckCode->setText(dataManager.GetSysString(1387));
if(deckManager.current_deck.main.size() > 0 || deckManager.current_deck.extra.size() > 0 || deckManager.current_deck.side.size() > 0) {
wchar_t deck_code[2048];
unsigned char deck_code_utf8[1024];
deckManager.SaveDeckToCode(deckManager.current_deck, deck_code_utf8);
BufferIO::DecodeUTF8((char*)deck_code_utf8, deck_code);
mainGame->ebDeckCode->setText(deck_code);
} else
mainGame->ebDeckCode->setText(L"");
mainGame->PopupElement(mainGame->wDeckCode);
mainGame->gMutex.unlock();
prev_operation = id;
prev_sel = sel;
break;
}
case BUTTON_DECK_CODE_SAVE: {
mainGame->HideElement(mainGame->wDeckCode);
if(prev_operation == BUTTON_DECK_CODE) {
Deck new_deck;
char pcode[1024];
BufferIO::EncodeUTF8(mainGame->ebDeckCode->getText(), pcode);
unsigned char deck_code[1024];
memcpy(deck_code, pcode, 1024);
if(deckManager.LoadDeckFromCode(new_deck, deck_code, strlen(pcode)))
deckManager.current_deck = new_deck;
else
mainGame->env->addMessageBox(L"", dataManager.GetSysString(1389));
}
prev_operation = 0;
prev_sel = -1;
break;
}
case BUTTON_DECK_CODE_CANCEL: {
mainGame->HideElement(mainGame->wDeckCode);
prev_operation = 0;
prev_sel = -1;
break;
}
case BUTTON_DELETE_DECK: {
int sel = mainGame->cbDBDecks->getSelected();
if(sel == -1)
......@@ -1556,6 +1600,7 @@ void DeckBuilder::FilterCards() {
} else {
match = CardNameContains(text.name.c_str(), elements_iterator->keyword.c_str())
|| text.text.find(elements_iterator->keyword) != std::wstring::npos
|| mainGame->CheckRegEx(text.text, elements_iterator->keyword)
|| data.is_setcodes(elements_iterator->setcodes);
}
if(elements_iterator->exclude)
......@@ -1623,7 +1668,7 @@ void DeckBuilder::SortList() {
auto left = results.begin();
const wchar_t* pstr = mainGame->ebCardName->getText();
for(auto it = results.begin(); it != results.end(); ++it) {
if(std::wcscmp(pstr, dataManager.GetName((*it)->first)) == 0) {
if(std::wcscmp(pstr, dataManager.GetName((*it)->first)) == 0 || mainGame->CheckRegEx(dataManager.GetName((*it)->first), pstr, true)) {
std::iter_swap(left, it);
++left;
}
......@@ -1791,6 +1836,8 @@ bool DeckBuilder::CardNameContains(const wchar_t* haystack, const wchar_t* needl
if(!haystack) {
return false;
}
if(mainGame->CheckRegEx(haystack, needle))
return true;
int i = 0;
int j = 0;
while(haystack[i]) {
......
......@@ -2,50 +2,49 @@
#include "game.h"
#include "myfilesystem.h"
#include "network.h"
#include "base64.h"
namespace ygo {
char DeckManager::deckBuffer[0x10000]{};
DeckManager deckManager;
void DeckManager::LoadLFListSingle(const char* path) {
auto cur = _lfList.rend();
void DeckManager::LoadLFListSingle(const char* path, bool insert) {
FILE* fp = myfopen(path, "r");
char linebuf[256]{};
wchar_t strBuffer[256]{};
char str1[16]{};
if(fp) {
while(std::fgets(linebuf, sizeof linebuf, fp)) {
if(linebuf[0] == '#')
continue;
if(linebuf[0] == '!') {
auto len = std::strcspn(linebuf, "\r\n");
linebuf[len] = 0;
BufferIO::DecodeUTF8(&linebuf[1], strBuffer);
LFList newlist;
newlist.listName = strBuffer;
newlist.hash = 0x7dfcee6a;
_lfList.push_back(newlist);
cur = _lfList.rbegin();
continue;
if (!fp) return;
_LoadLFListFromLineProvider([&](char* buf, size_t sz) {
return std::fgets(buf, sz, fp) != nullptr;
}, insert);
std::fclose(fp);
}
void DeckManager::LoadLFListSingle(const wchar_t* path, bool insert) {
FILE* fp = mywfopen(path, "r");
if (!fp) return;
_LoadLFListFromLineProvider([&](char* buf, size_t sz) {
return std::fgets(buf, sz, fp) != nullptr;
}, insert);
std::fclose(fp);
}
void DeckManager::LoadLFListSingle(irr::io::IReadFile* reader, bool insert) {
std::string linebuf;
char ch{};
_LoadLFListFromLineProvider([&](char* buf, size_t sz) {
while (reader->read(&ch, 1)) {
if (ch == '\0') break;
linebuf.push_back(ch);
if (ch == '\n' || linebuf.size() >= sz - 1) {
std::strncpy(buf, linebuf.c_str(), sz - 1);
buf[sz - 1] = '\0';
linebuf.clear();
return true;
}
if (cur == _lfList.rend())
continue;
unsigned int code = 0;
int count = -1;
if (std::sscanf(linebuf, "%10s%*[ ]%1d", str1, &count) != 2)
continue;
if (count < 0 || count > 2)
continue;
code = std::strtoul(str1, nullptr, 10);
cur->content[code] = count;
cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count)));
}
std::fclose(fp);
}
return false;
}, insert);
reader->drop();
}
void DeckManager::LoadLFList() {
LoadLFListSingle("expansions/lflist.conf");
LoadLFListSingle("specials/lflist.conf");
LoadLFListSingle("lflist.conf");
LFList nolimit;
nolimit.listName = L"N/A";
......@@ -69,6 +68,8 @@ const LFList* DeckManager::GetLFList(unsigned int lfhash) {
return nullptr;
}
static unsigned int checkAvail(unsigned int ot, unsigned int avail) {
if(!!(ot & 0x4))
return 0;
if((ot & avail) == avail)
return 0;
if((ot & AVAIL_OCG) && (avail != AVAIL_OCG))
......@@ -218,17 +219,21 @@ bool DeckManager::LoadSide(Deck& deck, uint32_t dbuf[], int mainc, int sidec) {
pcount[deck.side[i]->first]++;
Deck ndeck;
LoadDeck(ndeck, dbuf, mainc, sidec);
if (ndeck.main.size() != deck.main.size() || ndeck.extra.size() != deck.extra.size() || ndeck.side.size() != deck.side.size())
#ifndef YGOPRO_NO_SIDE_CHECK
if(ndeck.main.size() != deck.main.size() || ndeck.extra.size() != deck.extra.size() || ndeck.side.size() != deck.side.size())
return false;
#endif
for(size_t i = 0; i < ndeck.main.size(); ++i)
ncount[ndeck.main[i]->first]++;
for(size_t i = 0; i < ndeck.extra.size(); ++i)
ncount[ndeck.extra[i]->first]++;
for(size_t i = 0; i < ndeck.side.size(); ++i)
ncount[ndeck.side[i]->first]++;
#ifndef YGOPRO_NO_SIDE_CHECK
for (auto& cdit : ncount)
if (cdit.second != pcount[cdit.first])
return false;
#endif
deck = ndeck;
return true;
}
......@@ -342,6 +347,40 @@ bool DeckManager::SaveDeck(const Deck& deck, const wchar_t* file) {
bool DeckManager::DeleteDeck(const wchar_t* file) {
return FileSystem::RemoveFile(file);
}
int DeckManager::TypeCount(std::vector<code_pointer> list, unsigned int ctype) {
int res = 0;
for(size_t i = 0; i < list.size(); ++i) {
code_pointer cur = list[i];
if(cur->second.type & ctype)
res++;
}
return res;
}
bool DeckManager::LoadDeckFromCode(Deck& deck, const unsigned char *code, int len) {
unsigned char data[1024], *pdeck = data, *data_ = data;
int decoded_len = Base64::DecodedLength(code, len);
if(decoded_len > 1024 || decoded_len < 8 || !Base64::Decode(code, len, data_, decoded_len))
return false;
int mainc = BufferIO::ReadInt32(pdeck);
int sidec = BufferIO::ReadInt32(pdeck);
int errorcode = LoadDeck(deck, (uint32_t*)pdeck, mainc, sidec);
return (errorcode == 0);
}
int DeckManager::SaveDeckToCode(Deck& deck, unsigned char* code) {
unsigned char deckbuf[1024], *pdeck = deckbuf;
BufferIO::WriteInt32(pdeck, deck.main.size() + deck.extra.size());
BufferIO::WriteInt32(pdeck, deck.side.size());
for(size_t i = 0; i < deck.main.size(); ++i)
BufferIO::WriteInt32(pdeck, deck.main[i]->first);
for(size_t i = 0; i < deck.extra.size(); ++i)
BufferIO::WriteInt32(pdeck, deck.extra[i]->first);
for(size_t i = 0; i < deck.side.size(); ++i)
BufferIO::WriteInt32(pdeck, deck.side[i]->first);
int len = pdeck - deckbuf;
int encoded_len = Base64::EncodedLength(len);
Base64::Encode(deckbuf, len, code, encoded_len+1);
return encoded_len;
}
bool DeckManager::CreateCategory(const wchar_t* name) {
if(!FileSystem::IsDirExists(L"./deck") && !FileSystem::MakeDir(L"./deck"))
return false;
......
......@@ -5,12 +5,29 @@
#include <vector>
#include <sstream>
#include "data_manager.h"
#include "bufferio.h"
#ifndef YGOPRO_MAX_DECK
#define YGOPRO_MAX_DECK 60
#endif
#ifndef YGOPRO_MIN_DECK
#define YGOPRO_MIN_DECK 40
#endif
#ifndef YGOPRO_MAX_EXTRA
#define YGOPRO_MAX_EXTRA 15
#endif
#ifndef YGOPRO_MAX_SIDE
#define YGOPRO_MAX_SIDE 15
#endif
namespace ygo {
constexpr int DECK_MAX_SIZE = 60;
constexpr int DECK_MIN_SIZE = 40;
constexpr int EXTRA_MAX_SIZE = 15;
constexpr int SIDE_MAX_SIZE = 15;
constexpr int DECK_MAX_SIZE = YGOPRO_MAX_DECK;
constexpr int DECK_MIN_SIZE = YGOPRO_MIN_DECK;
constexpr int EXTRA_MAX_SIZE = YGOPRO_MAX_EXTRA;
constexpr int SIDE_MAX_SIZE = YGOPRO_MAX_SIDE;
constexpr int PACK_MAX_SIZE = 1000;
struct LFList {
......@@ -48,7 +65,9 @@ public:
static char deckBuffer[0x10000];
void LoadLFListSingle(const char* path);
void LoadLFListSingle(const char* path, bool insert = false);
void LoadLFListSingle(const wchar_t* path, bool insert = false);
void LoadLFListSingle(irr::io::IReadFile* reader, bool insert = false);
void LoadLFList();
const wchar_t* GetLFListName(unsigned int lfhash);
const LFList* GetLFList(unsigned int lfhash);
......@@ -56,6 +75,10 @@ public:
bool LoadCurrentDeck(const wchar_t* file, bool is_packlist = false);
bool LoadCurrentDeck(int category_index, const wchar_t* category_name, const wchar_t* deckname);
bool LoadCurrentDeck(std::istringstream& deckStream, bool is_packlist = false);
wchar_t DeckFormatBuffer[128];
int TypeCount(std::vector<code_pointer> list, unsigned int ctype);
bool LoadDeckFromCode(Deck& deck, const unsigned char *code, int len);
int SaveDeckToCode(Deck &deck, unsigned char *code);
static uint32_t LoadDeck(Deck& deck, uint32_t dbuf[], int mainc, int sidec, bool is_packlist = false);
static uint32_t LoadDeckFromStream(Deck& deck, std::istringstream& deckStream, bool is_packlist = false);
......@@ -71,6 +94,49 @@ public:
static bool RenameCategory(const wchar_t* oldname, const wchar_t* newname);
static bool DeleteCategory(const wchar_t* name);
static bool SaveDeckArray(const DeckArray& deck, const wchar_t* name);
private:
template<typename LineProvider>
void _LoadLFListFromLineProvider(LineProvider getLine, bool insert = false) {
std::vector<LFList> loadedLists;
auto cur = loadedLists.rend(); // 注意:在临时 list 上操作
char line[256]{};
wchar_t strBuffer[256]{};
char str1[16]{};
while (getLine(line, sizeof(line))) {
if (line[0] == '#')
continue;
if (line[0] == '!') {
auto len = std::strcspn(line, "\r\n");
line[len] = 0;
BufferIO::DecodeUTF8(&line[1], strBuffer);
LFList newlist;
newlist.listName = strBuffer;
newlist.hash = 0x7dfcee6a;
loadedLists.push_back(newlist);
cur = loadedLists.rbegin();
continue;
}
if (cur == loadedLists.rend())
continue;
unsigned int code = 0;
int count = -1;
if (std::sscanf(line, "%10s%*[ ]%1d", str1, &count) != 2)
continue;
if (count < 0 || count > 2)
continue;
code = std::strtoul(str1, nullptr, 10);
cur->content[code] = count;
cur->hash = cur->hash ^ ((code << 18) | (code >> 14)) ^ ((code << (27 + count)) | (code >> (5 - count)));
}
if (insert) {
_lfList.insert(_lfList.begin(), loadedLists.begin(), loadedLists.end());
} else {
_lfList.insert(_lfList.end(), loadedLists.begin(), loadedLists.end());
}
}
};
extern DeckManager deckManager;
......
This diff is collapsed.
This diff is collapsed.
......@@ -8,6 +8,45 @@
namespace ygo {
class HostResult {
public:
unsigned int host;
unsigned short port;
bool isValid() {
return host > 0 && port > 0;
}
HostResult() {
host = 0;
port = 0;
}
};
#ifndef _WIN32
#include <resolv.h>
#include <arpa/nameser.h>
#include <arpa/nameser_compat.h>
class RetrivedSRVRecord {
public:
bool valid;
unsigned short priority;
unsigned short weight;
unsigned short port;
char host[100];
RetrivedSRVRecord(ns_msg nsMsg, int i) {
valid = false;
ns_rr rr;
if (ns_parserr(&nsMsg, ns_s_an, i, &rr) < 0 || ns_rr_type(rr) != T_SRV)
return;
priority = ns_get16(ns_rr_rdata(rr));
weight = ns_get16(ns_rr_rdata(rr) + NS_INT16SZ);
port = ns_get16(ns_rr_rdata(rr) + 2 * NS_INT16SZ);
if (dn_expand(ns_msg_base(nsMsg), ns_msg_end(nsMsg), ns_rr_rdata(rr) + 3 * NS_INT16SZ, host, sizeof(host)) < 0)
return;
valid = true;
}
};
#endif
class DuelClient {
private:
static unsigned int connect_state;
......@@ -34,6 +73,10 @@ private:
static std::set<std::pair<unsigned int, unsigned short>> remotes;
public:
static unsigned int temp_ip;
static unsigned short temp_port;
static unsigned short temp_ver;
static bool try_needed;
static unsigned char selftype;
static bool StartClient(unsigned int ip, unsigned short port, bool create_game = true);
static void ConnectTimeout(evutil_socket_t fd, short events, void* arg);
......@@ -47,10 +90,17 @@ public:
static void SetResponseI(int32_t respI);
static void SetResponseB(void* respB, size_t len);
static void SendResponse();
static unsigned int LookupHost(char *host);
static bool LookupSRV(char *hostname, HostResult* result);
static bool CheckHostnameSplitter(char *hostname, HostResult *result);
static HostResult ParseHost(char *hostname);
static void SendPacketToServer(unsigned char proto) {
auto p = duel_client_write;
buffer_write<uint16_t>(p, 1);
buffer_write<uint8_t>(p, proto);
#ifdef YGOPRO_MESSAGE_DEBUG
printf("CTOS: %d\n", proto);
#endif
bufferevent_write(client_bev, duel_client_write, 3);
}
template<typename ST>
......@@ -60,6 +110,9 @@ public:
buffer_write<uint16_t>(p, (uint16_t)(1 + sizeof(ST)));
buffer_write<uint8_t>(p, proto);
std::memcpy(p, &st, sizeof(ST));
#ifdef YGOPRO_MESSAGE_DEBUG
printf("CTOS: %d Length: %ld\n", proto, sizeof(ST));
#endif
bufferevent_write(client_bev, duel_client_write, sizeof(ST) + 3);
}
static void SendBufferToServer(unsigned char proto, void* buffer, size_t len) {
......@@ -69,15 +122,19 @@ public:
buffer_write<uint16_t>(p, (uint16_t)(1 + len));
buffer_write<uint8_t>(p, proto);
std::memcpy(p, buffer, len);
#ifdef YGOPRO_MESSAGE_DEBUG
printf("CTOS: %d Length: %ld\n", proto, len);
#endif
bufferevent_write(client_bev, duel_client_write, len + 3);
}
static std::vector<HostPacket> hosts;
static std::vector<std::wstring> hosts;
static std::vector<std::wstring> hosts_srvpro;
static bool is_srvpro;
static void BeginRefreshHost();
static int RefreshThread(event_base* broadev);
static void BroadcastReply(evutil_socket_t fd, short events, void* arg);
};
}
#endif //DUELCLIENT_H
......@@ -222,6 +222,13 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
}
break;
}
case MSG_SELECT_IDLECMD: {
mainGame->HideElement(mainGame->wQuery);
if(current_mset_param) {
DuelClient::SetResponseI(current_mset_param);
DuelClient::SendResponse();
}
}
default: {
mainGame->HideElement(mainGame->wQuery);
break;
......@@ -355,6 +362,7 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
if(sel == -1)
break;
DuelClient::SetResponseI(ancard[sel]);
mainGame->dInfo.announce_cache.insert(mainGame->dInfo.announce_cache.begin(), ancard[sel]);
mainGame->HideElement(mainGame->wANCard, true);
break;
}
......@@ -514,8 +522,16 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
break;
for(size_t i = 0; i < msetable_cards.size(); ++i) {
if(msetable_cards[i] == menu_card) {
DuelClient::SetResponseI((i << 16) + 3);
DuelClient::SendResponse();
current_mset_param = (i << 16) + 3;
if(mainGame->gameConf.ask_mset) {
wchar_t wbuf[256];
myswprintf(wbuf, dataManager.GetSysString(1368), dataManager.GetName(clicked_card->code));
mainGame->stQMessage->setText(wbuf);
mainGame->PopupElement(mainGame->wQuery);
} else {
DuelClient::SetResponseI(current_mset_param);
DuelClient::SendResponse();
}
break;
}
}
......@@ -913,6 +929,8 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
myswprintf(formatBuffer, L"%ls[%d](%d)",
dataManager.FormatLocation(selectable_cards[i + pos]->overlayTarget->location, selectable_cards[i + pos]->overlayTarget->sequence),
selectable_cards[i + pos]->overlayTarget->sequence + 1, selectable_cards[i + pos]->sequence + 1);
else if (selectable_cards[i]->location == 0)
myswprintf(formatBuffer, L"");
else
myswprintf(formatBuffer, L"%ls[%d]", dataManager.FormatLocation(selectable_cards[i + pos]->location, selectable_cards[i + pos]->sequence),
selectable_cards[i + pos]->sequence + 1);
......@@ -1742,6 +1760,17 @@ bool ClientField::OnEvent(const irr::SEvent& event) {
}
break;
}
case irr::KEY_KEY_Z: {
if(!mainGame->dInfo.isReplay && !mainGame->HasFocus(irr::gui::EGUIET_EDIT_BOX)) {
mainGame->dInfo.isReplaySkiping = event.KeyInput.PressedDown;
if(mainGame->dInfo.isStarted && !mainGame->dInfo.isReplaySkiping) {
mainGame->gMutex.lock();
mainGame->dField.RefreshAllCards();
mainGame->gMutex.unlock();
}
}
break;
}
case irr::KEY_F1:
case irr::KEY_F2:
case irr::KEY_F3:
......@@ -1896,17 +1925,32 @@ bool ClientField::OnCommonEvent(const irr::SEvent& event) {
return true;
break;
}
case CHECKBOX_REGEX: {
mainGame->gameConf.search_regex = mainGame->chkRegex->isChecked() ? 1 : 0;
if(mainGame->is_building && !mainGame->is_siding)
mainGame->deckBuilder.InstantSearch();
return true;
break;
}
case CHECKBOX_ENABLE_MUSIC: {
if(!mainGame->chkEnableMusic->isChecked())
soundManager.StopBGM();
return true;
break;
}
case CHECKBOX_ENABLE_SOUND: {
if(!mainGame->chkEnableSound->isChecked())
soundManager.StopSound();
return true;
break;
}
case CHECKBOX_DISABLE_CHAT: {
bool show = (mainGame->is_building && !mainGame->is_siding) ? false : !mainGame->chkIgnore1->isChecked();
bool show = (mainGame->is_building && !mainGame->is_siding) ? false : true;
mainGame->wChat->setVisible(show);
/*
if(!show)
mainGame->ClearChatMsg();
*/
return true;
break;
}
......@@ -1932,6 +1976,11 @@ bool ClientField::OnCommonEvent(const irr::SEvent& event) {
return true;
break;
}
case CHECKBOX_ASK_MSET: {
mainGame->gameConf.ask_mset = mainGame->chkAskMSet->isChecked() ? 1 : 0;
return true;
break;
}
case CHECKBOX_LFLIST: {
mainGame->gameConf.use_lflist = mainGame->chkLFlist->isChecked() ? 1 : 0;
mainGame->cbLFlist->setEnabled(mainGame->gameConf.use_lflist);
......@@ -1953,6 +2002,12 @@ bool ClientField::OnCommonEvent(const irr::SEvent& event) {
return true;
break;
}
case COMBOBOX_LOCALE: {
myswprintf(mainGame->gameConf.locale, L"%ls", mainGame->cbLocale->getItem(mainGame->cbLocale->getSelected()));
mainGame->SaveConfig();
return true;
break;
}
}
break;
}
......@@ -2065,6 +2120,13 @@ bool ClientField::OnCommonEvent(const irr::SEvent& event) {
return true;
break;
}
case irr::KEY_KEY_X:
case irr::KEY_F12: {
if(!event.KeyInput.PressedDown && !mainGame->HasFocus(irr::gui::EGUIET_EDIT_BOX))
mainGame->takeScreenshot();
return true;
break;
}
default: break;
}
break;
......
This diff is collapsed.
......@@ -15,6 +15,7 @@
#include "client_field.h"
#include "deck_con.h"
#include "menu_handler.h"
#include "CGUISkinSystem/CGUISkinSystem.h"
#include <ctime>
#include <unordered_map>
#include <vector>
......@@ -22,7 +23,9 @@
#include <mutex>
#include <functional>
constexpr int DEFAULT_DUEL_RULE = 5;
#ifndef YGOPRO_DEFAULT_DUEL_RULE
#define YGOPRO_DEFAULT_DUEL_RULE 5
#endif
constexpr int CONFIG_LINE_SIZE = 1024;
constexpr int TEXT_LINE_SIZE = 256;
......@@ -55,11 +58,12 @@ struct Config {
#else
bool use_image_load_background_thread{ true };
#endif
bool freever{ true };
unsigned short antialias{ 0 };
unsigned short serverport{ 7911 };
unsigned char textfontsize{ 14 };
wchar_t lasthost[100]{};
wchar_t lastport[10]{};
// wchar_t lastport[10]{};
wchar_t nickname[20]{};
wchar_t gamename[20]{};
wchar_t roompass[20]{};
......@@ -69,6 +73,7 @@ struct Config {
wchar_t textfont[256]{};
wchar_t numfont[256]{};
wchar_t bot_deck_path[256]{};
wchar_t locale[64];
//settings
int chkMAutoPos{ 0 };
int chkSTAutoPos{ 1 };
......@@ -80,7 +85,7 @@ struct Config {
int chkIgnore2{ 0 };
int use_lflist{ 1 };
int default_lflist{ 0 };
int default_rule{ DEFAULT_DUEL_RULE };
int default_rule{ YGOPRO_DEFAULT_DUEL_RULE };
int hide_setname{ 0 };
int hide_hint_button{ 0 };
int control_mode{ 0 };
......@@ -105,6 +110,10 @@ struct Config {
int window_width{ 1024 };
int window_height{ 640 };
bool resize_popup_menu{ false };
int search_regex{ 0 };
int chkEnablePScale{ 1 };
int skin_index { -1 };
int ask_mset{ 0 };
};
struct DuelInfo {
......@@ -117,10 +126,13 @@ struct DuelInfo {
bool isTag{ false };
bool isSingleMode{ false };
bool is_shuffling{ false };
bool is_swapped{ false };
bool tag_player[2]{};
bool isReplaySwapped{ false };
int lp[2]{};
int start_lp{ 0 };
int card_count[2]{};
int total_attack[2]{};
int duel_rule{ 0 };
int turn{ 0 };
short curMsg{ 0 };
......@@ -134,6 +146,13 @@ struct DuelInfo {
unsigned char time_player{ 0 };
unsigned short time_limit{ 0 };
unsigned short time_left[2]{};
wchar_t str_time_left[2][16]{};
video::SColor time_color[2]{};
wchar_t str_card_count[2][16]{};
wchar_t str_total_attack[2][16]{};
video::SColor card_count_color[2]{};
video::SColor total_attack_color[2]{};
std::vector<unsigned int> announce_cache;
void Clear();
};
......@@ -165,20 +184,28 @@ class Game {
public:
bool Initialize();
void MainLoop();
void RefreshTimeDisplay();
void BuildProjectionMatrix(irr::core::matrix4& mProjection, irr::f32 left, irr::f32 right, irr::f32 bottom, irr::f32 top, irr::f32 znear, irr::f32 zfar);
void InitStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cWidth, irr::u32 cHeight, irr::gui::CGUITTFont* font, const wchar_t* text);
std::wstring SetStaticText(irr::gui::IGUIStaticText* pControl, irr::u32 cWidth, irr::gui::CGUITTFont* font, const wchar_t* text, irr::u32 pos = 0);
void LoadExpansions();
void RefreshCategoryDeck(irr::gui::IGUIComboBox* cbCategory, irr::gui::IGUIComboBox* cbDeck, bool selectlastused = true);
void LoadExpansions(const wchar_t* expansions_path);
void LoadExpansionsAll();
std::vector<std::wstring> GetExpansionsList(const wchar_t * suffix = nullptr);
std::vector<std::string> GetExpansionsListU(const char* suffix = nullptr);
void RefreshCategoryDeck(irr::gui::IGUIComboBox *cbCategory, irr::gui::IGUIComboBox *cbDeck, bool selectlastused = true);
void RefreshDeck(irr::gui::IGUIComboBox* cbCategory, irr::gui::IGUIComboBox* cbDeck);
void RefreshDeck(const wchar_t* deckpath, const std::function<void(const wchar_t*)>& additem);
void RefreshReplay();
void RefreshSingleplay();
void RefreshBot();
void RefreshLocales();
void RefreshLFList();
void RefreshServerList();
void DrawSelectionLine(irr::video::S3DVertex* vec, bool strip, int width, float* cv);
void DrawSelectionLine(irr::gui::IGUIElement* element, int width, irr::video::SColor color);
void DrawBackGround();
void DrawLinkedZones(ClientCard* pcard);
void DrawSpellLinkedZones(ClientCard* pcard);
void CheckMutual(ClientCard* pcard, int mark);
void DrawCards();
void DrawCard(ClientCard* pcard);
......@@ -193,6 +220,7 @@ public:
void WaitFrameSignal(int frame);
void DrawThumb(code_pointer cp, irr::core::vector2di pos, const LFList* lflist, bool drag = false);
void DrawDeckBd();
bool LoadConfigFromFile(const char* file);
void LoadConfig();
void SaveConfig();
void ShowCardInfo(int code, bool resize = false);
......@@ -202,6 +230,7 @@ public:
void ClearChatMsg();
void AddDebugMsg(const char* msgbuf);
void ErrorLog(const char* msgbuf);
void initUtils();
void ClearTextures();
void CloseGameButtons();
void CloseGameWindow();
......@@ -211,6 +240,9 @@ public:
int OppositePlayer(int player);
int ChatLocalPlayer(int player);
const wchar_t* LocalName(int local_player);
const char* GetLocaleDir(const char* dir);
const wchar_t* GetLocaleDirWide(const char* dir);
bool CheckRegEx(const std::wstring& text, const std::wstring& exp, bool exact = false);
bool HasFocus(irr::gui::EGUI_ELEMENT_TYPE type) const {
irr::gui::IGUIElement* focus = env->getFocus();
......@@ -241,7 +273,9 @@ public:
void SetWindowsIcon();
void SetWindowsScale(float scale);
void FlashWindow();
void takeScreenshot();
void SetCursor(irr::gui::ECURSOR_ICON icon);
void InjectEnvToRegistry(intptr_t pduel);
template<typename T>
static void DrawShadowText(irr::gui::CGUITTFont* font, const T& text, const irr::core::rect<irr::s32>& position, const irr::core::rect<irr::s32>& padding,
irr::video::SColor color = 0xffffffff, irr::video::SColor shadowcolor = 0xff000000, bool hcenter = false, bool vcenter = false, const irr::core::rect<irr::s32>* clip = nullptr);
......@@ -297,6 +331,11 @@ public:
float xScale{ 1.0f };
float yScale{ 1.0f };
CGUISkinSystem *skinSystem;
wchar_t locale_buf[256];
wchar_t orig_dir[64];
char locale_buf_utf8[256];
ClientField dField;
DeckBuilder deckBuilder;
MenuHandler menuHandler;
......@@ -309,6 +348,7 @@ public:
HWND hWnd;
#endif
std::vector<irr::gui::IGUIEditBox* > editbox_list;
//GUI
irr::gui::IGUIEnvironment* env;
irr::gui::CGUITTFont* guiFont;
......@@ -347,6 +387,7 @@ public:
irr::gui::IGUICheckBox* chkQuickAnimation;
irr::gui::IGUICheckBox* chkAutoSaveReplay;
irr::gui::IGUICheckBox* chkDrawSingleChain;
irr::gui::IGUICheckBox* chkAskMSet;
irr::gui::IGUICheckBox* chkHidePlayerName;
irr::gui::IGUIWindow* tabSystem;
irr::gui::IGUIElement* elmTabSystemLast;
......@@ -355,6 +396,7 @@ public:
irr::gui::IGUICheckBox* chkAutoSearch;
irr::gui::IGUICheckBox* chkMultiKeywords;
irr::gui::IGUICheckBox* chkPreferExpansionScript;
irr::gui::IGUICheckBox* chkRegex;
irr::gui::IGUICheckBox* chkLFlist;
irr::gui::IGUIComboBox* cbLFlist;
irr::gui::IGUICheckBox* chkEnableSound;
......@@ -366,6 +408,8 @@ public:
irr::gui::IGUIButton* btnWinResizeM;
irr::gui::IGUIButton* btnWinResizeL;
irr::gui::IGUIButton* btnWinResizeXL;
irr::gui::IGUICheckBox* chkEnablePScale;
irr::gui::IGUIComboBox* cbLocale;
//main menu
irr::gui::IGUIWindow* wMainMenu;
irr::gui::IGUIButton* btnLanMode;
......@@ -380,7 +424,6 @@ public:
irr::gui::IGUIListBox* lstHostList;
irr::gui::IGUIButton* btnLanRefresh;
irr::gui::IGUIEditBox* ebJoinHost;
irr::gui::IGUIEditBox* ebJoinPort;
irr::gui::IGUIEditBox* ebJoinPass;
irr::gui::IGUIButton* btnJoinHost;
irr::gui::IGUIButton* btnJoinCancel;
......@@ -550,6 +593,18 @@ public:
irr::gui::IGUIButton* btnSideSort;
irr::gui::IGUIButton* btnSideReload;
irr::gui::IGUIEditBox* ebDeckname;
irr::gui::IGUIButton* btnDeckCode;
//deck rename
irr::gui::IGUIWindow* wRenameDeck;
irr::gui::IGUIEditBox* ebREName;
irr::gui::IGUIButton* btnREYes;
irr::gui::IGUIButton* btnRENo;
//deck code
irr::gui::IGUIWindow* wDeckCode;
irr::gui::IGUIEditBox* ebDeckCode;
irr::gui::IGUIButton* btnDeckCodeYes;
irr::gui::IGUIButton* btnDeckCodeNo;
//
irr::gui::IGUIStaticText* stDBCategory;
irr::gui::IGUIStaticText* stDeck;
irr::gui::IGUIStaticText* stCategory;
......@@ -639,6 +694,11 @@ public:
irr::gui::IGUIButton* btnBigCardZoomIn;
irr::gui::IGUIButton* btnBigCardZoomOut;
irr::gui::IGUIButton* btnBigCardClose;
//server list
irr::gui::IGUIButton* btnServerList;
irr::gui::IGUIWindow* wServerList;
irr::gui::IGUIListBox* lstServerList;
irr::gui::IGUIButton* btnServerReturn;
};
extern Game* mainGame;
......@@ -786,6 +846,7 @@ extern Game* mainGame;
#define BUTTON_DISPLAY_4 294
#define SCROLL_CARD_DISPLAY 295
#define BUTTON_CARD_DISP_OK 296
#define BUTTON_SURRENDER_YES 297
#define BUTTON_SURRENDER_NO 298
......@@ -852,11 +913,31 @@ extern Game* mainGame;
#define CHECKBOX_DRAW_SINGLE_CHAIN 374
#define CHECKBOX_LFLIST 375
#define CHECKBOX_HIDE_PLAYER_NAME 376
#define CHECKBOX_REGEX 377
#define COMBOBOX_LOCALE 378
#define CHECKBOX_ASK_MSET 379
#define BUTTON_BIG_CARD_CLOSE 380
#define BUTTON_BIG_CARD_ZOOM_IN 381
#define BUTTON_BIG_CARD_ZOOM_OUT 382
#define BUTTON_BIG_CARD_ORIG_SIZE 383
#define BUTTON_DECK_CODE 389
#define BUTTON_DECK_CODE_SAVE 390
#define BUTTON_DECK_CODE_CANCEL 391
#define BUTTON_SERVER_LIST 392
#define LISTBOX_SERVER_LIST 393
#define BUTTON_SERVER_RETURN 394
#define TEXTURE_DUEL 0
#define TEXTURE_DECK 1
#define TEXTURE_MENU 2
#define TEXTURE_COVER_S 3
#define TEXTURE_COVER_O 4
#define TEXTURE_ATTACK 5
#define TEXTURE_ACTIVATE 6
#define AVAIL_OCG 0x1
#define AVAIL_TCG 0x2
#define AVAIL_CUSTOM 0x4
......
......@@ -4,15 +4,19 @@
#include <event2/thread.h>
#include <clocale>
#include <memory>
#ifdef __APPLE__
#import <CoreFoundation/CoreFoundation.h>
#endif
unsigned int enable_log = 0x3;
bool exit_on_return = false;
bool auto_watch_mode = false;
bool open_file = false;
wchar_t open_file_name[256] = L"";
bool bot_mode = false;
bool expansions_specified = false;
std::vector<std::wstring> expansions_list;
void ClickButton(irr::gui::IGUIElement* btn) {
irr::SEvent event;
......@@ -85,6 +89,7 @@ int main(int argc, char* argv[]) {
bool keep_on_return = false;
bool deckCategorySpecified = false;
expansions_list.push_back(L"./expansions");
for(int i = 1; i < wargc; ++i) {
if (wargc == 2 && std::wcslen(wargv[1]) >= 4) {
wchar_t* pstrext = wargv[1] + std::wcslen(wargv[1]) - 4;
......@@ -121,13 +126,21 @@ int main(int argc, char* argv[]) {
continue;
} else if(!std::wcscmp(wargv[i], L"-h")) { // Host address
++i;
if(i < wargc)
if(i < wargc) {
ygo::mainGame->ebJoinHost->setText(wargv[i]);
}
continue;
} else if(!std::wcscmp(wargv[i], L"-p")) { // host Port
++i;
if(i < wargc)
ygo::mainGame->ebJoinPort->setText(wargv[i]);
if(i < wargc) {
auto port = _wtoi(wargv[i]);
auto hostText = ygo::mainGame->ebJoinHost->getText();
if(port && hostText) {
wchar_t newHostStr[100];
myswprintf(newHostStr, L"%ls:%d", hostText, port);
ygo::mainGame->ebJoinHost->setText(newHostStr);
}
}
continue;
} else if(!std::wcscmp(wargv[i], L"-w")) { // host passWord
++i;
......@@ -137,6 +150,8 @@ int main(int argc, char* argv[]) {
} else if(!std::wcscmp(wargv[i], L"-k")) { // Keep on return
exit_on_return = false;
keep_on_return = true;
} else if(!std::wcscmp(wargv[i], L"--auto-watch")) { // Auto watch mode
auto_watch_mode = true;
} else if(!std::wcscmp(wargv[i], L"--deck-category")) {
++i;
if(i < wargc) {
......@@ -199,6 +214,16 @@ int main(int argc, char* argv[]) {
if(open_file)
ClickButton(ygo::mainGame->btnLoadSinglePlay);
break;
} else if(!std::wcscmp(wargv[i], L"--expansions")) { // specify expansions
++i;
if(i < wargc) {
if(!expansions_specified) {
expansions_list.clear();
expansions_specified = true;
}
expansions_list.push_back(wargv[i]);
}
continue;
}
}
ygo::mainGame->MainLoop();
......
This diff is collapsed.
......@@ -11,7 +11,14 @@ namespace ygo {
class ImageManager {
public:
std::vector<std::wstring> ImageList[7];
int saved_image_id[7];
bool Initial();
//random image
irr::video::ITexture* GetRandomImage(int image_type);
irr::video::ITexture* GetRandomImage(int image_type, irr::s32 width, irr::s32 height);
void RefreshRandomImageList();
void RefreshImageDir(std::wstring path, int image_type);
void SetDevice(irr::IrrlichtDevice* dev);
void ClearTexture();
void RemoveTexture(int code);
......@@ -55,8 +62,12 @@ public:
irr::video::ITexture* tBackGround;
irr::video::ITexture* tBackGround_menu;
irr::video::ITexture* tBackGround_deck;
irr::video::ITexture* tCardType;
irr::video::ITexture* tField[2];
irr::video::ITexture* tFieldTransparent[2];
irr::video::ITexture* tRScale[14];
irr::video::ITexture* tLScale[14];
irr::video::ITexture* tClock;
};
extern ImageManager imageManager;
......
......@@ -21,6 +21,7 @@ Materials::Materials() {
SetS3DVertex(vChainNum, -0.35f, -0.35f, 0.35f, 0.35f, 0, 1, 0, 0, 0.19375f, 0.2421875f);
SetS3DVertex(vActivate, -0.5f, -0.5f, 0.5f, 0.5f, 0, 1, 0, 0, 1, 1);
SetS3DVertex(vField, -1.0f, -4.0f, 9.0f, 4.0f, 0, 1, 0, 0, 1, 1);
SetS3DVertex(vPScale, -0.35f, -0.5, 0.35, 0.5f, 0, 1, 0, 0, 1, 1);
SetS3DVertex(vFieldSpell, 1.2f, -3.2f, 6.7f, 3.2f, 0, 1, 0, 0, 1, 1);
SetS3DVertex(vFieldSpell1, 1.2f, 0.8f, 6.7f, 3.2f, 0, 1, 0, 0.2f, 1, 0.63636f);
SetS3DVertex(vFieldSpell2, 1.2f, -3.2f, 6.7f, -0.8f, 0, 1, 1, 0.63636f, 0, 0.2f);
......
......@@ -14,6 +14,7 @@ public:
irr::video::S3DVertex vCardOutline[4];
irr::video::S3DVertex vCardOutliner[4];
irr::video::S3DVertex vCardBack[4];
irr::video::S3DVertex vPScale[4];
irr::video::S3DVertex vSymbol[4];
irr::video::S3DVertex vNegate[4];
irr::video::S3DVertex vChainNum[4];
......
This diff is collapsed.
......@@ -234,7 +234,7 @@ public:
stat(fname, &fileStat);
funit.filename = std::string(dirp->d_name);
funit.is_dir = S_ISDIR(fileStat.st_mode);
if(funit.is_dir && (std::strcmp(dirp->d_name, ".") == 0 || std::strcmp(dirp->d_name, "..") == 0))
if(funit.is_dir && (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) || strcmp(dirp->d_name, ".git") == 0)
continue;
file_list.push_back(funit);
}
......
......@@ -240,6 +240,7 @@ public:
intptr_t pduel{};
wchar_t name[20]{};
wchar_t pass[20]{};
std::vector<byte> registry_dump;
};
}
......@@ -298,6 +299,7 @@ public:
#define STOC_HS_WATCH_CHANGE 0x22 // STOC_HS_WatchChange
#define STOC_TEAMMATE_SURRENDER 0x23 // no data
#define STOC_FIELD_FINISH 0x30
#define STOC_SRVPRO_ROOMLIST 0x31
// STOC_GAME_MSG header
#define MSG_WAITING 3
......
......@@ -6,7 +6,7 @@ project "YGOPro"
rtti "Off"
openmp "On"
files { "*.cpp", "*.h" }
files { "*.cpp", "*.h", "CGUISkinSystem/*.cpp", "CGUISkinSystem/*.h", "CXMLRegistry/*.cpp", "CXMLRegistry/*.h" }
includedirs { "../ocgcore" }
links { "ocgcore", "clzma", "cspmemvfs", LUA_LIB_NAME, "sqlite3", "irrlicht", "freetype", "event" }
......@@ -74,7 +74,7 @@ project "YGOPro"
entrypoint "mainCRTStartup"
defines { "_IRR_WCHAR_FILESYSTEM" }
files "ygopro.rc"
links { "ws2_32", "iphlpapi" }
links { "ws2_32", "Dnsapi", "iphlpapi" }
if USE_AUDIO and AUDIO_LIB == "irrklang" then
links { "irrKlang" }
if IRRKLANG_PRO then
......@@ -86,6 +86,8 @@ project "YGOPro"
filter {}
end
end
filter "not system:windows"
links { "resolv" }
filter "not action:vs*"
cppdialect "C++14"
......@@ -105,7 +107,7 @@ project "YGOPro"
filter "system:linux"
links { "GL", "X11", "Xxf86vm", "dl", "pthread" }
linkoptions { "-fopenmp" }
linkoptions { "-fopenmp", "-static-libstdc++", "-static-libgcc" }
if USE_AUDIO and AUDIO_LIB == "irrklang" then
links { "IrrKlang" }
linkoptions{ IRRKLANG_LINK_RPATH }
......
This diff is collapsed.
This diff is collapsed.
......@@ -33,7 +33,7 @@ public:
void DuelEndProc();
void WaitforResponse(int playerid);
void RefreshMzone(int player, int flag = 0x881fff, int use_cache = 1);
void RefreshSzone(int player, int flag = 0x681fff, 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 RefreshGrave(int player, int flag = 0x81fff, int use_cache = 1);
void RefreshExtra(int player, int flag = 0xe81fff, int use_cache = 1);
......@@ -67,4 +67,3 @@ protected:
}
#endif //SINGLE_DUEL_H
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Subproject commit 16c1bc322fc5a012796d880f1f9284808e6aca7a
This diff is collapsed.
......@@ -117,7 +117,7 @@ project "miniaudio"
"HAVE_LRINTF",
"OP_HAVE_LRINTF",
}
if not TARGET_MAC_ARM then
if not TARGET_MAC_ARM and not IS_ARM and not MAC_INTEL then
files {
"external/opus/celt/x86/pitch_avx.c",
"external/opus/celt/x86/pitch_sse.c",
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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