diff --git a/.gitignore b/.gitignore index 4dcb6d4..edd86c0 100644 --- a/.gitignore +++ b/.gitignore @@ -333,3 +333,4 @@ ASALocalRun/ # Local History for Visual Studio .localhistory/ src/Branch.h +src/Version.h diff --git a/src/GUI/GUI.cpp b/src/GUI/GUI.cpp index 019d599..4a9778a 100644 --- a/src/GUI/GUI.cpp +++ b/src/GUI/GUI.cpp @@ -190,29 +190,6 @@ namespace GUI ImGui::NewFrame(); /* new frame end */ -//#define WATERMARK -#ifdef WATERMARK - ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f)); - ImGui::SetNextWindowPos(ImVec2(16.0f, Renderer::Height != 0 ? Renderer::Height - ImGui::GetTextLineHeight() - 16.0f : 0)); - if (ImGui::Begin("NEXUS_BUILDINFO", (bool*)0, WindowFlags_Watermark)) - { - ImGui::SetCursorPos(ImVec2(0, 0)); - ImGui::TextOutlined("Limited Test"); - ImGui::SameLine(); - ImGui::TextOutlined(__DATE__ " " __TIME__); - ImGui::SameLine(); - ImGui::TextOutlined(("(v" + Version->ToString() + ")").c_str()); - ImGui::SameLine(); -#ifdef _DEBUG - ImGui::TextOutlined("debug/" BRANCH_NAME); -#else - ImGui::TextOutlined("release/" BRANCH_NAME); -#endif - }; - ImGui::End(); - ImGui::PopStyleVar(); -#endif - /* draw overlay */ if (IsUIVisible) { diff --git a/src/GUI/Widgets/About/AboutBox.cpp b/src/GUI/Widgets/About/AboutBox.cpp index 5660f56..ae03760 100644 --- a/src/GUI/Widgets/About/AboutBox.cpp +++ b/src/GUI/Widgets/About/AboutBox.cpp @@ -11,7 +11,9 @@ namespace GUI ImGui::TextDisabled("Version:"); ImGui::Text(""); ImGui::SameLine(); ImGui::Text(Version->ToString().c_str()); #ifdef _DEBUG - ImGui::SameLine(); ImGui::TextDisabled("[DEBUG BUILD]"); + ImGui::SameLine(); ImGui::TextDisabled("debug/" BRANCH_NAME); +#else + ImGui::SameLine(); ImGui::TextDisabled("release/" BRANCH_NAME); #endif ImGui::TextDisabled("Location:"); ImGui::Text(""); ImGui::SameLine(); ImGui::Text(Path::F_HOST_DLL); @@ -19,7 +21,7 @@ namespace GUI { for (std::string param : Parameters) { - ImGui::TextDisabled(("-" + param).c_str()); + ImGui::TextDisabled(param.c_str()); } ImGui::EndTooltip(); diff --git a/src/GUI/Widgets/About/AboutBox.h b/src/GUI/Widgets/About/AboutBox.h index 3a19b52..004f49a 100644 --- a/src/GUI/Widgets/About/AboutBox.h +++ b/src/GUI/Widgets/About/AboutBox.h @@ -4,6 +4,7 @@ #include "../../../Shared.h" #include "../../../Paths.h" #include "../../../State.h" +#include "../../../Branch.h" #include "../../../imgui/imgui.h" #include "../../../imgui/imgui_extensions.h" diff --git a/src/Loader/AddonDefinition.cpp b/src/Loader/AddonDefinition.cpp index 1d26caf..0c992ef 100644 --- a/src/Loader/AddonDefinition.cpp +++ b/src/Loader/AddonDefinition.cpp @@ -14,7 +14,15 @@ bool operator>(AddonVersion lhs, AddonVersion rhs) } bool operator<(AddonVersion lhs, AddonVersion rhs) { - return !(lhs > rhs); + if ((lhs.Major < rhs.Major) || + (lhs.Major == rhs.Major && lhs.Minor < rhs.Minor) || + (lhs.Major == rhs.Major && lhs.Minor == rhs.Minor && lhs.Build < rhs.Build) || + (lhs.Major == rhs.Major && lhs.Minor == rhs.Minor && lhs.Build == rhs.Build && lhs.Revision < rhs.Revision)) + { + return true; + } + + return false; } bool AddonDefinition::HasMinimumRequirements() diff --git a/src/Loader/Loader.cpp b/src/Loader/Loader.cpp index 42b39c8..e35a191 100644 --- a/src/Loader/Loader.cpp +++ b/src/Loader/Loader.cpp @@ -124,6 +124,15 @@ namespace Loader /* why has god forsaken me */ AddonDefinition* tmpDefs = getAddonDef(); + + if (tmpDefs == nullptr) + { + LogDebug(CH_LOADER, "\"%s\" is Nexus-compatible but returned a nullptr. Incompatible I guess?", path); + addon->State = EAddonState::Incompatible; + FreeLibrary(hMod); + return; + } + AddonDefinition* defs = new AddonDefinition(); memcpy(defs, tmpDefs, sizeof(AddonDefinition)); defs->Name = new char[strlen(tmpDefs->Name) + 1]; diff --git a/src/Nexus.rc b/src/Nexus.rc index be7b901..ba8aae0 100644 --- a/src/Nexus.rc +++ b/src/Nexus.rc @@ -1,6 +1,9 @@ // Microsoft Visual C++ generated resource script. // +#include "Version.h" #include "resource.h" +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// @@ -51,8 +54,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,1 - PRODUCTVERSION 1,0,0,1 + FILEVERSION V_MAJOR,V_MINOR,V_BUILD,V_REVISION + PRODUCTVERSION V_MAJOR,V_MINOR,V_BUILD,V_REVISION FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -69,11 +72,11 @@ BEGIN BEGIN VALUE "CompanyName", "Raidcore" VALUE "FileDescription", "Unofficial Guild Wars 2 Addon Host" - VALUE "FileVersion", "1.0.0.1" + VALUE "FileVersion", TOSTRING(V_MAJOR) "." TOSTRING(V_MINOR) "." TOSTRING(V_BUILD) "." TOSTRING(V_REVISION) VALUE "InternalName", "nexus.dll" VALUE "LegalCopyright", "© 2023 Raidcore" VALUE "ProductName", "Nexus" - VALUE "ProductVersion", "1.0.0.1" + VALUE "ProductVersion", TOSTRING(V_MAJOR) "." TOSTRING(V_MINOR) "." TOSTRING(V_BUILD) "." TOSTRING(V_REVISION) END END BLOCK "VarFileInfo" diff --git a/src/Nexus.vcxproj b/src/Nexus.vcxproj index 2e56c5e..6b070c3 100644 --- a/src/Nexus.vcxproj +++ b/src/Nexus.vcxproj @@ -294,6 +294,7 @@ + @@ -392,7 +393,40 @@ set /p branchname=<temp_file.h set branchmacro=#define BRANCH_NAME "%branchname%" echo #pragma once > Branch.h echo %branchmacro% >> Branch.h -del temp_file.h +del temp_file.h + +:: Check WMIC is available +WMIC.EXE Alias /? >NUL 2>&1 || GOTO s_error + +:: Use WMIC to retrieve date and time +FOR /F "skip=1 tokens=1-6" %%G IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO ( + IF "%%~L"=="" goto s_done + Set _yyyy=%%L + Set _mm=00%%J + Set _dd=00%%G + Set _hour=00%%H + SET _minute=00%%I +) +:s_done + +:: Pad digits with leading zeros + Set _mm=%_mm:~-2% + Set _dd=%_dd:~-2% + Set _hour=%_hour:~-2% + Set _minute=%_minute:~-2% + +:: Display the date/time in ISO 8601 format: +Set _isodate=%_yyyy%-%_mm%-%_dd% %_hour%:%_minute% +Echo %_isodate% + +echo #pragma once > Version.h +echo #define V_MAJOR %_isodate:~0,4% >> Version.h +echo #define V_MINOR %_isodate:~5,2% >> Version.h +echo #define V_BUILD %_isodate:~8,2% >> Version.h +SET /A var_hours = %_isodate:~11,2% +SET /A var_minutes = %_isodate:~14,2% +SET /A var_res = %var_hours% * 60 + %var_minutes% +echo #define V_REVISION %var_res% >> Version.h mkdir $(TargetDir)$(API_BUILDER_TARGET_DIR) @@ -429,7 +463,40 @@ set /p branchname=<temp_file.h set branchmacro=#define BRANCH_NAME "%branchname%" echo #pragma once > Branch.h echo %branchmacro% >> Branch.h -del temp_file.h +del temp_file.h + +:: Check WMIC is available +WMIC.EXE Alias /? >NUL 2>&1 || GOTO s_error + +:: Use WMIC to retrieve date and time +FOR /F "skip=1 tokens=1-6" %%G IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO ( + IF "%%~L"=="" goto s_done + Set _yyyy=%%L + Set _mm=00%%J + Set _dd=00%%G + Set _hour=00%%H + SET _minute=00%%I +) +:s_done + +:: Pad digits with leading zeros + Set _mm=%_mm:~-2% + Set _dd=%_dd:~-2% + Set _hour=%_hour:~-2% + Set _minute=%_minute:~-2% + +:: Display the date/time in ISO 8601 format: +Set _isodate=%_yyyy%-%_mm%-%_dd% %_hour%:%_minute% +Echo %_isodate% + +echo #pragma once > Version.h +echo #define V_MAJOR %_isodate:~0,4% >> Version.h +echo #define V_MINOR %_isodate:~5,2% >> Version.h +echo #define V_BUILD %_isodate:~8,2% >> Version.h +SET /A var_hours = %_isodate:~11,2% +SET /A var_minutes = %_isodate:~14,2% +SET /A var_res = %var_hours% * 60 + %var_minutes% +echo #define V_REVISION %var_res% >> Version.h mkdir $(TargetDir)$(API_BUILDER_TARGET_DIR) diff --git a/src/Nexus.vcxproj.filters b/src/Nexus.vcxproj.filters index 3c8835e..c84587a 100644 --- a/src/Nexus.vcxproj.filters +++ b/src/Nexus.vcxproj.filters @@ -962,6 +962,9 @@ Updater + + Header Files + diff --git a/src/State.cpp b/src/State.cpp index 1c6d9d5..eb9bda9 100644 --- a/src/State.cpp +++ b/src/State.cpp @@ -19,50 +19,50 @@ namespace State bool first = true; bool customMumble = false; - std::string cmdline = GetCommandLineA(); - cmdline.append(" -;"); // append another space, so the last substring can be ignored - std::string delimiter = " -"; + int argc; + LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); - size_t pos = 0; - std::string token; - while ((pos = cmdline.find(delimiter)) != std::string::npos) + for (int i = 0; i < argc; i++) { - token = cmdline.substr(0, pos); + std::wstring paramW = argv[i]; + std::string token = WStrToStr(paramW); + std::string cmp = token; - cmdline.erase(0, pos + delimiter.length()); if (first) { first = false; continue; } // skip location param - Parameters.push_back(token); std::transform(cmp.begin(), cmp.end(), cmp.begin(), ::tolower); - //Log("dbg", "token: \"%s\" @ %d", token.c_str(), pos); - // token -> is the unmodified string as from the commandline // cmp -> same as token, except it's been normalised (aka written in lowercase) - if (cmp == "ggdev") { IsDeveloperMode = true; } - if (cmp == "ggconsole") { IsConsoleEnabled = true; } - if (cmp == "ggvanilla") { IsVanilla = true; } - if (cmp == "sharearchive") { MultiboxState = MultiboxState | EMultiboxState::ARCHIVE_SHARED; } - if (cmp == "multi") { MultiboxState = MultiboxState | EMultiboxState::LOCAL_SHARED; } + if (cmp == "-ggdev") { IsDeveloperMode = true; } + if (cmp == "-ggconsole") { IsConsoleEnabled = true; } + if (cmp == "-ggvanilla") { IsVanilla = true; } + if (cmp == "-sharearchive") { MultiboxState = MultiboxState | EMultiboxState::ARCHIVE_SHARED; } + if (cmp == "-multi") { MultiboxState = MultiboxState | EMultiboxState::LOCAL_SHARED; } - size_t subpos = 0; - std::string subtoken; - if ((subpos = cmp.find("mumble ")) != std::string::npos) + if (cmp == "-mumble" && i + 1 <= argc) { - subtoken = token.substr(7, token.length() - subpos); - if (std::regex_match(subtoken, std::regex("\"(.*?)\""))) - { - subtoken = subtoken.substr(1, subtoken.length() - 2); - } - //Log("dbg", "subtoken: \"%s\" @ %d", subtoken.c_str(), subpos); + std::wstring mumbleNameW = argv[i + 1]; + std::string mumbleName = WStrToStr(mumbleNameW); customMumble = true; - MumbleLink = (LinkedMem*)DataLink::ShareResource(DL_MUMBLE_LINK, sizeof(LinkedMem), subtoken.c_str()); + MumbleLink = (LinkedMem*)DataLink::ShareResource(DL_MUMBLE_LINK, sizeof(LinkedMem), mumbleName.c_str()); + + token.append(" "); + token.append(mumbleName); + Parameters.push_back(token); + i++; // manual increment to skip + } + else + { + Parameters.push_back(token); } } + /////////////////////////////////// + if (!customMumble) { MumbleLink = (LinkedMem*)DataLink::ShareResource(DL_MUMBLE_LINK, sizeof(LinkedMem), "MumbleLink"); diff --git a/src/State.h b/src/State.h index 05ba46f..770a9b4 100644 --- a/src/State.h +++ b/src/State.h @@ -7,6 +7,7 @@ #include #include +#include "core.h" #include "Consts.h" #include "Shared.h" diff --git a/src/core.h b/src/core.h index f02d1cf..8266f6a 100644 --- a/src/core.h +++ b/src/core.h @@ -21,102 +21,4 @@ std::wstring StrToWStr(std::string& aString); const char* ConvertToUTF8(const char* multibyteStr); -/* - * - * Created: 29.03.2018 - * - * Authors: - * - * Assembled from the code released on Stackoverflow by: - * Dennis (instructable.com/member/nqtronix) | https://stackoverflow.com/questions/23032002/c-c-how-to-get-integer-unix-timestamp-of-build-time-not-string - * and - * Alexis Wilke | https://stackoverflow.com/questions/10538444/do-you-know-of-a-c-macro-to-compute-unix-time-and-date - * - * Assembled by Jean Rabault - * - * UNIX_TIMESTAMP gives the UNIX timestamp (unsigned long integer of seconds since 1st Jan 1970) of compilation from macros using the compiler defined __TIME__ macro. - * This should include Gregorian calendar leap days, in particular the 29ths of February, 100 and 400 years modulo leaps. - * - * Careful: __TIME__ is the local time of the computer, NOT the UTC time in general! - * - */ - -#ifndef COMPILE_TIME_H_ -#define COMPILE_TIME_H_ - - // Some definitions for calculation -#define SEC_PER_MIN 60UL -#define SEC_PER_HOUR 3600UL -#define SEC_PER_DAY 86400UL -#define SEC_PER_YEAR (SEC_PER_DAY*365) - -// extracts 1..4 characters from a string and interprets it as a decimal value -#define CONV_STR2DEC_1(str, i) (str[i]>'0'?str[i]-'0':0) -#define CONV_STR2DEC_2(str, i) (CONV_STR2DEC_1(str, i)*10 + str[i+1]-'0') -#define CONV_STR2DEC_3(str, i) (CONV_STR2DEC_2(str, i)*10 + str[i+2]-'0') -#define CONV_STR2DEC_4(str, i) (CONV_STR2DEC_3(str, i)*10 + str[i+3]-'0') - -// Custom "glue logic" to convert the month name to a usable number -#define GET_MONTH(str, i) (str[i]=='J' && str[i+1]=='a' && str[i+2]=='n' ? 1 : \ - str[i]=='F' && str[i+1]=='e' && str[i+2]=='b' ? 2 : \ - str[i]=='M' && str[i+1]=='a' && str[i+2]=='r' ? 3 : \ - str[i]=='A' && str[i+1]=='p' && str[i+2]=='r' ? 4 : \ - str[i]=='M' && str[i+1]=='a' && str[i+2]=='y' ? 5 : \ - str[i]=='J' && str[i+1]=='u' && str[i+2]=='n' ? 6 : \ - str[i]=='J' && str[i+1]=='u' && str[i+2]=='l' ? 7 : \ - str[i]=='A' && str[i+1]=='u' && str[i+2]=='g' ? 8 : \ - str[i]=='S' && str[i+1]=='e' && str[i+2]=='p' ? 9 : \ - str[i]=='O' && str[i+1]=='c' && str[i+2]=='t' ? 10 : \ - str[i]=='N' && str[i+1]=='o' && str[i+2]=='v' ? 11 : \ - str[i]=='D' && str[i+1]=='e' && str[i+2]=='c' ? 12 : 0) - -// extract the information from the time string given by __TIME__ and __DATE__ -#define __TIME_SECONDS__ CONV_STR2DEC_2(__TIME__, 6) -#define __TIME_MINUTES__ CONV_STR2DEC_2(__TIME__, 3) -#define __TIME_HOURS__ CONV_STR2DEC_2(__TIME__, 0) -#define __TIME_DAYS__ CONV_STR2DEC_2(__DATE__, 4) -#define __TIME_MONTH__ GET_MONTH(__DATE__, 0) -#define __TIME_YEARS__ CONV_STR2DEC_4(__DATE__, 7) - -// Days in February -#define _UNIX_TIMESTAMP_FDAY(year) \ - (((year) % 400) == 0UL ? 29UL : \ - (((year) % 100) == 0UL ? 28UL : \ - (((year) % 4) == 0UL ? 29UL : \ - 28UL))) - -// Days in the year -#define _UNIX_TIMESTAMP_YDAY(year, month, day) \ - ( \ - /* January */ day \ - /* February */ + (month >= 2 ? 31UL : 0UL) \ - /* March */ + (month >= 3 ? _UNIX_TIMESTAMP_FDAY(year) : 0UL) \ - /* April */ + (month >= 4 ? 31UL : 0UL) \ - /* May */ + (month >= 5 ? 30UL : 0UL) \ - /* June */ + (month >= 6 ? 31UL : 0UL) \ - /* July */ + (month >= 7 ? 30UL : 0UL) \ - /* August */ + (month >= 8 ? 31UL : 0UL) \ - /* September */+ (month >= 9 ? 31UL : 0UL) \ - /* October */ + (month >= 10 ? 30UL : 0UL) \ - /* November */ + (month >= 11 ? 31UL : 0UL) \ - /* December */ + (month >= 12 ? 30UL : 0UL) \ - ) - -// get the UNIX timestamp from a digits representation -#define _UNIX_TIMESTAMP(year, month, day, hour, minute, second) \ - ( /* time */ second \ - + minute * SEC_PER_MIN \ - + hour * SEC_PER_HOUR \ - + /* year day (month + day) */ (_UNIX_TIMESTAMP_YDAY(year, month, day) - 1) * SEC_PER_DAY \ - + /* year */ (year - 1970UL) * SEC_PER_YEAR \ - + ((year - 1969UL) / 4UL) * SEC_PER_DAY \ - - ((year - 1901UL) / 100UL) * SEC_PER_DAY \ - + ((year - 1601UL) / 400UL) * SEC_PER_DAY \ - ) - -// the UNIX timestamp -#define UNIX_TIMESTAMP (_UNIX_TIMESTAMP(__TIME_YEARS__, __TIME_MONTH__, __TIME_DAYS__, __TIME_HOURS__, __TIME_MINUTES__, __TIME_SECONDS__)) - #endif - -#endif \ No newline at end of file diff --git a/src/entry.cpp b/src/entry.cpp index ed5ad55..3b9d2b5 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -5,6 +5,8 @@ #include "minhook/mh_hook.h" +#include "Version.h" + #include "core.h" #include "Paths.h" #include "State.h" @@ -47,16 +49,17 @@ void Initialize() { State::Nexus = ENexusState::LOAD; - Version->Major = __TIME_YEARS__; - Version->Minor = __TIME_MONTH__; - Version->Build = __TIME_DAYS__; - Version->Revision = (__TIME_HOURS__ * 60) + (__TIME_MINUTES__); + Version->Major = V_MAJOR; + Version->Minor = V_MINOR; + Version->Build = V_BUILD; + Version->Revision = V_REVISION; LogInfo(CH_CORE, GetCommandLineA()); LogInfo(CH_CORE, "Version: %s", Version->ToString().c_str()); State::Initialize(); Path::Initialize(NexusHandle); + //Paradigm::Initialize(); Updater::Initialize(); @@ -70,16 +73,21 @@ void Initialize() Keybinds::Initialize(); Keybinds::Load(); Settings::Load(); - - if (!Settings::Settings[OPT_DEVMODE].is_null()) - { - State::IsDeveloperMode = Settings::Settings[OPT_DEVMODE].get(); - } - else + + // if it's not already been explicitly set via command line, check settings + if (!State::IsDeveloperMode) { - State::IsDeveloperMode = false; - Settings::Settings[OPT_DEVMODE] = false; + if (!Settings::Settings[OPT_DEVMODE].is_null()) + { + State::IsDeveloperMode = Settings::Settings[OPT_DEVMODE].get(); + } + else + { + State::IsDeveloperMode = false; + Settings::Settings[OPT_DEVMODE] = false; + } } + //API::Initialize(); Mumble::Initialize();