Merge branch 'master' into 'bass-optional'
# Conflicts: # Attorney_Online.pro # include/aoapplication.h
This commit is contained in:
		
						commit
						4a2a167f7d
					
				
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -5,6 +5,7 @@
 | 
				
			|||||||
*.so
 | 
					*.so
 | 
				
			||||||
*.pro.autosave
 | 
					*.pro.autosave
 | 
				
			||||||
base_override.h
 | 
					base_override.h
 | 
				
			||||||
 | 
					.DS_Store
 | 
				
			||||||
 | 
					
 | 
				
			||||||
base-full/
 | 
					base-full/
 | 
				
			||||||
base/
 | 
					base/
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										196
									
								
								.gitlab-ci.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								.gitlab-ci.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,196 @@
 | 
				
			|||||||
 | 
					stages:
 | 
				
			||||||
 | 
					  - build
 | 
				
			||||||
 | 
					  - deploy
 | 
				
			||||||
 | 
					  - publish
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cache:
 | 
				
			||||||
 | 
					  key: ${CI_COMMIT_REF_SLUG}
 | 
				
			||||||
 | 
					  paths:
 | 
				
			||||||
 | 
					    - lib/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					before_script:
 | 
				
			||||||
 | 
					  - echo Current working directory is $(pwd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build linux x86_64:
 | 
				
			||||||
 | 
					  image: ubuntu
 | 
				
			||||||
 | 
					  stage: build
 | 
				
			||||||
 | 
					  tags:
 | 
				
			||||||
 | 
					    - docker
 | 
				
			||||||
 | 
					    - linux
 | 
				
			||||||
 | 
					  script:
 | 
				
			||||||
 | 
					    # Install dependencies
 | 
				
			||||||
 | 
					    - apt-get update
 | 
				
			||||||
 | 
					    - >
 | 
				
			||||||
 | 
					      apt-get install --no-install-recommends -y qt5-default qtmultimedia5-dev
 | 
				
			||||||
 | 
					      clang make git sudo curl ca-certificates pkg-config upx unzip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Print versions
 | 
				
			||||||
 | 
					    - qmake --version
 | 
				
			||||||
 | 
					    - clang --version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Extract BASS
 | 
				
			||||||
 | 
					    - mkdir bass
 | 
				
			||||||
 | 
					    - cd bass
 | 
				
			||||||
 | 
					    - curl http://www.un4seen.com/files/bass24-linux.zip -o bass.zip
 | 
				
			||||||
 | 
					    - unzip bass.zip
 | 
				
			||||||
 | 
					    - cp x64/libbass.so ../lib
 | 
				
			||||||
 | 
					    - curl http://www.un4seen.com/files/bassopus24-linux.zip -o bassopus.zip
 | 
				
			||||||
 | 
					    - unzip bassopus.zip
 | 
				
			||||||
 | 
					    - cp x64/libbassopus.so ../lib
 | 
				
			||||||
 | 
					    - cd ..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Extract Discord RPC
 | 
				
			||||||
 | 
					    - mkdir discord-rpc
 | 
				
			||||||
 | 
					    - cd discord-rpc
 | 
				
			||||||
 | 
					    - curl -L https://github.com/discordapp/discord-rpc/releases/download/v3.4.0/discord-rpc-linux.zip -o discord_rpc_linux.zip
 | 
				
			||||||
 | 
					    - unzip discord_rpc_linux.zip
 | 
				
			||||||
 | 
					    - cp discord-rpc/linux-dynamic/lib/libdiscord-rpc.so ../lib
 | 
				
			||||||
 | 
					    - cd ..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Extract QtApng
 | 
				
			||||||
 | 
					    - mkdir qtapng
 | 
				
			||||||
 | 
					    - cd qtapng
 | 
				
			||||||
 | 
					    - curl -L https://github.com/Skycoder42/QtApng/releases/download/1.1.0-5/build_gcc_64_5.12.0.tar.xz -o apng.tar.xz
 | 
				
			||||||
 | 
					    - tar -xvf apng.tar.xz
 | 
				
			||||||
 | 
					    - cp gcc_64/plugins/imageformats/libqapng.so ../lib
 | 
				
			||||||
 | 
					    - cd ..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Build
 | 
				
			||||||
 | 
					    - qmake -spec linux-clang
 | 
				
			||||||
 | 
					    - make -j4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Post-processing
 | 
				
			||||||
 | 
					    - upx --lzma -9 --force bin/Attorney_Online
 | 
				
			||||||
 | 
					  artifacts:
 | 
				
			||||||
 | 
					    paths:
 | 
				
			||||||
 | 
					      - bin/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					build windows i686:
 | 
				
			||||||
 | 
					  image: ${CI_REGISTRY_IMAGE}/builder-windows-i686
 | 
				
			||||||
 | 
					  stage: build
 | 
				
			||||||
 | 
					  tags:
 | 
				
			||||||
 | 
					    - docker
 | 
				
			||||||
 | 
					    - linux
 | 
				
			||||||
 | 
					  script:
 | 
				
			||||||
 | 
					    # Install dependencies
 | 
				
			||||||
 | 
					    - apt-get update
 | 
				
			||||||
 | 
					    - apt-get install --no-install-recommends -y make curl ca-certificates upx unzip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Extract BASS
 | 
				
			||||||
 | 
					    - mkdir bass
 | 
				
			||||||
 | 
					    - cd bass
 | 
				
			||||||
 | 
					    - curl http://www.un4seen.com/files/bass24.zip -o bass.zip
 | 
				
			||||||
 | 
					    - unzip bass.zip
 | 
				
			||||||
 | 
					    - cp bass.dll ../lib
 | 
				
			||||||
 | 
					    - curl http://www.un4seen.com/files/bassopus24.zip -o bassopus.zip
 | 
				
			||||||
 | 
					    - unzip bassopus.zip
 | 
				
			||||||
 | 
					    - cp bassopus.dll ../lib
 | 
				
			||||||
 | 
					    - cd ..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Build
 | 
				
			||||||
 | 
					    - /opt/mxe/usr/${TARGET_SPEC}/qt5/bin/qmake
 | 
				
			||||||
 | 
					    - make -j4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Post-processing
 | 
				
			||||||
 | 
					    - upx --lzma -9 --force bin/Attorney_Online.exe
 | 
				
			||||||
 | 
					  artifacts:
 | 
				
			||||||
 | 
					    paths:
 | 
				
			||||||
 | 
					      - bin/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Base folder
 | 
				
			||||||
 | 
					.deploy_base: &deploy_base |
 | 
				
			||||||
 | 
					    mkdir base
 | 
				
			||||||
 | 
					    mkdir base/themes
 | 
				
			||||||
 | 
					    cp -a ../base/themes/default base/themes/
 | 
				
			||||||
 | 
					    cp -a ../base/config.ini base/config.sample.ini
 | 
				
			||||||
 | 
					    cp -a ../base/serverlist.txt base/serverlist.sample.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Miscellaneous files
 | 
				
			||||||
 | 
					.deploy_misc: &deploy_misc |
 | 
				
			||||||
 | 
					    cp -a ../README.md README.md.txt
 | 
				
			||||||
 | 
					    cp -a ../LICENSE.MIT LICENSE.txt
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					deploy linux x86_64:
 | 
				
			||||||
 | 
					  stage: deploy
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    - build linux x86_64
 | 
				
			||||||
 | 
					  tags:
 | 
				
			||||||
 | 
					    - docker
 | 
				
			||||||
 | 
					    - linux
 | 
				
			||||||
 | 
					  script:
 | 
				
			||||||
 | 
					    - mkdir artifact
 | 
				
			||||||
 | 
					    - cd artifact
 | 
				
			||||||
 | 
					    - *deploy_base
 | 
				
			||||||
 | 
					    - *deploy_misc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Platform-specific
 | 
				
			||||||
 | 
					    - cp -a ../lib/*.so .
 | 
				
			||||||
 | 
					    - cp -a ../bin/Attorney_Online .
 | 
				
			||||||
 | 
					    - echo "#!/bin/sh" >> ./run.sh
 | 
				
			||||||
 | 
					    - echo "LD_LIBRARY_PATH=.:\$LD_LIBRARY_PATH ./Attorney_Online" >> ./run.sh
 | 
				
			||||||
 | 
					    - chmod +x ./run.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Zipping
 | 
				
			||||||
 | 
					    # zip -r -9 -l Attorney_Online_$(git describe --tags)_linux_x86_64.zip .
 | 
				
			||||||
 | 
					    - mkdir ../zip
 | 
				
			||||||
 | 
					    - tar cavf ../zip/Attorney_Online_$(git describe --tags)_linux_x64.tar.xz *
 | 
				
			||||||
 | 
					    - sha1sum ../zip/*
 | 
				
			||||||
 | 
					  artifacts:
 | 
				
			||||||
 | 
					    paths:
 | 
				
			||||||
 | 
					      - zip/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					deploy windows i686:
 | 
				
			||||||
 | 
					  image: ubuntu
 | 
				
			||||||
 | 
					  stage: deploy
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    - build windows i686
 | 
				
			||||||
 | 
					  tags:
 | 
				
			||||||
 | 
					    - docker
 | 
				
			||||||
 | 
					    - linux
 | 
				
			||||||
 | 
					  script:
 | 
				
			||||||
 | 
					    - apt-get update
 | 
				
			||||||
 | 
					    - apt-get install --no-install-recommends -y zip git
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    - mkdir artifact
 | 
				
			||||||
 | 
					    - cd artifact
 | 
				
			||||||
 | 
					    - *deploy_base
 | 
				
			||||||
 | 
					    - *deploy_misc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Platform-specific
 | 
				
			||||||
 | 
					    - cp -a ../lib/*.dll .
 | 
				
			||||||
 | 
					    - cp -a ../bin/Attorney_Online.exe .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Zipping
 | 
				
			||||||
 | 
					    # -r: recursive; -9: max compression; -l: convert to CR LF
 | 
				
			||||||
 | 
					    - mkdir ../zip
 | 
				
			||||||
 | 
					    - zip -r -9 -l ../zip/Attorney_Online_$(git describe --tags)_windows_x86.zip .
 | 
				
			||||||
 | 
					    - sha1sum ../zip/*
 | 
				
			||||||
 | 
					  artifacts:
 | 
				
			||||||
 | 
					    paths:
 | 
				
			||||||
 | 
					      - zip/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					publish linux x86_64:
 | 
				
			||||||
 | 
					  image: ubuntu
 | 
				
			||||||
 | 
					  stage: publish
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    - deploy linux x86_64
 | 
				
			||||||
 | 
					  when: manual
 | 
				
			||||||
 | 
					  script:
 | 
				
			||||||
 | 
					    - cd zip
 | 
				
			||||||
 | 
					    - ../scripts/wasabi.sh
 | 
				
			||||||
 | 
					  variables:
 | 
				
			||||||
 | 
					    MANIFEST: program_linux_x86_64.json
 | 
				
			||||||
 | 
					    ARTIFACT_SUFFIX: _linux_x64.tar.xz
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					publish windows i686:
 | 
				
			||||||
 | 
					  image: ubuntu
 | 
				
			||||||
 | 
					  stage: publish
 | 
				
			||||||
 | 
					  dependencies:
 | 
				
			||||||
 | 
					    - deploy windows i686
 | 
				
			||||||
 | 
					  when: manual
 | 
				
			||||||
 | 
					  script:
 | 
				
			||||||
 | 
					    - cd zip
 | 
				
			||||||
 | 
					    - ../scripts/wasabi.sh
 | 
				
			||||||
 | 
					  variables:
 | 
				
			||||||
 | 
					    MANIFEST: program_winnt_i386.json
 | 
				
			||||||
 | 
					    ARTIFACT_SUFFIX: _windows_x86.zip
 | 
				
			||||||
							
								
								
									
										11
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					language: cpp
 | 
				
			||||||
 | 
					os: osx
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					addons:
 | 
				
			||||||
 | 
					    homebrew:
 | 
				
			||||||
 | 
					        packages:
 | 
				
			||||||
 | 
					            - qt5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					script:
 | 
				
			||||||
 | 
					    - ./scripts/macos_build.sh
 | 
				
			||||||
 | 
					    - ./scripts/macos_post_build.sh
 | 
				
			||||||
@ -16,13 +16,13 @@ HEADERS += $$files($$PWD/include/*.h)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
LIBS += -L$$PWD/lib
 | 
					LIBS += -L$$PWD/lib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#DEFINES += DISCORD
 | 
					DEFINES += DISCORD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
contains(DEFINES, DISCORD) {
 | 
					contains(DEFINES, DISCORD) {
 | 
				
			||||||
LIBS += -ldiscord-rpc
 | 
					LIBS += -ldiscord-rpc
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#DEFINES += BASSAUDIO
 | 
					DEFINES += BASSAUDIO
 | 
				
			||||||
 | 
					
 | 
				
			||||||
contains(DEFINES, BASSAUDIO) {
 | 
					contains(DEFINES, BASSAUDIO) {
 | 
				
			||||||
LIBS += -lbass
 | 
					LIBS += -lbass
 | 
				
			||||||
@ -34,6 +34,9 @@ contains(DEFINES, QTAUDIO) {
 | 
				
			|||||||
QT += multimedia
 | 
					QT += multimedia
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					macx:LIBS += -framework CoreFoundation -framework Foundation -framework CoreServices
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG += c++14
 | 
					CONFIG += c++14
 | 
				
			||||||
 | 
					
 | 
				
			||||||
RESOURCES += resources.qrc
 | 
					RESOURCES += resources.qrc
 | 
				
			||||||
 | 
				
			|||||||
@ -8,18 +8,36 @@ This program has five main dependencies
 | 
				
			|||||||
* Discord Rich Presence (https://github.com/discordapp/discord-rpc/releases)
 | 
					* Discord Rich Presence (https://github.com/discordapp/discord-rpc/releases)
 | 
				
			||||||
* Qt Apng Plugin (https://github.com/Skycoder42/QtApng/releases)
 | 
					* Qt Apng Plugin (https://github.com/Skycoder42/QtApng/releases)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Help
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you're having issues with any of this, ask in the offical Discord: https://discord.gg/wWvQ3pw
 | 
				
			||||||
 | 
					Alternatively, you can ask OmniTroid#4004 on Discord.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### How to build dynamically (the easy way)
 | 
					### How to build dynamically (the easy way)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### General preparation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What you want to do is first download the latest version of Qt from the first link. (get the prebuilt dynamic version)
 | 
					What you want to do is first download the latest version of Qt from the first link. (get the prebuilt dynamic version)
 | 
				
			||||||
If you're on Ubuntu, go to the scripts/ folder and run configure_ubuntu.sh. This should fetch all the required dependencies automatically.  
 | 
					After going through the OS-specific steps below, compiling in Qt creator should work.
 | 
				
			||||||
If not, go to each one of the links above and find the right dynamic library for your platform:
 | 
					 | 
				
			||||||
* Windows: .dll
 | 
					 | 
				
			||||||
* Linux: .so
 | 
					 | 
				
			||||||
* Mac: .dylib
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
And put them in BOTH lib/ and the repository root (lib/ is required for linking and root is required for runtime)
 | 
					#### Windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Launch Qt creator, open the .pro file and try running it. Ask in the Discord if you're having issues: https://discord.gg/wWvQ3pw  
 | 
					If you're on Windows, you need to go find all the dependencies (see above) and put them in the lib/ folder.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### MacOS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you're on MacOS, you can simply go to terminal and run ./scripts/configure_macos.sh
 | 
				
			||||||
 | 
					This will automatically fetch all the required dependencies. Additionally, if you need to create a standalone release, just run ./scripts/release_macos.sh
 | 
				
			||||||
 | 
					This will make the .app bundle in bin/ able to execute as a standalone.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Ubuntu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you're on Ubuntu, just go to terminal and run ./scripts/configure_ubuntu.sh
 | 
				
			||||||
 | 
					This should fetch all the required dependencies automatically.  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#### Other Linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With some tweaks to the ubuntu script, it shouldn't be a big hassle to compile it on a modern linux. Look in the script and see what you may have to modify.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### How to build statically (the hard way)
 | 
					### How to build statically (the hard way)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -22,6 +22,7 @@
 | 
				
			|||||||
#include <QTextStream>
 | 
					#include <QTextStream>
 | 
				
			||||||
#include <QStringList>
 | 
					#include <QStringList>
 | 
				
			||||||
#include <QColor>
 | 
					#include <QColor>
 | 
				
			||||||
 | 
					#include <QScreen>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NetworkManager;
 | 
					class NetworkManager;
 | 
				
			||||||
class Lobby;
 | 
					class Lobby;
 | 
				
			||||||
 | 
				
			|||||||
@ -35,8 +35,10 @@ protected:
 | 
				
			|||||||
  void enterEvent(QEvent *e);
 | 
					  void enterEvent(QEvent *e);
 | 
				
			||||||
  void leaveEvent(QEvent *e);
 | 
					  void leaveEvent(QEvent *e);
 | 
				
			||||||
  void mouseDoubleClickEvent(QMouseEvent *e);
 | 
					  void mouseDoubleClickEvent(QMouseEvent *e);
 | 
				
			||||||
 | 
					  /*
 | 
				
			||||||
  void dragLeaveEvent(QMouseEvent *e);
 | 
					  void dragLeaveEvent(QMouseEvent *e);
 | 
				
			||||||
  void dragEnterEvent(QMouseEvent *e);
 | 
					  void dragEnterEvent(QMouseEvent *e);
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
signals:
 | 
					signals:
 | 
				
			||||||
  void evidence_clicked(int p_id);
 | 
					  void evidence_clicked(int p_id);
 | 
				
			||||||
 | 
				
			|||||||
@ -35,7 +35,6 @@
 | 
				
			|||||||
#include <QSlider>
 | 
					#include <QSlider>
 | 
				
			||||||
#include <QVector>
 | 
					#include <QVector>
 | 
				
			||||||
#include <QCloseEvent>
 | 
					#include <QCloseEvent>
 | 
				
			||||||
#include <QSignalMapper>
 | 
					 | 
				
			||||||
#include <QMap>
 | 
					#include <QMap>
 | 
				
			||||||
#include <QTextBrowser>
 | 
					#include <QTextBrowser>
 | 
				
			||||||
#include <QSpinBox>
 | 
					#include <QSpinBox>
 | 
				
			||||||
@ -48,6 +47,7 @@
 | 
				
			|||||||
#include <QFont>
 | 
					#include <QFont>
 | 
				
			||||||
#include <QInputDialog>
 | 
					#include <QInputDialog>
 | 
				
			||||||
#include <QFileDialog>
 | 
					#include <QFileDialog>
 | 
				
			||||||
 | 
					#include <QTextBoundaryFinder>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stack>
 | 
					#include <stack>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -272,8 +272,6 @@ private:
 | 
				
			|||||||
  QVector<QString> arup_cms;
 | 
					  QVector<QString> arup_cms;
 | 
				
			||||||
  QVector<QString> arup_locks;
 | 
					  QVector<QString> arup_locks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QSignalMapper *char_button_mapper;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  QVector<chatlogpiece> ic_chatlog_history;
 | 
					  QVector<chatlogpiece> ic_chatlog_history;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // These map music row items and area row items to their actual IDs.
 | 
					  // These map music row items and area row items to their actual IDs.
 | 
				
			||||||
@ -537,6 +535,7 @@ private:
 | 
				
			|||||||
  void construct_char_select();
 | 
					  void construct_char_select();
 | 
				
			||||||
  void set_char_select();
 | 
					  void set_char_select();
 | 
				
			||||||
  void set_char_select_page();
 | 
					  void set_char_select_page();
 | 
				
			||||||
 | 
					  void char_clicked(int n_char);
 | 
				
			||||||
  void put_button_in_place(int starting, int chars_on_this_page);
 | 
					  void put_button_in_place(int starting, int chars_on_this_page);
 | 
				
			||||||
  void filter_character_list();
 | 
					  void filter_character_list();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -651,14 +650,12 @@ private slots:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  void on_char_select_left_clicked();
 | 
					  void on_char_select_left_clicked();
 | 
				
			||||||
  void on_char_select_right_clicked();
 | 
					  void on_char_select_right_clicked();
 | 
				
			||||||
  void on_char_search_changed(const QString& newtext);
 | 
					  void on_char_search_changed();
 | 
				
			||||||
  void on_char_taken_clicked(int newstate);
 | 
					  void on_char_taken_clicked();
 | 
				
			||||||
  void on_char_passworded_clicked(int newstate);
 | 
					  void on_char_passworded_clicked();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void on_spectator_clicked();
 | 
					  void on_spectator_clicked();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void char_clicked(int n_char);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void on_switch_area_music_clicked();
 | 
					  void on_switch_area_music_clicked();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void on_casing_clicked();
 | 
					  void on_casing_clicked();
 | 
				
			||||||
 | 
				
			|||||||
@ -44,13 +44,14 @@ public:
 | 
				
			|||||||
  QString ms_nosrv_hostname = "master.aceattorneyonline.com";
 | 
					  QString ms_nosrv_hostname = "master.aceattorneyonline.com";
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const int ms_port = 27016;
 | 
					  const quint16 ms_port = 27016;
 | 
				
			||||||
  const int timeout_milliseconds = 2000;
 | 
					  const int timeout_milliseconds = 2000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const int ms_reconnect_delay_ms = 7000;
 | 
					  // in seconds
 | 
				
			||||||
 | 
					  const int ms_reconnect_delay = 7;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // kind of arbitrary max buffer size
 | 
					  // kind of arbitrary max buffer size
 | 
				
			||||||
  const size_t buffer_max_size = 16384;
 | 
					  #define BUFFER_MAX_SIZE 16384
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool ms_partial_packet = false;
 | 
					  bool ms_partial_packet = false;
 | 
				
			||||||
  QString ms_temp_packet = "";
 | 
					  QString ms_temp_packet = "";
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										6
									
								
								scripts/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								scripts/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					node_modules/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Cursed file
 | 
				
			||||||
 | 
					package-lock.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					s3_keys.sh
 | 
				
			||||||
							
								
								
									
										42
									
								
								scripts/configure_macos.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										42
									
								
								scripts/configure_macos.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This script fetches all build dependencies for MacOS
 | 
				
			||||||
 | 
					# Tested on MacOS 10.14 (Mojave), Qt 5.13 and XCode 10.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Exit on errors and unset variables
 | 
				
			||||||
 | 
					set -eu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cd ${ROOT_DIR}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LIB_TARGET="../../lib"
 | 
				
			||||||
 | 
					BASS_LINK="http://uk.un4seen.com/files/bass24-osx.zip"
 | 
				
			||||||
 | 
					BASSOPUS_LINK="http://www.un4seen.com/files/bassopus24-osx.zip"
 | 
				
			||||||
 | 
					DISCORD_RPC_LINK="https://github.com/discordapp/discord-rpc/releases/download/v3.4.0/discord-rpc-osx.zip"
 | 
				
			||||||
 | 
					APNG_LINK="https://github.com/Skycoder42/QtApng/releases/download/1.1.2-2/qtapng_clang_64_5.13.0.tar.xz"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Easier if we don't need to worry about an existing tmp folder tbh smh
 | 
				
			||||||
 | 
					#      v Add a slash here for free tmp folder cleanup in true javascript community style
 | 
				
			||||||
 | 
					rm -rf tmp
 | 
				
			||||||
 | 
					mkdir tmp
 | 
				
			||||||
 | 
					cd tmp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					curl -Ls ${BASS_LINK} -o bass.zip
 | 
				
			||||||
 | 
					unzip -qq bass.zip
 | 
				
			||||||
 | 
					cp libbass.dylib ${LIB_TARGET}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					curl -Ls ${BASSOPUS_LINK} -o bassopus.zip
 | 
				
			||||||
 | 
					unzip -qq bassopus.zip
 | 
				
			||||||
 | 
					cp libbassopus.dylib ${LIB_TARGET}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					curl -Ls ${DISCORD_RPC_LINK} -o discord_rpc.zip
 | 
				
			||||||
 | 
					unzip -qq discord_rpc.zip
 | 
				
			||||||
 | 
					cp discord-rpc/osx-dynamic/lib/libdiscord-rpc.dylib ${LIB_TARGET}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					curl -Ls ${APNG_LINK} -o apng.tar.xz
 | 
				
			||||||
 | 
					tar -xf apng.tar.xz
 | 
				
			||||||
 | 
					cp clang_64/plugins/imageformats/libqapng.dylib ../../lib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					rm -rf tmp
 | 
				
			||||||
@ -1,6 +1,13 @@
 | 
				
			|||||||
#!/bin/bash
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#assumes a somewhat recent 64-bit ubuntu
 | 
					# Assumes a somewhat recent 64-bit ubuntu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Exit on errors and unset variables
 | 
				
			||||||
 | 
					set -eu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cd ${ROOT_DIR}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#need some openGL stuff
 | 
					#need some openGL stuff
 | 
				
			||||||
sudo apt install libgl1-mesa-dev
 | 
					sudo apt install libgl1-mesa-dev
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										33
									
								
								scripts/macos_build.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										33
									
								
								scripts/macos_build.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set -Eexo pipefail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig:/usr/local/opt/openssl/lib/pkgconfig
 | 
				
			||||||
 | 
					export PATH=$PATH:/usr/local/opt/qt5/bin:/usr/local/bin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mkdir bass
 | 
				
			||||||
 | 
					cd bass
 | 
				
			||||||
 | 
					curl http://www.un4seen.com/files/bass24-osx.zip -o bass.zip
 | 
				
			||||||
 | 
					unzip bass.zip
 | 
				
			||||||
 | 
					cp libbass.dylib ../lib
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					curl http://www.un4seen.com/files/bassopus24-osx.zip -o bassopus.zip
 | 
				
			||||||
 | 
					unzip bassopus.zip
 | 
				
			||||||
 | 
					cp libbassopus.dylib ../lib
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mkdir discord-rpc
 | 
				
			||||||
 | 
					cd discord-rpc
 | 
				
			||||||
 | 
					curl -L https://github.com/discordapp/discord-rpc/releases/download/v3.4.0/discord-rpc-osx.zip -o discord_rpc_osx.zip
 | 
				
			||||||
 | 
					unzip discord_rpc_osx.zip
 | 
				
			||||||
 | 
					cp discord-rpc/osx-static/lib/libdiscord-rpc.a ../lib
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mkdir qtapng
 | 
				
			||||||
 | 
					cd qtapng
 | 
				
			||||||
 | 
					curl -L https://github.com/Skycoder42/QtApng/releases/download/1.1.0-5/build_clang_64_5.12.0.tar.xz -o apng.tar.xz
 | 
				
			||||||
 | 
					tar -xvf apng.tar.xz
 | 
				
			||||||
 | 
					cp clang_64/plugins/imageformats/libqapng.dylib ../lib
 | 
				
			||||||
 | 
					cd ..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					qmake && make -j2
 | 
				
			||||||
@ -1,16 +1,22 @@
 | 
				
			|||||||
#!/bin/bash
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DST_FOLDER="./bin/Attorney_Online.app/Contents/Frameworks"
 | 
					# This script prepares the compiled bundle for shipping as a standalone release
 | 
				
			||||||
 | 
					# Assumes the Qt bin folder is in PATH
 | 
				
			||||||
 | 
					# Should be used on a "Release" build from QT creator
 | 
				
			||||||
 | 
					# Note that this DOES NOT add the base/ folder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cd ..
 | 
					# Exit on errors and unset variables
 | 
				
			||||||
 | 
					set -eu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
mkdir $DST_FOLDER
 | 
					ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cp ./lib/libbass.dylib $DST_FOLDER
 | 
					cd ${ROOT_DIR}
 | 
				
			||||||
cp ./lib/libbassopus.dylib $DST_FOLDER
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_name_tool -id @executable_path/../Frameworks/libbass.dylib $DST_FOLDER/libbass.dylib
 | 
					# This thing basically does all the work
 | 
				
			||||||
 | 
					macdeployqt ../bin/Attorney_Online.app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_name_tool -id @executable_path/../Frameworks/libbassopus.dylib $DST_FOLDER/libbassopus.dylib
 | 
					# Need to add the dependencies
 | 
				
			||||||
 | 
					cp ../lib/* ../bin/Attorney_Online.app/Contents/Frameworks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
install_name_tool -change @loader_path/libbass.dylib @executable_path/../Frameworks/libbass.dylib ./bin/Attorney_Online.app/Contents/MacOS/Attorney_Online
 | 
					# libbass has a funny path for some reason, just use rpath
 | 
				
			||||||
 | 
					install_name_tool -change @loader_path/libbass.dylib @rpath/libbass.dylib ../bin/Attorney_Online.app/Contents/MacOS/Attorney_Online
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										9
									
								
								scripts/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								scripts/package.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "ao-ci-scripts",
 | 
				
			||||||
 | 
					  "version": "1.0.0",
 | 
				
			||||||
 | 
					  "main": "update_manifest.js",
 | 
				
			||||||
 | 
					  "dependencies": {
 | 
				
			||||||
 | 
					    "argparse": "^1.0.10"
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "license": "ISC"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										22
									
								
								scripts/release_macos.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								scripts/release_macos.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This script prepares the compiled bundle for shipping as a standalone release
 | 
				
			||||||
 | 
					# Assumes the Qt bin folder is in PATH
 | 
				
			||||||
 | 
					# Should be used on a "Release" build from QT creator
 | 
				
			||||||
 | 
					# Note that this DOES NOT add the base/ folder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Exit on errors and unset variables
 | 
				
			||||||
 | 
					set -eu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					cd ${ROOT_DIR}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This thing basically does all the work
 | 
				
			||||||
 | 
					macdeployqt ../bin/Attorney_Online.app
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Need to add the dependencies
 | 
				
			||||||
 | 
					cp ../lib/* ../bin/Attorney_Online.app/Contents/Frameworks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# libbass has a funny path for some reason, just use rpath
 | 
				
			||||||
 | 
					install_name_tool -change @loader_path/libbass.dylib @rpath/libbass.dylib ../bin/Attorney_Online.app/Contents/MacOS/Attorney_Online
 | 
				
			||||||
							
								
								
									
										151
									
								
								scripts/update_manifest.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										151
									
								
								scripts/update_manifest.js
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,151 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const fs = require("fs");
 | 
				
			||||||
 | 
					const crypto = require("crypto");
 | 
				
			||||||
 | 
					const path = require("path");
 | 
				
			||||||
 | 
					const ArgumentParser = require("argparse").ArgumentParser;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function isFile(file) {
 | 
				
			||||||
 | 
					    if (!fs.existsSync(file)) {
 | 
				
			||||||
 | 
					        console.error(`File '${file}' not found. Try again.`);
 | 
				
			||||||
 | 
					        throw Error();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return file;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const argParser = new ArgumentParser({
 | 
				
			||||||
 | 
					    addHelp: true,
 | 
				
			||||||
 | 
					    description: "Adds a new latest version to the manifest file based on the " +
 | 
				
			||||||
 | 
					        "provided zip file, including an incremental update."
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					argParser.addArgument("manifestFile", {
 | 
				
			||||||
 | 
					    metavar: "<manifest file>", type: isFile
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					argParser.addArgument("version", {
 | 
				
			||||||
 | 
					    metavar: "<version>"
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					argParser.addArgument([ "-f", "--full" ], {
 | 
				
			||||||
 | 
					    metavar: "<full zip file>", type: isFile, nargs: 1,
 | 
				
			||||||
 | 
					    dest: "fullZipFileArgs"
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					argParser.addArgument([ "-i", "--incremental" ], {
 | 
				
			||||||
 | 
					    type: isFile, nargs: 2, dest: "incrementalArgs",
 | 
				
			||||||
 | 
					    metavar: ["<incremental zip file>", "<file containing list of changed files>"]
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					argParser.addArgument([ "-e", "--executable" ], {
 | 
				
			||||||
 | 
					    metavar: "[executable file]", nargs: 1,
 | 
				
			||||||
 | 
					    dest: "executableArgs"
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const {
 | 
				
			||||||
 | 
					    manifestFile,
 | 
				
			||||||
 | 
					    version,
 | 
				
			||||||
 | 
					    fullZipFileArgs,
 | 
				
			||||||
 | 
					    incrementalArgs,
 | 
				
			||||||
 | 
					    executableArgs
 | 
				
			||||||
 | 
					} = argParser.parseArgs();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [incrementalZipFile, changesFile] = incrementalArgs || [];
 | 
				
			||||||
 | 
					const [fullZipFile] = fullZipFileArgs || [];
 | 
				
			||||||
 | 
					const [executable] = executableArgs || [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Do one final check
 | 
				
			||||||
 | 
					if (!incrementalZipFile && !fullZipFile) {
 | 
				
			||||||
 | 
					    console.error("No download archive specified! Abort.");
 | 
				
			||||||
 | 
					    process.exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Do a quick litmus test to prevent deleting everything incorrectly
 | 
				
			||||||
 | 
					if (changesFile && !fs.existsSync("base")) {
 | 
				
			||||||
 | 
					    console.error("The working directory must be set to an " +
 | 
				
			||||||
 | 
					                  "asset folder in order for deleted directories " +
 | 
				
			||||||
 | 
					                  "to be calculated correctly. Abort.");
 | 
				
			||||||
 | 
					    process.exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const manifest = JSON.parse(fs.readFileSync(manifestFile));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const dirsDeleted = new Set();
 | 
				
			||||||
 | 
					const specialActions = changesFile ?
 | 
				
			||||||
 | 
					    fs.readFileSync(changesFile)
 | 
				
			||||||
 | 
					    .toString()
 | 
				
			||||||
 | 
					    .trim()
 | 
				
			||||||
 | 
					    .split("\n")
 | 
				
			||||||
 | 
					    .map(line => line.split("\t"))
 | 
				
			||||||
 | 
					    .map(([mode, target, source]) => {
 | 
				
			||||||
 | 
					        switch (mode[0]) {
 | 
				
			||||||
 | 
					            case "D": // Deleted
 | 
				
			||||||
 | 
					                // Check if the folder exists relative to the working
 | 
				
			||||||
 | 
					                // directory, and if not, add it to the dirsDeleted list.
 | 
				
			||||||
 | 
					                // Keep going up the tree to see how many directories were
 | 
				
			||||||
 | 
					                // deleted.
 | 
				
			||||||
 | 
					                let dir = path.dirname(target);
 | 
				
			||||||
 | 
					                while (!dirsDeleted.has(dir) && !fs.existsSync(dir)) {
 | 
				
			||||||
 | 
					                    dirsDeleted.add(dir);
 | 
				
			||||||
 | 
					                    dir = path.dirname(dir);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                return { action: "delete", target };
 | 
				
			||||||
 | 
					            case "R": // Renamed
 | 
				
			||||||
 | 
					                // NOTE: Make sure that the launcher's implementation of
 | 
				
			||||||
 | 
					                // the move action also creates directories when needed.
 | 
				
			||||||
 | 
					                return { action: "move", source, target};
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    // Remove ignored file mode changes
 | 
				
			||||||
 | 
					    .filter(action => action !== null)
 | 
				
			||||||
 | 
					    // Create actions based on directories to be deleted.
 | 
				
			||||||
 | 
					    // Always have deeper directories first, to guarantee that deleting
 | 
				
			||||||
 | 
					    // higher-level directories will succeed.
 | 
				
			||||||
 | 
					    .concat(Array.from(dirsDeleted.values())
 | 
				
			||||||
 | 
					        .sort((a, b) => b.split("/").length - a.split("/").length)
 | 
				
			||||||
 | 
					        .map(dir => {
 | 
				
			||||||
 | 
					            return { action: "deleteDir", target: dir };
 | 
				
			||||||
 | 
					        }))
 | 
				
			||||||
 | 
					    : [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const urlBase = "https://s3.wasabisys.com/ao-downloads/";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const versionEntry = {
 | 
				
			||||||
 | 
					    version,
 | 
				
			||||||
 | 
					    executable,
 | 
				
			||||||
 | 
					    prev: manifest.versions[0] ? manifest.versions[0].version : undefined,
 | 
				
			||||||
 | 
					    full: fullZipFile ? [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            action: "dl",
 | 
				
			||||||
 | 
					            url: urlBase + encodeURIComponent(path.basename(fullZipFile)),
 | 
				
			||||||
 | 
					            hash: crypto.createHash("sha1")
 | 
				
			||||||
 | 
					                .update(fs.readFileSync(fullZipFile))
 | 
				
			||||||
 | 
					                .digest("hex")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ] : undefined,
 | 
				
			||||||
 | 
					    update: incrementalArgs ? [
 | 
				
			||||||
 | 
					        ...specialActions,
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            action: "dl",
 | 
				
			||||||
 | 
					            url: urlBase + encodeURIComponent(path.basename(incrementalZipFile)),
 | 
				
			||||||
 | 
					            hash: crypto.createHash("sha1")
 | 
				
			||||||
 | 
					                .update(fs.readFileSync(incrementalZipFile))
 | 
				
			||||||
 | 
					                .digest("hex")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ] : undefined
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					console.log("Generated version entry:", versionEntry);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const existingVersions = manifest.versions.filter(v => v.version == version);
 | 
				
			||||||
 | 
					if (existingVersions.length > 0) {
 | 
				
			||||||
 | 
					    console.warn(`Warning: version ${version} already exists. Adding new values.`);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Don't overwrite prev - it will cause headaches
 | 
				
			||||||
 | 
					    delete versionEntry.prev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Object.assign(existingVersions[0], versionEntry);
 | 
				
			||||||
 | 
					    console.log("Merged version entry:", existingVersions[0]);
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
					    manifest.versions = [versionEntry, ...manifest.versions];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fs.writeFileSync(manifestFile, JSON.stringify(manifest, null, 4));
 | 
				
			||||||
							
								
								
									
										39
									
								
								scripts/update_program_manifest.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										39
									
								
								scripts/update_program_manifest.js
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env node
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const fs = require("fs");
 | 
				
			||||||
 | 
					const crypto = require("crypto");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const [ _nodeExe, _jsPath, manifestFile, version, zipFile ] = process.argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!manifestFile || !version || !zipFile) {
 | 
				
			||||||
 | 
					    console.log(`Usage: update_program_manifest <manifest file> <version> <zip file>`);
 | 
				
			||||||
 | 
					    console.log(`Adds a new latest version to the manifest file based on the ` +
 | 
				
			||||||
 | 
					                `provided zip file.`);
 | 
				
			||||||
 | 
					    process.exit(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!fs.existsSync(manifestFile)) {
 | 
				
			||||||
 | 
					    console.error(`Manifest file '${manifestFile}' not found. Try again.`);
 | 
				
			||||||
 | 
					    process.exit(2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if (!fs.existsSync(zipFile)) {
 | 
				
			||||||
 | 
					    console.error(`Zip file '${zipFile}' not found. Try again.`);
 | 
				
			||||||
 | 
					    process.exit(2);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const manifest = JSON.parse(fs.readFileSync(manifestFile));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					manifest.versions = [{
 | 
				
			||||||
 | 
					    version,
 | 
				
			||||||
 | 
					    executable: "Attorney_Online.exe",
 | 
				
			||||||
 | 
					    full: [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            action: "dl",
 | 
				
			||||||
 | 
					            url: "https://s3.wasabisys.com/ao-downloads/" + encodeURIComponent(zipFile),
 | 
				
			||||||
 | 
					            hash: crypto.createHash("sha1").update(fs.readFileSync(zipFile)).digest("hex")
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}, ...manifest.versions];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fs.writeFileSync(manifestFile, JSON.stringify(manifest, null, 4));
 | 
				
			||||||
							
								
								
									
										73
									
								
								scripts/wasabi.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										73
									
								
								scripts/wasabi.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					# Updates the specified program manifest to a new archive and version
 | 
				
			||||||
 | 
					# and uploads the new archive and manifest to S3/Wasabi.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Requires:
 | 
				
			||||||
 | 
					#   MANIFEST: name of the manifest file
 | 
				
			||||||
 | 
					#   S3_ACCESS_KEY, S3_SECRET_KEY: S3 credentials
 | 
				
			||||||
 | 
					#   S3_MANIFESTS, S3_ARCHIVES: S3 paths to manifests and downloads
 | 
				
			||||||
 | 
					#   ARCHIVE_FULL: name of the full archive (if desired)
 | 
				
			||||||
 | 
					#   ARCHIVE_INCR: name of the incremental archive (if desired)
 | 
				
			||||||
 | 
					#   VERSION: name of the new version
 | 
				
			||||||
 | 
					#   EXECUTABLE: name of the executable (if program manifest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -E: inherit ERR trap by shell functions
 | 
				
			||||||
 | 
					# -e: stop script on ERR trap
 | 
				
			||||||
 | 
					# -u: stop script on unbound variables
 | 
				
			||||||
 | 
					# -x: print command before running it
 | 
				
			||||||
 | 
					# -o pipefail: fail if any command in a pipeline fails
 | 
				
			||||||
 | 
					set -Eeuxo pipefail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					aws configure set aws_access_key_id ${S3_ACCESS_KEY}
 | 
				
			||||||
 | 
					aws configure set aws_secret_access_key ${S3_SECRET_KEY}
 | 
				
			||||||
 | 
					aws configure set default.region us-east-1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export S3_COPY="aws s3 cp --endpoint-url=https://s3.wasabisys.com"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export ARCHIVE_FULL_ARG=""
 | 
				
			||||||
 | 
					export ARCHIVE_INCR_ARG=""
 | 
				
			||||||
 | 
					export EXECUTABLE_ARG=""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export LAST_TAGGED_VERSION=$(git rev-list --tags --skip=1 --max-count=1)
 | 
				
			||||||
 | 
					echo "Previous tagged version: ${LAST_TAGGED_VERSION}"
 | 
				
			||||||
 | 
					echo "Current tagged version: ${VERSION}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [[ -n $ARCHIVE_INCR && -n $LAST_TAGGED_VERSION ]]; then
 | 
				
			||||||
 | 
					    echo "Incremental archive: ${ARCHIVE_INCR}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Get all files
 | 
				
			||||||
 | 
					    export CHANGES_FILE="changes.txt"
 | 
				
			||||||
 | 
					    git diff --name-status ${LAST_TAGGED_VERSION}..HEAD > ${CHANGES_FILE}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Get added/modified files
 | 
				
			||||||
 | 
					    git diff --name-only --diff-filter=dr ${LAST_TAGGED_VERSION}..HEAD | \
 | 
				
			||||||
 | 
					        zip ${ARCHIVE_INCR} -@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    export ARCHIVE_INCR_ARG="-i ${ARCHIVE_INCR} ${CHANGES_FILE}"
 | 
				
			||||||
 | 
					elif [[ -n $ARCHIVE_INCR && -z $LAST_TAGGED_VERSION ]]; then
 | 
				
			||||||
 | 
					    echo "Incremental archive was requested, but there is no previous version"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [[ -n $ARCHIVE_FULL ]]; then
 | 
				
			||||||
 | 
					    echo "Full archive: ${ARCHIVE_INCR}"
 | 
				
			||||||
 | 
					    export ARCHIVE_FULL_ARG="-f ${ARCHIVE_FULL}"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [[ -v EXECUTABLE ]]; then
 | 
				
			||||||
 | 
					    export EXECUTABLE_ARG="-e ${EXECUTABLE}"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${S3_COPY} ${S3_MANIFESTS}/${MANIFEST} .
 | 
				
			||||||
 | 
					node $(dirname $0)/update_manifest.js ${MANIFEST} ${VERSION} \
 | 
				
			||||||
 | 
					    ${ARCHIVE_FULL_ARG} ${ARCHIVE_INCR_ARG} ${EXECUTABLE_ARG}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [[ -n $ARCHIVE_INCR_ARG ]]; then
 | 
				
			||||||
 | 
					    ${S3_COPY} ${ARCHIVE_INCR} ${S3_ARCHIVES}
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [[ -n $ARCHIVE_FULL_ARG ]]; then
 | 
				
			||||||
 | 
					    ${S3_COPY} ${ARCHIVE_FULL} ${S3_ARCHIVES}
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${S3_COPY} ${MANIFEST} ${S3_MANIFESTS}
 | 
				
			||||||
							
								
								
									
										35
									
								
								scripts/wasabi_program.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										35
									
								
								scripts/wasabi_program.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					# Updates the specified program manifest to a new archive and version
 | 
				
			||||||
 | 
					# and uploads the new archive and manifest to S3/Wasabi.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Requires:
 | 
				
			||||||
 | 
					#   MANIFEST: name of the manifest file
 | 
				
			||||||
 | 
					#   ARTIFACT_SUFFIX: suffix of the archive to be uploaded (including extension)
 | 
				
			||||||
 | 
					#   S3_ACCESS_KEY and S3_SECRET_KEY
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# -E: inherit ERR trap by shell functions
 | 
				
			||||||
 | 
					# -e: stop script on ERR trap
 | 
				
			||||||
 | 
					# -u: stop script on unbound variables
 | 
				
			||||||
 | 
					# -x: print command before running it
 | 
				
			||||||
 | 
					# -o pipefail: fail if any command in a pipeline fails
 | 
				
			||||||
 | 
					set -Eeuxo pipefail
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					aws configure set aws_access_key_id ${S3_ACCESS_KEY}
 | 
				
			||||||
 | 
					aws configure set aws_secret_access_key ${S3_SECRET_KEY}
 | 
				
			||||||
 | 
					aws configure set default.region us-east-1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export S3_COPY="aws s3 cp --endpoint-url=https://s3.wasabisys.com"
 | 
				
			||||||
 | 
					export S3_MANIFESTS="s3://ao-manifests"
 | 
				
			||||||
 | 
					export S3_ARCHIVES="s3://ao-downloads"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export VERSION=$(git describe --tags)
 | 
				
			||||||
 | 
					export ARCHIVE="Attorney_Online_${VERSION}_${ARTIFACT_SUFFIX}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					${S3_COPY} ${S3_MANIFESTS}/${MANIFEST} .
 | 
				
			||||||
 | 
					node $(dirname $0)/update_manifest.js ${MANIFEST} ${VERSION} \
 | 
				
			||||||
 | 
					    -f ${ARCHIVE} -e Attorney_Online.exe
 | 
				
			||||||
 | 
					${S3_COPY} ${ARCHIVE} ${S3_ARCHIVES}
 | 
				
			||||||
 | 
					${S3_COPY} ${MANIFEST} ${S3_MANIFESTS}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					rm -f ${MANIFEST}
 | 
				
			||||||
							
								
								
									
										17
									
								
								scripts/windows/Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								scripts/windows/Dockerfile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					FROM oldmud0/mxe-qt:5.12.1-win32-static-posix
 | 
				
			||||||
 | 
					#FROM fffaraz/qt:windows
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ENV TARGET_SPEC i686-w64-mingw32.static.posix
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build Discord RPC statically
 | 
				
			||||||
 | 
					RUN git clone https://github.com/discordapp/discord-rpc
 | 
				
			||||||
 | 
					WORKDIR discord-rpc/build
 | 
				
			||||||
 | 
					RUN /opt/mxe/usr/bin/${TARGET_SPEC}-cmake .. -DCMAKE_INSTALL_PREFIX=/opt/mxe/usr/${TARGET_SPEC}
 | 
				
			||||||
 | 
					RUN /opt/mxe/usr/bin/${TARGET_SPEC}-cmake --build . --config Release --target install
 | 
				
			||||||
 | 
					WORKDIR ../..
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Build QtApng statically
 | 
				
			||||||
 | 
					RUN git clone https://github.com/Skycoder42/QtApng
 | 
				
			||||||
 | 
					WORKDIR QtApng
 | 
				
			||||||
 | 
					RUN /opt/mxe/usr/${TARGET_SPEC}/qt5/bin/qmake && make qmake_all && make && make install
 | 
				
			||||||
 | 
					WORKDIR ..
 | 
				
			||||||
							
								
								
									
										44
									
								
								scripts/windows/Dockerfile-mxe
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								scripts/windows/Dockerfile-mxe
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					FROM ubuntu:18.04
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN apt-get update
 | 
				
			||||||
 | 
					RUN apt-get install -y \
 | 
				
			||||||
 | 
					    autoconf \
 | 
				
			||||||
 | 
					    automake \
 | 
				
			||||||
 | 
					    autopoint \
 | 
				
			||||||
 | 
					    bash \
 | 
				
			||||||
 | 
					    bison \
 | 
				
			||||||
 | 
					    bzip2 \
 | 
				
			||||||
 | 
					    flex \
 | 
				
			||||||
 | 
					    g++ \
 | 
				
			||||||
 | 
					    g++-multilib \
 | 
				
			||||||
 | 
					    gettext \
 | 
				
			||||||
 | 
					    git \
 | 
				
			||||||
 | 
					    gperf \
 | 
				
			||||||
 | 
					    intltool \
 | 
				
			||||||
 | 
					    libc6-dev-i386 \
 | 
				
			||||||
 | 
					    libgdk-pixbuf2.0-dev \
 | 
				
			||||||
 | 
					    libltdl-dev \
 | 
				
			||||||
 | 
					    libssl-dev \
 | 
				
			||||||
 | 
					    libtool-bin \
 | 
				
			||||||
 | 
					    libxml-parser-perl \
 | 
				
			||||||
 | 
					    lzip \
 | 
				
			||||||
 | 
					    make \
 | 
				
			||||||
 | 
					    openssl \
 | 
				
			||||||
 | 
					    p7zip-full \
 | 
				
			||||||
 | 
					    patch \
 | 
				
			||||||
 | 
					    perl \
 | 
				
			||||||
 | 
					    pkg-config \
 | 
				
			||||||
 | 
					    python \
 | 
				
			||||||
 | 
					    ruby \
 | 
				
			||||||
 | 
					    sed \
 | 
				
			||||||
 | 
					    unzip \
 | 
				
			||||||
 | 
					    wget \
 | 
				
			||||||
 | 
					    xz-utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN git clone https://github.com/mxe/mxe.git
 | 
				
			||||||
 | 
					RUN mv mxe /opt/mxe
 | 
				
			||||||
 | 
					WORKDIR /opt/mxe
 | 
				
			||||||
 | 
					RUN make -j4 MXE_TARGETS="i686-w64-mingw32.static.posix" qtbase qtmultimedia
 | 
				
			||||||
 | 
					ENV PATH=/opt/mxe/usr/bin:$PATH
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WORKDIR /
 | 
				
			||||||
							
								
								
									
										19
									
								
								scripts/windows/how-to-push.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								scripts/windows/how-to-push.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					When you want to build a new version of Qt:
 | 
				
			||||||
 | 
					```docker
 | 
				
			||||||
 | 
					docker build -t mxe-windows-static . -f Dockerfile-mxe
 | 
				
			||||||
 | 
					docker tag mxe-windows-static oldmud0/mxe-qt:5.12.1-win32-static-posix
 | 
				
			||||||
 | 
					docker push oldmud0/mxe-qt:5.12.1-win32-static-posix
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Remember to log into Docker Hub before attempting to push.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When you want to build a new version of any dependency required for building AO:
 | 
				
			||||||
 | 
					```docker
 | 
				
			||||||
 | 
					docker build -t mxe-windows-static-ao . -f Dockerfile
 | 
				
			||||||
 | 
					docker tag mxe-windows-static-ao registry.gitlab.com/attorneyonline/ao2-client/builder-windows-i686
 | 
				
			||||||
 | 
					docker push registry.gitlab.com/attorneyonline/ao2-client/builder-windows-i686
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Remember to create an access token in GitLab before attempting to push.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GitLab CI depends on `builder-windows-i686` image to be present in the repository's registry in order for the Windows build to succeed. 
 | 
				
			||||||
@ -37,9 +37,9 @@ void AOApplication::construct_lobby()
 | 
				
			|||||||
  w_lobby = new Lobby(this);
 | 
					  w_lobby = new Lobby(this);
 | 
				
			||||||
  lobby_constructed = true;
 | 
					  lobby_constructed = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QRect screenGeometry = QApplication::desktop()->screenGeometry();
 | 
					  QRect geometry = QGuiApplication::primaryScreen()->geometry();
 | 
				
			||||||
  int x = (screenGeometry.width()-w_lobby->width()) / 2;
 | 
					  int x = (geometry.width()-w_lobby->width()) / 2;
 | 
				
			||||||
  int y = (screenGeometry.height()-w_lobby->height()) / 2;
 | 
					  int y = (geometry.height()-w_lobby->height()) / 2;
 | 
				
			||||||
  w_lobby->move(x, y);
 | 
					  w_lobby->move(x, y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (is_discord_enabled())
 | 
					  if (is_discord_enabled())
 | 
				
			||||||
@ -72,9 +72,9 @@ void AOApplication::construct_courtroom()
 | 
				
			|||||||
  w_courtroom = new Courtroom(this);
 | 
					  w_courtroom = new Courtroom(this);
 | 
				
			||||||
  courtroom_constructed = true;
 | 
					  courtroom_constructed = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QRect screenGeometry = QApplication::desktop()->screenGeometry();
 | 
					  QRect geometry = QGuiApplication::primaryScreen()->geometry();
 | 
				
			||||||
  int x = (screenGeometry.width()-w_courtroom->width()) / 2;
 | 
					  int x = (geometry.width()-w_courtroom->width()) / 2;
 | 
				
			||||||
  int y = (screenGeometry.height()-w_courtroom->height()) / 2;
 | 
					  int y = (geometry.height()-w_courtroom->height()) / 2;
 | 
				
			||||||
  w_courtroom->move(x, y);
 | 
					  w_courtroom->move(x, y);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -161,7 +161,7 @@ void AOApplication::ms_connect_finished(bool connected, bool will_retry)
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
      if (lobby_constructed)
 | 
					      if (lobby_constructed)
 | 
				
			||||||
        w_lobby->append_error("Error connecting to master server. Will try again in "
 | 
					        w_lobby->append_error("Error connecting to master server. Will try again in "
 | 
				
			||||||
                            + QString::number(net_manager->ms_reconnect_delay_ms / 1000.f) + " seconds.");
 | 
					                            + QString::number(net_manager->ms_reconnect_delay) + " seconds.");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
				
			|||||||
@ -86,6 +86,7 @@ void AOEvidenceButton::mouseDoubleClickEvent(QMouseEvent *e)
 | 
				
			|||||||
  evidence_double_clicked(m_id);
 | 
					  evidence_double_clicked(m_id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
void AOEvidenceButton::dragLeaveEvent(QMouseEvent *e)
 | 
					void AOEvidenceButton::dragLeaveEvent(QMouseEvent *e)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  //QWidget::dragLeaveEvent(e);
 | 
					  //QWidget::dragLeaveEvent(e);
 | 
				
			||||||
@ -99,6 +100,7 @@ void AOEvidenceButton::dragEnterEvent(QMouseEvent *e)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  qDebug() << "drag enter event";
 | 
					  qDebug() << "drag enter event";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AOEvidenceButton::enterEvent(QEvent * e)
 | 
					void AOEvidenceButton::enterEvent(QEvent * e)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,6 @@ void Courtroom::construct_char_select()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  set_size_and_pos(ui_char_buttons, "char_buttons");
 | 
					  set_size_and_pos(ui_char_buttons, "char_buttons");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  connect (char_button_mapper, SIGNAL(mapped(int)), this, SLOT(char_clicked(int)));
 | 
					 | 
				
			||||||
  connect(ui_back_to_lobby, SIGNAL(clicked()), this, SLOT(on_back_to_lobby_clicked()));
 | 
					  connect(ui_back_to_lobby, SIGNAL(clicked()), this, SLOT(on_back_to_lobby_clicked()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  connect(ui_char_select_left, SIGNAL(clicked()), this, SLOT(on_char_select_left_clicked()));
 | 
					  connect(ui_char_select_left, SIGNAL(clicked()), this, SLOT(on_char_select_left_clicked()));
 | 
				
			||||||
@ -52,9 +51,9 @@ void Courtroom::construct_char_select()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  connect(ui_spectator, SIGNAL(clicked()), this, SLOT(on_spectator_clicked()));
 | 
					  connect(ui_spectator, SIGNAL(clicked()), this, SLOT(on_spectator_clicked()));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  connect(ui_char_search, SIGNAL(textEdited(const QString&)), this, SLOT(on_char_search_changed(const QString&)));
 | 
					  connect(ui_char_search, SIGNAL(textEdited(const QString&)), this, SLOT(on_char_search_changed()));
 | 
				
			||||||
  connect(ui_char_passworded, SIGNAL(stateChanged(int)), this, SLOT(on_char_passworded_clicked(int)));
 | 
					  connect(ui_char_passworded, SIGNAL(stateChanged(int)), this, SLOT(on_char_passworded_clicked()));
 | 
				
			||||||
  connect(ui_char_taken, SIGNAL(stateChanged(int)), this, SLOT(on_char_taken_clicked(int)));
 | 
					  connect(ui_char_taken, SIGNAL(stateChanged(int)), this, SLOT(on_char_taken_clicked()));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::set_char_select()
 | 
					void Courtroom::set_char_select()
 | 
				
			||||||
@ -197,14 +196,15 @@ void Courtroom::character_loading_finished()
 | 
				
			|||||||
    // Later on, we'll be revealing buttons as we need them.
 | 
					    // Later on, we'll be revealing buttons as we need them.
 | 
				
			||||||
    for (int n = 0; n < char_list.size(); n++)
 | 
					    for (int n = 0; n < char_list.size(); n++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      AOCharButton* character = new AOCharButton(ui_char_buttons, ao_app, 0, 0, char_list.at(n).taken);
 | 
					      AOCharButton* char_button = new AOCharButton(ui_char_buttons, ao_app, 0, 0, char_list.at(n).taken);
 | 
				
			||||||
      character->reset();
 | 
					      char_button->reset();
 | 
				
			||||||
      character->hide();
 | 
					      char_button->hide();
 | 
				
			||||||
      character->set_image(char_list.at(n).name);
 | 
					      char_button->set_image(char_list.at(n).name);
 | 
				
			||||||
      ui_char_button_list.append(character);
 | 
					      ui_char_button_list.append(char_button);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      connect(character, SIGNAL(clicked()), char_button_mapper, SLOT(map()));
 | 
					      connect(char_button, &AOCharButton::clicked, [this, n](){
 | 
				
			||||||
      char_button_mapper->setMapping(character, ui_char_button_list.size() - 1);
 | 
					        this->char_clicked(n);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // This part here serves as a way of showing to the player that the game is still running, it is
 | 
					      // This part here serves as a way of showing to the player that the game is still running, it is
 | 
				
			||||||
      // just loading the pictures of the characters.
 | 
					      // just loading the pictures of the characters.
 | 
				
			||||||
@ -252,17 +252,17 @@ void Courtroom::filter_character_list()
 | 
				
			|||||||
    set_char_select_page();
 | 
					    set_char_select_page();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::on_char_search_changed(const QString& newtext)
 | 
					void Courtroom::on_char_search_changed()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    filter_character_list();
 | 
					    filter_character_list();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::on_char_passworded_clicked(int newstate)
 | 
					void Courtroom::on_char_passworded_clicked()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    filter_character_list();
 | 
					    filter_character_list();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::on_char_taken_clicked(int newstate)
 | 
					void Courtroom::on_char_taken_clicked()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    filter_character_list();
 | 
					    filter_character_list();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
 | 
				
			|||||||
  #ifdef BASSAUDIO
 | 
					  #ifdef BASSAUDIO
 | 
				
			||||||
  // Change the default audio output device to be the one the user has given
 | 
					  // Change the default audio output device to be the one the user has given
 | 
				
			||||||
  // in his config.ini file for now.
 | 
					  // in his config.ini file for now.
 | 
				
			||||||
  int a = 0;
 | 
					  unsigned int a = 0;
 | 
				
			||||||
  BASS_DEVICEINFO info;
 | 
					  BASS_DEVICEINFO info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (ao_app->get_audio_output_device() == "default")
 | 
					  if (ao_app->get_audio_output_device() == "default")
 | 
				
			||||||
@ -21,7 +21,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
 | 
				
			|||||||
          if (ao_app->get_audio_output_device() == info.name)
 | 
					          if (ao_app->get_audio_output_device() == info.name)
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
              BASS_SetDevice(a);
 | 
					              BASS_SetDevice(a);
 | 
				
			||||||
              BASS_Init(a, 48000, BASS_DEVICE_LATENCY, nullptr, nullptr);
 | 
					              BASS_Init(static_cast<int>(a), 48000, BASS_DEVICE_LATENCY, nullptr, nullptr);
 | 
				
			||||||
              load_bass_opus_plugin();
 | 
					              load_bass_opus_plugin();
 | 
				
			||||||
              qDebug() << info.name << "was set as the default audio output device.";
 | 
					              qDebug() << info.name << "was set as the default audio output device.";
 | 
				
			||||||
              break;
 | 
					              break;
 | 
				
			||||||
@ -50,8 +50,6 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
 | 
				
			|||||||
  testimony_hide_timer = new QTimer(this);
 | 
					  testimony_hide_timer = new QTimer(this);
 | 
				
			||||||
  testimony_hide_timer->setSingleShot(true);
 | 
					  testimony_hide_timer->setSingleShot(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  char_button_mapper = new QSignalMapper(this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  music_player = new AOMusicPlayer(this, ao_app);
 | 
					  music_player = new AOMusicPlayer(this, ao_app);
 | 
				
			||||||
  music_player->set_volume(0);
 | 
					  music_player->set_volume(0);
 | 
				
			||||||
  sfx_player = new AOSfxPlayer(this, ao_app);
 | 
					  sfx_player = new AOSfxPlayer(this, ao_app);
 | 
				
			||||||
@ -2025,6 +2023,7 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
  //do not perform heavy operations here
 | 
					  //do not perform heavy operations here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QString f_message = m_chatmessage[MESSAGE];
 | 
					  QString f_message = m_chatmessage[MESSAGE];
 | 
				
			||||||
 | 
					  f_message.remove(0, tick_pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Due to our new text speed system, we always need to stop the timer now.
 | 
					  // Due to our new text speed system, we always need to stop the timer now.
 | 
				
			||||||
  chat_tick_timer->stop();
 | 
					  chat_tick_timer->stop();
 | 
				
			||||||
@ -2039,7 +2038,7 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
    f_message.remove(0,2);
 | 
					    f_message.remove(0,2);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (tick_pos >= f_message.size())
 | 
					  if (f_message.size() == 0)
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    text_state = 2;
 | 
					    text_state = 2;
 | 
				
			||||||
    if (anim_state != 4)
 | 
					    if (anim_state != 4)
 | 
				
			||||||
@ -2051,9 +2050,21 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    QString f_character = f_message.at(tick_pos);
 | 
					    QTextBoundaryFinder tbf(QTextBoundaryFinder::Grapheme, f_message);
 | 
				
			||||||
 | 
					    QString f_character;
 | 
				
			||||||
 | 
					    int f_char_length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tbf.toNextBoundary();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (tbf.position() == -1)
 | 
				
			||||||
 | 
					      f_character = f_message;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      f_character = f_message.left(tbf.position());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    f_char_length = f_character.length();
 | 
				
			||||||
    f_character = f_character.toHtmlEscaped();
 | 
					    f_character = f_character.toHtmlEscaped();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (f_character == " ")
 | 
					    if (f_character == " ")
 | 
				
			||||||
      ui_vp_message->insertPlainText(" ");
 | 
					      ui_vp_message->insertPlainText(" ");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2146,7 +2157,7 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            next_character_is_not_special = true;
 | 
					            next_character_is_not_special = true;
 | 
				
			||||||
            tick_pos--;
 | 
					            tick_pos -= f_char_length;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2167,7 +2178,7 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
        else
 | 
					        else
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            next_character_is_not_special = true;
 | 
					            next_character_is_not_special = true;
 | 
				
			||||||
            tick_pos--;
 | 
					            tick_pos -= f_char_length;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2211,11 +2222,7 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
          case INLINE_GREY:
 | 
					          case INLINE_GREY:
 | 
				
			||||||
              ui_vp_message->insertHtml("<font color=\""+ get_text_color("_inline_grey").name() +"\">" + f_character + "</font>");
 | 
					              ui_vp_message->insertHtml("<font color=\""+ get_text_color("_inline_grey").name() +"\">" + f_character + "</font>");
 | 
				
			||||||
              break;
 | 
					              break;
 | 
				
			||||||
          default:
 | 
					 | 
				
			||||||
              ui_vp_message->insertHtml(f_character);
 | 
					 | 
				
			||||||
              break;
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
@ -2266,7 +2273,7 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
    if(blank_blip)
 | 
					    if(blank_blip)
 | 
				
			||||||
      qDebug() << "blank_blip found true";
 | 
					      qDebug() << "blank_blip found true";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (f_message.at(tick_pos) != ' ' || blank_blip)
 | 
					    if (f_character != ' ' || blank_blip)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (blip_pos % blip_rate == 0 && !formatting_char)
 | 
					      if (blip_pos % blip_rate == 0 && !formatting_char)
 | 
				
			||||||
@ -2278,7 +2285,7 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
      ++blip_pos;
 | 
					      ++blip_pos;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ++tick_pos;
 | 
					    tick_pos += f_char_length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Restart the timer, but according to the newly set speeds, if there were any.
 | 
					    // Restart the timer, but according to the newly set speeds, if there were any.
 | 
				
			||||||
    // Keep the speed at bay.
 | 
					    // Keep the speed at bay.
 | 
				
			||||||
@ -2305,6 +2312,7 @@ void Courtroom::chat_tick()
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::show_testimony()
 | 
					void Courtroom::show_testimony()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  if (!testimony_in_progress || m_chatmessage[SIDE] != "wit")
 | 
					  if (!testimony_in_progress || m_chatmessage[SIDE] != "wit")
 | 
				
			||||||
@ -2697,6 +2705,7 @@ void Courtroom::on_ooc_return_pressed()
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      else
 | 
					      else
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
 | 
					        other_charid = -1;
 | 
				
			||||||
        append_server_chatmessage("CLIENT", "You are no longer paired with anyone.", "1");
 | 
					        append_server_chatmessage("CLIENT", "You are no longer paired with anyone.", "1");
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -2853,6 +2862,60 @@ void Courtroom::on_ooc_return_pressed()
 | 
				
			|||||||
    ui_ooc_chat_message->clear();
 | 
					    ui_ooc_chat_message->clear();
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  else if(ooc_message.startsWith("/save_case"))
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					      QStringList command = ooc_message.split(" ", QString::SkipEmptyParts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      QDir casefolder("base/cases");
 | 
				
			||||||
 | 
					      if (!casefolder.exists())
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					          QDir::current().mkdir("base/" + casefolder.dirName());
 | 
				
			||||||
 | 
					          append_server_chatmessage("CLIENT", "You don't have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it's likely that you somehow deleted it.", "1");
 | 
				
			||||||
 | 
					          ui_ooc_chat_message->clear();
 | 
				
			||||||
 | 
					          return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      QStringList caseslist = casefolder.entryList();
 | 
				
			||||||
 | 
					      caseslist.removeOne(".");
 | 
				
			||||||
 | 
					      caseslist.removeOne("..");
 | 
				
			||||||
 | 
					      caseslist.replaceInStrings(".ini","");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (command.size() < 3)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        append_server_chatmessage("CLIENT", "You need to give a filename to save (extension not needed) and the courtroom status!", "1");
 | 
				
			||||||
 | 
					        ui_ooc_chat_message->clear();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (command.size() > 3)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        append_server_chatmessage("CLIENT", "Too many arguments to save a case! You only need a filename without extension and the courtroom status!", "1");
 | 
				
			||||||
 | 
					        ui_ooc_chat_message->clear();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      QSettings casefile("base/cases/" + command[1] + ".ini", QSettings::IniFormat);
 | 
				
			||||||
 | 
					      casefile.setValue("author",ui_ooc_chat_name->text());
 | 
				
			||||||
 | 
					      casefile.setValue("cmdoc","");
 | 
				
			||||||
 | 
					      casefile.setValue("doc", "");
 | 
				
			||||||
 | 
					      casefile.setValue("status",command[2]);
 | 
				
			||||||
 | 
					      casefile.sync();
 | 
				
			||||||
 | 
					      for(int i = local_evidence_list.size() - 1; i >= 0; i--)
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					           QString clean_evidence_dsc =  local_evidence_list[i].description.replace(QRegularExpression("<owner = ...>..."), "");
 | 
				
			||||||
 | 
					           clean_evidence_dsc = clean_evidence_dsc.replace(clean_evidence_dsc.lastIndexOf(">"), 1, "");
 | 
				
			||||||
 | 
					           casefile.beginGroup(QString::number(i));
 | 
				
			||||||
 | 
					           casefile.sync();
 | 
				
			||||||
 | 
					           casefile.setValue("name",local_evidence_list[i].name);
 | 
				
			||||||
 | 
					           casefile.setValue("description",local_evidence_list[i].description);
 | 
				
			||||||
 | 
					           casefile.setValue("image",local_evidence_list[i].image);
 | 
				
			||||||
 | 
					           casefile.endGroup();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      casefile.sync();
 | 
				
			||||||
 | 
					      append_server_chatmessage("CLIENT", "Succesfully saved, edit doc and cmdoc link on the ini!", "1");
 | 
				
			||||||
 | 
					      ui_ooc_chat_message->clear();
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QStringList packet_contents;
 | 
					  QStringList packet_contents;
 | 
				
			||||||
  packet_contents.append(ui_ooc_chat_name->text());
 | 
					  packet_contents.append(ui_ooc_chat_name->text());
 | 
				
			||||||
@ -2982,6 +3045,7 @@ void Courtroom::on_pair_list_clicked(QModelIndex p_index)
 | 
				
			|||||||
  QListWidgetItem *f_item = ui_pair_list->item(p_index.row());
 | 
					  QListWidgetItem *f_item = ui_pair_list->item(p_index.row());
 | 
				
			||||||
  QString f_char = f_item->text();
 | 
					  QString f_char = f_item->text();
 | 
				
			||||||
  QString real_char;
 | 
					  QString real_char;
 | 
				
			||||||
 | 
					  int f_cid = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (f_char.endsWith(" [x]"))
 | 
					  if (f_char.endsWith(" [x]"))
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@ -2989,17 +3053,19 @@ void Courtroom::on_pair_list_clicked(QModelIndex p_index)
 | 
				
			|||||||
    f_item->setText(real_char);
 | 
					    f_item->setText(real_char);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
   real_char = f_char;
 | 
					   real_char = f_char;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  int f_cid = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
   for (int n_char = 0 ; n_char < char_list.size() ; n_char++)
 | 
					   for (int n_char = 0 ; n_char < char_list.size() ; n_char++)
 | 
				
			||||||
   {
 | 
					   {
 | 
				
			||||||
    if (char_list.at(n_char).name == real_char)
 | 
					    if (char_list.at(n_char).name == real_char)
 | 
				
			||||||
      f_cid = n_char;
 | 
					      f_cid = n_char;
 | 
				
			||||||
   }
 | 
					   }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (f_cid < 0 || f_cid >= char_list.size())
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (f_cid < -2 || f_cid >= char_list.size())
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    qDebug() << "W: " << real_char << " not present in char_list";
 | 
					    qDebug() << "W: " << real_char << " not present in char_list";
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
@ -3018,8 +3084,10 @@ void Courtroom::on_pair_list_clicked(QModelIndex p_index)
 | 
				
			|||||||
  for (int i = 0; i < ui_pair_list->count(); i++) {
 | 
					  for (int i = 0; i < ui_pair_list->count(); i++) {
 | 
				
			||||||
    ui_pair_list->item(i)->setText(sorted_pair_list.at(i));
 | 
					    ui_pair_list->item(i)->setText(sorted_pair_list.at(i));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  if(other_charid != -1)
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
   f_item->setText(real_char + " [x]");
 | 
					   f_item->setText(real_char + " [x]");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Courtroom::on_music_list_double_clicked(QModelIndex p_model)
 | 
					void Courtroom::on_music_list_double_clicked(QModelIndex p_model)
 | 
				
			||||||
 | 
				
			|||||||
@ -12,10 +12,10 @@ Discord::Discord()
 | 
				
			|||||||
    qInfo() << "Discord RPC ready";
 | 
					    qInfo() << "Discord RPC ready";
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  handlers.disconnected = [](int errorCode, const char* message) {
 | 
					  handlers.disconnected = [](int errorCode, const char* message) {
 | 
				
			||||||
    qInfo() << "Discord RPC disconnected! " << message;
 | 
					    qInfo() << "Discord RPC disconnected! " << message << errorCode;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  handlers.errored = [](int errorCode, const char* message) {
 | 
					  handlers.errored = [](int errorCode, const char* message) {
 | 
				
			||||||
    qWarning() << "Discord RPC errored out! " << message;
 | 
					    qWarning() << "Discord RPC errored out! " << message << errorCode;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  qInfo() << "Initializing Discord RPC";
 | 
					  qInfo() << "Initializing Discord RPC";
 | 
				
			||||||
  Discord_Initialize(APPLICATION_ID, &handlers, 1, nullptr);
 | 
					  Discord_Initialize(APPLICATION_ID, &handlers, 1, nullptr);
 | 
				
			||||||
 | 
				
			|||||||
@ -188,11 +188,12 @@ void Courtroom::on_evidence_image_name_edited()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void Courtroom::on_evidence_image_button_clicked()
 | 
					void Courtroom::on_evidence_image_button_clicked()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  QDir dir(ao_app->get_base_path() + "evidence");
 | 
				
			||||||
  QFileDialog dialog(this);
 | 
					  QFileDialog dialog(this);
 | 
				
			||||||
  dialog.setFileMode(QFileDialog::ExistingFile);
 | 
					  dialog.setFileMode(QFileDialog::ExistingFile);
 | 
				
			||||||
  dialog.setNameFilter(tr("Images (*.png)"));
 | 
					  dialog.setNameFilter(tr("Images (*.png)"));
 | 
				
			||||||
  dialog.setViewMode(QFileDialog::List);
 | 
					  dialog.setViewMode(QFileDialog::List);
 | 
				
			||||||
  dialog.setDirectory(ao_app->get_base_path() + "evidence");
 | 
					  dialog.setDirectory(dir);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QStringList filenames;
 | 
					  QStringList filenames;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -203,13 +204,8 @@ void Courtroom::on_evidence_image_button_clicked()
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QString filename = filenames.at(0);
 | 
					  QString filename = filenames.at(0);
 | 
				
			||||||
 | 
					  filename = dir.relativeFilePath(filename);
 | 
				
			||||||
  QStringList split_filename = filename.split("/");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  filename = split_filename.at(split_filename.size() - 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  ui_evidence_image_name->setText(filename);
 | 
					  ui_evidence_image_name->setText(filename);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  on_evidence_image_name_edited();
 | 
					  on_evidence_image_name_edited();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -5,12 +5,12 @@
 | 
				
			|||||||
#if (defined (_WIN32) || defined (_WIN64))
 | 
					#if (defined (_WIN32) || defined (_WIN64))
 | 
				
			||||||
#include <windows.h>
 | 
					#include <windows.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DWORD dwVolSerial;
 | 
					static DWORD dwVolSerial;
 | 
				
			||||||
BOOL bIsRetrieved;
 | 
					static BOOL bIsRetrieved;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QString get_hdid()
 | 
					QString get_hdid()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  bIsRetrieved = GetVolumeInformation(TEXT("C:\\"), NULL, NULL, &dwVolSerial, NULL, NULL, NULL, NULL);
 | 
					  bIsRetrieved = GetVolumeInformation(TEXT("C:\\"), nullptr, 0, &dwVolSerial, nullptr, nullptr, nullptr, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (bIsRetrieved)
 | 
					  if (bIsRetrieved)
 | 
				
			||||||
    return QString::number(dwVolSerial, 16);
 | 
					    return QString::number(dwVolSerial, 16);
 | 
				
			||||||
@ -18,7 +18,6 @@ QString get_hdid()
 | 
				
			|||||||
    //a totally random string
 | 
					    //a totally random string
 | 
				
			||||||
    //what could possibly go wrong
 | 
					    //what could possibly go wrong
 | 
				
			||||||
    return "gxsps32sa9fnwic92mfbs0";
 | 
					    return "gxsps32sa9fnwic92mfbs0";
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#elif (defined (LINUX) || defined (__linux__))
 | 
					#elif (defined (LINUX) || defined (__linux__))
 | 
				
			||||||
 | 
				
			|||||||
@ -78,9 +78,9 @@ void NetworkManager::ship_server_packet(QString p_packet)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void NetworkManager::handle_ms_packet()
 | 
					void NetworkManager::handle_ms_packet()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  char buffer[buffer_max_size];
 | 
					  char buffer[BUFFER_MAX_SIZE];
 | 
				
			||||||
  std::memset(buffer, 0, buffer_max_size);
 | 
					  std::memset(buffer, 0, BUFFER_MAX_SIZE);
 | 
				
			||||||
  ms_socket->read(buffer, buffer_max_size);
 | 
					  ms_socket->read(buffer, BUFFER_MAX_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QString in_data = buffer;
 | 
					  QString in_data = buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -137,7 +137,9 @@ void NetworkManager::on_srv_lookup()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (const QDnsServiceRecord &record : srv_records)
 | 
					    for (const QDnsServiceRecord &record : srv_records)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					#ifdef DEBUG_NETWORK
 | 
				
			||||||
      qDebug() << "Connecting to " << record.target() << ":" << record.port();
 | 
					      qDebug() << "Connecting to " << record.target() << ":" << record.port();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
      ms_socket->connectToHost(record.target(), record.port());
 | 
					      ms_socket->connectToHost(record.target(), record.port());
 | 
				
			||||||
      QTime timer;
 | 
					      QTime timer;
 | 
				
			||||||
      timer.start();
 | 
					      timer.start();
 | 
				
			||||||
@ -206,7 +208,7 @@ void NetworkManager::on_ms_socket_error(QAbstractSocket::SocketError error)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  emit ms_connect_finished(false, true);
 | 
					  emit ms_connect_finished(false, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ms_reconnect_timer->start(ms_reconnect_delay_ms);
 | 
					  ms_reconnect_timer->start(ms_reconnect_delay * 1000);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void NetworkManager::retry_ms_connect()
 | 
					void NetworkManager::retry_ms_connect()
 | 
				
			||||||
@ -217,9 +219,9 @@ void NetworkManager::retry_ms_connect()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void NetworkManager::handle_server_packet()
 | 
					void NetworkManager::handle_server_packet()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  char buffer[buffer_max_size];
 | 
					  char buffer[BUFFER_MAX_SIZE];
 | 
				
			||||||
  std::memset(buffer, 0, buffer_max_size);
 | 
					  std::memset(buffer, 0, BUFFER_MAX_SIZE);
 | 
				
			||||||
  server_socket->read(buffer, buffer_max_size);
 | 
					  server_socket->read(buffer, BUFFER_MAX_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  QString in_data = buffer;
 | 
					  QString in_data = buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -14,8 +14,10 @@ void AOApplication::ms_packet_received(AOPacket *p_packet)
 | 
				
			|||||||
  QString header = p_packet->get_header();
 | 
					  QString header = p_packet->get_header();
 | 
				
			||||||
  QStringList f_contents = p_packet->get_contents();
 | 
					  QStringList f_contents = p_packet->get_contents();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DEBUG_NETWORK
 | 
				
			||||||
  if (header != "CHECK")
 | 
					  if (header != "CHECK")
 | 
				
			||||||
    qDebug() << "R(ms):" << p_packet->to_string();
 | 
					    qDebug() << "R(ms):" << p_packet->to_string();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (header == "ALL")
 | 
					  if (header == "ALL")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@ -127,8 +129,10 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
 | 
				
			|||||||
  QStringList f_contents = p_packet->get_contents();
 | 
					  QStringList f_contents = p_packet->get_contents();
 | 
				
			||||||
  QString f_packet = p_packet->to_string();
 | 
					  QString f_packet = p_packet->to_string();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DEBUG_NETWORK
 | 
				
			||||||
  if (header != "checkconnection")
 | 
					  if (header != "checkconnection")
 | 
				
			||||||
    qDebug() << "R:" << f_packet;
 | 
					    qDebug() << "R:" << f_packet;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (header == "decryptor")
 | 
					  if (header == "decryptor")
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@ -677,7 +681,9 @@ void AOApplication::send_ms_packet(AOPacket *p_packet)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  net_manager->ship_ms_packet(f_packet);
 | 
					  net_manager->ship_ms_packet(f_packet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DEBUG_NETWORK
 | 
				
			||||||
  qDebug() << "S(ms):" << f_packet;
 | 
					  qDebug() << "S(ms):" << f_packet;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  delete p_packet;
 | 
					  delete p_packet;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -691,14 +697,18 @@ void AOApplication::send_server_packet(AOPacket *p_packet, bool encoded)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (encryption_needed)
 | 
					  if (encryption_needed)
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
 | 
					#ifdef DEBUG_NETWORK
 | 
				
			||||||
    qDebug() << "S(e):" << f_packet;
 | 
					    qDebug() << "S(e):" << f_packet;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    p_packet->encrypt_header(s_decryptor);
 | 
					    p_packet->encrypt_header(s_decryptor);
 | 
				
			||||||
    f_packet = p_packet->to_string();
 | 
					    f_packet = p_packet->to_string();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
 | 
					#ifdef DEBUG_NETWORK
 | 
				
			||||||
    qDebug() << "S:" << f_packet;
 | 
					    qDebug() << "S:" << f_packet;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  net_manager->ship_server_packet(f_packet);
 | 
					  net_manager->ship_server_packet(f_packet);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user