diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..fef9ac6 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,18 @@ +cmake_minimum_required(VERSION 3.1) + +project(Observer) + +# Specify output directories. +set(EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin") + +# Build with c++14 support, required by sc2api. +set(CMAKE_CXX_STANDARD 14) + +# Disable building of examples in the cpp-sc2 submodule. +set(BUILD_API_EXAMPLES OFF CACHE INTERNAL "" FORCE) + +# Disable building of tests in the cpp-sc2 submodule. +set(BUILD_API_TESTS OFF CACHE INTERNAL "" FORCE) + +add_subdirectory("cpp-sc2") +add_subdirectory("src") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..c93bad9 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,41 @@ +add_executable(Observer) + +target_sources(Observer + PRIVATE + CameraModule.h + CameraModule.cpp + Observer.cpp + Timer.hpp + Tools.h + $<$:ToolsWindows.cpp> + $<$:ToolsUnix.cpp> +) + +include_directories(SYSTEM + ${PROJECT_SOURCE_DIR}/cpp-sc2/include + ${PROJECT_SOURCE_DIR}/cpp-sc2/contrib/protobuf/src + ${PROJECT_BINARY_DIR}/cpp-sc2/generated + "." +) + +if (MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /WX-") +elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything \ + -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-padded \ + -Wno-switch-enum -Wno-weak-vtables -Wno-exit-time-destructors \ + -Wno-float-equal -Wno-global-constructors" + ) +endif () + +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") + +link_directories(${PROJECT_BINARY_DIR}/cpp-sc2/bin) + +target_link_libraries(Observer + sc2api sc2utils +) + +if (APPLE) + target_link_libraries(Observer "-framework Carbon") +endif () diff --git a/src/CameraModule.cpp b/src/CameraModule.cpp index 6ac0b43..40dcde3 100644 --- a/src/CameraModule.cpp +++ b/src/CameraModule.cpp @@ -1,6 +1,7 @@ #include "CameraModule.h" #include #include "sc2api/sc2_api.h" +#include "sc2api/sc2_unit_filters.h" #include "sc2api/sc2_proto_interface.h" // Radius to detect groups of army units diff --git a/src/Observer.cpp b/src/Observer.cpp index a9735a3..b040980 100644 --- a/src/Observer.cpp +++ b/src/Observer.cpp @@ -1,108 +1,15 @@ +#include "CameraModule.h" +#include "Timer.hpp" +#include "Tools.h" + #include "sc2api/sc2_api.h" +#include "sc2api/sc2_gametypes.h" #include "sc2utils/sc2_manage_process.h" #include "sc2utils/sc2_arg_parser.h" #include -#include #include -#include "CameraModule.h" -#include "Timer.hpp" -#include "sc2api/sc2_gametypes.h" - -bool loadReplayPaths(std::string & name, std::vector & v) -{ - if (name.find("2Replay") != std::string::npos) - { - v.push_back(name); - return false; - } - - std::string pattern(name); - pattern.append("\\*"); - WIN32_FIND_DATAA data; - HANDLE hFind; - if ((hFind = FindFirstFileA(pattern.c_str(), &data)) != INVALID_HANDLE_VALUE) - { - do - { - if (data.dwFileAttributes != 16lu) - { - const std::string fileName = name + "/" + data.cFileName; - if (std::find(v.begin(), v.end(), fileName) == v.end()) - { - v.push_back(fileName); - } - } - } - while (FindNextFileA(hFind, &data) != 0); - FindClose(hFind); - } - return true; -} - -void pressDKey() -{ - auto hwnd = FindWindow(NULL, TEXT("StarCraft II")); - if (hwnd != 0) - { - SetForegroundWindow(hwnd); - SetFocus(hwnd); - SetActiveWindow(hwnd); - INPUT ip; - ip.type = INPUT_KEYBOARD; - ip.ki.wScan = 0; // hardware scan code for key - ip.ki.time = 0; - ip.ki.dwExtraInfo = 0; - - // Press the "D" key - ip.ki.wVk = 0x44; // virtual-key code for the "D" key - ip.ki.dwFlags = 0; // 0 for key press - SendInput(1, &ip, sizeof(INPUT)); - - // Release the "D" key. - ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release - SendInput(1, &ip, sizeof(INPUT)); - } -} - -void pressAltEnter() -{ - auto hwnd = FindWindow(NULL, TEXT("StarCraft II")); - if (hwnd != 0) - { - SetForegroundWindow(hwnd); - SetFocus(hwnd); - SetActiveWindow(hwnd); - INPUT ip; - ip.type = INPUT_KEYBOARD; - ip.ki.wScan = 0; // hardware scan code for key - ip.ki.time = 0; - ip.ki.dwExtraInfo = 0; - - // Press keys - ip.ki.dwFlags = 0; // 0 for key press - - // Press the "alt" key - ip.ki.wVk = 0x12; // virtual-key code for the "alt" key - SendInput(1, &ip, sizeof(INPUT)); - - // Press the "enter" key - ip.ki.wVk = 0x0D; // virtual-key code for the "alt" key - SendInput(1, &ip, sizeof(INPUT)); - - // Release keys - ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release - - // Release the "alt" key - ip.ki.wVk = 0x12; - SendInput(1, &ip, sizeof(INPUT)); - - // Release the "enter" key - ip.ki.wVk = 0x0D; - SendInput(1, &ip, sizeof(INPUT)); - } -} class Replay : public sc2::ReplayObserver { @@ -238,7 +145,7 @@ int main(int argc, char* argv[]) { std::cout << "If you provide a directory please do not end the path with an '\'" << std::endl; } - Sleep(30000); + sc2::SleepFor(30000); continue; } const std::string replayFile = replayFiles[replayIndex]; @@ -254,22 +161,7 @@ int main(int argc, char* argv[]) std::cout << "Please provide the replay path as command line argument." << std::endl; return 1; } - if (!FindWindow(NULL, TEXT("StarCraft II"))) - { - // Update once so that the game launches - coordinator.Update(); - // Wait for launch and then Full screen mode - int counter = 0; - while (!FindWindow(NULL, TEXT("StarCraft II")) && counter < 10) - { - ++counter; - sc2::SleepFor(500); - } - //if (counter < 10) - //{ - // pressAltEnter(); - //} - } + // FIXME(alkurbatov): Launch in fullscreen mode! while (coordinator.Update() && !coordinator.AllGamesEnded()) { } diff --git a/src/Timer.hpp b/src/Timer.hpp index 9b7da82..8777633 100644 --- a/src/Timer.hpp +++ b/src/Timer.hpp @@ -4,18 +4,20 @@ #include #include -#ifdef WIN32 // Windows system specific +#ifdef _WIN32 // Windows system specific #include #else // Unix based system specific #include #endif +#include + class Timer { double startTimeInMicroSec; // starting time in micro-second double endTimeInMicroSec; // ending time in micro-second int stopped; // stop flag -#ifdef WIN32 +#ifdef _WIN32 LARGE_INTEGER frequency; // ticks per second LARGE_INTEGER startCount; // LARGE_INTEGER endCount; // @@ -28,7 +30,7 @@ class Timer Timer() { -#ifdef WIN32 +#ifdef _WIN32 QueryPerformanceFrequency(&frequency); startCount.QuadPart = 0; endCount.QuadPart = 0; @@ -50,7 +52,7 @@ class Timer { stopped = 0; // reset stop flag -#ifdef WIN32 +#ifdef _WIN32 QueryPerformanceCounter(&startCount); #else gettimeofday(&startCount, NULL); @@ -61,7 +63,7 @@ class Timer { stopped = 1; // set timer stopped flag -#ifdef WIN32 +#ifdef _WIN32 QueryPerformanceCounter(&endCount); #else gettimeofday(&endCount, NULL); @@ -70,7 +72,7 @@ class Timer double getElapsedTimeInMicroSec() { -#ifdef WIN32 +#ifdef _WIN32 if (!stopped) QueryPerformanceCounter(&endCount); diff --git a/src/Tools.h b/src/Tools.h new file mode 100644 index 0000000..ced2a57 --- /dev/null +++ b/src/Tools.h @@ -0,0 +1,9 @@ +#pragma once + +#include +#include + + +bool loadReplayPaths(std::string & name, std::vector & v); + +void pressDKey(); diff --git a/src/ToolsUnix.cpp b/src/ToolsUnix.cpp new file mode 100644 index 0000000..6e71335 --- /dev/null +++ b/src/ToolsUnix.cpp @@ -0,0 +1,11 @@ +#include "Tools.h" + + +bool loadReplayPaths(std::string &, std::vector &) +{ + return true; +} + +void pressDKey() +{ +} diff --git a/src/ToolsWindows.cpp b/src/ToolsWindows.cpp new file mode 100644 index 0000000..43e611d --- /dev/null +++ b/src/ToolsWindows.cpp @@ -0,0 +1,60 @@ +#include "Tools.h" + +#include + + +bool loadReplayPaths(std::string & name, std::vector & v) +{ + if (name.find("2Replay") != std::string::npos) + { + v.push_back(name); + return false; + } + + std::string pattern(name); + pattern.append("\\*"); + WIN32_FIND_DATAA data; + HANDLE hFind; + if ((hFind = FindFirstFileA(pattern.c_str(), &data)) != INVALID_HANDLE_VALUE) + { + do + { + if (data.dwFileAttributes != 16lu) + { + const std::string fileName = name + "/" + data.cFileName; + if (std::find(v.begin(), v.end(), fileName) == v.end()) + { + v.push_back(fileName); + } + } + } + while (FindNextFileA(hFind, &data) != 0); + FindClose(hFind); + } + return true; +} + +void pressDKey() +{ + auto hwnd = FindWindow(NULL, TEXT("StarCraft II")); + if (hwnd != 0) + { + SetForegroundWindow(hwnd); + SetFocus(hwnd); + SetActiveWindow(hwnd); + INPUT ip; + ip.type = INPUT_KEYBOARD; + ip.ki.wScan = 0; // hardware scan code for key + ip.ki.time = 0; + ip.ki.dwExtraInfo = 0; + + // Press the "D" key + ip.ki.wVk = 0x44; // virtual-key code for the "D" key + ip.ki.dwFlags = 0; // 0 for key press + SendInput(1, &ip, sizeof(INPUT)); + + // Release the "D" key. + ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release + SendInput(1, &ip, sizeof(INPUT)); + } +}