diff --git a/.gitignore b/.gitignore index e2b99c4e..0a633322 100644 --- a/.gitignore +++ b/.gitignore @@ -375,3 +375,4 @@ Crawler/Crawler.wasm Crawler/pixelGameEngine_wasm.o *.tiled-session /Crawler/Crawler.tiled-session +/Crawler/assets/discordAPI.txt diff --git a/Crawler/Crawler.cpp b/Crawler/Crawler.cpp index 921169fb..6f69c247 100644 --- a/Crawler/Crawler.cpp +++ b/Crawler/Crawler.cpp @@ -67,6 +67,9 @@ All rights reserved. #include "olcPGEX_TTF.h" #include "MenuItemItemButton.h" #include "Merchant.h" +#ifndef __EMSCRIPTEN__ +#include "discord-files/discord.h" +#endif INCLUDE_EMITTER_LIST @@ -89,14 +92,14 @@ InputGroup Crawler::KEY_DOWN; InputGroup Crawler::KEY_ATTACK; InputGroup Crawler::KEY_CONFIRM; InputGroup Crawler::KEY_MENU; +#ifndef __EMSCRIPTEN__ + ::discord::Core*Discord{}; +#endif float Crawler::SIZE_CHANGE_SPEED=1; Crawler::Crawler() { - sAppName = "Crawler Concept"; - game=this; - utils::datafile::Read(DATA,"assets/config/configuration.txt"); _DEBUG_MAP_LOAD_INFO=bool("debug_map_load_info"_I); @@ -141,6 +144,9 @@ Crawler::Crawler() } utils::datafile::DEBUG_ACCESS_OPTIONS="debug_access_options"_I; + + sAppName = "GAME_NAME"_S; + game=this; } bool Crawler::OnUserCreate(){ @@ -202,6 +208,8 @@ bool Crawler::OnUserCreate(){ utils::datafile::INITIAL_SETUP_COMPLETE=true; ValidateGameStatus(); //Checks to make sure everything has been initialized properly. + + SetupDiscord(); return true; } @@ -216,6 +224,11 @@ bool Crawler::OnUserUpdate(float fElapsedTime){ RenderMenu(); RenderFadeout(); RenderVersionInfo(); + #ifndef __EMSCRIPTEN__ + if(Discord){ + Discord->RunCallbacks(); + } + #endif return !gameEnd; } @@ -2276,4 +2289,43 @@ bool Crawler::GamePaused(){ void Crawler::EndGame(){ gameEnd=true; +} + +void Crawler::SetupDiscord(){ + gameStarted=time(NULL); + #ifndef __EMSCRIPTEN__ + auto result = ::discord::Core::Create(1186719371750555780,DiscordCreateFlags_NoRequireDiscord,&Discord); + if(result==::discord::Result::Ok){ + Discord->SetLogHook( + discord::LogLevel::Debug, [](discord::LogLevel level, const char* message) { + std::cerr << "Log(" << static_cast(level) << "): " << message << "\n"; + }); + std::cout<<"Connected to Discord!"<GetClassName()); + } + #endif +} + +void Crawler::UpdateDiscordStatus(std::string levelName,std::string className){ + #ifndef __EMSCRIPTEN__ + if(Discord){ + ::discord::Activity newActivity{}; + newActivity.SetDetails(levelName.c_str()); + newActivity.SetState(("Class: "+className).c_str()); + discord::ActivityTimestamps×tamps=newActivity.GetTimestamps(); + timestamps.SetStart(gameStarted); + newActivity.SetType(discord::ActivityType::Playing); + discord::ActivityAssets&assets=newActivity.GetAssets(); + assets.SetLargeImage("heart_512"); + if(levelName!="Main Menu"){ + std::for_each(className.begin(),className.end(),[](char&c){c=std::tolower(c);}); + assets.SetSmallImage(("nico-"+className+"_512").c_str()); + } + assets.SetLargeText(game->sAppName.c_str()); + assets.SetSmallText(className.c_str()); + Discord->ActivityManager().UpdateActivity(newActivity,[](::discord::Result result){ + std::cout<<"Discord Activity successfully updated!"<monstersToBeSpawned; + time_t gameStarted; void ValidateGameStatus(); + void SetupDiscord(); public: Crawler(); bool OnUserCreate() override; @@ -197,6 +199,7 @@ public: void RenderFadeout(); bool GamePaused(); void EndGame(); + void UpdateDiscordStatus(std::string levelName,std::string className); struct TileGroupData{ vi2d tilePos; diff --git a/Crawler/Crawler.vcxproj b/Crawler/Crawler.vcxproj index 93ab2218..7096085d 100644 --- a/Crawler/Crawler.vcxproj +++ b/Crawler/Crawler.vcxproj @@ -131,14 +131,14 @@ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 - C:\Users\sigon\Documents\include;%(AdditionalIncludeDirectories) + C:\Users\sigon\source\repos\Crawler\Crawler\discord-files;C:\Users\sigon\Documents\include;%(AdditionalIncludeDirectories) /MP8 %(AdditionalOptions) Console true C:\Users\sigon\source\repos\Crawler\Crawler;%(AdditionalLibraryDirectories) - freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + discord_game_sdk.dll.lib;freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies); powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h" @@ -154,14 +154,14 @@ true stdcpp20 /MP8 %(AdditionalOptions) - C:\Users\sigon\Documents\include; + C:\Users\sigon\source\repos\Crawler\Crawler\discord-files;C:\Users\sigon\Documents\include; Console true true true - freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies);discord_game_sdk.dll.lib powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h" @@ -177,14 +177,14 @@ true stdcpp20 /MP8 %(AdditionalOptions) - C:\Users\sigon\Documents\include; + C:\Users\sigon\source\repos\Crawler\Crawler\discord-files;C:\Users\sigon\Documents\include;C:\Users\sigon\source\repos\Crawler\Crawler\discord-files Console true true true - freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + discord_game_sdk.dll.lib;freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies);discord_game_sdk.dll.lib powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h" @@ -197,14 +197,14 @@ _DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpp20 - C:\Users\sigon\Documents\include;%(AdditionalIncludeDirectories) + C:\Users\sigon\source\repos\Crawler\Crawler\discord-files;C:\Users\sigon\Documents\include;%(AdditionalIncludeDirectories) /MP8 %(AdditionalOptions) Console true C:\Users\sigon\source\repos\Crawler\Crawler;%(AdditionalLibraryDirectories) - freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + discord_game_sdk.dll.lib;freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies); powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h" @@ -224,14 +224,14 @@ true stdcpp20 /MP8 %(AdditionalOptions) - C:\Users\sigon\Documents\include; + C:\Users\sigon\source\repos\Crawler\Crawler\discord-files;C:\Users\sigon\Documents\include; Console true true true - freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies);discord_game_sdk.dll.lib powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h" @@ -250,14 +250,14 @@ true stdcpp20 /MP8 %(AdditionalOptions) - C:\Users\sigon\Documents\include; + C:\Users\sigon\source\repos\Crawler\Crawler\discord-files;C:\Users\sigon\Documents\include;C:\Users\sigon\source\repos\Crawler\Crawler\discord-files Console true true true - freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies) + discord_game_sdk.dll.lib;freetype.lib;$(CoreLibraryDependencies);%(AdditionalDependencies);discord_game_sdk.dll.lib powershell.exe -ExecutionPolicy Bypass -NoProfile -NonInteractive -File update_version.ps1 "./version.h" @@ -270,17 +270,21 @@ Console + $(CoreLibraryDependencies);%(AdditionalDependencies);discord_game_sdk.dll.lib stdcpp20 + C:\Users\sigon\source\repos\Crawler\Crawler\discord-files; Console + $(CoreLibraryDependencies);%(AdditionalDependencies);discord_game_sdk.dll.lib stdcpp20 + C:\Users\sigon\source\repos\Crawler\Crawler\discord-files; @@ -307,6 +311,23 @@ + + + + + + + + + + + + + + + + + @@ -428,6 +449,20 @@ + + + + + + + + + + + + + + diff --git a/Crawler/Crawler.vcxproj.filters b/Crawler/Crawler.vcxproj.filters index 8ba3bc07..d3b2877b 100644 --- a/Crawler/Crawler.vcxproj.filters +++ b/Crawler/Crawler.vcxproj.filters @@ -73,6 +73,12 @@ {9ab34e07-c7ba-4f4b-9dad-29c7602c1550} + + {4fada79e-3b17-42df-8609-adf564fe12d9} + + + {8911e0bb-703c-4a2b-b3dd-259192956733} + @@ -312,6 +318,57 @@ Header Files + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + + + Header Files\discord-files + @@ -506,6 +563,48 @@ Source Files + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + + + Source Files\discord-files + diff --git a/Crawler/Menu.h b/Crawler/Menu.h index 4cdbfcf9..ee6be985 100644 --- a/Crawler/Menu.h +++ b/Crawler/Menu.h @@ -237,6 +237,7 @@ T*Component(MenuType menu,std::string componentName){ }else{ ERR("WARNING! Attempting to cast a button that isn't a "<(OVERWORLD_LEVEL_SELECT,"Spawns List")->UpdateSpawns(currentConnectionPoint->spawns); Component(OVERWORLD_LEVEL_SELECT,"Enter Button")->Enable(currentConnectionPoint->levelDataExists); Menu::OpenMenu(OVERWORLD_LEVEL_SELECT,false); + game->UpdateDiscordStatus("Overworld Map",game->GetPlayer()->GetClassName()); }; void State_OverworldMap::OnUserUpdate(Crawler*game){ if(Menu::stack.size()>1)return; @@ -156,6 +157,7 @@ ConnectionPoint&State_OverworldMap::GetCurrentConnectionPoint(){ } void State_OverworldMap::StartLevel(){ + game->UpdateDiscordStatus(State_OverworldMap::GetCurrentConnectionPoint().name,game->GetPlayer()->GetClassName()); if(State_OverworldMap::GetCurrentConnectionPoint().map.starts_with("STORY")){ VisualNovel::LoadVisualNovel(State_OverworldMap::GetCurrentConnectionPoint().map); }else{ diff --git a/Crawler/Version.h b/Crawler/Version.h index 58ca8324..3c78c82c 100644 --- a/Crawler/Version.h +++ b/Crawler/Version.h @@ -39,7 +39,7 @@ All rights reserved. #define VERSION_MAJOR 0 #define VERSION_MINOR 2 #define VERSION_PATCH 1 -#define VERSION_BUILD 4156 +#define VERSION_BUILD 4187 #define stringify(a) stringify_(a) #define stringify_(a) #a diff --git a/Crawler/assets/config/configuration.txt b/Crawler/assets/config/configuration.txt index e9b9ab57..84a7fc9e 100644 --- a/Crawler/assets/config/configuration.txt +++ b/Crawler/assets/config/configuration.txt @@ -3,6 +3,8 @@ config_path = assets/config/ # 360x240 is 15x10 tiles of visibility. WINDOW_SIZE = 360,240 +GAME_NAME = Crawler Project + # Graphics Loading Config gfx_config = gfx/gfx.txt diff --git a/Crawler/assets/heart_512.png b/Crawler/assets/heart_512.png new file mode 100644 index 00000000..db6bb0dd Binary files /dev/null and b/Crawler/assets/heart_512.png differ diff --git a/Crawler/assets/nico-Ranger_512.png b/Crawler/assets/nico-Ranger_512.png new file mode 100644 index 00000000..3e1dada7 Binary files /dev/null and b/Crawler/assets/nico-Ranger_512.png differ diff --git a/Crawler/assets/nico-Thief_512.png b/Crawler/assets/nico-Thief_512.png new file mode 100644 index 00000000..1d336f83 Binary files /dev/null and b/Crawler/assets/nico-Thief_512.png differ diff --git a/Crawler/assets/nico-Trapper_512.png b/Crawler/assets/nico-Trapper_512.png new file mode 100644 index 00000000..fd5ea273 Binary files /dev/null and b/Crawler/assets/nico-Trapper_512.png differ diff --git a/Crawler/assets/nico-Warrior_512.png b/Crawler/assets/nico-Warrior_512.png new file mode 100644 index 00000000..1c8ea73e Binary files /dev/null and b/Crawler/assets/nico-Warrior_512.png differ diff --git a/Crawler/assets/nico-Witch_512.png b/Crawler/assets/nico-Witch_512.png new file mode 100644 index 00000000..c3036ebe Binary files /dev/null and b/Crawler/assets/nico-Witch_512.png differ diff --git a/Crawler/assets/nico-Wizard_512.png b/Crawler/assets/nico-Wizard_512.png new file mode 100644 index 00000000..c192b0f0 Binary files /dev/null and b/Crawler/assets/nico-Wizard_512.png differ diff --git a/Crawler/discord-files/achievement_manager.cpp b/Crawler/discord-files/achievement_manager.cpp new file mode 100644 index 00000000..43a6d4c9 --- /dev/null +++ b/Crawler/discord-files/achievement_manager.cpp @@ -0,0 +1,99 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "achievement_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +class AchievementEvents final { +public: + static void DISCORD_CALLBACK OnUserAchievementUpdate(void* callbackData, + DiscordUserAchievement* userAchievement) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->AchievementManager(); + module.OnUserAchievementUpdate(*reinterpret_cast(userAchievement)); + } +}; + +IDiscordAchievementEvents AchievementManager::events_{ + &AchievementEvents::OnUserAchievementUpdate, +}; + +void AchievementManager::SetUserAchievement(Snowflake achievementId, + std::uint8_t percentComplete, + std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->set_user_achievement( + internal_, achievementId, percentComplete, cb.release(), wrapper); +} + +void AchievementManager::FetchUserAchievements(std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->fetch_user_achievements(internal_, cb.release(), wrapper); +} + +void AchievementManager::CountUserAchievements(std::int32_t* count) +{ + if (!count) { + return; + } + + internal_->count_user_achievements(internal_, reinterpret_cast(count)); +} + +Result AchievementManager::GetUserAchievement(Snowflake userAchievementId, + UserAchievement* userAchievement) +{ + if (!userAchievement) { + return Result::InternalError; + } + + auto result = internal_->get_user_achievement( + internal_, userAchievementId, reinterpret_cast(userAchievement)); + return static_cast(result); +} + +Result AchievementManager::GetUserAchievementAt(std::int32_t index, + UserAchievement* userAchievement) +{ + if (!userAchievement) { + return Result::InternalError; + } + + auto result = internal_->get_user_achievement_at( + internal_, index, reinterpret_cast(userAchievement)); + return static_cast(result); +} + +} // namespace discord diff --git a/Crawler/discord-files/achievement_manager.h b/Crawler/discord-files/achievement_manager.h new file mode 100644 index 00000000..1f58c8eb --- /dev/null +++ b/Crawler/discord-files/achievement_manager.h @@ -0,0 +1,34 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class AchievementManager final { +public: + ~AchievementManager() = default; + + void SetUserAchievement(Snowflake achievementId, + std::uint8_t percentComplete, + std::function callback); + void FetchUserAchievements(std::function callback); + void CountUserAchievements(std::int32_t* count); + Result GetUserAchievement(Snowflake userAchievementId, UserAchievement* userAchievement); + Result GetUserAchievementAt(std::int32_t index, UserAchievement* userAchievement); + + Event OnUserAchievementUpdate; + +private: + friend class Core; + + AchievementManager() = default; + AchievementManager(AchievementManager const& rhs) = delete; + AchievementManager& operator=(AchievementManager const& rhs) = delete; + AchievementManager(AchievementManager&& rhs) = delete; + AchievementManager& operator=(AchievementManager&& rhs) = delete; + + IDiscordAchievementManager* internal_; + static IDiscordAchievementEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/activity_manager.cpp b/Crawler/discord-files/activity_manager.cpp new file mode 100644 index 00000000..3c200746 --- /dev/null +++ b/Crawler/discord-files/activity_manager.cpp @@ -0,0 +1,177 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "activity_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +class ActivityEvents final { +public: + static void DISCORD_CALLBACK OnActivityJoin(void* callbackData, char const* secret) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->ActivityManager(); + module.OnActivityJoin(static_cast(secret)); + } + + static void DISCORD_CALLBACK OnActivitySpectate(void* callbackData, char const* secret) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->ActivityManager(); + module.OnActivitySpectate(static_cast(secret)); + } + + static void DISCORD_CALLBACK OnActivityJoinRequest(void* callbackData, DiscordUser* user) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->ActivityManager(); + module.OnActivityJoinRequest(*reinterpret_cast(user)); + } + + static void DISCORD_CALLBACK OnActivityInvite(void* callbackData, + EDiscordActivityActionType type, + DiscordUser* user, + DiscordActivity* activity) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->ActivityManager(); + module.OnActivityInvite(static_cast(type), + *reinterpret_cast(user), + *reinterpret_cast(activity)); + } +}; + +IDiscordActivityEvents ActivityManager::events_{ + &ActivityEvents::OnActivityJoin, + &ActivityEvents::OnActivitySpectate, + &ActivityEvents::OnActivityJoinRequest, + &ActivityEvents::OnActivityInvite, +}; + +Result ActivityManager::RegisterCommand(char const* command) +{ + auto result = internal_->register_command(internal_, const_cast(command)); + return static_cast(result); +} + +Result ActivityManager::RegisterSteam(std::uint32_t steamId) +{ + auto result = internal_->register_steam(internal_, steamId); + return static_cast(result); +} + +void ActivityManager::UpdateActivity(Activity const& activity, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->update_activity(internal_, + reinterpret_cast(const_cast(&activity)), + cb.release(), + wrapper); +} + +void ActivityManager::ClearActivity(std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->clear_activity(internal_, cb.release(), wrapper); +} + +void ActivityManager::SendRequestReply(UserId userId, + ActivityJoinRequestReply reply, + std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->send_request_reply(internal_, + userId, + static_cast(reply), + cb.release(), + wrapper); +} + +void ActivityManager::SendInvite(UserId userId, + ActivityActionType type, + char const* content, + std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->send_invite(internal_, + userId, + static_cast(type), + const_cast(content), + cb.release(), + wrapper); +} + +void ActivityManager::AcceptInvite(UserId userId, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->accept_invite(internal_, userId, cb.release(), wrapper); +} + +} // namespace discord diff --git a/Crawler/discord-files/activity_manager.h b/Crawler/discord-files/activity_manager.h new file mode 100644 index 00000000..c107be27 --- /dev/null +++ b/Crawler/discord-files/activity_manager.h @@ -0,0 +1,42 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class ActivityManager final { +public: + ~ActivityManager() = default; + + Result RegisterCommand(char const* command); + Result RegisterSteam(std::uint32_t steamId); + void UpdateActivity(Activity const& activity, std::function callback); + void ClearActivity(std::function callback); + void SendRequestReply(UserId userId, + ActivityJoinRequestReply reply, + std::function callback); + void SendInvite(UserId userId, + ActivityActionType type, + char const* content, + std::function callback); + void AcceptInvite(UserId userId, std::function callback); + + Event OnActivityJoin; + Event OnActivitySpectate; + Event OnActivityJoinRequest; + Event OnActivityInvite; + +private: + friend class Core; + + ActivityManager() = default; + ActivityManager(ActivityManager const& rhs) = delete; + ActivityManager& operator=(ActivityManager const& rhs) = delete; + ActivityManager(ActivityManager&& rhs) = delete; + ActivityManager& operator=(ActivityManager&& rhs) = delete; + + IDiscordActivityManager* internal_; + static IDiscordActivityEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/application_manager.cpp b/Crawler/discord-files/application_manager.cpp new file mode 100644 index 00000000..0e05f3f3 --- /dev/null +++ b/Crawler/discord-files/application_manager.cpp @@ -0,0 +1,78 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "application_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +void ApplicationManager::ValidateOrExit(std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->validate_or_exit(internal_, cb.release(), wrapper); +} + +void ApplicationManager::GetCurrentLocale(char locale[128]) +{ + if (!locale) { + return; + } + + internal_->get_current_locale(internal_, reinterpret_cast(locale)); +} + +void ApplicationManager::GetCurrentBranch(char branch[4096]) +{ + if (!branch) { + return; + } + + internal_->get_current_branch(internal_, reinterpret_cast(branch)); +} + +void ApplicationManager::GetOAuth2Token(std::function callback) +{ + static auto wrapper = + [](void* callbackData, EDiscordResult result, DiscordOAuth2Token* oauth2Token) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result), *reinterpret_cast(oauth2Token)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->get_oauth2_token(internal_, cb.release(), wrapper); +} + +void ApplicationManager::GetTicket(std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result, char const* data) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result), static_cast(data)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->get_ticket(internal_, cb.release(), wrapper); +} + +} // namespace discord diff --git a/Crawler/discord-files/application_manager.h b/Crawler/discord-files/application_manager.h new file mode 100644 index 00000000..ab0e8563 --- /dev/null +++ b/Crawler/discord-files/application_manager.h @@ -0,0 +1,30 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class ApplicationManager final { +public: + ~ApplicationManager() = default; + + void ValidateOrExit(std::function callback); + void GetCurrentLocale(char locale[128]); + void GetCurrentBranch(char branch[4096]); + void GetOAuth2Token(std::function callback); + void GetTicket(std::function callback); + +private: + friend class Core; + + ApplicationManager() = default; + ApplicationManager(ApplicationManager const& rhs) = delete; + ApplicationManager& operator=(ApplicationManager const& rhs) = delete; + ApplicationManager(ApplicationManager&& rhs) = delete; + ApplicationManager& operator=(ApplicationManager&& rhs) = delete; + + IDiscordApplicationManager* internal_; + static IDiscordApplicationEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/core.cpp b/Crawler/discord-files/core.cpp new file mode 100644 index 00000000..110c9ef6 --- /dev/null +++ b/Crawler/discord-files/core.cpp @@ -0,0 +1,182 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "core.h" + +#include +#include + +namespace discord { + +Result Core::Create(ClientId clientId, std::uint64_t flags, Core** instance) +{ + if (!instance) { + return Result::InternalError; + } + + (*instance) = new Core(); + DiscordCreateParams params{}; + DiscordCreateParamsSetDefault(¶ms); + params.client_id = clientId; + params.flags = flags; + params.events = nullptr; + params.event_data = *instance; + params.user_events = &UserManager::events_; + params.activity_events = &ActivityManager::events_; + params.relationship_events = &RelationshipManager::events_; + params.lobby_events = &LobbyManager::events_; + params.network_events = &NetworkManager::events_; + params.overlay_events = &OverlayManager::events_; + params.store_events = &StoreManager::events_; + params.voice_events = &VoiceManager::events_; + params.achievement_events = &AchievementManager::events_; + auto result = DiscordCreate(DISCORD_VERSION, ¶ms, &((*instance)->internal_)); + if (result != DiscordResult_Ok || !(*instance)->internal_) { + delete (*instance); + (*instance) = nullptr; + } + + return static_cast(result); +} + +Core::~Core() +{ + if (internal_) { + internal_->destroy(internal_); + internal_ = nullptr; + } +} + +Result Core::RunCallbacks() +{ + auto result = internal_->run_callbacks(internal_); + return static_cast(result); +} + +void Core::SetLogHook(LogLevel minLevel, std::function hook) +{ + setLogHook_.DisconnectAll(); + setLogHook_.Connect(std::move(hook)); + static auto wrapper = + [](void* callbackData, EDiscordLogLevel level, char const* message) -> void { + auto cb(reinterpret_cast(callbackData)); + if (!cb) { + return; + } + (*cb)(static_cast(level), static_cast(message)); + }; + + internal_->set_log_hook( + internal_, static_cast(minLevel), &setLogHook_, wrapper); +} + +discord::ApplicationManager& Core::ApplicationManager() +{ + if (!applicationManager_.internal_) { + applicationManager_.internal_ = internal_->get_application_manager(internal_); + } + + return applicationManager_; +} + +discord::UserManager& Core::UserManager() +{ + if (!userManager_.internal_) { + userManager_.internal_ = internal_->get_user_manager(internal_); + } + + return userManager_; +} + +discord::ImageManager& Core::ImageManager() +{ + if (!imageManager_.internal_) { + imageManager_.internal_ = internal_->get_image_manager(internal_); + } + + return imageManager_; +} + +discord::ActivityManager& Core::ActivityManager() +{ + if (!activityManager_.internal_) { + activityManager_.internal_ = internal_->get_activity_manager(internal_); + } + + return activityManager_; +} + +discord::RelationshipManager& Core::RelationshipManager() +{ + if (!relationshipManager_.internal_) { + relationshipManager_.internal_ = internal_->get_relationship_manager(internal_); + } + + return relationshipManager_; +} + +discord::LobbyManager& Core::LobbyManager() +{ + if (!lobbyManager_.internal_) { + lobbyManager_.internal_ = internal_->get_lobby_manager(internal_); + } + + return lobbyManager_; +} + +discord::NetworkManager& Core::NetworkManager() +{ + if (!networkManager_.internal_) { + networkManager_.internal_ = internal_->get_network_manager(internal_); + } + + return networkManager_; +} + +discord::OverlayManager& Core::OverlayManager() +{ + if (!overlayManager_.internal_) { + overlayManager_.internal_ = internal_->get_overlay_manager(internal_); + } + + return overlayManager_; +} + +discord::StorageManager& Core::StorageManager() +{ + if (!storageManager_.internal_) { + storageManager_.internal_ = internal_->get_storage_manager(internal_); + } + + return storageManager_; +} + +discord::StoreManager& Core::StoreManager() +{ + if (!storeManager_.internal_) { + storeManager_.internal_ = internal_->get_store_manager(internal_); + } + + return storeManager_; +} + +discord::VoiceManager& Core::VoiceManager() +{ + if (!voiceManager_.internal_) { + voiceManager_.internal_ = internal_->get_voice_manager(internal_); + } + + return voiceManager_; +} + +discord::AchievementManager& Core::AchievementManager() +{ + if (!achievementManager_.internal_) { + achievementManager_.internal_ = internal_->get_achievement_manager(internal_); + } + + return achievementManager_; +} + +} // namespace discord diff --git a/Crawler/discord-files/core.h b/Crawler/discord-files/core.h new file mode 100644 index 00000000..8af6fca2 --- /dev/null +++ b/Crawler/discord-files/core.h @@ -0,0 +1,64 @@ +#pragma once + +#include "types.h" +#include "application_manager.h" +#include "user_manager.h" +#include "image_manager.h" +#include "activity_manager.h" +#include "relationship_manager.h" +#include "lobby_manager.h" +#include "network_manager.h" +#include "overlay_manager.h" +#include "storage_manager.h" +#include "store_manager.h" +#include "voice_manager.h" +#include "achievement_manager.h" + +namespace discord { + +class Core final { +public: + static Result Create(ClientId clientId, std::uint64_t flags, Core** instance); + + ~Core(); + + Result RunCallbacks(); + void SetLogHook(LogLevel minLevel, std::function hook); + + discord::ApplicationManager& ApplicationManager(); + discord::UserManager& UserManager(); + discord::ImageManager& ImageManager(); + discord::ActivityManager& ActivityManager(); + discord::RelationshipManager& RelationshipManager(); + discord::LobbyManager& LobbyManager(); + discord::NetworkManager& NetworkManager(); + discord::OverlayManager& OverlayManager(); + discord::StorageManager& StorageManager(); + discord::StoreManager& StoreManager(); + discord::VoiceManager& VoiceManager(); + discord::AchievementManager& AchievementManager(); + +private: + Core() = default; + Core(Core const& rhs) = delete; + Core& operator=(Core const& rhs) = delete; + Core(Core&& rhs) = delete; + Core& operator=(Core&& rhs) = delete; + + IDiscordCore* internal_; + Event setLogHook_; + discord::ApplicationManager applicationManager_; + discord::UserManager userManager_; + discord::ImageManager imageManager_; + discord::ActivityManager activityManager_; + discord::RelationshipManager relationshipManager_; + discord::LobbyManager lobbyManager_; + discord::NetworkManager networkManager_; + discord::OverlayManager overlayManager_; + discord::StorageManager storageManager_; + discord::StoreManager storeManager_; + discord::VoiceManager voiceManager_; + discord::AchievementManager achievementManager_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/discord.h b/Crawler/discord-files/discord.h new file mode 100644 index 00000000..c9912129 --- /dev/null +++ b/Crawler/discord-files/discord.h @@ -0,0 +1,16 @@ +#pragma once + +#include "types.h" +#include "core.h" +#include "application_manager.h" +#include "user_manager.h" +#include "image_manager.h" +#include "activity_manager.h" +#include "relationship_manager.h" +#include "lobby_manager.h" +#include "network_manager.h" +#include "overlay_manager.h" +#include "storage_manager.h" +#include "store_manager.h" +#include "voice_manager.h" +#include "achievement_manager.h" diff --git a/Crawler/discord-files/event.h b/Crawler/discord-files/event.h new file mode 100644 index 00000000..610887d1 --- /dev/null +++ b/Crawler/discord-files/event.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include + +namespace discord { + +template +class Event final { +public: + using Token = int; + + Event() { slots_.reserve(4); } + + Event(Event const&) = default; + Event(Event&&) = default; + ~Event() = default; + + Event& operator=(Event const&) = default; + Event& operator=(Event&&) = default; + + template + Token Connect(EventHandler slot) + { + slots_.emplace_back(Slot{nextToken_, std::move(slot)}); + return nextToken_++; + } + + void Disconnect(Token token) + { + for (auto& slot : slots_) { + if (slot.token == token) { + slot = slots_.back(); + slots_.pop_back(); + break; + } + } + } + + void DisconnectAll() { slots_ = {}; } + + void operator()(Args... args) + { + for (auto const& slot : slots_) { + slot.fn(std::forward(args)...); + } + } + +private: + struct Slot { + Token token; + std::function fn; + }; + + Token nextToken_{}; + std::vector slots_{}; +}; + +} // namespace discord diff --git a/Crawler/discord-files/ffi.h b/Crawler/discord-files/ffi.h new file mode 100644 index 00000000..4a210574 --- /dev/null +++ b/Crawler/discord-files/ffi.h @@ -0,0 +1,1113 @@ +#ifndef _DISCORD_GAME_SDK_H_ +#define _DISCORD_GAME_SDK_H_ + +#ifdef _WIN32 +#include +#include +#endif + +#ifdef _WIN32 +#ifdef _WIN64 +#define DISCORD_API +#else +#define DISCORD_API __stdcall +#endif +#else +#define DISCORD_API +#endif + +#define DISCORD_CALLBACK DISCORD_API + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#ifndef __cplusplus +#include +#endif + +#define DISCORD_VERSION 3 +#define DISCORD_APPLICATION_MANAGER_VERSION 1 +#define DISCORD_USER_MANAGER_VERSION 1 +#define DISCORD_IMAGE_MANAGER_VERSION 1 +#define DISCORD_ACTIVITY_MANAGER_VERSION 1 +#define DISCORD_RELATIONSHIP_MANAGER_VERSION 1 +#define DISCORD_LOBBY_MANAGER_VERSION 1 +#define DISCORD_NETWORK_MANAGER_VERSION 1 +#define DISCORD_OVERLAY_MANAGER_VERSION 2 +#define DISCORD_STORAGE_MANAGER_VERSION 1 +#define DISCORD_STORE_MANAGER_VERSION 1 +#define DISCORD_VOICE_MANAGER_VERSION 1 +#define DISCORD_ACHIEVEMENT_MANAGER_VERSION 1 + +enum EDiscordResult { + DiscordResult_Ok = 0, + DiscordResult_ServiceUnavailable = 1, + DiscordResult_InvalidVersion = 2, + DiscordResult_LockFailed = 3, + DiscordResult_InternalError = 4, + DiscordResult_InvalidPayload = 5, + DiscordResult_InvalidCommand = 6, + DiscordResult_InvalidPermissions = 7, + DiscordResult_NotFetched = 8, + DiscordResult_NotFound = 9, + DiscordResult_Conflict = 10, + DiscordResult_InvalidSecret = 11, + DiscordResult_InvalidJoinSecret = 12, + DiscordResult_NoEligibleActivity = 13, + DiscordResult_InvalidInvite = 14, + DiscordResult_NotAuthenticated = 15, + DiscordResult_InvalidAccessToken = 16, + DiscordResult_ApplicationMismatch = 17, + DiscordResult_InvalidDataUrl = 18, + DiscordResult_InvalidBase64 = 19, + DiscordResult_NotFiltered = 20, + DiscordResult_LobbyFull = 21, + DiscordResult_InvalidLobbySecret = 22, + DiscordResult_InvalidFilename = 23, + DiscordResult_InvalidFileSize = 24, + DiscordResult_InvalidEntitlement = 25, + DiscordResult_NotInstalled = 26, + DiscordResult_NotRunning = 27, + DiscordResult_InsufficientBuffer = 28, + DiscordResult_PurchaseCanceled = 29, + DiscordResult_InvalidGuild = 30, + DiscordResult_InvalidEvent = 31, + DiscordResult_InvalidChannel = 32, + DiscordResult_InvalidOrigin = 33, + DiscordResult_RateLimited = 34, + DiscordResult_OAuth2Error = 35, + DiscordResult_SelectChannelTimeout = 36, + DiscordResult_GetGuildTimeout = 37, + DiscordResult_SelectVoiceForceRequired = 38, + DiscordResult_CaptureShortcutAlreadyListening = 39, + DiscordResult_UnauthorizedForAchievement = 40, + DiscordResult_InvalidGiftCode = 41, + DiscordResult_PurchaseError = 42, + DiscordResult_TransactionAborted = 43, + DiscordResult_DrawingInitFailed = 44, +}; + +enum EDiscordCreateFlags { + DiscordCreateFlags_Default = 0, + DiscordCreateFlags_NoRequireDiscord = 1, +}; + +enum EDiscordLogLevel { + DiscordLogLevel_Error = 1, + DiscordLogLevel_Warn, + DiscordLogLevel_Info, + DiscordLogLevel_Debug, +}; + +enum EDiscordUserFlag { + DiscordUserFlag_Partner = 2, + DiscordUserFlag_HypeSquadEvents = 4, + DiscordUserFlag_HypeSquadHouse1 = 64, + DiscordUserFlag_HypeSquadHouse2 = 128, + DiscordUserFlag_HypeSquadHouse3 = 256, +}; + +enum EDiscordPremiumType { + DiscordPremiumType_None = 0, + DiscordPremiumType_Tier1 = 1, + DiscordPremiumType_Tier2 = 2, +}; + +enum EDiscordImageType { + DiscordImageType_User, +}; + +enum EDiscordActivityPartyPrivacy { + DiscordActivityPartyPrivacy_Private = 0, + DiscordActivityPartyPrivacy_Public = 1, +}; + +enum EDiscordActivityType { + DiscordActivityType_Playing, + DiscordActivityType_Streaming, + DiscordActivityType_Listening, + DiscordActivityType_Watching, +}; + +enum EDiscordActivityActionType { + DiscordActivityActionType_Join = 1, + DiscordActivityActionType_Spectate, +}; + +enum EDiscordActivitySupportedPlatformFlags { + DiscordActivitySupportedPlatformFlags_Desktop = 1, + DiscordActivitySupportedPlatformFlags_Android = 2, + DiscordActivitySupportedPlatformFlags_iOS = 4, +}; + +enum EDiscordActivityJoinRequestReply { + DiscordActivityJoinRequestReply_No, + DiscordActivityJoinRequestReply_Yes, + DiscordActivityJoinRequestReply_Ignore, +}; + +enum EDiscordStatus { + DiscordStatus_Offline = 0, + DiscordStatus_Online = 1, + DiscordStatus_Idle = 2, + DiscordStatus_DoNotDisturb = 3, +}; + +enum EDiscordRelationshipType { + DiscordRelationshipType_None, + DiscordRelationshipType_Friend, + DiscordRelationshipType_Blocked, + DiscordRelationshipType_PendingIncoming, + DiscordRelationshipType_PendingOutgoing, + DiscordRelationshipType_Implicit, +}; + +enum EDiscordLobbyType { + DiscordLobbyType_Private = 1, + DiscordLobbyType_Public, +}; + +enum EDiscordLobbySearchComparison { + DiscordLobbySearchComparison_LessThanOrEqual = -2, + DiscordLobbySearchComparison_LessThan, + DiscordLobbySearchComparison_Equal, + DiscordLobbySearchComparison_GreaterThan, + DiscordLobbySearchComparison_GreaterThanOrEqual, + DiscordLobbySearchComparison_NotEqual, +}; + +enum EDiscordLobbySearchCast { + DiscordLobbySearchCast_String = 1, + DiscordLobbySearchCast_Number, +}; + +enum EDiscordLobbySearchDistance { + DiscordLobbySearchDistance_Local, + DiscordLobbySearchDistance_Default, + DiscordLobbySearchDistance_Extended, + DiscordLobbySearchDistance_Global, +}; + +enum EDiscordKeyVariant { + DiscordKeyVariant_Normal, + DiscordKeyVariant_Right, + DiscordKeyVariant_Left, +}; + +enum EDiscordMouseButton { + DiscordMouseButton_Left, + DiscordMouseButton_Middle, + DiscordMouseButton_Right, +}; + +enum EDiscordEntitlementType { + DiscordEntitlementType_Purchase = 1, + DiscordEntitlementType_PremiumSubscription, + DiscordEntitlementType_DeveloperGift, + DiscordEntitlementType_TestModePurchase, + DiscordEntitlementType_FreePurchase, + DiscordEntitlementType_UserGift, + DiscordEntitlementType_PremiumPurchase, +}; + +enum EDiscordSkuType { + DiscordSkuType_Application = 1, + DiscordSkuType_DLC, + DiscordSkuType_Consumable, + DiscordSkuType_Bundle, +}; + +enum EDiscordInputModeType { + DiscordInputModeType_VoiceActivity = 0, + DiscordInputModeType_PushToTalk, +}; + +typedef int64_t DiscordClientId; +typedef int32_t DiscordVersion; +typedef int64_t DiscordSnowflake; +typedef int64_t DiscordTimestamp; +typedef DiscordSnowflake DiscordUserId; +typedef char DiscordLocale[128]; +typedef char DiscordBranch[4096]; +typedef DiscordSnowflake DiscordLobbyId; +typedef char DiscordLobbySecret[128]; +typedef char DiscordMetadataKey[256]; +typedef char DiscordMetadataValue[4096]; +typedef uint64_t DiscordNetworkPeerId; +typedef uint8_t DiscordNetworkChannelId; +#ifdef __APPLE__ +typedef void IDXGISwapChain; +#endif +#ifdef __linux__ +typedef void IDXGISwapChain; +#endif +#ifdef __APPLE__ +typedef void MSG; +#endif +#ifdef __linux__ +typedef void MSG; +#endif +typedef char DiscordPath[4096]; +typedef char DiscordDateTime[64]; + +struct DiscordUser { + DiscordUserId id; + char username[256]; + char discriminator[8]; + char avatar[128]; + bool bot; +}; + +struct DiscordOAuth2Token { + char access_token[128]; + char scopes[1024]; + DiscordTimestamp expires; +}; + +struct DiscordImageHandle { + enum EDiscordImageType type; + int64_t id; + uint32_t size; +}; + +struct DiscordImageDimensions { + uint32_t width; + uint32_t height; +}; + +struct DiscordActivityTimestamps { + DiscordTimestamp start; + DiscordTimestamp end; +}; + +struct DiscordActivityAssets { + char large_image[128]; + char large_text[128]; + char small_image[128]; + char small_text[128]; +}; + +struct DiscordPartySize { + int32_t current_size; + int32_t max_size; +}; + +struct DiscordActivityParty { + char id[128]; + struct DiscordPartySize size; + enum EDiscordActivityPartyPrivacy privacy; +}; + +struct DiscordActivitySecrets { + char match[128]; + char join[128]; + char spectate[128]; +}; + +struct DiscordActivity { + enum EDiscordActivityType type; + int64_t application_id; + char name[128]; + char state[128]; + char details[128]; + struct DiscordActivityTimestamps timestamps; + struct DiscordActivityAssets assets; + struct DiscordActivityParty party; + struct DiscordActivitySecrets secrets; + bool instance; + uint32_t supported_platforms; +}; + +struct DiscordPresence { + enum EDiscordStatus status; + struct DiscordActivity activity; +}; + +struct DiscordRelationship { + enum EDiscordRelationshipType type; + struct DiscordUser user; + struct DiscordPresence presence; +}; + +struct DiscordLobby { + DiscordLobbyId id; + enum EDiscordLobbyType type; + DiscordUserId owner_id; + DiscordLobbySecret secret; + uint32_t capacity; + bool locked; +}; + +struct DiscordImeUnderline { + int32_t from; + int32_t to; + uint32_t color; + uint32_t background_color; + bool thick; +}; + +struct DiscordRect { + int32_t left; + int32_t top; + int32_t right; + int32_t bottom; +}; + +struct DiscordFileStat { + char filename[260]; + uint64_t size; + uint64_t last_modified; +}; + +struct DiscordEntitlement { + DiscordSnowflake id; + enum EDiscordEntitlementType type; + DiscordSnowflake sku_id; +}; + +struct DiscordSkuPrice { + uint32_t amount; + char currency[16]; +}; + +struct DiscordSku { + DiscordSnowflake id; + enum EDiscordSkuType type; + char name[256]; + struct DiscordSkuPrice price; +}; + +struct DiscordInputMode { + enum EDiscordInputModeType type; + char shortcut[256]; +}; + +struct DiscordUserAchievement { + DiscordSnowflake user_id; + DiscordSnowflake achievement_id; + uint8_t percent_complete; + DiscordDateTime unlocked_at; +}; + +struct IDiscordLobbyTransaction { + enum EDiscordResult(DISCORD_API* set_type)(struct IDiscordLobbyTransaction* lobby_transaction, + enum EDiscordLobbyType type); + enum EDiscordResult(DISCORD_API* set_owner)(struct IDiscordLobbyTransaction* lobby_transaction, + DiscordUserId owner_id); + enum EDiscordResult(DISCORD_API* set_capacity)( + struct IDiscordLobbyTransaction* lobby_transaction, + uint32_t capacity); + enum EDiscordResult(DISCORD_API* set_metadata)( + struct IDiscordLobbyTransaction* lobby_transaction, + DiscordMetadataKey key, + DiscordMetadataValue value); + enum EDiscordResult(DISCORD_API* delete_metadata)( + struct IDiscordLobbyTransaction* lobby_transaction, + DiscordMetadataKey key); + enum EDiscordResult(DISCORD_API* set_locked)(struct IDiscordLobbyTransaction* lobby_transaction, + bool locked); +}; + +struct IDiscordLobbyMemberTransaction { + enum EDiscordResult(DISCORD_API* set_metadata)( + struct IDiscordLobbyMemberTransaction* lobby_member_transaction, + DiscordMetadataKey key, + DiscordMetadataValue value); + enum EDiscordResult(DISCORD_API* delete_metadata)( + struct IDiscordLobbyMemberTransaction* lobby_member_transaction, + DiscordMetadataKey key); +}; + +struct IDiscordLobbySearchQuery { + enum EDiscordResult(DISCORD_API* filter)(struct IDiscordLobbySearchQuery* lobby_search_query, + DiscordMetadataKey key, + enum EDiscordLobbySearchComparison comparison, + enum EDiscordLobbySearchCast cast, + DiscordMetadataValue value); + enum EDiscordResult(DISCORD_API* sort)(struct IDiscordLobbySearchQuery* lobby_search_query, + DiscordMetadataKey key, + enum EDiscordLobbySearchCast cast, + DiscordMetadataValue value); + enum EDiscordResult(DISCORD_API* limit)(struct IDiscordLobbySearchQuery* lobby_search_query, + uint32_t limit); + enum EDiscordResult(DISCORD_API* distance)(struct IDiscordLobbySearchQuery* lobby_search_query, + enum EDiscordLobbySearchDistance distance); +}; + +typedef void* IDiscordApplicationEvents; + +struct IDiscordApplicationManager { + void(DISCORD_API* validate_or_exit)(struct IDiscordApplicationManager* manager, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* get_current_locale)(struct IDiscordApplicationManager* manager, + DiscordLocale* locale); + void(DISCORD_API* get_current_branch)(struct IDiscordApplicationManager* manager, + DiscordBranch* branch); + void(DISCORD_API* get_oauth2_token)( + struct IDiscordApplicationManager* manager, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result, + struct DiscordOAuth2Token* oauth2_token)); + void(DISCORD_API* get_ticket)(struct IDiscordApplicationManager* manager, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result, + const char* data)); +}; + +struct IDiscordUserEvents { + void(DISCORD_API* on_current_user_update)(void* event_data); +}; + +struct IDiscordUserManager { + enum EDiscordResult(DISCORD_API* get_current_user)(struct IDiscordUserManager* manager, + struct DiscordUser* current_user); + void(DISCORD_API* get_user)(struct IDiscordUserManager* manager, + DiscordUserId user_id, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result, + struct DiscordUser* user)); + enum EDiscordResult(DISCORD_API* get_current_user_premium_type)( + struct IDiscordUserManager* manager, + enum EDiscordPremiumType* premium_type); + enum EDiscordResult(DISCORD_API* current_user_has_flag)(struct IDiscordUserManager* manager, + enum EDiscordUserFlag flag, + bool* has_flag); +}; + +typedef void* IDiscordImageEvents; + +struct IDiscordImageManager { + void(DISCORD_API* fetch)(struct IDiscordImageManager* manager, + struct DiscordImageHandle handle, + bool refresh, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result, + struct DiscordImageHandle handle_result)); + enum EDiscordResult(DISCORD_API* get_dimensions)(struct IDiscordImageManager* manager, + struct DiscordImageHandle handle, + struct DiscordImageDimensions* dimensions); + enum EDiscordResult(DISCORD_API* get_data)(struct IDiscordImageManager* manager, + struct DiscordImageHandle handle, + uint8_t* data, + uint32_t data_length); +}; + +struct IDiscordActivityEvents { + void(DISCORD_API* on_activity_join)(void* event_data, const char* secret); + void(DISCORD_API* on_activity_spectate)(void* event_data, const char* secret); + void(DISCORD_API* on_activity_join_request)(void* event_data, struct DiscordUser* user); + void(DISCORD_API* on_activity_invite)(void* event_data, + enum EDiscordActivityActionType type, + struct DiscordUser* user, + struct DiscordActivity* activity); +}; + +struct IDiscordActivityManager { + enum EDiscordResult(DISCORD_API* register_command)(struct IDiscordActivityManager* manager, + const char* command); + enum EDiscordResult(DISCORD_API* register_steam)(struct IDiscordActivityManager* manager, + uint32_t steam_id); + void(DISCORD_API* update_activity)(struct IDiscordActivityManager* manager, + struct DiscordActivity* activity, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* clear_activity)(struct IDiscordActivityManager* manager, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* send_request_reply)(struct IDiscordActivityManager* manager, + DiscordUserId user_id, + enum EDiscordActivityJoinRequestReply reply, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* send_invite)(struct IDiscordActivityManager* manager, + DiscordUserId user_id, + enum EDiscordActivityActionType type, + const char* content, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* accept_invite)(struct IDiscordActivityManager* manager, + DiscordUserId user_id, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); +}; + +struct IDiscordRelationshipEvents { + void(DISCORD_API* on_refresh)(void* event_data); + void(DISCORD_API* on_relationship_update)(void* event_data, + struct DiscordRelationship* relationship); +}; + +struct IDiscordRelationshipManager { + void(DISCORD_API* filter)(struct IDiscordRelationshipManager* manager, + void* filter_data, + bool(DISCORD_API* filter)(void* filter_data, + struct DiscordRelationship* relationship)); + enum EDiscordResult(DISCORD_API* count)(struct IDiscordRelationshipManager* manager, + int32_t* count); + enum EDiscordResult(DISCORD_API* get)(struct IDiscordRelationshipManager* manager, + DiscordUserId user_id, + struct DiscordRelationship* relationship); + enum EDiscordResult(DISCORD_API* get_at)(struct IDiscordRelationshipManager* manager, + uint32_t index, + struct DiscordRelationship* relationship); +}; + +struct IDiscordLobbyEvents { + void(DISCORD_API* on_lobby_update)(void* event_data, int64_t lobby_id); + void(DISCORD_API* on_lobby_delete)(void* event_data, int64_t lobby_id, uint32_t reason); + void(DISCORD_API* on_member_connect)(void* event_data, int64_t lobby_id, int64_t user_id); + void(DISCORD_API* on_member_update)(void* event_data, int64_t lobby_id, int64_t user_id); + void(DISCORD_API* on_member_disconnect)(void* event_data, int64_t lobby_id, int64_t user_id); + void(DISCORD_API* on_lobby_message)(void* event_data, + int64_t lobby_id, + int64_t user_id, + uint8_t* data, + uint32_t data_length); + void(DISCORD_API* on_speaking)(void* event_data, + int64_t lobby_id, + int64_t user_id, + bool speaking); + void(DISCORD_API* on_network_message)(void* event_data, + int64_t lobby_id, + int64_t user_id, + uint8_t channel_id, + uint8_t* data, + uint32_t data_length); +}; + +struct IDiscordLobbyManager { + enum EDiscordResult(DISCORD_API* get_lobby_create_transaction)( + struct IDiscordLobbyManager* manager, + struct IDiscordLobbyTransaction** transaction); + enum EDiscordResult(DISCORD_API* get_lobby_update_transaction)( + struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + struct IDiscordLobbyTransaction** transaction); + enum EDiscordResult(DISCORD_API* get_member_update_transaction)( + struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + DiscordUserId user_id, + struct IDiscordLobbyMemberTransaction** transaction); + void(DISCORD_API* create_lobby)(struct IDiscordLobbyManager* manager, + struct IDiscordLobbyTransaction* transaction, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result, + struct DiscordLobby* lobby)); + void(DISCORD_API* update_lobby)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + struct IDiscordLobbyTransaction* transaction, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* delete_lobby)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* connect_lobby)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + DiscordLobbySecret secret, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result, + struct DiscordLobby* lobby)); + void(DISCORD_API* connect_lobby_with_activity_secret)( + struct IDiscordLobbyManager* manager, + DiscordLobbySecret activity_secret, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result, + struct DiscordLobby* lobby)); + void(DISCORD_API* disconnect_lobby)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + enum EDiscordResult(DISCORD_API* get_lobby)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + struct DiscordLobby* lobby); + enum EDiscordResult(DISCORD_API* get_lobby_activity_secret)( + struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + DiscordLobbySecret* secret); + enum EDiscordResult(DISCORD_API* get_lobby_metadata_value)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + DiscordMetadataKey key, + DiscordMetadataValue* value); + enum EDiscordResult(DISCORD_API* get_lobby_metadata_key)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + int32_t index, + DiscordMetadataKey* key); + enum EDiscordResult(DISCORD_API* lobby_metadata_count)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + int32_t* count); + enum EDiscordResult(DISCORD_API* member_count)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + int32_t* count); + enum EDiscordResult(DISCORD_API* get_member_user_id)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + int32_t index, + DiscordUserId* user_id); + enum EDiscordResult(DISCORD_API* get_member_user)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + DiscordUserId user_id, + struct DiscordUser* user); + enum EDiscordResult(DISCORD_API* get_member_metadata_value)( + struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + DiscordUserId user_id, + DiscordMetadataKey key, + DiscordMetadataValue* value); + enum EDiscordResult(DISCORD_API* get_member_metadata_key)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + DiscordUserId user_id, + int32_t index, + DiscordMetadataKey* key); + enum EDiscordResult(DISCORD_API* member_metadata_count)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + DiscordUserId user_id, + int32_t* count); + void(DISCORD_API* update_member)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + DiscordUserId user_id, + struct IDiscordLobbyMemberTransaction* transaction, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* send_lobby_message)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + uint8_t* data, + uint32_t data_length, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + enum EDiscordResult(DISCORD_API* get_search_query)(struct IDiscordLobbyManager* manager, + struct IDiscordLobbySearchQuery** query); + void(DISCORD_API* search)(struct IDiscordLobbyManager* manager, + struct IDiscordLobbySearchQuery* query, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* lobby_count)(struct IDiscordLobbyManager* manager, int32_t* count); + enum EDiscordResult(DISCORD_API* get_lobby_id)(struct IDiscordLobbyManager* manager, + int32_t index, + DiscordLobbyId* lobby_id); + void(DISCORD_API* connect_voice)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* disconnect_voice)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + enum EDiscordResult(DISCORD_API* connect_network)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id); + enum EDiscordResult(DISCORD_API* disconnect_network)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id); + enum EDiscordResult(DISCORD_API* flush_network)(struct IDiscordLobbyManager* manager); + enum EDiscordResult(DISCORD_API* open_network_channel)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + uint8_t channel_id, + bool reliable); + enum EDiscordResult(DISCORD_API* send_network_message)(struct IDiscordLobbyManager* manager, + DiscordLobbyId lobby_id, + DiscordUserId user_id, + uint8_t channel_id, + uint8_t* data, + uint32_t data_length); +}; + +struct IDiscordNetworkEvents { + void(DISCORD_API* on_message)(void* event_data, + DiscordNetworkPeerId peer_id, + DiscordNetworkChannelId channel_id, + uint8_t* data, + uint32_t data_length); + void(DISCORD_API* on_route_update)(void* event_data, const char* route_data); +}; + +struct IDiscordNetworkManager { + /** + * Get the local peer ID for this process. + */ + void(DISCORD_API* get_peer_id)(struct IDiscordNetworkManager* manager, + DiscordNetworkPeerId* peer_id); + /** + * Send pending network messages. + */ + enum EDiscordResult(DISCORD_API* flush)(struct IDiscordNetworkManager* manager); + /** + * Open a connection to a remote peer. + */ + enum EDiscordResult(DISCORD_API* open_peer)(struct IDiscordNetworkManager* manager, + DiscordNetworkPeerId peer_id, + const char* route_data); + /** + * Update the route data for a connected peer. + */ + enum EDiscordResult(DISCORD_API* update_peer)(struct IDiscordNetworkManager* manager, + DiscordNetworkPeerId peer_id, + const char* route_data); + /** + * Close the connection to a remote peer. + */ + enum EDiscordResult(DISCORD_API* close_peer)(struct IDiscordNetworkManager* manager, + DiscordNetworkPeerId peer_id); + /** + * Open a message channel to a connected peer. + */ + enum EDiscordResult(DISCORD_API* open_channel)(struct IDiscordNetworkManager* manager, + DiscordNetworkPeerId peer_id, + DiscordNetworkChannelId channel_id, + bool reliable); + /** + * Close a message channel to a connected peer. + */ + enum EDiscordResult(DISCORD_API* close_channel)(struct IDiscordNetworkManager* manager, + DiscordNetworkPeerId peer_id, + DiscordNetworkChannelId channel_id); + /** + * Send a message to a connected peer over an opened message channel. + */ + enum EDiscordResult(DISCORD_API* send_message)(struct IDiscordNetworkManager* manager, + DiscordNetworkPeerId peer_id, + DiscordNetworkChannelId channel_id, + uint8_t* data, + uint32_t data_length); +}; + +struct IDiscordOverlayEvents { + void(DISCORD_API* on_toggle)(void* event_data, bool locked); +}; + +struct IDiscordOverlayManager { + void(DISCORD_API* is_enabled)(struct IDiscordOverlayManager* manager, bool* enabled); + void(DISCORD_API* is_locked)(struct IDiscordOverlayManager* manager, bool* locked); + void(DISCORD_API* set_locked)(struct IDiscordOverlayManager* manager, + bool locked, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* open_activity_invite)( + struct IDiscordOverlayManager* manager, + enum EDiscordActivityActionType type, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, enum EDiscordResult result)); + void(DISCORD_API* open_guild_invite)(struct IDiscordOverlayManager* manager, + const char* code, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* open_voice_settings)(struct IDiscordOverlayManager* manager, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + enum EDiscordResult(DISCORD_API* init_drawing_dxgi)(struct IDiscordOverlayManager* manager, + IDXGISwapChain* swapchain, + bool use_message_forwarding); + void(DISCORD_API* on_present)(struct IDiscordOverlayManager* manager); + void(DISCORD_API* forward_message)(struct IDiscordOverlayManager* manager, MSG* message); + void(DISCORD_API* key_event)(struct IDiscordOverlayManager* manager, + bool down, + const char* key_code, + enum EDiscordKeyVariant variant); + void(DISCORD_API* char_event)(struct IDiscordOverlayManager* manager, const char* character); + void(DISCORD_API* mouse_button_event)(struct IDiscordOverlayManager* manager, + uint8_t down, + int32_t click_count, + enum EDiscordMouseButton which, + int32_t x, + int32_t y); + void(DISCORD_API* mouse_motion_event)(struct IDiscordOverlayManager* manager, + int32_t x, + int32_t y); + void(DISCORD_API* ime_commit_text)(struct IDiscordOverlayManager* manager, const char* text); + void(DISCORD_API* ime_set_composition)(struct IDiscordOverlayManager* manager, + const char* text, + struct DiscordImeUnderline* underlines, + uint32_t underlines_length, + int32_t from, + int32_t to); + void(DISCORD_API* ime_cancel_composition)(struct IDiscordOverlayManager* manager); + void(DISCORD_API* set_ime_composition_range_callback)( + struct IDiscordOverlayManager* manager, + void* on_ime_composition_range_changed_data, + void(DISCORD_API* on_ime_composition_range_changed)( + void* on_ime_composition_range_changed_data, + int32_t from, + int32_t to, + struct DiscordRect* bounds, + uint32_t bounds_length)); + void(DISCORD_API* set_ime_selection_bounds_callback)( + struct IDiscordOverlayManager* manager, + void* on_ime_selection_bounds_changed_data, + void(DISCORD_API* on_ime_selection_bounds_changed)(void* on_ime_selection_bounds_changed_data, + struct DiscordRect anchor, + struct DiscordRect focus, + bool is_anchor_first)); + bool(DISCORD_API* is_point_inside_click_zone)(struct IDiscordOverlayManager* manager, + int32_t x, + int32_t y); +}; + +typedef void* IDiscordStorageEvents; + +struct IDiscordStorageManager { + enum EDiscordResult(DISCORD_API* read)(struct IDiscordStorageManager* manager, + const char* name, + uint8_t* data, + uint32_t data_length, + uint32_t* read); + void(DISCORD_API* read_async)(struct IDiscordStorageManager* manager, + const char* name, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result, + uint8_t* data, + uint32_t data_length)); + void(DISCORD_API* read_async_partial)(struct IDiscordStorageManager* manager, + const char* name, + uint64_t offset, + uint64_t length, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result, + uint8_t* data, + uint32_t data_length)); + enum EDiscordResult(DISCORD_API* write)(struct IDiscordStorageManager* manager, + const char* name, + uint8_t* data, + uint32_t data_length); + void(DISCORD_API* write_async)(struct IDiscordStorageManager* manager, + const char* name, + uint8_t* data, + uint32_t data_length, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + enum EDiscordResult(DISCORD_API* delete_)(struct IDiscordStorageManager* manager, + const char* name); + enum EDiscordResult(DISCORD_API* exists)(struct IDiscordStorageManager* manager, + const char* name, + bool* exists); + void(DISCORD_API* count)(struct IDiscordStorageManager* manager, int32_t* count); + enum EDiscordResult(DISCORD_API* stat)(struct IDiscordStorageManager* manager, + const char* name, + struct DiscordFileStat* stat); + enum EDiscordResult(DISCORD_API* stat_at)(struct IDiscordStorageManager* manager, + int32_t index, + struct DiscordFileStat* stat); + enum EDiscordResult(DISCORD_API* get_path)(struct IDiscordStorageManager* manager, + DiscordPath* path); +}; + +struct IDiscordStoreEvents { + void(DISCORD_API* on_entitlement_create)(void* event_data, + struct DiscordEntitlement* entitlement); + void(DISCORD_API* on_entitlement_delete)(void* event_data, + struct DiscordEntitlement* entitlement); +}; + +struct IDiscordStoreManager { + void(DISCORD_API* fetch_skus)(struct IDiscordStoreManager* manager, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* count_skus)(struct IDiscordStoreManager* manager, int32_t* count); + enum EDiscordResult(DISCORD_API* get_sku)(struct IDiscordStoreManager* manager, + DiscordSnowflake sku_id, + struct DiscordSku* sku); + enum EDiscordResult(DISCORD_API* get_sku_at)(struct IDiscordStoreManager* manager, + int32_t index, + struct DiscordSku* sku); + void(DISCORD_API* fetch_entitlements)(struct IDiscordStoreManager* manager, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + void(DISCORD_API* count_entitlements)(struct IDiscordStoreManager* manager, int32_t* count); + enum EDiscordResult(DISCORD_API* get_entitlement)(struct IDiscordStoreManager* manager, + DiscordSnowflake entitlement_id, + struct DiscordEntitlement* entitlement); + enum EDiscordResult(DISCORD_API* get_entitlement_at)(struct IDiscordStoreManager* manager, + int32_t index, + struct DiscordEntitlement* entitlement); + enum EDiscordResult(DISCORD_API* has_sku_entitlement)(struct IDiscordStoreManager* manager, + DiscordSnowflake sku_id, + bool* has_entitlement); + void(DISCORD_API* start_purchase)(struct IDiscordStoreManager* manager, + DiscordSnowflake sku_id, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); +}; + +struct IDiscordVoiceEvents { + void(DISCORD_API* on_settings_update)(void* event_data); +}; + +struct IDiscordVoiceManager { + enum EDiscordResult(DISCORD_API* get_input_mode)(struct IDiscordVoiceManager* manager, + struct DiscordInputMode* input_mode); + void(DISCORD_API* set_input_mode)(struct IDiscordVoiceManager* manager, + struct DiscordInputMode input_mode, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, + enum EDiscordResult result)); + enum EDiscordResult(DISCORD_API* is_self_mute)(struct IDiscordVoiceManager* manager, + bool* mute); + enum EDiscordResult(DISCORD_API* set_self_mute)(struct IDiscordVoiceManager* manager, + bool mute); + enum EDiscordResult(DISCORD_API* is_self_deaf)(struct IDiscordVoiceManager* manager, + bool* deaf); + enum EDiscordResult(DISCORD_API* set_self_deaf)(struct IDiscordVoiceManager* manager, + bool deaf); + enum EDiscordResult(DISCORD_API* is_local_mute)(struct IDiscordVoiceManager* manager, + DiscordSnowflake user_id, + bool* mute); + enum EDiscordResult(DISCORD_API* set_local_mute)(struct IDiscordVoiceManager* manager, + DiscordSnowflake user_id, + bool mute); + enum EDiscordResult(DISCORD_API* get_local_volume)(struct IDiscordVoiceManager* manager, + DiscordSnowflake user_id, + uint8_t* volume); + enum EDiscordResult(DISCORD_API* set_local_volume)(struct IDiscordVoiceManager* manager, + DiscordSnowflake user_id, + uint8_t volume); +}; + +struct IDiscordAchievementEvents { + void(DISCORD_API* on_user_achievement_update)(void* event_data, + struct DiscordUserAchievement* user_achievement); +}; + +struct IDiscordAchievementManager { + void(DISCORD_API* set_user_achievement)( + struct IDiscordAchievementManager* manager, + DiscordSnowflake achievement_id, + uint8_t percent_complete, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, enum EDiscordResult result)); + void(DISCORD_API* fetch_user_achievements)( + struct IDiscordAchievementManager* manager, + void* callback_data, + void(DISCORD_API* callback)(void* callback_data, enum EDiscordResult result)); + void(DISCORD_API* count_user_achievements)(struct IDiscordAchievementManager* manager, + int32_t* count); + enum EDiscordResult(DISCORD_API* get_user_achievement)( + struct IDiscordAchievementManager* manager, + DiscordSnowflake user_achievement_id, + struct DiscordUserAchievement* user_achievement); + enum EDiscordResult(DISCORD_API* get_user_achievement_at)( + struct IDiscordAchievementManager* manager, + int32_t index, + struct DiscordUserAchievement* user_achievement); +}; + +typedef void* IDiscordCoreEvents; + +struct IDiscordCore { + void(DISCORD_API* destroy)(struct IDiscordCore* core); + enum EDiscordResult(DISCORD_API* run_callbacks)(struct IDiscordCore* core); + void(DISCORD_API* set_log_hook)(struct IDiscordCore* core, + enum EDiscordLogLevel min_level, + void* hook_data, + void(DISCORD_API* hook)(void* hook_data, + enum EDiscordLogLevel level, + const char* message)); + struct IDiscordApplicationManager*(DISCORD_API* get_application_manager)( + struct IDiscordCore* core); + struct IDiscordUserManager*(DISCORD_API* get_user_manager)(struct IDiscordCore* core); + struct IDiscordImageManager*(DISCORD_API* get_image_manager)(struct IDiscordCore* core); + struct IDiscordActivityManager*(DISCORD_API* get_activity_manager)(struct IDiscordCore* core); + struct IDiscordRelationshipManager*(DISCORD_API* get_relationship_manager)( + struct IDiscordCore* core); + struct IDiscordLobbyManager*(DISCORD_API* get_lobby_manager)(struct IDiscordCore* core); + struct IDiscordNetworkManager*(DISCORD_API* get_network_manager)(struct IDiscordCore* core); + struct IDiscordOverlayManager*(DISCORD_API* get_overlay_manager)(struct IDiscordCore* core); + struct IDiscordStorageManager*(DISCORD_API* get_storage_manager)(struct IDiscordCore* core); + struct IDiscordStoreManager*(DISCORD_API* get_store_manager)(struct IDiscordCore* core); + struct IDiscordVoiceManager*(DISCORD_API* get_voice_manager)(struct IDiscordCore* core); + struct IDiscordAchievementManager*(DISCORD_API* get_achievement_manager)( + struct IDiscordCore* core); +}; + +struct DiscordCreateParams { + DiscordClientId client_id; + uint64_t flags; + IDiscordCoreEvents* events; + void* event_data; + IDiscordApplicationEvents* application_events; + DiscordVersion application_version; + struct IDiscordUserEvents* user_events; + DiscordVersion user_version; + IDiscordImageEvents* image_events; + DiscordVersion image_version; + struct IDiscordActivityEvents* activity_events; + DiscordVersion activity_version; + struct IDiscordRelationshipEvents* relationship_events; + DiscordVersion relationship_version; + struct IDiscordLobbyEvents* lobby_events; + DiscordVersion lobby_version; + struct IDiscordNetworkEvents* network_events; + DiscordVersion network_version; + struct IDiscordOverlayEvents* overlay_events; + DiscordVersion overlay_version; + IDiscordStorageEvents* storage_events; + DiscordVersion storage_version; + struct IDiscordStoreEvents* store_events; + DiscordVersion store_version; + struct IDiscordVoiceEvents* voice_events; + DiscordVersion voice_version; + struct IDiscordAchievementEvents* achievement_events; + DiscordVersion achievement_version; +}; + +#ifdef __cplusplus +inline +#else +static +#endif + void + DiscordCreateParamsSetDefault(struct DiscordCreateParams* params) +{ + memset(params, 0, sizeof(struct DiscordCreateParams)); + params->application_version = DISCORD_APPLICATION_MANAGER_VERSION; + params->user_version = DISCORD_USER_MANAGER_VERSION; + params->image_version = DISCORD_IMAGE_MANAGER_VERSION; + params->activity_version = DISCORD_ACTIVITY_MANAGER_VERSION; + params->relationship_version = DISCORD_RELATIONSHIP_MANAGER_VERSION; + params->lobby_version = DISCORD_LOBBY_MANAGER_VERSION; + params->network_version = DISCORD_NETWORK_MANAGER_VERSION; + params->overlay_version = DISCORD_OVERLAY_MANAGER_VERSION; + params->storage_version = DISCORD_STORAGE_MANAGER_VERSION; + params->store_version = DISCORD_STORE_MANAGER_VERSION; + params->voice_version = DISCORD_VOICE_MANAGER_VERSION; + params->achievement_version = DISCORD_ACHIEVEMENT_MANAGER_VERSION; +} + +enum EDiscordResult DISCORD_API DiscordCreate(DiscordVersion version, + struct DiscordCreateParams* params, + struct IDiscordCore** result); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Crawler/discord-files/image_manager.cpp b/Crawler/discord-files/image_manager.cpp new file mode 100644 index 00000000..03b1db49 --- /dev/null +++ b/Crawler/discord-files/image_manager.cpp @@ -0,0 +1,57 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "image_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +void ImageManager::Fetch(ImageHandle handle, + bool refresh, + std::function callback) +{ + static auto wrapper = + [](void* callbackData, EDiscordResult result, DiscordImageHandle handleResult) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result), *reinterpret_cast(&handleResult)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->fetch(internal_, + *reinterpret_cast(&handle), + (refresh ? 1 : 0), + cb.release(), + wrapper); +} + +Result ImageManager::GetDimensions(ImageHandle handle, ImageDimensions* dimensions) +{ + if (!dimensions) { + return Result::InternalError; + } + + auto result = internal_->get_dimensions(internal_, + *reinterpret_cast(&handle), + reinterpret_cast(dimensions)); + return static_cast(result); +} + +Result ImageManager::GetData(ImageHandle handle, std::uint8_t* data, std::uint32_t dataLength) +{ + auto result = internal_->get_data(internal_, + *reinterpret_cast(&handle), + reinterpret_cast(data), + dataLength); + return static_cast(result); +} + +} // namespace discord diff --git a/Crawler/discord-files/image_manager.h b/Crawler/discord-files/image_manager.h new file mode 100644 index 00000000..b096b171 --- /dev/null +++ b/Crawler/discord-files/image_manager.h @@ -0,0 +1,28 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class ImageManager final { +public: + ~ImageManager() = default; + + void Fetch(ImageHandle handle, bool refresh, std::function callback); + Result GetDimensions(ImageHandle handle, ImageDimensions* dimensions); + Result GetData(ImageHandle handle, std::uint8_t* data, std::uint32_t dataLength); + +private: + friend class Core; + + ImageManager() = default; + ImageManager(ImageManager const& rhs) = delete; + ImageManager& operator=(ImageManager const& rhs) = delete; + ImageManager(ImageManager&& rhs) = delete; + ImageManager& operator=(ImageManager&& rhs) = delete; + + IDiscordImageManager* internal_; + static IDiscordImageEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/lobby_manager.cpp b/Crawler/discord-files/lobby_manager.cpp new file mode 100644 index 00000000..3a95b1a0 --- /dev/null +++ b/Crawler/discord-files/lobby_manager.cpp @@ -0,0 +1,554 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "lobby_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +class LobbyEvents final { +public: + static void DISCORD_CALLBACK OnLobbyUpdate(void* callbackData, int64_t lobbyId) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->LobbyManager(); + module.OnLobbyUpdate(lobbyId); + } + + static void DISCORD_CALLBACK OnLobbyDelete(void* callbackData, int64_t lobbyId, uint32_t reason) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->LobbyManager(); + module.OnLobbyDelete(lobbyId, reason); + } + + static void DISCORD_CALLBACK OnMemberConnect(void* callbackData, + int64_t lobbyId, + int64_t userId) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->LobbyManager(); + module.OnMemberConnect(lobbyId, userId); + } + + static void DISCORD_CALLBACK OnMemberUpdate(void* callbackData, int64_t lobbyId, int64_t userId) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->LobbyManager(); + module.OnMemberUpdate(lobbyId, userId); + } + + static void DISCORD_CALLBACK OnMemberDisconnect(void* callbackData, + int64_t lobbyId, + int64_t userId) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->LobbyManager(); + module.OnMemberDisconnect(lobbyId, userId); + } + + static void DISCORD_CALLBACK OnLobbyMessage(void* callbackData, + int64_t lobbyId, + int64_t userId, + uint8_t* data, + uint32_t dataLength) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->LobbyManager(); + module.OnLobbyMessage(lobbyId, userId, data, dataLength); + } + + static void DISCORD_CALLBACK OnSpeaking(void* callbackData, + int64_t lobbyId, + int64_t userId, + bool speaking) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->LobbyManager(); + module.OnSpeaking(lobbyId, userId, (speaking != 0)); + } + + static void DISCORD_CALLBACK OnNetworkMessage(void* callbackData, + int64_t lobbyId, + int64_t userId, + uint8_t channelId, + uint8_t* data, + uint32_t dataLength) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->LobbyManager(); + module.OnNetworkMessage(lobbyId, userId, channelId, data, dataLength); + } +}; + +IDiscordLobbyEvents LobbyManager::events_{ + &LobbyEvents::OnLobbyUpdate, + &LobbyEvents::OnLobbyDelete, + &LobbyEvents::OnMemberConnect, + &LobbyEvents::OnMemberUpdate, + &LobbyEvents::OnMemberDisconnect, + &LobbyEvents::OnLobbyMessage, + &LobbyEvents::OnSpeaking, + &LobbyEvents::OnNetworkMessage, +}; + +Result LobbyManager::GetLobbyCreateTransaction(LobbyTransaction* transaction) +{ + if (!transaction) { + return Result::InternalError; + } + + auto result = internal_->get_lobby_create_transaction(internal_, transaction->Receive()); + return static_cast(result); +} + +Result LobbyManager::GetLobbyUpdateTransaction(LobbyId lobbyId, LobbyTransaction* transaction) +{ + if (!transaction) { + return Result::InternalError; + } + + auto result = + internal_->get_lobby_update_transaction(internal_, lobbyId, transaction->Receive()); + return static_cast(result); +} + +Result LobbyManager::GetMemberUpdateTransaction(LobbyId lobbyId, + UserId userId, + LobbyMemberTransaction* transaction) +{ + if (!transaction) { + return Result::InternalError; + } + + auto result = + internal_->get_member_update_transaction(internal_, lobbyId, userId, transaction->Receive()); + return static_cast(result); +} + +void LobbyManager::CreateLobby(LobbyTransaction const& transaction, + std::function callback) +{ + static auto wrapper = + [](void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result), *reinterpret_cast(lobby)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->create_lobby( + internal_, const_cast(transaction).Internal(), cb.release(), wrapper); +} + +void LobbyManager::UpdateLobby(LobbyId lobbyId, + LobbyTransaction const& transaction, + std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->update_lobby(internal_, + lobbyId, + const_cast(transaction).Internal(), + cb.release(), + wrapper); +} + +void LobbyManager::DeleteLobby(LobbyId lobbyId, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->delete_lobby(internal_, lobbyId, cb.release(), wrapper); +} + +void LobbyManager::ConnectLobby(LobbyId lobbyId, + LobbySecret secret, + std::function callback) +{ + static auto wrapper = + [](void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result), *reinterpret_cast(lobby)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->connect_lobby(internal_, lobbyId, const_cast(secret), cb.release(), wrapper); +} + +void LobbyManager::ConnectLobbyWithActivitySecret( + LobbySecret activitySecret, + std::function callback) +{ + static auto wrapper = + [](void* callbackData, EDiscordResult result, DiscordLobby* lobby) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result), *reinterpret_cast(lobby)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->connect_lobby_with_activity_secret( + internal_, const_cast(activitySecret), cb.release(), wrapper); +} + +void LobbyManager::DisconnectLobby(LobbyId lobbyId, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->disconnect_lobby(internal_, lobbyId, cb.release(), wrapper); +} + +Result LobbyManager::GetLobby(LobbyId lobbyId, Lobby* lobby) +{ + if (!lobby) { + return Result::InternalError; + } + + auto result = internal_->get_lobby(internal_, lobbyId, reinterpret_cast(lobby)); + return static_cast(result); +} + +Result LobbyManager::GetLobbyActivitySecret(LobbyId lobbyId, char secret[128]) +{ + if (!secret) { + return Result::InternalError; + } + + auto result = internal_->get_lobby_activity_secret( + internal_, lobbyId, reinterpret_cast(secret)); + return static_cast(result); +} + +Result LobbyManager::GetLobbyMetadataValue(LobbyId lobbyId, MetadataKey key, char value[4096]) +{ + if (!value) { + return Result::InternalError; + } + + auto result = internal_->get_lobby_metadata_value( + internal_, lobbyId, const_cast(key), reinterpret_cast(value)); + return static_cast(result); +} + +Result LobbyManager::GetLobbyMetadataKey(LobbyId lobbyId, std::int32_t index, char key[256]) +{ + if (!key) { + return Result::InternalError; + } + + auto result = internal_->get_lobby_metadata_key( + internal_, lobbyId, index, reinterpret_cast(key)); + return static_cast(result); +} + +Result LobbyManager::LobbyMetadataCount(LobbyId lobbyId, std::int32_t* count) +{ + if (!count) { + return Result::InternalError; + } + + auto result = + internal_->lobby_metadata_count(internal_, lobbyId, reinterpret_cast(count)); + return static_cast(result); +} + +Result LobbyManager::MemberCount(LobbyId lobbyId, std::int32_t* count) +{ + if (!count) { + return Result::InternalError; + } + + auto result = internal_->member_count(internal_, lobbyId, reinterpret_cast(count)); + return static_cast(result); +} + +Result LobbyManager::GetMemberUserId(LobbyId lobbyId, std::int32_t index, UserId* userId) +{ + if (!userId) { + return Result::InternalError; + } + + auto result = + internal_->get_member_user_id(internal_, lobbyId, index, reinterpret_cast(userId)); + return static_cast(result); +} + +Result LobbyManager::GetMemberUser(LobbyId lobbyId, UserId userId, User* user) +{ + if (!user) { + return Result::InternalError; + } + + auto result = + internal_->get_member_user(internal_, lobbyId, userId, reinterpret_cast(user)); + return static_cast(result); +} + +Result LobbyManager::GetMemberMetadataValue(LobbyId lobbyId, + UserId userId, + MetadataKey key, + char value[4096]) +{ + if (!value) { + return Result::InternalError; + } + + auto result = + internal_->get_member_metadata_value(internal_, + lobbyId, + userId, + const_cast(key), + reinterpret_cast(value)); + return static_cast(result); +} + +Result LobbyManager::GetMemberMetadataKey(LobbyId lobbyId, + UserId userId, + std::int32_t index, + char key[256]) +{ + if (!key) { + return Result::InternalError; + } + + auto result = internal_->get_member_metadata_key( + internal_, lobbyId, userId, index, reinterpret_cast(key)); + return static_cast(result); +} + +Result LobbyManager::MemberMetadataCount(LobbyId lobbyId, UserId userId, std::int32_t* count) +{ + if (!count) { + return Result::InternalError; + } + + auto result = internal_->member_metadata_count( + internal_, lobbyId, userId, reinterpret_cast(count)); + return static_cast(result); +} + +void LobbyManager::UpdateMember(LobbyId lobbyId, + UserId userId, + LobbyMemberTransaction const& transaction, + std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->update_member(internal_, + lobbyId, + userId, + const_cast(transaction).Internal(), + cb.release(), + wrapper); +} + +void LobbyManager::SendLobbyMessage(LobbyId lobbyId, + std::uint8_t* data, + std::uint32_t dataLength, + std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->send_lobby_message( + internal_, lobbyId, reinterpret_cast(data), dataLength, cb.release(), wrapper); +} + +Result LobbyManager::GetSearchQuery(LobbySearchQuery* query) +{ + if (!query) { + return Result::InternalError; + } + + auto result = internal_->get_search_query(internal_, query->Receive()); + return static_cast(result); +} + +void LobbyManager::Search(LobbySearchQuery const& query, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->search( + internal_, const_cast(query).Internal(), cb.release(), wrapper); +} + +void LobbyManager::LobbyCount(std::int32_t* count) +{ + if (!count) { + return; + } + + internal_->lobby_count(internal_, reinterpret_cast(count)); +} + +Result LobbyManager::GetLobbyId(std::int32_t index, LobbyId* lobbyId) +{ + if (!lobbyId) { + return Result::InternalError; + } + + auto result = internal_->get_lobby_id(internal_, index, reinterpret_cast(lobbyId)); + return static_cast(result); +} + +void LobbyManager::ConnectVoice(LobbyId lobbyId, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->connect_voice(internal_, lobbyId, cb.release(), wrapper); +} + +void LobbyManager::DisconnectVoice(LobbyId lobbyId, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->disconnect_voice(internal_, lobbyId, cb.release(), wrapper); +} + +Result LobbyManager::ConnectNetwork(LobbyId lobbyId) +{ + auto result = internal_->connect_network(internal_, lobbyId); + return static_cast(result); +} + +Result LobbyManager::DisconnectNetwork(LobbyId lobbyId) +{ + auto result = internal_->disconnect_network(internal_, lobbyId); + return static_cast(result); +} + +Result LobbyManager::FlushNetwork() +{ + auto result = internal_->flush_network(internal_); + return static_cast(result); +} + +Result LobbyManager::OpenNetworkChannel(LobbyId lobbyId, std::uint8_t channelId, bool reliable) +{ + auto result = + internal_->open_network_channel(internal_, lobbyId, channelId, (reliable ? 1 : 0)); + return static_cast(result); +} + +Result LobbyManager::SendNetworkMessage(LobbyId lobbyId, + UserId userId, + std::uint8_t channelId, + std::uint8_t* data, + std::uint32_t dataLength) +{ + auto result = internal_->send_network_message( + internal_, lobbyId, userId, channelId, reinterpret_cast(data), dataLength); + return static_cast(result); +} + +} // namespace discord diff --git a/Crawler/discord-files/lobby_manager.h b/Crawler/discord-files/lobby_manager.h new file mode 100644 index 00000000..96380cbf --- /dev/null +++ b/Crawler/discord-files/lobby_manager.h @@ -0,0 +1,88 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class LobbyManager final { +public: + ~LobbyManager() = default; + + Result GetLobbyCreateTransaction(LobbyTransaction* transaction); + Result GetLobbyUpdateTransaction(LobbyId lobbyId, LobbyTransaction* transaction); + Result GetMemberUpdateTransaction(LobbyId lobbyId, + UserId userId, + LobbyMemberTransaction* transaction); + void CreateLobby(LobbyTransaction const& transaction, + std::function callback); + void UpdateLobby(LobbyId lobbyId, + LobbyTransaction const& transaction, + std::function callback); + void DeleteLobby(LobbyId lobbyId, std::function callback); + void ConnectLobby(LobbyId lobbyId, + LobbySecret secret, + std::function callback); + void ConnectLobbyWithActivitySecret(LobbySecret activitySecret, + std::function callback); + void DisconnectLobby(LobbyId lobbyId, std::function callback); + Result GetLobby(LobbyId lobbyId, Lobby* lobby); + Result GetLobbyActivitySecret(LobbyId lobbyId, char secret[128]); + Result GetLobbyMetadataValue(LobbyId lobbyId, MetadataKey key, char value[4096]); + Result GetLobbyMetadataKey(LobbyId lobbyId, std::int32_t index, char key[256]); + Result LobbyMetadataCount(LobbyId lobbyId, std::int32_t* count); + Result MemberCount(LobbyId lobbyId, std::int32_t* count); + Result GetMemberUserId(LobbyId lobbyId, std::int32_t index, UserId* userId); + Result GetMemberUser(LobbyId lobbyId, UserId userId, User* user); + Result GetMemberMetadataValue(LobbyId lobbyId, + UserId userId, + MetadataKey key, + char value[4096]); + Result GetMemberMetadataKey(LobbyId lobbyId, UserId userId, std::int32_t index, char key[256]); + Result MemberMetadataCount(LobbyId lobbyId, UserId userId, std::int32_t* count); + void UpdateMember(LobbyId lobbyId, + UserId userId, + LobbyMemberTransaction const& transaction, + std::function callback); + void SendLobbyMessage(LobbyId lobbyId, + std::uint8_t* data, + std::uint32_t dataLength, + std::function callback); + Result GetSearchQuery(LobbySearchQuery* query); + void Search(LobbySearchQuery const& query, std::function callback); + void LobbyCount(std::int32_t* count); + Result GetLobbyId(std::int32_t index, LobbyId* lobbyId); + void ConnectVoice(LobbyId lobbyId, std::function callback); + void DisconnectVoice(LobbyId lobbyId, std::function callback); + Result ConnectNetwork(LobbyId lobbyId); + Result DisconnectNetwork(LobbyId lobbyId); + Result FlushNetwork(); + Result OpenNetworkChannel(LobbyId lobbyId, std::uint8_t channelId, bool reliable); + Result SendNetworkMessage(LobbyId lobbyId, + UserId userId, + std::uint8_t channelId, + std::uint8_t* data, + std::uint32_t dataLength); + + Event OnLobbyUpdate; + Event OnLobbyDelete; + Event OnMemberConnect; + Event OnMemberUpdate; + Event OnMemberDisconnect; + Event OnLobbyMessage; + Event OnSpeaking; + Event OnNetworkMessage; + +private: + friend class Core; + + LobbyManager() = default; + LobbyManager(LobbyManager const& rhs) = delete; + LobbyManager& operator=(LobbyManager const& rhs) = delete; + LobbyManager(LobbyManager&& rhs) = delete; + LobbyManager& operator=(LobbyManager&& rhs) = delete; + + IDiscordLobbyManager* internal_; + static IDiscordLobbyEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/network_manager.cpp b/Crawler/discord-files/network_manager.cpp new file mode 100644 index 00000000..36031b32 --- /dev/null +++ b/Crawler/discord-files/network_manager.cpp @@ -0,0 +1,103 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "network_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +class NetworkEvents final { +public: + static void DISCORD_CALLBACK OnMessage(void* callbackData, + DiscordNetworkPeerId peerId, + DiscordNetworkChannelId channelId, + uint8_t* data, + uint32_t dataLength) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->NetworkManager(); + module.OnMessage(peerId, channelId, data, dataLength); + } + + static void DISCORD_CALLBACK OnRouteUpdate(void* callbackData, char const* routeData) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->NetworkManager(); + module.OnRouteUpdate(static_cast(routeData)); + } +}; + +IDiscordNetworkEvents NetworkManager::events_{ + &NetworkEvents::OnMessage, + &NetworkEvents::OnRouteUpdate, +}; + +void NetworkManager::GetPeerId(NetworkPeerId* peerId) +{ + if (!peerId) { + return; + } + + internal_->get_peer_id(internal_, reinterpret_cast(peerId)); +} + +Result NetworkManager::Flush() +{ + auto result = internal_->flush(internal_); + return static_cast(result); +} + +Result NetworkManager::OpenPeer(NetworkPeerId peerId, char const* routeData) +{ + auto result = internal_->open_peer(internal_, peerId, const_cast(routeData)); + return static_cast(result); +} + +Result NetworkManager::UpdatePeer(NetworkPeerId peerId, char const* routeData) +{ + auto result = internal_->update_peer(internal_, peerId, const_cast(routeData)); + return static_cast(result); +} + +Result NetworkManager::ClosePeer(NetworkPeerId peerId) +{ + auto result = internal_->close_peer(internal_, peerId); + return static_cast(result); +} + +Result NetworkManager::OpenChannel(NetworkPeerId peerId, NetworkChannelId channelId, bool reliable) +{ + auto result = internal_->open_channel(internal_, peerId, channelId, (reliable ? 1 : 0)); + return static_cast(result); +} + +Result NetworkManager::CloseChannel(NetworkPeerId peerId, NetworkChannelId channelId) +{ + auto result = internal_->close_channel(internal_, peerId, channelId); + return static_cast(result); +} + +Result NetworkManager::SendMessage(NetworkPeerId peerId, + NetworkChannelId channelId, + std::uint8_t* data, + std::uint32_t dataLength) +{ + auto result = internal_->send_message( + internal_, peerId, channelId, reinterpret_cast(data), dataLength); + return static_cast(result); +} + +} // namespace discord diff --git a/Crawler/discord-files/network_manager.h b/Crawler/discord-files/network_manager.h new file mode 100644 index 00000000..e374670a --- /dev/null +++ b/Crawler/discord-files/network_manager.h @@ -0,0 +1,63 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class NetworkManager final { +public: + ~NetworkManager() = default; + + /** + * Get the local peer ID for this process. + */ + void GetPeerId(NetworkPeerId* peerId); + /** + * Send pending network messages. + */ + Result Flush(); + /** + * Open a connection to a remote peer. + */ + Result OpenPeer(NetworkPeerId peerId, char const* routeData); + /** + * Update the route data for a connected peer. + */ + Result UpdatePeer(NetworkPeerId peerId, char const* routeData); + /** + * Close the connection to a remote peer. + */ + Result ClosePeer(NetworkPeerId peerId); + /** + * Open a message channel to a connected peer. + */ + Result OpenChannel(NetworkPeerId peerId, NetworkChannelId channelId, bool reliable); + /** + * Close a message channel to a connected peer. + */ + Result CloseChannel(NetworkPeerId peerId, NetworkChannelId channelId); + /** + * Send a message to a connected peer over an opened message channel. + */ + Result SendMessage(NetworkPeerId peerId, + NetworkChannelId channelId, + std::uint8_t* data, + std::uint32_t dataLength); + + Event OnMessage; + Event OnRouteUpdate; + +private: + friend class Core; + + NetworkManager() = default; + NetworkManager(NetworkManager const& rhs) = delete; + NetworkManager& operator=(NetworkManager const& rhs) = delete; + NetworkManager(NetworkManager&& rhs) = delete; + NetworkManager& operator=(NetworkManager&& rhs) = delete; + + IDiscordNetworkManager* internal_; + static IDiscordNetworkEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/overlay_manager.cpp b/Crawler/discord-files/overlay_manager.cpp new file mode 100644 index 00000000..f4b1fba7 --- /dev/null +++ b/Crawler/discord-files/overlay_manager.cpp @@ -0,0 +1,229 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "overlay_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +class OverlayEvents final { +public: + static void DISCORD_CALLBACK OnToggle(void* callbackData, bool locked) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->OverlayManager(); + module.OnToggle((locked != 0)); + } +}; + +IDiscordOverlayEvents OverlayManager::events_{ + &OverlayEvents::OnToggle, +}; + +void OverlayManager::IsEnabled(bool* enabled) +{ + if (!enabled) { + return; + } + + internal_->is_enabled(internal_, reinterpret_cast(enabled)); +} + +void OverlayManager::IsLocked(bool* locked) +{ + if (!locked) { + return; + } + + internal_->is_locked(internal_, reinterpret_cast(locked)); +} + +void OverlayManager::SetLocked(bool locked, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->set_locked(internal_, (locked ? 1 : 0), cb.release(), wrapper); +} + +void OverlayManager::OpenActivityInvite(ActivityActionType type, + std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->open_activity_invite( + internal_, static_cast(type), cb.release(), wrapper); +} + +void OverlayManager::OpenGuildInvite(char const* code, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->open_guild_invite(internal_, const_cast(code), cb.release(), wrapper); +} + +void OverlayManager::OpenVoiceSettings(std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->open_voice_settings(internal_, cb.release(), wrapper); +} + +Result OverlayManager::InitDrawingDxgi(IDXGISwapChain* swapchain, bool useMessageForwarding) +{ + auto result = + internal_->init_drawing_dxgi(internal_, swapchain, (useMessageForwarding ? 1 : 0)); + return static_cast(result); +} + +void OverlayManager::OnPresent() +{ + internal_->on_present(internal_); +} + +void OverlayManager::ForwardMessage(MSG* message) +{ + internal_->forward_message(internal_, message); +} + +void OverlayManager::KeyEvent(bool down, char const* keyCode, KeyVariant variant) +{ + internal_->key_event(internal_, + (down ? 1 : 0), + const_cast(keyCode), + static_cast(variant)); +} + +void OverlayManager::CharEvent(char const* character) +{ + internal_->char_event(internal_, const_cast(character)); +} + +void OverlayManager::MouseButtonEvent(std::uint8_t down, + std::int32_t clickCount, + MouseButton which, + std::int32_t x, + std::int32_t y) +{ + internal_->mouse_button_event( + internal_, down, clickCount, static_cast(which), x, y); +} + +void OverlayManager::MouseMotionEvent(std::int32_t x, std::int32_t y) +{ + internal_->mouse_motion_event(internal_, x, y); +} + +void OverlayManager::ImeCommitText(char const* text) +{ + internal_->ime_commit_text(internal_, const_cast(text)); +} + +void OverlayManager::ImeSetComposition(char const* text, + ImeUnderline* underlines, + std::uint32_t underlinesLength, + std::int32_t from, + std::int32_t to) +{ + internal_->ime_set_composition(internal_, + const_cast(text), + reinterpret_cast(underlines), + underlinesLength, + from, + to); +} + +void OverlayManager::ImeCancelComposition() +{ + internal_->ime_cancel_composition(internal_); +} + +void OverlayManager::SetImeCompositionRangeCallback( + std::function + onImeCompositionRangeChanged) +{ + static auto wrapper = [](void* callbackData, + int32_t from, + int32_t to, + DiscordRect* bounds, + uint32_t boundsLength) -> void { + std::unique_ptr> cb( + reinterpret_cast*>( + callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(from, to, reinterpret_cast(bounds), boundsLength); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function( + std::move(onImeCompositionRangeChanged))); + internal_->set_ime_composition_range_callback(internal_, cb.release(), wrapper); +} + +void OverlayManager::SetImeSelectionBoundsCallback( + std::function onImeSelectionBoundsChanged) +{ + static auto wrapper = + [](void* callbackData, DiscordRect anchor, DiscordRect focus, bool isAnchorFirst) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(*reinterpret_cast(&anchor), + *reinterpret_cast(&focus), + (isAnchorFirst != 0)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(onImeSelectionBoundsChanged))); + internal_->set_ime_selection_bounds_callback(internal_, cb.release(), wrapper); +} + +bool OverlayManager::IsPointInsideClickZone(std::int32_t x, std::int32_t y) +{ + auto result = internal_->is_point_inside_click_zone(internal_, x, y); + return (result != 0); +} + +} // namespace discord diff --git a/Crawler/discord-files/overlay_manager.h b/Crawler/discord-files/overlay_manager.h new file mode 100644 index 00000000..5f73a367 --- /dev/null +++ b/Crawler/discord-files/overlay_manager.h @@ -0,0 +1,57 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class OverlayManager final { +public: + ~OverlayManager() = default; + + void IsEnabled(bool* enabled); + void IsLocked(bool* locked); + void SetLocked(bool locked, std::function callback); + void OpenActivityInvite(ActivityActionType type, std::function callback); + void OpenGuildInvite(char const* code, std::function callback); + void OpenVoiceSettings(std::function callback); + Result InitDrawingDxgi(IDXGISwapChain* swapchain, bool useMessageForwarding); + void OnPresent(); + void ForwardMessage(MSG* message); + void KeyEvent(bool down, char const* keyCode, KeyVariant variant); + void CharEvent(char const* character); + void MouseButtonEvent(std::uint8_t down, + std::int32_t clickCount, + MouseButton which, + std::int32_t x, + std::int32_t y); + void MouseMotionEvent(std::int32_t x, std::int32_t y); + void ImeCommitText(char const* text); + void ImeSetComposition(char const* text, + ImeUnderline* underlines, + std::uint32_t underlinesLength, + std::int32_t from, + std::int32_t to); + void ImeCancelComposition(); + void SetImeCompositionRangeCallback( + std::function + onImeCompositionRangeChanged); + void SetImeSelectionBoundsCallback( + std::function onImeSelectionBoundsChanged); + bool IsPointInsideClickZone(std::int32_t x, std::int32_t y); + + Event OnToggle; + +private: + friend class Core; + + OverlayManager() = default; + OverlayManager(OverlayManager const& rhs) = delete; + OverlayManager& operator=(OverlayManager const& rhs) = delete; + OverlayManager(OverlayManager&& rhs) = delete; + OverlayManager& operator=(OverlayManager&& rhs) = delete; + + IDiscordOverlayManager* internal_; + static IDiscordOverlayEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/relationship_manager.cpp b/Crawler/discord-files/relationship_manager.cpp new file mode 100644 index 00000000..dce874ea --- /dev/null +++ b/Crawler/discord-files/relationship_manager.cpp @@ -0,0 +1,91 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "relationship_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +class RelationshipEvents final { +public: + static void DISCORD_CALLBACK OnRefresh(void* callbackData) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->RelationshipManager(); + module.OnRefresh(); + } + + static void DISCORD_CALLBACK OnRelationshipUpdate(void* callbackData, + DiscordRelationship* relationship) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->RelationshipManager(); + module.OnRelationshipUpdate(*reinterpret_cast(relationship)); + } +}; + +IDiscordRelationshipEvents RelationshipManager::events_{ + &RelationshipEvents::OnRefresh, + &RelationshipEvents::OnRelationshipUpdate, +}; + +void RelationshipManager::Filter(std::function filter) +{ + static auto wrapper = [](void* callbackData, DiscordRelationship* relationship) -> bool { + auto cb(reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return {}; + } + return (*cb)(*reinterpret_cast(relationship)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(filter))); + internal_->filter(internal_, cb.get(), wrapper); +} + +Result RelationshipManager::Count(std::int32_t* count) +{ + if (!count) { + return Result::InternalError; + } + + auto result = internal_->count(internal_, reinterpret_cast(count)); + return static_cast(result); +} + +Result RelationshipManager::Get(UserId userId, Relationship* relationship) +{ + if (!relationship) { + return Result::InternalError; + } + + auto result = + internal_->get(internal_, userId, reinterpret_cast(relationship)); + return static_cast(result); +} + +Result RelationshipManager::GetAt(std::uint32_t index, Relationship* relationship) +{ + if (!relationship) { + return Result::InternalError; + } + + auto result = + internal_->get_at(internal_, index, reinterpret_cast(relationship)); + return static_cast(result); +} + +} // namespace discord diff --git a/Crawler/discord-files/relationship_manager.h b/Crawler/discord-files/relationship_manager.h new file mode 100644 index 00000000..e9cd0161 --- /dev/null +++ b/Crawler/discord-files/relationship_manager.h @@ -0,0 +1,32 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class RelationshipManager final { +public: + ~RelationshipManager() = default; + + void Filter(std::function filter); + Result Count(std::int32_t* count); + Result Get(UserId userId, Relationship* relationship); + Result GetAt(std::uint32_t index, Relationship* relationship); + + Event<> OnRefresh; + Event OnRelationshipUpdate; + +private: + friend class Core; + + RelationshipManager() = default; + RelationshipManager(RelationshipManager const& rhs) = delete; + RelationshipManager& operator=(RelationshipManager const& rhs) = delete; + RelationshipManager(RelationshipManager&& rhs) = delete; + RelationshipManager& operator=(RelationshipManager&& rhs) = delete; + + IDiscordRelationshipManager* internal_; + static IDiscordRelationshipEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/storage_manager.cpp b/Crawler/discord-files/storage_manager.cpp new file mode 100644 index 00000000..fbf9ca75 --- /dev/null +++ b/Crawler/discord-files/storage_manager.cpp @@ -0,0 +1,158 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "storage_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +Result StorageManager::Read(char const* name, + std::uint8_t* data, + std::uint32_t dataLength, + std::uint32_t* read) +{ + if (!read) { + return Result::InternalError; + } + + auto result = internal_->read(internal_, + const_cast(name), + reinterpret_cast(data), + dataLength, + reinterpret_cast(read)); + return static_cast(result); +} + +void StorageManager::ReadAsync(char const* name, + std::function callback) +{ + static auto wrapper = + [](void* callbackData, EDiscordResult result, uint8_t* data, uint32_t dataLength) -> void { + std::unique_ptr> cb( + reinterpret_cast*>( + callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result), data, dataLength); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->read_async(internal_, const_cast(name), cb.release(), wrapper); +} + +void StorageManager::ReadAsyncPartial( + char const* name, + std::uint64_t offset, + std::uint64_t length, + std::function callback) +{ + static auto wrapper = + [](void* callbackData, EDiscordResult result, uint8_t* data, uint32_t dataLength) -> void { + std::unique_ptr> cb( + reinterpret_cast*>( + callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result), data, dataLength); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->read_async_partial( + internal_, const_cast(name), offset, length, cb.release(), wrapper); +} + +Result StorageManager::Write(char const* name, std::uint8_t* data, std::uint32_t dataLength) +{ + auto result = internal_->write( + internal_, const_cast(name), reinterpret_cast(data), dataLength); + return static_cast(result); +} + +void StorageManager::WriteAsync(char const* name, + std::uint8_t* data, + std::uint32_t dataLength, + std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->write_async(internal_, + const_cast(name), + reinterpret_cast(data), + dataLength, + cb.release(), + wrapper); +} + +Result StorageManager::Delete(char const* name) +{ + auto result = internal_->delete_(internal_, const_cast(name)); + return static_cast(result); +} + +Result StorageManager::Exists(char const* name, bool* exists) +{ + if (!exists) { + return Result::InternalError; + } + + auto result = + internal_->exists(internal_, const_cast(name), reinterpret_cast(exists)); + return static_cast(result); +} + +void StorageManager::Count(std::int32_t* count) +{ + if (!count) { + return; + } + + internal_->count(internal_, reinterpret_cast(count)); +} + +Result StorageManager::Stat(char const* name, FileStat* stat) +{ + if (!stat) { + return Result::InternalError; + } + + auto result = + internal_->stat(internal_, const_cast(name), reinterpret_cast(stat)); + return static_cast(result); +} + +Result StorageManager::StatAt(std::int32_t index, FileStat* stat) +{ + if (!stat) { + return Result::InternalError; + } + + auto result = internal_->stat_at(internal_, index, reinterpret_cast(stat)); + return static_cast(result); +} + +Result StorageManager::GetPath(char path[4096]) +{ + if (!path) { + return Result::InternalError; + } + + auto result = internal_->get_path(internal_, reinterpret_cast(path)); + return static_cast(result); +} + +} // namespace discord diff --git a/Crawler/discord-files/storage_manager.h b/Crawler/discord-files/storage_manager.h new file mode 100644 index 00000000..5d6d17b1 --- /dev/null +++ b/Crawler/discord-files/storage_manager.h @@ -0,0 +1,46 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class StorageManager final { +public: + ~StorageManager() = default; + + Result Read(char const* name, + std::uint8_t* data, + std::uint32_t dataLength, + std::uint32_t* read); + void ReadAsync(char const* name, + std::function callback); + void ReadAsyncPartial(char const* name, + std::uint64_t offset, + std::uint64_t length, + std::function callback); + Result Write(char const* name, std::uint8_t* data, std::uint32_t dataLength); + void WriteAsync(char const* name, + std::uint8_t* data, + std::uint32_t dataLength, + std::function callback); + Result Delete(char const* name); + Result Exists(char const* name, bool* exists); + void Count(std::int32_t* count); + Result Stat(char const* name, FileStat* stat); + Result StatAt(std::int32_t index, FileStat* stat); + Result GetPath(char path[4096]); + +private: + friend class Core; + + StorageManager() = default; + StorageManager(StorageManager const& rhs) = delete; + StorageManager& operator=(StorageManager const& rhs) = delete; + StorageManager(StorageManager&& rhs) = delete; + StorageManager& operator=(StorageManager&& rhs) = delete; + + IDiscordStorageManager* internal_; + static IDiscordStorageEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/store_manager.cpp b/Crawler/discord-files/store_manager.cpp new file mode 100644 index 00000000..40c7e656 --- /dev/null +++ b/Crawler/discord-files/store_manager.cpp @@ -0,0 +1,162 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "store_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +class StoreEvents final { +public: + static void DISCORD_CALLBACK OnEntitlementCreate(void* callbackData, + DiscordEntitlement* entitlement) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->StoreManager(); + module.OnEntitlementCreate(*reinterpret_cast(entitlement)); + } + + static void DISCORD_CALLBACK OnEntitlementDelete(void* callbackData, + DiscordEntitlement* entitlement) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->StoreManager(); + module.OnEntitlementDelete(*reinterpret_cast(entitlement)); + } +}; + +IDiscordStoreEvents StoreManager::events_{ + &StoreEvents::OnEntitlementCreate, + &StoreEvents::OnEntitlementDelete, +}; + +void StoreManager::FetchSkus(std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->fetch_skus(internal_, cb.release(), wrapper); +} + +void StoreManager::CountSkus(std::int32_t* count) +{ + if (!count) { + return; + } + + internal_->count_skus(internal_, reinterpret_cast(count)); +} + +Result StoreManager::GetSku(Snowflake skuId, Sku* sku) +{ + if (!sku) { + return Result::InternalError; + } + + auto result = internal_->get_sku(internal_, skuId, reinterpret_cast(sku)); + return static_cast(result); +} + +Result StoreManager::GetSkuAt(std::int32_t index, Sku* sku) +{ + if (!sku) { + return Result::InternalError; + } + + auto result = internal_->get_sku_at(internal_, index, reinterpret_cast(sku)); + return static_cast(result); +} + +void StoreManager::FetchEntitlements(std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->fetch_entitlements(internal_, cb.release(), wrapper); +} + +void StoreManager::CountEntitlements(std::int32_t* count) +{ + if (!count) { + return; + } + + internal_->count_entitlements(internal_, reinterpret_cast(count)); +} + +Result StoreManager::GetEntitlement(Snowflake entitlementId, Entitlement* entitlement) +{ + if (!entitlement) { + return Result::InternalError; + } + + auto result = internal_->get_entitlement( + internal_, entitlementId, reinterpret_cast(entitlement)); + return static_cast(result); +} + +Result StoreManager::GetEntitlementAt(std::int32_t index, Entitlement* entitlement) +{ + if (!entitlement) { + return Result::InternalError; + } + + auto result = internal_->get_entitlement_at( + internal_, index, reinterpret_cast(entitlement)); + return static_cast(result); +} + +Result StoreManager::HasSkuEntitlement(Snowflake skuId, bool* hasEntitlement) +{ + if (!hasEntitlement) { + return Result::InternalError; + } + + auto result = + internal_->has_sku_entitlement(internal_, skuId, reinterpret_cast(hasEntitlement)); + return static_cast(result); +} + +void StoreManager::StartPurchase(Snowflake skuId, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->start_purchase(internal_, skuId, cb.release(), wrapper); +} + +} // namespace discord diff --git a/Crawler/discord-files/store_manager.h b/Crawler/discord-files/store_manager.h new file mode 100644 index 00000000..8e0df8ac --- /dev/null +++ b/Crawler/discord-files/store_manager.h @@ -0,0 +1,38 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class StoreManager final { +public: + ~StoreManager() = default; + + void FetchSkus(std::function callback); + void CountSkus(std::int32_t* count); + Result GetSku(Snowflake skuId, Sku* sku); + Result GetSkuAt(std::int32_t index, Sku* sku); + void FetchEntitlements(std::function callback); + void CountEntitlements(std::int32_t* count); + Result GetEntitlement(Snowflake entitlementId, Entitlement* entitlement); + Result GetEntitlementAt(std::int32_t index, Entitlement* entitlement); + Result HasSkuEntitlement(Snowflake skuId, bool* hasEntitlement); + void StartPurchase(Snowflake skuId, std::function callback); + + Event OnEntitlementCreate; + Event OnEntitlementDelete; + +private: + friend class Core; + + StoreManager() = default; + StoreManager(StoreManager const& rhs) = delete; + StoreManager& operator=(StoreManager const& rhs) = delete; + StoreManager(StoreManager&& rhs) = delete; + StoreManager& operator=(StoreManager&& rhs) = delete; + + IDiscordStoreManager* internal_; + static IDiscordStoreEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/types.cpp b/Crawler/discord-files/types.cpp new file mode 100644 index 00000000..b60dded0 --- /dev/null +++ b/Crawler/discord-files/types.cpp @@ -0,0 +1,879 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "types.h" + +#include +#include + +namespace discord { + +void User::SetId(UserId id) +{ + internal_.id = id; +} + +UserId User::GetId() const +{ + return internal_.id; +} + +void User::SetUsername(char const* username) +{ + strncpy(internal_.username, username, 256); + internal_.username[256 - 1] = '\0'; +} + +char const* User::GetUsername() const +{ + return internal_.username; +} + +void User::SetDiscriminator(char const* discriminator) +{ + strncpy(internal_.discriminator, discriminator, 8); + internal_.discriminator[8 - 1] = '\0'; +} + +char const* User::GetDiscriminator() const +{ + return internal_.discriminator; +} + +void User::SetAvatar(char const* avatar) +{ + strncpy(internal_.avatar, avatar, 128); + internal_.avatar[128 - 1] = '\0'; +} + +char const* User::GetAvatar() const +{ + return internal_.avatar; +} + +void User::SetBot(bool bot) +{ + internal_.bot = bot; +} + +bool User::GetBot() const +{ + return internal_.bot != 0; +} + +void OAuth2Token::SetAccessToken(char const* accessToken) +{ + strncpy(internal_.access_token, accessToken, 128); + internal_.access_token[128 - 1] = '\0'; +} + +char const* OAuth2Token::GetAccessToken() const +{ + return internal_.access_token; +} + +void OAuth2Token::SetScopes(char const* scopes) +{ + strncpy(internal_.scopes, scopes, 1024); + internal_.scopes[1024 - 1] = '\0'; +} + +char const* OAuth2Token::GetScopes() const +{ + return internal_.scopes; +} + +void OAuth2Token::SetExpires(Timestamp expires) +{ + internal_.expires = expires; +} + +Timestamp OAuth2Token::GetExpires() const +{ + return internal_.expires; +} + +void ImageHandle::SetType(ImageType type) +{ + internal_.type = static_cast(type); +} + +ImageType ImageHandle::GetType() const +{ + return static_cast(internal_.type); +} + +void ImageHandle::SetId(std::int64_t id) +{ + internal_.id = id; +} + +std::int64_t ImageHandle::GetId() const +{ + return internal_.id; +} + +void ImageHandle::SetSize(std::uint32_t size) +{ + internal_.size = size; +} + +std::uint32_t ImageHandle::GetSize() const +{ + return internal_.size; +} + +void ImageDimensions::SetWidth(std::uint32_t width) +{ + internal_.width = width; +} + +std::uint32_t ImageDimensions::GetWidth() const +{ + return internal_.width; +} + +void ImageDimensions::SetHeight(std::uint32_t height) +{ + internal_.height = height; +} + +std::uint32_t ImageDimensions::GetHeight() const +{ + return internal_.height; +} + +void ActivityTimestamps::SetStart(Timestamp start) +{ + internal_.start = start; +} + +Timestamp ActivityTimestamps::GetStart() const +{ + return internal_.start; +} + +void ActivityTimestamps::SetEnd(Timestamp end) +{ + internal_.end = end; +} + +Timestamp ActivityTimestamps::GetEnd() const +{ + return internal_.end; +} + +void ActivityAssets::SetLargeImage(char const* largeImage) +{ + strncpy(internal_.large_image, largeImage, 128); + internal_.large_image[128 - 1] = '\0'; +} + +char const* ActivityAssets::GetLargeImage() const +{ + return internal_.large_image; +} + +void ActivityAssets::SetLargeText(char const* largeText) +{ + strncpy(internal_.large_text, largeText, 128); + internal_.large_text[128 - 1] = '\0'; +} + +char const* ActivityAssets::GetLargeText() const +{ + return internal_.large_text; +} + +void ActivityAssets::SetSmallImage(char const* smallImage) +{ + strncpy(internal_.small_image, smallImage, 128); + internal_.small_image[128 - 1] = '\0'; +} + +char const* ActivityAssets::GetSmallImage() const +{ + return internal_.small_image; +} + +void ActivityAssets::SetSmallText(char const* smallText) +{ + strncpy(internal_.small_text, smallText, 128); + internal_.small_text[128 - 1] = '\0'; +} + +char const* ActivityAssets::GetSmallText() const +{ + return internal_.small_text; +} + +void PartySize::SetCurrentSize(std::int32_t currentSize) +{ + internal_.current_size = currentSize; +} + +std::int32_t PartySize::GetCurrentSize() const +{ + return internal_.current_size; +} + +void PartySize::SetMaxSize(std::int32_t maxSize) +{ + internal_.max_size = maxSize; +} + +std::int32_t PartySize::GetMaxSize() const +{ + return internal_.max_size; +} + +void ActivityParty::SetId(char const* id) +{ + strncpy(internal_.id, id, 128); + internal_.id[128 - 1] = '\0'; +} + +char const* ActivityParty::GetId() const +{ + return internal_.id; +} + +PartySize& ActivityParty::GetSize() +{ + return reinterpret_cast(internal_.size); +} + +PartySize const& ActivityParty::GetSize() const +{ + return reinterpret_cast(internal_.size); +} + +void ActivityParty::SetPrivacy(ActivityPartyPrivacy privacy) +{ + internal_.privacy = static_cast(privacy); +} + +ActivityPartyPrivacy ActivityParty::GetPrivacy() const +{ + return static_cast(internal_.privacy); +} + +void ActivitySecrets::SetMatch(char const* match) +{ + strncpy(internal_.match, match, 128); + internal_.match[128 - 1] = '\0'; +} + +char const* ActivitySecrets::GetMatch() const +{ + return internal_.match; +} + +void ActivitySecrets::SetJoin(char const* join) +{ + strncpy(internal_.join, join, 128); + internal_.join[128 - 1] = '\0'; +} + +char const* ActivitySecrets::GetJoin() const +{ + return internal_.join; +} + +void ActivitySecrets::SetSpectate(char const* spectate) +{ + strncpy(internal_.spectate, spectate, 128); + internal_.spectate[128 - 1] = '\0'; +} + +char const* ActivitySecrets::GetSpectate() const +{ + return internal_.spectate; +} + +void Activity::SetType(ActivityType type) +{ + internal_.type = static_cast(type); +} + +ActivityType Activity::GetType() const +{ + return static_cast(internal_.type); +} + +void Activity::SetApplicationId(std::int64_t applicationId) +{ + internal_.application_id = applicationId; +} + +std::int64_t Activity::GetApplicationId() const +{ + return internal_.application_id; +} + +void Activity::SetName(char const* name) +{ + strncpy(internal_.name, name, 128); + internal_.name[128 - 1] = '\0'; +} + +char const* Activity::GetName() const +{ + return internal_.name; +} + +void Activity::SetState(char const* state) +{ + strncpy(internal_.state, state, 128); + internal_.state[128 - 1] = '\0'; +} + +char const* Activity::GetState() const +{ + return internal_.state; +} + +void Activity::SetDetails(char const* details) +{ + strncpy(internal_.details, details, 128); + internal_.details[128 - 1] = '\0'; +} + +char const* Activity::GetDetails() const +{ + return internal_.details; +} + +ActivityTimestamps& Activity::GetTimestamps() +{ + return reinterpret_cast(internal_.timestamps); +} + +ActivityTimestamps const& Activity::GetTimestamps() const +{ + return reinterpret_cast(internal_.timestamps); +} + +ActivityAssets& Activity::GetAssets() +{ + return reinterpret_cast(internal_.assets); +} + +ActivityAssets const& Activity::GetAssets() const +{ + return reinterpret_cast(internal_.assets); +} + +ActivityParty& Activity::GetParty() +{ + return reinterpret_cast(internal_.party); +} + +ActivityParty const& Activity::GetParty() const +{ + return reinterpret_cast(internal_.party); +} + +ActivitySecrets& Activity::GetSecrets() +{ + return reinterpret_cast(internal_.secrets); +} + +ActivitySecrets const& Activity::GetSecrets() const +{ + return reinterpret_cast(internal_.secrets); +} + +void Activity::SetInstance(bool instance) +{ + internal_.instance = instance; +} + +bool Activity::GetInstance() const +{ + return internal_.instance != 0; +} + +void Activity::SetSupportedPlatforms(std::uint32_t supportedPlatforms) +{ + internal_.supported_platforms = supportedPlatforms; +} + +std::uint32_t Activity::GetSupportedPlatforms() const +{ + return internal_.supported_platforms; +} + +void Presence::SetStatus(Status status) +{ + internal_.status = static_cast(status); +} + +Status Presence::GetStatus() const +{ + return static_cast(internal_.status); +} + +Activity& Presence::GetActivity() +{ + return reinterpret_cast(internal_.activity); +} + +Activity const& Presence::GetActivity() const +{ + return reinterpret_cast(internal_.activity); +} + +void Relationship::SetType(RelationshipType type) +{ + internal_.type = static_cast(type); +} + +RelationshipType Relationship::GetType() const +{ + return static_cast(internal_.type); +} + +User& Relationship::GetUser() +{ + return reinterpret_cast(internal_.user); +} + +User const& Relationship::GetUser() const +{ + return reinterpret_cast(internal_.user); +} + +Presence& Relationship::GetPresence() +{ + return reinterpret_cast(internal_.presence); +} + +Presence const& Relationship::GetPresence() const +{ + return reinterpret_cast(internal_.presence); +} + +void Lobby::SetId(LobbyId id) +{ + internal_.id = id; +} + +LobbyId Lobby::GetId() const +{ + return internal_.id; +} + +void Lobby::SetType(LobbyType type) +{ + internal_.type = static_cast(type); +} + +LobbyType Lobby::GetType() const +{ + return static_cast(internal_.type); +} + +void Lobby::SetOwnerId(UserId ownerId) +{ + internal_.owner_id = ownerId; +} + +UserId Lobby::GetOwnerId() const +{ + return internal_.owner_id; +} + +void Lobby::SetSecret(LobbySecret secret) +{ + strncpy(internal_.secret, secret, 128); + internal_.secret[128 - 1] = '\0'; +} + +LobbySecret Lobby::GetSecret() const +{ + return internal_.secret; +} + +void Lobby::SetCapacity(std::uint32_t capacity) +{ + internal_.capacity = capacity; +} + +std::uint32_t Lobby::GetCapacity() const +{ + return internal_.capacity; +} + +void Lobby::SetLocked(bool locked) +{ + internal_.locked = locked; +} + +bool Lobby::GetLocked() const +{ + return internal_.locked != 0; +} + +void ImeUnderline::SetFrom(std::int32_t from) +{ + internal_.from = from; +} + +std::int32_t ImeUnderline::GetFrom() const +{ + return internal_.from; +} + +void ImeUnderline::SetTo(std::int32_t to) +{ + internal_.to = to; +} + +std::int32_t ImeUnderline::GetTo() const +{ + return internal_.to; +} + +void ImeUnderline::SetColor(std::uint32_t color) +{ + internal_.color = color; +} + +std::uint32_t ImeUnderline::GetColor() const +{ + return internal_.color; +} + +void ImeUnderline::SetBackgroundColor(std::uint32_t backgroundColor) +{ + internal_.background_color = backgroundColor; +} + +std::uint32_t ImeUnderline::GetBackgroundColor() const +{ + return internal_.background_color; +} + +void ImeUnderline::SetThick(bool thick) +{ + internal_.thick = thick; +} + +bool ImeUnderline::GetThick() const +{ + return internal_.thick != 0; +} + +void Rect::SetLeft(std::int32_t left) +{ + internal_.left = left; +} + +std::int32_t Rect::GetLeft() const +{ + return internal_.left; +} + +void Rect::SetTop(std::int32_t top) +{ + internal_.top = top; +} + +std::int32_t Rect::GetTop() const +{ + return internal_.top; +} + +void Rect::SetRight(std::int32_t right) +{ + internal_.right = right; +} + +std::int32_t Rect::GetRight() const +{ + return internal_.right; +} + +void Rect::SetBottom(std::int32_t bottom) +{ + internal_.bottom = bottom; +} + +std::int32_t Rect::GetBottom() const +{ + return internal_.bottom; +} + +void FileStat::SetFilename(char const* filename) +{ + strncpy(internal_.filename, filename, 260); + internal_.filename[260 - 1] = '\0'; +} + +char const* FileStat::GetFilename() const +{ + return internal_.filename; +} + +void FileStat::SetSize(std::uint64_t size) +{ + internal_.size = size; +} + +std::uint64_t FileStat::GetSize() const +{ + return internal_.size; +} + +void FileStat::SetLastModified(std::uint64_t lastModified) +{ + internal_.last_modified = lastModified; +} + +std::uint64_t FileStat::GetLastModified() const +{ + return internal_.last_modified; +} + +void Entitlement::SetId(Snowflake id) +{ + internal_.id = id; +} + +Snowflake Entitlement::GetId() const +{ + return internal_.id; +} + +void Entitlement::SetType(EntitlementType type) +{ + internal_.type = static_cast(type); +} + +EntitlementType Entitlement::GetType() const +{ + return static_cast(internal_.type); +} + +void Entitlement::SetSkuId(Snowflake skuId) +{ + internal_.sku_id = skuId; +} + +Snowflake Entitlement::GetSkuId() const +{ + return internal_.sku_id; +} + +void SkuPrice::SetAmount(std::uint32_t amount) +{ + internal_.amount = amount; +} + +std::uint32_t SkuPrice::GetAmount() const +{ + return internal_.amount; +} + +void SkuPrice::SetCurrency(char const* currency) +{ + strncpy(internal_.currency, currency, 16); + internal_.currency[16 - 1] = '\0'; +} + +char const* SkuPrice::GetCurrency() const +{ + return internal_.currency; +} + +void Sku::SetId(Snowflake id) +{ + internal_.id = id; +} + +Snowflake Sku::GetId() const +{ + return internal_.id; +} + +void Sku::SetType(SkuType type) +{ + internal_.type = static_cast(type); +} + +SkuType Sku::GetType() const +{ + return static_cast(internal_.type); +} + +void Sku::SetName(char const* name) +{ + strncpy(internal_.name, name, 256); + internal_.name[256 - 1] = '\0'; +} + +char const* Sku::GetName() const +{ + return internal_.name; +} + +SkuPrice& Sku::GetPrice() +{ + return reinterpret_cast(internal_.price); +} + +SkuPrice const& Sku::GetPrice() const +{ + return reinterpret_cast(internal_.price); +} + +void InputMode::SetType(InputModeType type) +{ + internal_.type = static_cast(type); +} + +InputModeType InputMode::GetType() const +{ + return static_cast(internal_.type); +} + +void InputMode::SetShortcut(char const* shortcut) +{ + strncpy(internal_.shortcut, shortcut, 256); + internal_.shortcut[256 - 1] = '\0'; +} + +char const* InputMode::GetShortcut() const +{ + return internal_.shortcut; +} + +void UserAchievement::SetUserId(Snowflake userId) +{ + internal_.user_id = userId; +} + +Snowflake UserAchievement::GetUserId() const +{ + return internal_.user_id; +} + +void UserAchievement::SetAchievementId(Snowflake achievementId) +{ + internal_.achievement_id = achievementId; +} + +Snowflake UserAchievement::GetAchievementId() const +{ + return internal_.achievement_id; +} + +void UserAchievement::SetPercentComplete(std::uint8_t percentComplete) +{ + internal_.percent_complete = percentComplete; +} + +std::uint8_t UserAchievement::GetPercentComplete() const +{ + return internal_.percent_complete; +} + +void UserAchievement::SetUnlockedAt(DateTime unlockedAt) +{ + strncpy(internal_.unlocked_at, unlockedAt, 64); + internal_.unlocked_at[64 - 1] = '\0'; +} + +DateTime UserAchievement::GetUnlockedAt() const +{ + return internal_.unlocked_at; +} + +Result LobbyTransaction::SetType(LobbyType type) +{ + auto result = internal_->set_type(internal_, static_cast(type)); + return static_cast(result); +} + +Result LobbyTransaction::SetOwner(UserId ownerId) +{ + auto result = internal_->set_owner(internal_, ownerId); + return static_cast(result); +} + +Result LobbyTransaction::SetCapacity(std::uint32_t capacity) +{ + auto result = internal_->set_capacity(internal_, capacity); + return static_cast(result); +} + +Result LobbyTransaction::SetMetadata(MetadataKey key, MetadataValue value) +{ + auto result = + internal_->set_metadata(internal_, const_cast(key), const_cast(value)); + return static_cast(result); +} + +Result LobbyTransaction::DeleteMetadata(MetadataKey key) +{ + auto result = internal_->delete_metadata(internal_, const_cast(key)); + return static_cast(result); +} + +Result LobbyTransaction::SetLocked(bool locked) +{ + auto result = internal_->set_locked(internal_, (locked ? 1 : 0)); + return static_cast(result); +} + +Result LobbyMemberTransaction::SetMetadata(MetadataKey key, MetadataValue value) +{ + auto result = + internal_->set_metadata(internal_, const_cast(key), const_cast(value)); + return static_cast(result); +} + +Result LobbyMemberTransaction::DeleteMetadata(MetadataKey key) +{ + auto result = internal_->delete_metadata(internal_, const_cast(key)); + return static_cast(result); +} + +Result LobbySearchQuery::Filter(MetadataKey key, + LobbySearchComparison comparison, + LobbySearchCast cast, + MetadataValue value) +{ + auto result = internal_->filter(internal_, + const_cast(key), + static_cast(comparison), + static_cast(cast), + const_cast(value)); + return static_cast(result); +} + +Result LobbySearchQuery::Sort(MetadataKey key, LobbySearchCast cast, MetadataValue value) +{ + auto result = internal_->sort(internal_, + const_cast(key), + static_cast(cast), + const_cast(value)); + return static_cast(result); +} + +Result LobbySearchQuery::Limit(std::uint32_t limit) +{ + auto result = internal_->limit(internal_, limit); + return static_cast(result); +} + +Result LobbySearchQuery::Distance(LobbySearchDistance distance) +{ + auto result = + internal_->distance(internal_, static_cast(distance)); + return static_cast(result); +} + +} // namespace discord diff --git a/Crawler/discord-files/types.h b/Crawler/discord-files/types.h new file mode 100644 index 00000000..76c43117 --- /dev/null +++ b/Crawler/discord-files/types.h @@ -0,0 +1,567 @@ +#pragma once + +#include "ffi.h" +#include "event.h" +#ifdef _WIN32 +#include +#include +#endif + +namespace discord { + +enum class Result { + Ok = 0, + ServiceUnavailable = 1, + InvalidVersion = 2, + LockFailed = 3, + InternalError = 4, + InvalidPayload = 5, + InvalidCommand = 6, + InvalidPermissions = 7, + NotFetched = 8, + NotFound = 9, + Conflict = 10, + InvalidSecret = 11, + InvalidJoinSecret = 12, + NoEligibleActivity = 13, + InvalidInvite = 14, + NotAuthenticated = 15, + InvalidAccessToken = 16, + ApplicationMismatch = 17, + InvalidDataUrl = 18, + InvalidBase64 = 19, + NotFiltered = 20, + LobbyFull = 21, + InvalidLobbySecret = 22, + InvalidFilename = 23, + InvalidFileSize = 24, + InvalidEntitlement = 25, + NotInstalled = 26, + NotRunning = 27, + InsufficientBuffer = 28, + PurchaseCanceled = 29, + InvalidGuild = 30, + InvalidEvent = 31, + InvalidChannel = 32, + InvalidOrigin = 33, + RateLimited = 34, + OAuth2Error = 35, + SelectChannelTimeout = 36, + GetGuildTimeout = 37, + SelectVoiceForceRequired = 38, + CaptureShortcutAlreadyListening = 39, + UnauthorizedForAchievement = 40, + InvalidGiftCode = 41, + PurchaseError = 42, + TransactionAborted = 43, + DrawingInitFailed = 44, +}; + +enum class CreateFlags { + Default = 0, + NoRequireDiscord = 1, +}; + +enum class LogLevel { + Error = 1, + Warn, + Info, + Debug, +}; + +enum class UserFlag { + Partner = 2, + HypeSquadEvents = 4, + HypeSquadHouse1 = 64, + HypeSquadHouse2 = 128, + HypeSquadHouse3 = 256, +}; + +enum class PremiumType { + None = 0, + Tier1 = 1, + Tier2 = 2, +}; + +enum class ImageType { + User, +}; + +enum class ActivityPartyPrivacy { + Private = 0, + Public = 1, +}; + +enum class ActivityType { + Playing, + Streaming, + Listening, + Watching, +}; + +enum class ActivityActionType { + Join = 1, + Spectate, +}; + +enum class ActivitySupportedPlatformFlags { + Desktop = 1, + Android = 2, + iOS = 4, +}; + +enum class ActivityJoinRequestReply { + No, + Yes, + Ignore, +}; + +enum class Status { + Offline = 0, + Online = 1, + Idle = 2, + DoNotDisturb = 3, +}; + +enum class RelationshipType { + None, + Friend, + Blocked, + PendingIncoming, + PendingOutgoing, + Implicit, +}; + +enum class LobbyType { + Private = 1, + Public, +}; + +enum class LobbySearchComparison { + LessThanOrEqual = -2, + LessThan, + Equal, + GreaterThan, + GreaterThanOrEqual, + NotEqual, +}; + +enum class LobbySearchCast { + String = 1, + Number, +}; + +enum class LobbySearchDistance { + Local, + Default, + Extended, + Global, +}; + +enum class KeyVariant { + Normal, + Right, + Left, +}; + +enum class MouseButton { + Left, + Middle, + Right, +}; + +enum class EntitlementType { + Purchase = 1, + PremiumSubscription, + DeveloperGift, + TestModePurchase, + FreePurchase, + UserGift, + PremiumPurchase, +}; + +enum class SkuType { + Application = 1, + DLC, + Consumable, + Bundle, +}; + +enum class InputModeType { + VoiceActivity = 0, + PushToTalk, +}; + +using ClientId = std::int64_t; +using Version = std::int32_t; +using Snowflake = std::int64_t; +using Timestamp = std::int64_t; +using UserId = Snowflake; +using Locale = char const*; +using Branch = char const*; +using LobbyId = Snowflake; +using LobbySecret = char const*; +using MetadataKey = char const*; +using MetadataValue = char const*; +using NetworkPeerId = std::uint64_t; +using NetworkChannelId = std::uint8_t; +#ifdef __APPLE__ +using IDXGISwapChain = void; +#endif +#ifdef __linux__ +using IDXGISwapChain = void; +#endif +#ifdef __APPLE__ +using MSG = void; +#endif +#ifdef __linux__ +using MSG = void; +#endif +using Path = char const*; +using DateTime = char const*; + +class User final { +public: + void SetId(UserId id); + UserId GetId() const; + void SetUsername(char const* username); + char const* GetUsername() const; + void SetDiscriminator(char const* discriminator); + char const* GetDiscriminator() const; + void SetAvatar(char const* avatar); + char const* GetAvatar() const; + void SetBot(bool bot); + bool GetBot() const; + +private: + DiscordUser internal_; +}; + +class OAuth2Token final { +public: + void SetAccessToken(char const* accessToken); + char const* GetAccessToken() const; + void SetScopes(char const* scopes); + char const* GetScopes() const; + void SetExpires(Timestamp expires); + Timestamp GetExpires() const; + +private: + DiscordOAuth2Token internal_; +}; + +class ImageHandle final { +public: + void SetType(ImageType type); + ImageType GetType() const; + void SetId(std::int64_t id); + std::int64_t GetId() const; + void SetSize(std::uint32_t size); + std::uint32_t GetSize() const; + +private: + DiscordImageHandle internal_; +}; + +class ImageDimensions final { +public: + void SetWidth(std::uint32_t width); + std::uint32_t GetWidth() const; + void SetHeight(std::uint32_t height); + std::uint32_t GetHeight() const; + +private: + DiscordImageDimensions internal_; +}; + +class ActivityTimestamps final { +public: + void SetStart(Timestamp start); + Timestamp GetStart() const; + void SetEnd(Timestamp end); + Timestamp GetEnd() const; + +private: + DiscordActivityTimestamps internal_; +}; + +class ActivityAssets final { +public: + void SetLargeImage(char const* largeImage); + char const* GetLargeImage() const; + void SetLargeText(char const* largeText); + char const* GetLargeText() const; + void SetSmallImage(char const* smallImage); + char const* GetSmallImage() const; + void SetSmallText(char const* smallText); + char const* GetSmallText() const; + +private: + DiscordActivityAssets internal_; +}; + +class PartySize final { +public: + void SetCurrentSize(std::int32_t currentSize); + std::int32_t GetCurrentSize() const; + void SetMaxSize(std::int32_t maxSize); + std::int32_t GetMaxSize() const; + +private: + DiscordPartySize internal_; +}; + +class ActivityParty final { +public: + void SetId(char const* id); + char const* GetId() const; + PartySize& GetSize(); + PartySize const& GetSize() const; + void SetPrivacy(ActivityPartyPrivacy privacy); + ActivityPartyPrivacy GetPrivacy() const; + +private: + DiscordActivityParty internal_; +}; + +class ActivitySecrets final { +public: + void SetMatch(char const* match); + char const* GetMatch() const; + void SetJoin(char const* join); + char const* GetJoin() const; + void SetSpectate(char const* spectate); + char const* GetSpectate() const; + +private: + DiscordActivitySecrets internal_; +}; + +class Activity final { +public: + void SetType(ActivityType type); + ActivityType GetType() const; + void SetApplicationId(std::int64_t applicationId); + std::int64_t GetApplicationId() const; + void SetName(char const* name); + char const* GetName() const; + void SetState(char const* state); + char const* GetState() const; + void SetDetails(char const* details); + char const* GetDetails() const; + ActivityTimestamps& GetTimestamps(); + ActivityTimestamps const& GetTimestamps() const; + ActivityAssets& GetAssets(); + ActivityAssets const& GetAssets() const; + ActivityParty& GetParty(); + ActivityParty const& GetParty() const; + ActivitySecrets& GetSecrets(); + ActivitySecrets const& GetSecrets() const; + void SetInstance(bool instance); + bool GetInstance() const; + void SetSupportedPlatforms(std::uint32_t supportedPlatforms); + std::uint32_t GetSupportedPlatforms() const; + +private: + DiscordActivity internal_; +}; + +class Presence final { +public: + void SetStatus(Status status); + Status GetStatus() const; + Activity& GetActivity(); + Activity const& GetActivity() const; + +private: + DiscordPresence internal_; +}; + +class Relationship final { +public: + void SetType(RelationshipType type); + RelationshipType GetType() const; + User& GetUser(); + User const& GetUser() const; + Presence& GetPresence(); + Presence const& GetPresence() const; + +private: + DiscordRelationship internal_; +}; + +class Lobby final { +public: + void SetId(LobbyId id); + LobbyId GetId() const; + void SetType(LobbyType type); + LobbyType GetType() const; + void SetOwnerId(UserId ownerId); + UserId GetOwnerId() const; + void SetSecret(LobbySecret secret); + LobbySecret GetSecret() const; + void SetCapacity(std::uint32_t capacity); + std::uint32_t GetCapacity() const; + void SetLocked(bool locked); + bool GetLocked() const; + +private: + DiscordLobby internal_; +}; + +class ImeUnderline final { +public: + void SetFrom(std::int32_t from); + std::int32_t GetFrom() const; + void SetTo(std::int32_t to); + std::int32_t GetTo() const; + void SetColor(std::uint32_t color); + std::uint32_t GetColor() const; + void SetBackgroundColor(std::uint32_t backgroundColor); + std::uint32_t GetBackgroundColor() const; + void SetThick(bool thick); + bool GetThick() const; + +private: + DiscordImeUnderline internal_; +}; + +class Rect final { +public: + void SetLeft(std::int32_t left); + std::int32_t GetLeft() const; + void SetTop(std::int32_t top); + std::int32_t GetTop() const; + void SetRight(std::int32_t right); + std::int32_t GetRight() const; + void SetBottom(std::int32_t bottom); + std::int32_t GetBottom() const; + +private: + DiscordRect internal_; +}; + +class FileStat final { +public: + void SetFilename(char const* filename); + char const* GetFilename() const; + void SetSize(std::uint64_t size); + std::uint64_t GetSize() const; + void SetLastModified(std::uint64_t lastModified); + std::uint64_t GetLastModified() const; + +private: + DiscordFileStat internal_; +}; + +class Entitlement final { +public: + void SetId(Snowflake id); + Snowflake GetId() const; + void SetType(EntitlementType type); + EntitlementType GetType() const; + void SetSkuId(Snowflake skuId); + Snowflake GetSkuId() const; + +private: + DiscordEntitlement internal_; +}; + +class SkuPrice final { +public: + void SetAmount(std::uint32_t amount); + std::uint32_t GetAmount() const; + void SetCurrency(char const* currency); + char const* GetCurrency() const; + +private: + DiscordSkuPrice internal_; +}; + +class Sku final { +public: + void SetId(Snowflake id); + Snowflake GetId() const; + void SetType(SkuType type); + SkuType GetType() const; + void SetName(char const* name); + char const* GetName() const; + SkuPrice& GetPrice(); + SkuPrice const& GetPrice() const; + +private: + DiscordSku internal_; +}; + +class InputMode final { +public: + void SetType(InputModeType type); + InputModeType GetType() const; + void SetShortcut(char const* shortcut); + char const* GetShortcut() const; + +private: + DiscordInputMode internal_; +}; + +class UserAchievement final { +public: + void SetUserId(Snowflake userId); + Snowflake GetUserId() const; + void SetAchievementId(Snowflake achievementId); + Snowflake GetAchievementId() const; + void SetPercentComplete(std::uint8_t percentComplete); + std::uint8_t GetPercentComplete() const; + void SetUnlockedAt(DateTime unlockedAt); + DateTime GetUnlockedAt() const; + +private: + DiscordUserAchievement internal_; +}; + +class LobbyTransaction final { +public: + Result SetType(LobbyType type); + Result SetOwner(UserId ownerId); + Result SetCapacity(std::uint32_t capacity); + Result SetMetadata(MetadataKey key, MetadataValue value); + Result DeleteMetadata(MetadataKey key); + Result SetLocked(bool locked); + + IDiscordLobbyTransaction** Receive() { return &internal_; } + IDiscordLobbyTransaction* Internal() { return internal_; } + +private: + IDiscordLobbyTransaction* internal_; +}; + +class LobbyMemberTransaction final { +public: + Result SetMetadata(MetadataKey key, MetadataValue value); + Result DeleteMetadata(MetadataKey key); + + IDiscordLobbyMemberTransaction** Receive() { return &internal_; } + IDiscordLobbyMemberTransaction* Internal() { return internal_; } + +private: + IDiscordLobbyMemberTransaction* internal_; +}; + +class LobbySearchQuery final { +public: + Result Filter(MetadataKey key, + LobbySearchComparison comparison, + LobbySearchCast cast, + MetadataValue value); + Result Sort(MetadataKey key, LobbySearchCast cast, MetadataValue value); + Result Limit(std::uint32_t limit); + Result Distance(LobbySearchDistance distance); + + IDiscordLobbySearchQuery** Receive() { return &internal_; } + IDiscordLobbySearchQuery* Internal() { return internal_; } + +private: + IDiscordLobbySearchQuery* internal_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/user_manager.cpp b/Crawler/discord-files/user_manager.cpp new file mode 100644 index 00000000..ddb6d5ca --- /dev/null +++ b/Crawler/discord-files/user_manager.cpp @@ -0,0 +1,80 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "user_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +class UserEvents final { +public: + static void DISCORD_CALLBACK OnCurrentUserUpdate(void* callbackData) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->UserManager(); + module.OnCurrentUserUpdate(); + } +}; + +IDiscordUserEvents UserManager::events_{ + &UserEvents::OnCurrentUserUpdate, +}; + +Result UserManager::GetCurrentUser(User* currentUser) +{ + if (!currentUser) { + return Result::InternalError; + } + + auto result = + internal_->get_current_user(internal_, reinterpret_cast(currentUser)); + return static_cast(result); +} + +void UserManager::GetUser(UserId userId, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result, DiscordUser* user) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result), *reinterpret_cast(user)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->get_user(internal_, userId, cb.release(), wrapper); +} + +Result UserManager::GetCurrentUserPremiumType(PremiumType* premiumType) +{ + if (!premiumType) { + return Result::InternalError; + } + + auto result = internal_->get_current_user_premium_type( + internal_, reinterpret_cast(premiumType)); + return static_cast(result); +} + +Result UserManager::CurrentUserHasFlag(UserFlag flag, bool* hasFlag) +{ + if (!hasFlag) { + return Result::InternalError; + } + + auto result = internal_->current_user_has_flag( + internal_, static_cast(flag), reinterpret_cast(hasFlag)); + return static_cast(result); +} + +} // namespace discord diff --git a/Crawler/discord-files/user_manager.h b/Crawler/discord-files/user_manager.h new file mode 100644 index 00000000..d85de1b5 --- /dev/null +++ b/Crawler/discord-files/user_manager.h @@ -0,0 +1,31 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class UserManager final { +public: + ~UserManager() = default; + + Result GetCurrentUser(User* currentUser); + void GetUser(UserId userId, std::function callback); + Result GetCurrentUserPremiumType(PremiumType* premiumType); + Result CurrentUserHasFlag(UserFlag flag, bool* hasFlag); + + Event<> OnCurrentUserUpdate; + +private: + friend class Core; + + UserManager() = default; + UserManager(UserManager const& rhs) = delete; + UserManager& operator=(UserManager const& rhs) = delete; + UserManager(UserManager&& rhs) = delete; + UserManager& operator=(UserManager&& rhs) = delete; + + IDiscordUserManager* internal_; + static IDiscordUserEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord-files/voice_manager.cpp b/Crawler/discord-files/voice_manager.cpp new file mode 100644 index 00000000..014ceb3f --- /dev/null +++ b/Crawler/discord-files/voice_manager.cpp @@ -0,0 +1,124 @@ +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "voice_manager.h" + +#include "core.h" + +#include +#include + +namespace discord { + +class VoiceEvents final { +public: + static void DISCORD_CALLBACK OnSettingsUpdate(void* callbackData) + { + auto* core = reinterpret_cast(callbackData); + if (!core) { + return; + } + + auto& module = core->VoiceManager(); + module.OnSettingsUpdate(); + } +}; + +IDiscordVoiceEvents VoiceManager::events_{ + &VoiceEvents::OnSettingsUpdate, +}; + +Result VoiceManager::GetInputMode(InputMode* inputMode) +{ + if (!inputMode) { + return Result::InternalError; + } + + auto result = + internal_->get_input_mode(internal_, reinterpret_cast(inputMode)); + return static_cast(result); +} + +void VoiceManager::SetInputMode(InputMode inputMode, std::function callback) +{ + static auto wrapper = [](void* callbackData, EDiscordResult result) -> void { + std::unique_ptr> cb( + reinterpret_cast*>(callbackData)); + if (!cb || !(*cb)) { + return; + } + (*cb)(static_cast(result)); + }; + std::unique_ptr> cb{}; + cb.reset(new std::function(std::move(callback))); + internal_->set_input_mode( + internal_, *reinterpret_cast(&inputMode), cb.release(), wrapper); +} + +Result VoiceManager::IsSelfMute(bool* mute) +{ + if (!mute) { + return Result::InternalError; + } + + auto result = internal_->is_self_mute(internal_, reinterpret_cast(mute)); + return static_cast(result); +} + +Result VoiceManager::SetSelfMute(bool mute) +{ + auto result = internal_->set_self_mute(internal_, (mute ? 1 : 0)); + return static_cast(result); +} + +Result VoiceManager::IsSelfDeaf(bool* deaf) +{ + if (!deaf) { + return Result::InternalError; + } + + auto result = internal_->is_self_deaf(internal_, reinterpret_cast(deaf)); + return static_cast(result); +} + +Result VoiceManager::SetSelfDeaf(bool deaf) +{ + auto result = internal_->set_self_deaf(internal_, (deaf ? 1 : 0)); + return static_cast(result); +} + +Result VoiceManager::IsLocalMute(Snowflake userId, bool* mute) +{ + if (!mute) { + return Result::InternalError; + } + + auto result = internal_->is_local_mute(internal_, userId, reinterpret_cast(mute)); + return static_cast(result); +} + +Result VoiceManager::SetLocalMute(Snowflake userId, bool mute) +{ + auto result = internal_->set_local_mute(internal_, userId, (mute ? 1 : 0)); + return static_cast(result); +} + +Result VoiceManager::GetLocalVolume(Snowflake userId, std::uint8_t* volume) +{ + if (!volume) { + return Result::InternalError; + } + + auto result = + internal_->get_local_volume(internal_, userId, reinterpret_cast(volume)); + return static_cast(result); +} + +Result VoiceManager::SetLocalVolume(Snowflake userId, std::uint8_t volume) +{ + auto result = internal_->set_local_volume(internal_, userId, volume); + return static_cast(result); +} + +} // namespace discord diff --git a/Crawler/discord-files/voice_manager.h b/Crawler/discord-files/voice_manager.h new file mode 100644 index 00000000..95b20e99 --- /dev/null +++ b/Crawler/discord-files/voice_manager.h @@ -0,0 +1,37 @@ +#pragma once + +#include "types.h" + +namespace discord { + +class VoiceManager final { +public: + ~VoiceManager() = default; + + Result GetInputMode(InputMode* inputMode); + void SetInputMode(InputMode inputMode, std::function callback); + Result IsSelfMute(bool* mute); + Result SetSelfMute(bool mute); + Result IsSelfDeaf(bool* deaf); + Result SetSelfDeaf(bool deaf); + Result IsLocalMute(Snowflake userId, bool* mute); + Result SetLocalMute(Snowflake userId, bool mute); + Result GetLocalVolume(Snowflake userId, std::uint8_t* volume); + Result SetLocalVolume(Snowflake userId, std::uint8_t volume); + + Event<> OnSettingsUpdate; + +private: + friend class Core; + + VoiceManager() = default; + VoiceManager(VoiceManager const& rhs) = delete; + VoiceManager& operator=(VoiceManager const& rhs) = delete; + VoiceManager(VoiceManager&& rhs) = delete; + VoiceManager& operator=(VoiceManager&& rhs) = delete; + + IDiscordVoiceManager* internal_; + static IDiscordVoiceEvents events_; +}; + +} // namespace discord diff --git a/Crawler/discord_game_sdk.bundle b/Crawler/discord_game_sdk.bundle new file mode 100644 index 00000000..3402426b Binary files /dev/null and b/Crawler/discord_game_sdk.bundle differ diff --git a/Crawler/discord_game_sdk.dll b/Crawler/discord_game_sdk.dll new file mode 100644 index 00000000..be946ea7 Binary files /dev/null and b/Crawler/discord_game_sdk.dll differ diff --git a/Crawler/discord_game_sdk.dll.lib b/Crawler/discord_game_sdk.dll.lib new file mode 100644 index 00000000..562b01cd Binary files /dev/null and b/Crawler/discord_game_sdk.dll.lib differ diff --git a/Crawler/discord_game_sdk.dylib b/Crawler/discord_game_sdk.dylib new file mode 100644 index 00000000..3402426b Binary files /dev/null and b/Crawler/discord_game_sdk.dylib differ diff --git a/Crawler/discord_game_sdk.so b/Crawler/discord_game_sdk.so new file mode 100644 index 00000000..9dacf946 Binary files /dev/null and b/Crawler/discord_game_sdk.so differ diff --git a/Crawler/emscripten_build.ps1 b/Crawler/emscripten_build.ps1 index 48be344a..3ca64ce8 100644 --- a/Crawler/emscripten_build.ps1 +++ b/Crawler/emscripten_build.ps1 @@ -1,2 +1,2 @@ ~\Documents\emsdk\emsdk_env.ps1 activate latest -em++ -std=c++20 -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_LIBPNG=1 -s USE_FREETYPE=1 $(Get-ChildItem *.cpp) -o pge.html --preload-file assets \ No newline at end of file +em++ -std=c++20 -fexperimental-library -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_LIBPNG=1 -s USE_FREETYPE=1 $(Get-ChildItem *.cpp) -o pge.html --preload-file assets \ No newline at end of file diff --git a/Crawler/loc.sh b/Crawler/loc.sh index 46432d0e..1af1ec79 100755 --- a/Crawler/loc.sh +++ b/Crawler/loc.sh @@ -1,3 +1,3 @@ -TOTAL=$(wc -l $(find *.cpp *.h -not -name "olc*.h")|grep "total"|awk '{print $1}') -FILECOUNT=$(find *.cpp *.h -not -name "olc*.h"|wc -l) +TOTAL=$(wc -l $(find *.cpp *.h -not -name "miniaudio.h" -not -name "olc*.h")|grep "total"|awk '{print $1}') +FILECOUNT=$(find *.cpp *.h -not -name "miniaudio.h" -not -name "olc*.h"|wc -l) echo "$[TOTAL-FILECOUNT*37] (License lines Excluded)" diff --git a/Crawler/olcPixelGameEngine.h b/Crawler/olcPixelGameEngine.h index 49acf016..d224b45e 100644 --- a/Crawler/olcPixelGameEngine.h +++ b/Crawler/olcPixelGameEngine.h @@ -6801,19 +6801,19 @@ namespace olc mapKeys[DOM_PK_QUOTE] = Key::OEM_7; mapKeys[DOM_PK_BACKSLASH] = Key::OEM_8; // Keyboard Callbacks - emscripten_set_keydown_callback("body", 0, 1, keyboard_callback); - emscripten_set_keyup_callback("body", 0, 1, keyboard_callback); + emscripten_set_keydown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 1, keyboard_callback); + emscripten_set_keyup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 1, keyboard_callback); // Mouse Callbacks emscripten_set_wheel_callback("#canvas", 0, 1, wheel_callback); - emscripten_set_mousedown_callback("body", 0, 1, mouse_callback); - emscripten_set_mouseup_callback("body", 0, 1, mouse_callback); - emscripten_set_mousemove_callback("body", 0, 1, mouse_callback); + emscripten_set_mousedown_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 1, mouse_callback); + emscripten_set_mouseup_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 1, mouse_callback); + emscripten_set_mousemove_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 1, mouse_callback); // Touch Callbacks - emscripten_set_touchstart_callback("body", 0, 1, touch_callback); - emscripten_set_touchmove_callback("body", 0, 1, touch_callback); - emscripten_set_touchend_callback("body", 0, 1, touch_callback); + emscripten_set_touchstart_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 1, touch_callback); + emscripten_set_touchmove_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 1, touch_callback); + emscripten_set_touchend_callback(EMSCRIPTEN_EVENT_TARGET_WINDOW, 0, 1, touch_callback); // Canvas Focus Callbacks emscripten_set_blur_callback("#canvas", 0, 1, focus_callback); diff --git a/Crawler/pge.data b/Crawler/pge.data index ce2ba6ab..b84c842c 100644 Binary files a/Crawler/pge.data and b/Crawler/pge.data differ diff --git a/Crawler/pge.js b/Crawler/pge.js index 35024634..a2984532 100644 --- a/Crawler/pge.js +++ b/Crawler/pge.js @@ -1 +1 @@ -var Module=typeof Module!="undefined"?Module:{};if(!Module.expectedDataFileDownloads){Module.expectedDataFileDownloads=0}Module.expectedDataFileDownloads++;(function(){if(Module["ENVIRONMENT_IS_PTHREAD"]||Module["$ww"])return;var loadPackage=function(metadata){var PACKAGE_PATH="";if(typeof window==="object"){PACKAGE_PATH=window["encodeURIComponent"](window.location.pathname.toString().substring(0,window.location.pathname.toString().lastIndexOf("/"))+"/")}else if(typeof process==="undefined"&&typeof location!=="undefined"){PACKAGE_PATH=encodeURIComponent(location.pathname.toString().substring(0,location.pathname.toString().lastIndexOf("/"))+"/")}var PACKAGE_NAME="pge.data";var REMOTE_PACKAGE_BASE="pge.data";if(typeof Module["locateFilePackage"]==="function"&&!Module["locateFile"]){Module["locateFile"]=Module["locateFilePackage"];err("warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)")}var REMOTE_PACKAGE_NAME=Module["locateFile"]?Module["locateFile"](REMOTE_PACKAGE_BASE,""):REMOTE_PACKAGE_BASE;var REMOTE_PACKAGE_SIZE=metadata["remote_package_size"];function fetchRemotePackage(packageName,packageSize,callback,errback){if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){require("fs").readFile(packageName,function(err,contents){if(err){errback(err)}else{callback(contents.buffer)}});return}var xhr=new XMLHttpRequest;xhr.open("GET",packageName,true);xhr.responseType="arraybuffer";xhr.onprogress=function(event){var url=packageName;var size=packageSize;if(event.total)size=event.total;if(event.loaded){if(!xhr.addedTotal){xhr.addedTotal=true;if(!Module.dataFileDownloads)Module.dataFileDownloads={};Module.dataFileDownloads[url]={loaded:event.loaded,total:size}}else{Module.dataFileDownloads[url].loaded=event.loaded}var total=0;var loaded=0;var num=0;for(var download in Module.dataFileDownloads){var data=Module.dataFileDownloads[download];total+=data.total;loaded+=data.loaded;num++}total=Math.ceil(total*Module.expectedDataFileDownloads/num);if(Module["setStatus"])Module["setStatus"](`Downloading data... (${loaded}/${total})`)}else if(!Module.dataFileDownloads){if(Module["setStatus"])Module["setStatus"]("Downloading data...")}};xhr.onerror=function(event){throw new Error("NetworkError for: "+packageName)};xhr.onload=function(event){if(xhr.status==200||xhr.status==304||xhr.status==206||xhr.status==0&&xhr.response){var packageData=xhr.response;callback(packageData)}else{throw new Error(xhr.statusText+" : "+xhr.responseURL)}};xhr.send(null)}function handleError(error){console.error("package error:",error)}var fetchedCallback=null;var fetched=Module["getPreloadedPackage"]?Module["getPreloadedPackage"](REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE):null;if(!fetched)fetchRemotePackage(REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE,function(data){if(fetchedCallback){fetchedCallback(data);fetchedCallback=null}else{fetched=data}},handleError);function runWithFS(){function assert(check,msg){if(!check)throw msg+(new Error).stack}Module["FS_createPath"]("/","assets",true,true);Module["FS_createPath"]("/assets","Ability Icons",true,true);Module["FS_createPath"]("/assets","Campaigns",true,true);Module["FS_createPath"]("/assets","backgrounds",true,true);Module["FS_createPath"]("/assets","characters",true,true);Module["FS_createPath"]("/assets","config",true,true);Module["FS_createPath"]("/assets/config","classes",true,true);Module["FS_createPath"]("/assets/config","gfx",true,true);Module["FS_createPath"]("/assets/config","items",true,true);Module["FS_createPath"]("/assets/config","story",true,true);Module["FS_createPath"]("/assets","items",true,true);Module["FS_createPath"]("/assets","maps",true,true);Module["FS_createPath"]("/assets/maps","commercial_assets",true,true);Module["FS_createPath"]("/assets","menus",true,true);Module["FS_createPath"]("/assets","monsters",true,true);Module["FS_createPath"]("/assets","themes",true,true);function DataRequest(start,end,audio){this.start=start;this.end=end;this.audio=audio}DataRequest.prototype={requests:{},open:function(mode,name){this.name=name;this.requests[name]=this;Module["addRunDependency"](`fp ${this.name}`)},send:function(){},onload:function(){var byteArray=this.byteArray.subarray(this.start,this.end);this.finish(byteArray)},finish:function(byteArray){var that=this;Module["FS_createDataFile"](this.name,null,byteArray,true,true,true);Module["removeRunDependency"](`fp ${that.name}`);this.requests[this.name]=null}};var files=metadata["files"];for(var i=0;i{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");if(ENVIRONMENT_IS_WORKER){scriptDirectory=nodePath.dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=(filename,binary)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret};readAsync=(filename,onload,onerror,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)onerror(err);else onload(binary?data.buffer:data)})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);if(typeof module!="undefined"){module["exports"]=Module}process.on("uncaughtException",ex=>{if(ex!=="unwind"&&!(ex instanceof ExitStatus)&&!(ex.context instanceof ExitStatus)){throw ex}});var nodeMajor=process.versions.node.split(".")[0];if(nodeMajor<15){process.on("unhandledRejection",reason=>{throw reason})}quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow};Module["inspect"]=()=>"[Emscripten Module object]"}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort(text)}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeKeepaliveCounter=0;function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounter>0}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith("file://")}var wasmBinaryFile;wasmBinaryFile="pge.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}catch(err){abort(err)}}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"&&!isFileURI(binaryFile)){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{if(!response["ok"]){throw"failed to load wasm binary file at '"+binaryFile+"'"}return response["arrayBuffer"]()}).catch(()=>getBinary(binaryFile))}else{if(readAsync){return new Promise((resolve,reject)=>{readAsync(binaryFile,response=>resolve(new Uint8Array(response)),reject)})}}}return Promise.resolve().then(()=>getBinary(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>{return WebAssembly.instantiate(binary,imports)}).then(instance=>{return instance}).then(receiver,reason=>{err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}else{return instantiateArrayBuffer(binaryFile,imports,callback)}}function createWasm(){var info={"env":wasmImports,"wasi_snapshot_preview1":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["memory"];updateMemoryViews();wasmTable=Module["asm"]["__indirect_function_table"];addOnInit(Module["asm"]["__wasm_call_ctors"]);removeRunDependency("wasm-instantiate");return exports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}var tempDouble;var tempI64;var ASM_CONSTS={184524:()=>{window.onunload=Module._olc_OnPageUnload},184568:($0,$1)=>{Module.olc_AspectRatio=$0/$1;Module.olc_AssumeDefaultShells=document.querySelectorAll(".emscripten").length>=3?true:false;oncontextmenu=function(e){return false};var olc_ResizeHandler=function(){let isFullscreen=document.fullscreenElement!=null;let width=isFullscreen?window.innerWidth:Module.canvas.parentNode.clientWidth;let height=isFullscreen?window.innerHeight:Module.canvas.parentNode.clientHeight;let viewWidth=width;let viewHeight=width/Module.olc_AspectRatio;if(viewHeight>height){viewWidth=height*Module.olc_AspectRatio;viewHeight=height}viewWidth=parseInt(viewWidth);viewHeight=parseInt(viewHeight);setTimeout(function(){if(Module.olc_AssumeDefaultShells)Module.canvas.parentNode.setAttribute("style","width: 100%; height: 70vh; margin-left: auto; margin-right: auto;");Module.canvas.setAttribute("width",viewWidth);Module.canvas.setAttribute("height",viewHeight);Module.canvas.setAttribute("style",`width: ${viewWidth}px; height: ${viewHeight}px;`);Module._olc_PGE_UpdateWindowSize(viewWidth,viewHeight);Module.canvas.focus()},200)};var olc_Init=function(){if(Module.olc_AspectRatio===undefined){setTimeout(function(){Module.olc_Init()},50);return}let resizeObserver=new ResizeObserver(function(entries){Module.olc_ResizeHandler()}).observe(Module.canvas.parentNode);let mutationObserver=new MutationObserver(function(mutationsList,observer){setTimeout(function(){Module.olc_ResizeHandler()},200)}).observe(Module.canvas.parentNode,{attributes:false,childList:true,subtree:false});window.addEventListener("fullscreenchange",function(e){setTimeout(function(){Module.olc_ResizeHandler()},200)})};Module.olc_ResizeHandler=Module.olc_ResizeHandler!=undefined?Module.olc_ResizeHandler:olc_ResizeHandler;Module.olc_Init=Module.olc_Init!=undefined?Module.olc_Init:olc_Init;Module.olc_Init()},186541:()=>{return window.scrollX},186565:()=>{return window.scrollY},186589:()=>{return window.scrollX},186613:()=>{return window.scrollY},186637:()=>{return window.scrollX},186661:()=>{return window.scrollY},186685:()=>{return Module.canvas.getBoundingClientRect().left},186737:()=>{return Module.canvas.getBoundingClientRect().top},186788:()=>{return Module.canvas.getBoundingClientRect().left},186840:()=>{return Module.canvas.getBoundingClientRect().top}};function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){callbacks.shift()(Module)}}var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heapOrArray,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function ___assert_fail(condition,filename,line,func){abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}var exceptionCaught=[];var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_rethrow(){var info=exceptionCaught.pop();if(!info){abort("no exception to throw")}var ptr=info.excPtr;if(!info.get_rethrown()){exceptionCaught.push(info);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}exceptionLast=ptr;throw exceptionLast}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast}function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:function(){var paths=Array.prototype.slice.call(arguments);return PATH.normalize(paths.join("/"))},join2:(l,r)=>{return PATH.normalize(l+"/"+r)}};function initRandomFill(){if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");var randomFillSync=crypto_module["randomFillSync"];if(randomFillSync){return view=>crypto_module["randomFillSync"](view)}var randomBytes=crypto_module["randomBytes"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort("initRandomDevice")}function randomFill(view){return(randomFill=initRandomFill())(view)}var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var TTY={ttys:[],init:function(){},shutdown:function(){},register:function(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open:function(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close:function(stream){stream.tty.ops.fsync(stream.tty)},fsync:function(stream){stream.tty.ops.fsync(stream.tty)},read:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};function mmapAlloc(size){abort()}var MEMFS={ops_table:null,mount:function(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode:function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray:function(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage:function(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr:function(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr:function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup:function(parent,name){throw FS.genericErrors[44]},mknod:function(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename:function(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp;old_node.parent=new_dir},unlink:function(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir:function(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir:function(node){var entries=[".",".."];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries},symlink:function(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink:function(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read:function(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},event=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)}var preloadPlugins=Module["preloadPlugins"]||[];function FS_handledByPreloadPlugin(byteArray,fullname,finish,onerror){if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(function(plugin){if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled}function FS_createPreloadedFile(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish){var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){if(preFinish)preFinish();if(!dontCreateFile){FS.createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}if(onload)onload();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{if(onerror)onerror();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,byteArray=>processData(byteArray),onerror)}else{processData(url)}}function FS_modeStringToFlags(str){var flagModes={"r":0,"r+":2,"w":512|64|1,"w+":512|64|2,"a":1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags}function FS_getMode(canRead,canWrite){var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode}var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:(path,opts={})=>{path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:node=>{var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName:(parentid,name)=>{var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode:node=>{var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:node=>{var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:(parent,name)=>{var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:(parent,name,mode,rdev)=>{var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:node=>{FS.hashRemoveNode(node)},isRoot:node=>{return node===node.parent},isMountpoint:node=>{return!!node.mounted},isFile:mode=>{return(mode&61440)===32768},isDir:mode=>{return(mode&61440)===16384},isLink:mode=>{return(mode&61440)===40960},isChrdev:mode=>{return(mode&61440)===8192},isBlkdev:mode=>{return(mode&61440)===24576},isFIFO:mode=>{return(mode&61440)===4096},isSocket:mode=>{return(mode&49152)===49152},flagsToPermissionString:flag=>{var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:(node,perms)=>{if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup:dir=>{var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:(dir,name)=>{try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:(dir,name,isdir)=>{var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:(node,flags)=>{if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:()=>{for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStream:fd=>FS.streams[fd],createStream:(stream,fd=-1)=>{if(!FS.FSStream){FS.FSStream=function(){this.shared={}};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}},flags:{get:function(){return this.shared.flags},set:function(val){this.shared.flags=val}},position:{get:function(){return this.shared.position},set:function(val){this.shared.position=val}}})}stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:fd=>{FS.streams[fd]=null},chrdev_stream_ops:{open:stream=>{var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:()=>{throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice:(dev,ops)=>{FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts:mount=>{var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:(populate,callback)=>{if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:(type,opts,mountpoint)=>{var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:mountpoint=>{var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:(parent,name)=>{return parent.node_ops.lookup(parent,name)},mknod:(path,mode,dev)=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:(path,mode)=>{mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:(path,mode)=>{mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:(path,mode)=>{var dirs=path.split("/");var d="";for(var i=0;i{if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink:(oldpath,newpath)=>{if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename:(old_path,new_path)=>{var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir:path=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(54)}return node.node_ops.readdir(node)},unlink:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink:path=>{var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return PATH_FS.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))},stat:(path,dontFollow)=>{var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(44)}if(!node.node_ops.getattr){throw new FS.ErrnoError(63)}return node.node_ops.getattr(node)},lstat:path=>{return FS.stat(path,true)},chmod:(path,mode,dontFollow)=>{var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})},lchmod:(path,mode)=>{FS.chmod(path,mode,true)},fchmod:(fd,mode)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}FS.chmod(stream.node,mode)},chown:(path,uid,gid,dontFollow)=>{var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{timestamp:Date.now()})},lchown:(path,uid,gid)=>{FS.chown(path,uid,gid,true)},fchown:(fd,uid,gid)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}FS.chown(stream.node,uid,gid)},truncate:(path,len)=>{if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})},ftruncate:(fd,len)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.truncate(stream.node,len)},utime:(path,atime,mtime)=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})},open:(path,flags,mode)=>{if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;mode=typeof mode=="undefined"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path=="object"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module["logReadFiles"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close:stream=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed:stream=>{return stream.fd===null},llseek:(stream,offset,whence)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read:(stream,buffer,offset,length,position)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write:(stream,buffer,offset,length,position,canOwn)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate:(stream,offset,length)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap:(stream,length,position,prot,flags)=>{if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync:(stream,buffer,offset,length,mmapFlags)=>{if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:stream=>0,ioctl:(stream,cmd,arg)=>{if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile:(path,opts={})=>{opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile:(path,data,opts={})=>{opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir:path=>{var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories:()=>{FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices:()=>{FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories:()=>{FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount:()=>{var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup:(parent,name)=>{var fd=+name;var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams:()=>{if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},ensureErrnoError:()=>{if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.name="ErrnoError";this.node=node;this.setErrno=function(errno){this.errno=errno};this.setErrno(errno);this.message="FS error"};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""})},staticInit:()=>{FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={"MEMFS":MEMFS}},init:(input,output,error)=>{FS.init.initialized=true;FS.ensureErrnoError();Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit:()=>{FS.init.initialized=false;for(var i=0;i{var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath:(path,dontResolveLastLink)=>{try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath:(parent,path,canRead,canWrite)=>{parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current},createFile:(parent,name,properties,canRead,canWrite)=>{var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile:(parent,name,data,canRead,canWrite,canOwn)=>{var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;i{var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open:stream=>{stream.seekable=false},close:stream=>{if(output&&output.buffer&&output.buffer.length){output(10)}},read:(stream,buffer,offset,length,pos)=>{var bytesRead=0;for(var i=0;i{for(var i=0;i{if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;if(typeof XMLHttpRequest!="undefined"){throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")}else if(read_){try{obj.contents=intArrayFromString(read_(obj.url),true);obj.usedBytes=obj.contents.length}catch(e){throw new FS.ErrnoError(29)}}else{throw new Error("Cannot load without read() or XMLHttpRequest.")}},createLazyFile:(parent,name,url,canRead,canWrite)=>{function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt:function(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat:function(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-54}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAPU32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAP32[buf+48>>2]=4096;HEAP32[buf+52>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];HEAPU32[buf+64>>2]=atime%1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];HEAPU32[buf+80>>2]=mtime%1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];HEAPU32[buf+96>>2]=ctime%1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+104>>2]=tempI64[0],HEAP32[buf+108>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);return stream}};function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}var newStream;newStream=FS.createStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 5:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 6:case 7:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:case 21505:{if(!stream.tty)return-59;return 0}case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:{if(!stream.tty)return-59;return 0}case 21519:{if(!stream.tty)return-59;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;return 0}case 21524:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?SYSCALLS.get():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var nowIsMonotonic=true;function __emscripten_get_now_is_monotonic(){return nowIsMonotonic}function __emscripten_throw_longjmp(){throw Infinity}function _abort(){abort("")}function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.timingMode=mode;Browser.mainLoop.timingValue=value;if(!Browser.mainLoop.func){return 1}if(!Browser.mainLoop.running){Browser.mainLoop.running=true}if(mode==0){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setTimeout(){var timeUntilNextTick=Math.max(0,Browser.mainLoop.tickStartTime+value-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,timeUntilNextTick)};Browser.mainLoop.method="timeout"}else if(mode==1){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_rAF(){Browser.requestAnimationFrame(Browser.mainLoop.runner)};Browser.mainLoop.method="rAF"}else if(mode==2){if(typeof setImmediate=="undefined"){var setImmediates=[];var emscriptenMainLoopMessageId="setimmediate";var Browser_setImmediate_messageHandler=event=>{if(event.data===emscriptenMainLoopMessageId||event.data.target===emscriptenMainLoopMessageId){event.stopPropagation();setImmediates.shift()()}};addEventListener("message",Browser_setImmediate_messageHandler,true);setImmediate=function Browser_emulated_setImmediate(func){setImmediates.push(func);if(ENVIRONMENT_IS_WORKER){if(Module["setImmediates"]===undefined)Module["setImmediates"]=[];Module["setImmediates"].push(func);postMessage({target:emscriptenMainLoopMessageId})}else postMessage(emscriptenMainLoopMessageId,"*")}}Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setImmediate(){setImmediate(Browser.mainLoop.runner)};Browser.mainLoop.method="immediate"}return 0}var _emscripten_get_now;if(ENVIRONMENT_IS_NODE){global.performance=require("perf_hooks").performance}_emscripten_get_now=()=>performance.now();function setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg,noSetTiming){assert(!Browser.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.");Browser.mainLoop.func=browserIterationFunc;Browser.mainLoop.arg=arg;var thisMainLoopId=Browser.mainLoop.currentlyRunningMainloop;function checkIsRunning(){if(thisMainLoopId0){var start=Date.now();var blocker=Browser.mainLoop.queue.shift();blocker.func(blocker.arg);if(Browser.mainLoop.remainingBlockers){var remaining=Browser.mainLoop.remainingBlockers;var next=remaining%1==0?remaining-1:Math.floor(remaining);if(blocker.counted){Browser.mainLoop.remainingBlockers=next}else{next=next+.5;Browser.mainLoop.remainingBlockers=(8*remaining+next)/9}}out('main loop blocker "'+blocker.name+'" took '+(Date.now()-start)+" ms");Browser.mainLoop.updateStatus();if(!checkIsRunning())return;setTimeout(Browser.mainLoop.runner,0);return}if(!checkIsRunning())return;Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0;if(Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else if(Browser.mainLoop.timingMode==0){Browser.mainLoop.tickStartTime=_emscripten_get_now()}Browser.mainLoop.runIter(browserIterationFunc);if(!checkIsRunning())return;if(typeof SDL=="object"&&SDL.audio&&SDL.audio.queueNewAudioData)SDL.audio.queueNewAudioData();Browser.mainLoop.scheduler()};if(!noSetTiming){if(fps&&fps>0){_emscripten_set_main_loop_timing(0,1e3/fps)}else{_emscripten_set_main_loop_timing(1,1)}Browser.mainLoop.scheduler()}if(simulateInfiniteLoop){throw"unwind"}}function handleException(e){if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)}function _proc_exit(code){EXITSTATUS=code;if(!keepRuntimeAlive()){if(Module["onExit"])Module["onExit"](code);ABORT=true}quit_(code,new ExitStatus(code))}function exitJS(status,implicit){EXITSTATUS=status;_proc_exit(status)}var _exit=exitJS;function maybeExit(){if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}}function callUserCallback(func){if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}}function safeSetTimeout(func,timeout){return setTimeout(()=>{callUserCallback(func)},timeout)}var Browser={mainLoop:{running:false,scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null;Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var timingMode=Browser.mainLoop.timingMode;var timingValue=Browser.mainLoop.timingValue;var func=Browser.mainLoop.func;Browser.mainLoop.func=null;setMainLoop(func,0,false,Browser.mainLoop.arg,true);_emscripten_set_main_loop_timing(timingMode,timingValue);Browser.mainLoop.scheduler()},updateStatus:function(){if(Module["setStatus"]){var message=Module["statusMessage"]||"Please wait...";var remaining=Browser.mainLoop.remainingBlockers;var expected=Browser.mainLoop.expectedBlockers;if(remaining){if(remaining{assert(img.complete,"Image "+name+" could not be decoded");var canvas=document.createElement("canvas");canvas.width=img.width;canvas.height=img.height;var ctx=canvas.getContext("2d");ctx.drawImage(img,0,0);preloadedImages[name]=canvas;URL.revokeObjectURL(url);if(onload)onload(byteArray)};img.onerror=event=>{out("Image "+url+" could not be decoded");if(onerror)onerror()};img.src=url};preloadPlugins.push(imagePlugin);var audioPlugin={};audioPlugin["canHandle"]=function audioPlugin_canHandle(name){return!Module.noAudioDecoding&&name.substr(-4)in{".ogg":1,".wav":1,".mp3":1}};audioPlugin["handle"]=function audioPlugin_handle(byteArray,name,onload,onerror){var done=false;function finish(audio){if(done)return;done=true;preloadedAudios[name]=audio;if(onload)onload(byteArray)}var b=new Blob([byteArray],{type:Browser.getMimetype(name)});var url=URL.createObjectURL(b);var audio=new Audio;audio.addEventListener("canplaythrough",()=>finish(audio),false);audio.onerror=function audio_onerror(event){if(done)return;err("warning: browser could not fully decode audio "+name+", trying slower base64 approach");function encode64(data){var BASE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var PAD="=";var ret="";var leftchar=0;var leftbits=0;for(var i=0;i=6){var curr=leftchar>>leftbits-6&63;leftbits-=6;ret+=BASE[curr]}}if(leftbits==2){ret+=BASE[(leftchar&3)<<4];ret+=PAD+PAD}else if(leftbits==4){ret+=BASE[(leftchar&15)<<2];ret+=PAD}return ret}audio.src="data:audio/x-"+name.substr(-3)+";base64,"+encode64(byteArray);finish(audio)};audio.src=url;safeSetTimeout(()=>{finish(audio)},1e4)};preloadPlugins.push(audioPlugin);function pointerLockChange(){Browser.pointerLock=document["pointerLockElement"]===Module["canvas"]||document["mozPointerLockElement"]===Module["canvas"]||document["webkitPointerLockElement"]===Module["canvas"]||document["msPointerLockElement"]===Module["canvas"]}var canvas=Module["canvas"];if(canvas){canvas.requestPointerLock=canvas["requestPointerLock"]||canvas["mozRequestPointerLock"]||canvas["webkitRequestPointerLock"]||canvas["msRequestPointerLock"]||(()=>{});canvas.exitPointerLock=document["exitPointerLock"]||document["mozExitPointerLock"]||document["webkitExitPointerLock"]||document["msExitPointerLock"]||(()=>{});canvas.exitPointerLock=canvas.exitPointerLock.bind(document);document.addEventListener("pointerlockchange",pointerLockChange,false);document.addEventListener("mozpointerlockchange",pointerLockChange,false);document.addEventListener("webkitpointerlockchange",pointerLockChange,false);document.addEventListener("mspointerlockchange",pointerLockChange,false);if(Module["elementPointerLock"]){canvas.addEventListener("click",ev=>{if(!Browser.pointerLock&&Module["canvas"].requestPointerLock){Module["canvas"].requestPointerLock();ev.preventDefault()}},false)}}},createContext:function(canvas,useWebGL,setInModule,webGLContextAttributes){if(useWebGL&&Module.ctx&&canvas==Module.canvas)return Module.ctx;var ctx;var contextHandle;if(useWebGL){var contextAttributes={antialias:false,alpha:false,majorVersion:2};if(webGLContextAttributes){for(var attribute in webGLContextAttributes){contextAttributes[attribute]=webGLContextAttributes[attribute]}}if(typeof GL!="undefined"){contextHandle=GL.createContext(canvas,contextAttributes);if(contextHandle){ctx=GL.getContext(contextHandle).GLctx}}}else{ctx=canvas.getContext("2d")}if(!ctx)return null;if(setInModule){if(!useWebGL)assert(typeof GLctx=="undefined","cannot set in module if GLctx is used, but we are a non-GL context that would replace it");Module.ctx=ctx;if(useWebGL)GL.makeContextCurrent(contextHandle);Module.useWebGL=useWebGL;Browser.moduleContextCreatedCallbacks.forEach(callback=>callback());Browser.init()}return ctx},destroyContext:function(canvas,useWebGL,setInModule){},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer,resizeCanvas){Browser.lockPointer=lockPointer;Browser.resizeCanvas=resizeCanvas;if(typeof Browser.lockPointer=="undefined")Browser.lockPointer=true;if(typeof Browser.resizeCanvas=="undefined")Browser.resizeCanvas=false;var canvas=Module["canvas"];function fullscreenChange(){Browser.isFullscreen=false;var canvasContainer=canvas.parentNode;if((document["fullscreenElement"]||document["mozFullScreenElement"]||document["msFullscreenElement"]||document["webkitFullscreenElement"]||document["webkitCurrentFullScreenElement"])===canvasContainer){canvas.exitFullscreen=Browser.exitFullscreen;if(Browser.lockPointer)canvas.requestPointerLock();Browser.isFullscreen=true;if(Browser.resizeCanvas){Browser.setFullscreenCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}else{canvasContainer.parentNode.insertBefore(canvas,canvasContainer);canvasContainer.parentNode.removeChild(canvasContainer);if(Browser.resizeCanvas){Browser.setWindowedCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}if(Module["onFullScreen"])Module["onFullScreen"](Browser.isFullscreen);if(Module["onFullscreen"])Module["onFullscreen"](Browser.isFullscreen)}if(!Browser.fullscreenHandlersInstalled){Browser.fullscreenHandlersInstalled=true;document.addEventListener("fullscreenchange",fullscreenChange,false);document.addEventListener("mozfullscreenchange",fullscreenChange,false);document.addEventListener("webkitfullscreenchange",fullscreenChange,false);document.addEventListener("MSFullscreenChange",fullscreenChange,false)}var canvasContainer=document.createElement("div");canvas.parentNode.insertBefore(canvasContainer,canvas);canvasContainer.appendChild(canvas);canvasContainer.requestFullscreen=canvasContainer["requestFullscreen"]||canvasContainer["mozRequestFullScreen"]||canvasContainer["msRequestFullscreen"]||(canvasContainer["webkitRequestFullscreen"]?()=>canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"]):null)||(canvasContainer["webkitRequestFullScreen"]?()=>canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"]):null);canvasContainer.requestFullscreen()},exitFullscreen:function(){if(!Browser.isFullscreen){return false}var CFS=document["exitFullscreen"]||document["cancelFullScreen"]||document["mozCancelFullScreen"]||document["msExitFullscreen"]||document["webkitCancelFullScreen"]||(()=>{});CFS.apply(document,[]);return true},nextRAF:0,fakeRequestAnimationFrame:function(func){var now=Date.now();if(Browser.nextRAF===0){Browser.nextRAF=now+1e3/60}else{while(now+2>=Browser.nextRAF){Browser.nextRAF+=1e3/60}}var delay=Math.max(Browser.nextRAF-now,0);setTimeout(func,delay)},requestAnimationFrame:function(func){if(typeof requestAnimationFrame=="function"){requestAnimationFrame(func);return}var RAF=Browser.fakeRequestAnimationFrame;RAF(func)},safeSetTimeout:function(func,timeout){return safeSetTimeout(func,timeout)},safeRequestAnimationFrame:function(func){return Browser.requestAnimationFrame(()=>{callUserCallback(func)})},getMimetype:function(name){return{"jpg":"image/jpeg","jpeg":"image/jpeg","png":"image/png","bmp":"image/bmp","ogg":"audio/ogg","wav":"audio/wav","mp3":"audio/mpeg"}[name.substr(name.lastIndexOf(".")+1)]},getUserMedia:function(func){if(!window.getUserMedia){window.getUserMedia=navigator["getUserMedia"]||navigator["mozGetUserMedia"]}window.getUserMedia(func)},getMovementX:function(event){return event["movementX"]||event["mozMovementX"]||event["webkitMovementX"]||0},getMovementY:function(event){return event["movementY"]||event["mozMovementY"]||event["webkitMovementY"]||0},getMouseWheelDelta:function(event){var delta=0;switch(event.type){case"DOMMouseScroll":delta=event.detail/3;break;case"mousewheel":delta=event.wheelDelta/120;break;case"wheel":delta=event.deltaY;switch(event.deltaMode){case 0:delta/=100;break;case 1:delta/=3;break;case 2:delta*=80;break;default:throw"unrecognized mouse wheel delta mode: "+event.deltaMode}break;default:throw"unrecognized mouse wheel event: "+event.type}return delta},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(event){if(Browser.pointerLock){if(event.type!="mousemove"&&"mozMovementX"in event){Browser.mouseMovementX=Browser.mouseMovementY=0}else{Browser.mouseMovementX=Browser.getMovementX(event);Browser.mouseMovementY=Browser.getMovementY(event)}if(typeof SDL!="undefined"){Browser.mouseX=SDL.mouseX+Browser.mouseMovementX;Browser.mouseY=SDL.mouseY+Browser.mouseMovementY}else{Browser.mouseX+=Browser.mouseMovementX;Browser.mouseY+=Browser.mouseMovementY}}else{var rect=Module["canvas"].getBoundingClientRect();var cw=Module["canvas"].width;var ch=Module["canvas"].height;var scrollX=typeof window.scrollX!="undefined"?window.scrollX:window.pageXOffset;var scrollY=typeof window.scrollY!="undefined"?window.scrollY:window.pageYOffset;if(event.type==="touchstart"||event.type==="touchend"||event.type==="touchmove"){var touch=event.touch;if(touch===undefined){return}var adjustedX=touch.pageX-(scrollX+rect.left);var adjustedY=touch.pageY-(scrollY+rect.top);adjustedX=adjustedX*(cw/rect.width);adjustedY=adjustedY*(ch/rect.height);var coords={x:adjustedX,y:adjustedY};if(event.type==="touchstart"){Browser.lastTouches[touch.identifier]=coords;Browser.touches[touch.identifier]=coords}else if(event.type==="touchend"||event.type==="touchmove"){var last=Browser.touches[touch.identifier];if(!last)last=coords;Browser.lastTouches[touch.identifier]=last;Browser.touches[touch.identifier]=coords}return}var x=event.pageX-(scrollX+rect.left);var y=event.pageY-(scrollY+rect.top);x=x*(cw/rect.width);y=y*(ch/rect.height);Browser.mouseMovementX=x-Browser.mouseX;Browser.mouseMovementY=y-Browser.mouseY;Browser.mouseX=x;Browser.mouseY=y}},resizeListeners:[],updateResizeListeners:function(){var canvas=Module["canvas"];Browser.resizeListeners.forEach(listener=>listener(canvas.width,canvas.height))},setCanvasSize:function(width,height,noUpdates){var canvas=Module["canvas"];Browser.updateCanvasDimensions(canvas,width,height);if(!noUpdates)Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen>>2];flags=flags|8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module["canvas"]);Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen>>2];flags=flags&~8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module["canvas"]);Browser.updateResizeListeners()},updateCanvasDimensions:function(canvas,wNative,hNative){if(wNative&&hNative){canvas.widthNative=wNative;canvas.heightNative=hNative}else{wNative=canvas.widthNative;hNative=canvas.heightNative}var w=wNative;var h=hNative;if(Module["forcedAspectRatio"]&&Module["forcedAspectRatio"]>0){if(w/h>2];if(param==12321){var alphaSize=HEAP32[attribList+4>>2];EGL.contextAttributes.alpha=alphaSize>0}else if(param==12325){var depthSize=HEAP32[attribList+4>>2];EGL.contextAttributes.depth=depthSize>0}else if(param==12326){var stencilSize=HEAP32[attribList+4>>2];EGL.contextAttributes.stencil=stencilSize>0}else if(param==12337){var samples=HEAP32[attribList+4>>2];EGL.contextAttributes.antialias=samples>0}else if(param==12338){var samples=HEAP32[attribList+4>>2];EGL.contextAttributes.antialias=samples==1}else if(param==12544){var requestedPriority=HEAP32[attribList+4>>2];EGL.contextAttributes.lowLatency=requestedPriority!=12547}else if(param==12344){break}attribList+=8}}if((!config||!config_size)&&!numConfigs){EGL.setErrorCode(12300);return 0}if(numConfigs){HEAP32[numConfigs>>2]=1}if(config&&config_size>0){HEAP32[config>>2]=62002}EGL.setErrorCode(12288);return 1}};function _eglChooseConfig(display,attrib_list,configs,config_size,numConfigs){return EGL.chooseConfig(display,attrib_list,configs,config_size,numConfigs)}function webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(ctx){return!!(ctx.dibvbi=ctx.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"))}function webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(ctx){return!!(ctx.mdibvbi=ctx.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance"))}function webgl_enable_WEBGL_multi_draw(ctx){return!!(ctx.multiDrawWebgl=ctx.getExtension("WEBGL_multi_draw"))}var GL={counter:1,buffers:[],programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:function(table){var ret=GL.counter++;for(var i=table.length;i>2]:-1;source+=UTF8ToString(HEAP32[string+i*4>>2],len<0?undefined:len)}return source},createContext:function(canvas,webGLContextAttributes){if(!canvas.getContextSafariWebGL2Fixed){canvas.getContextSafariWebGL2Fixed=canvas.getContext;function fixedGetContext(ver,attrs){var gl=canvas.getContextSafariWebGL2Fixed(ver,attrs);return ver=="webgl"==gl instanceof WebGLRenderingContext?gl:null}canvas.getContext=fixedGetContext}var ctx=canvas.getContext("webgl2",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=GL.getNewId(GL.contexts);var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault=="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context)}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return!(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents=="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;GL.contexts[contextHandle]=null},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);if(context.version>=2){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query_webgl2")}if(context.version<2||!GLctx.disjointTimerQueryExt){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query")}webgl_enable_WEBGL_multi_draw(GLctx);var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(!ext.includes("lose_context")&&!ext.includes("debug")){GLctx.getExtension(ext)}})}};function _eglCreateContext(display,config,hmm,contextAttribs){if(display!=62e3){EGL.setErrorCode(12296);return 0}var glesContextVersion=1;for(;;){var param=HEAP32[contextAttribs>>2];if(param==12440){glesContextVersion=HEAP32[contextAttribs+4>>2]}else if(param==12344){break}else{EGL.setErrorCode(12292);return 0}contextAttribs+=8}if(glesContextVersion<2||glesContextVersion>3){EGL.setErrorCode(12293);return 0}EGL.contextAttributes.majorVersion=glesContextVersion-1;EGL.contextAttributes.minorVersion=0;EGL.context=GL.createContext(Module["canvas"],EGL.contextAttributes);if(EGL.context!=0){EGL.setErrorCode(12288);GL.makeContextCurrent(EGL.context);Module.useWebGL=true;Browser.moduleContextCreatedCallbacks.forEach(function(callback){callback()});GL.makeContextCurrent(null);return 62004}else{EGL.setErrorCode(12297);return 0}}function _eglCreateWindowSurface(display,config,win,attrib_list){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(config!=62002){EGL.setErrorCode(12293);return 0}EGL.setErrorCode(12288);return 62006}function _eglDestroyContext(display,context){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(context!=62004){EGL.setErrorCode(12294);return 0}GL.deleteContext(EGL.context);EGL.setErrorCode(12288);if(EGL.currentContext==context){EGL.currentContext=0}return 1}function _eglDestroySurface(display,surface){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(surface!=62006){EGL.setErrorCode(12301);return 1}if(EGL.currentReadSurface==surface){EGL.currentReadSurface=0}if(EGL.currentDrawSurface==surface){EGL.currentDrawSurface=0}EGL.setErrorCode(12288);return 1}function _eglGetDisplay(nativeDisplayType){EGL.setErrorCode(12288);return 62e3}function _eglInitialize(display,majorVersion,minorVersion){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(majorVersion){HEAP32[majorVersion>>2]=1}if(minorVersion){HEAP32[minorVersion>>2]=4}EGL.defaultDisplayInitialized=true;EGL.setErrorCode(12288);return 1}function _eglMakeCurrent(display,draw,read,context){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(context!=0&&context!=62004){EGL.setErrorCode(12294);return 0}if(read!=0&&read!=62006||draw!=0&&draw!=62006){EGL.setErrorCode(12301);return 0}GL.makeContextCurrent(context?EGL.context:null);EGL.currentContext=context;EGL.currentDrawSurface=draw;EGL.currentReadSurface=read;EGL.setErrorCode(12288);return 1}function _eglSwapBuffers(dpy,surface){if(!EGL.defaultDisplayInitialized){EGL.setErrorCode(12289)}else if(!Module.ctx){EGL.setErrorCode(12290)}else if(Module.ctx.isContextLost()){EGL.setErrorCode(12302)}else{EGL.setErrorCode(12288);return 1}return 0}function _eglSwapInterval(display,interval){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(interval==0)_emscripten_set_main_loop_timing(0,0);else _emscripten_set_main_loop_timing(1,interval);EGL.setErrorCode(12288);return 1}function _eglTerminate(display){if(display!=62e3){EGL.setErrorCode(12296);return 0}EGL.currentContext=0;EGL.currentReadSurface=0;EGL.currentDrawSurface=0;EGL.defaultDisplayInitialized=false;EGL.setErrorCode(12288);return 1}var readEmAsmArgsArray=[];function readEmAsmArgs(sigPtr,buf){readEmAsmArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){buf+=ch!=105&buf;readEmAsmArgsArray.push(ch==105?HEAP32[buf]:HEAPF64[buf++>>1]);++buf}return readEmAsmArgsArray}function runEmAsmFunction(code,sigPtr,argbuf){var args=readEmAsmArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)}function _emscripten_asm_const_int(code,sigPtr,argbuf){return runEmAsmFunction(code,sigPtr,argbuf)}function _emscripten_cancel_main_loop(){Browser.mainLoop.pause();Browser.mainLoop.func=null}function _emscripten_date_now(){return Date.now()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function getHeapMax(){return 2147483648}function emscripten_realloc_buffer(size){var b=wasmMemory.buffer;try{wasmMemory.grow(size-b.byteLength+65535>>>16);updateMemoryViews();return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var JSEvents={inEventHandler:0,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i)}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[]},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){__ATEXIT__.push(JSEvents.removeAllEventListeners);JSEvents.removeEventListenersRegistered=true}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!="undefined"?document:0,typeof window!="undefined"?window:0];function findEventTarget(target){target=maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!="undefined"?document.querySelector(target):undefined);return domElement}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}var wasmTableMirror=[];function getWasmTableEntry(funcPtr){var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func}function registerFocusEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.focusEvent)JSEvents.focusEvent=_malloc(256);var focusEventHandlerFunc=function(e=event){var nodeName=JSEvents.getNodeNameForTarget(e.target);var id=e.target.id?e.target.id:"";var focusEvent=JSEvents.focusEvent;stringToUTF8(nodeName,focusEvent+0,128);stringToUTF8(id,focusEvent+128,128);if(getWasmTableEntry(callbackfunc)(eventTypeId,focusEvent,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:focusEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_blur_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerFocusEventCallback(target,userData,useCapture,callbackfunc,12,"blur",targetThread)}function findCanvasEventTarget(target){return findEventTarget(target)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=findCanvasEventTarget(target);if(!canvas)return-4;canvas.width=width;canvas.height=height;return 0}function _emscripten_set_focus_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerFocusEventCallback(target,userData,useCapture,callbackfunc,13,"focus",targetThread)}function registerKeyEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.keyEvent)JSEvents.keyEvent=_malloc(176);var keyEventHandlerFunc=function(e){var keyEventData=JSEvents.keyEvent;HEAPF64[keyEventData>>3]=e.timeStamp;var idx=keyEventData>>2;HEAP32[idx+2]=e.location;HEAP32[idx+3]=e.ctrlKey;HEAP32[idx+4]=e.shiftKey;HEAP32[idx+5]=e.altKey;HEAP32[idx+6]=e.metaKey;HEAP32[idx+7]=e.repeat;HEAP32[idx+8]=e.charCode;HEAP32[idx+9]=e.keyCode;HEAP32[idx+10]=e.which;stringToUTF8(e.key||"",keyEventData+44,32);stringToUTF8(e.code||"",keyEventData+76,32);stringToUTF8(e.char||"",keyEventData+108,32);stringToUTF8(e.locale||"",keyEventData+140,32);if(getWasmTableEntry(callbackfunc)(eventTypeId,keyEventData,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:keyEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_keydown_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerKeyEventCallback(target,userData,useCapture,callbackfunc,2,"keydown",targetThread)}function _emscripten_set_keyup_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerKeyEventCallback(target,userData,useCapture,callbackfunc,3,"keyup",targetThread)}function _emscripten_set_main_loop(func,fps,simulateInfiniteLoop){var browserIterationFunc=getWasmTableEntry(func);setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop)}function getBoundingClientRect(e){return specialHTMLTargets.indexOf(e)<0?e.getBoundingClientRect():{"left":0,"top":0}}function fillMouseEventData(eventStruct,e,target){HEAPF64[eventStruct>>3]=e.timeStamp;var idx=eventStruct>>2;HEAP32[idx+2]=e.screenX;HEAP32[idx+3]=e.screenY;HEAP32[idx+4]=e.clientX;HEAP32[idx+5]=e.clientY;HEAP32[idx+6]=e.ctrlKey;HEAP32[idx+7]=e.shiftKey;HEAP32[idx+8]=e.altKey;HEAP32[idx+9]=e.metaKey;HEAP16[idx*2+20]=e.button;HEAP16[idx*2+21]=e.buttons;HEAP32[idx+11]=e["movementX"];HEAP32[idx+12]=e["movementY"];var rect=getBoundingClientRect(target);HEAP32[idx+13]=e.clientX-rect.left;HEAP32[idx+14]=e.clientY-rect.top}function registerMouseEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.mouseEvent)JSEvents.mouseEvent=_malloc(72);target=findEventTarget(target);var mouseEventHandlerFunc=function(e=event){fillMouseEventData(JSEvents.mouseEvent,e,target);if(getWasmTableEntry(callbackfunc)(eventTypeId,JSEvents.mouseEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString!="mousemove"&&eventTypeString!="mouseenter"&&eventTypeString!="mouseleave",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:mouseEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_mousedown_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerMouseEventCallback(target,userData,useCapture,callbackfunc,5,"mousedown",targetThread)}function _emscripten_set_mousemove_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerMouseEventCallback(target,userData,useCapture,callbackfunc,8,"mousemove",targetThread)}function _emscripten_set_mouseup_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerMouseEventCallback(target,userData,useCapture,callbackfunc,6,"mouseup",targetThread)}function registerTouchEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.touchEvent)JSEvents.touchEvent=_malloc(1696);target=findEventTarget(target);var touchEventHandlerFunc=function(e){var t,touches={},et=e.touches;for(var i=0;i>3]=e.timeStamp;var idx=touchEvent>>2;HEAP32[idx+3]=e.ctrlKey;HEAP32[idx+4]=e.shiftKey;HEAP32[idx+5]=e.altKey;HEAP32[idx+6]=e.metaKey;idx+=7;var targetRect=getBoundingClientRect(target);var numTouches=0;for(var i in touches){t=touches[i];HEAP32[idx+0]=t.identifier;HEAP32[idx+1]=t.screenX;HEAP32[idx+2]=t.screenY;HEAP32[idx+3]=t.clientX;HEAP32[idx+4]=t.clientY;HEAP32[idx+5]=t.pageX;HEAP32[idx+6]=t.pageY;HEAP32[idx+7]=t.isChanged;HEAP32[idx+8]=t.onTarget;HEAP32[idx+9]=t.clientX-targetRect.left;HEAP32[idx+10]=t.clientY-targetRect.top;idx+=13;if(++numTouches>31){break}}HEAP32[touchEvent+8>>2]=numTouches;if(getWasmTableEntry(callbackfunc)(eventTypeId,touchEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString=="touchstart"||eventTypeString=="touchend",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:touchEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_touchend_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerTouchEventCallback(target,userData,useCapture,callbackfunc,23,"touchend",targetThread)}function _emscripten_set_touchmove_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerTouchEventCallback(target,userData,useCapture,callbackfunc,24,"touchmove",targetThread)}function _emscripten_set_touchstart_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerTouchEventCallback(target,userData,useCapture,callbackfunc,22,"touchstart",targetThread)}function registerWheelEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.wheelEvent)JSEvents.wheelEvent=_malloc(104);var wheelHandlerFunc=function(e=event){var wheelEvent=JSEvents.wheelEvent;fillMouseEventData(wheelEvent,e,target);HEAPF64[wheelEvent+72>>3]=e["deltaX"];HEAPF64[wheelEvent+80>>3]=e["deltaY"];HEAPF64[wheelEvent+88>>3]=e["deltaZ"];HEAP32[wheelEvent+96>>2]=e["deltaMode"];if(getWasmTableEntry(callbackfunc)(eventTypeId,wheelEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:wheelHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_wheel_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){target=findEventTarget(target);if(!target)return-4;if(typeof target.onwheel!="undefined"){return registerWheelEventCallback(target,userData,useCapture,callbackfunc,9,"wheel",targetThread)}else{return-1}}function _emscripten_set_window_title(title){setWindowTitle(UTF8ToString(title))}var ENV={};function getExecutableName(){return thisProgram||"./this.program"}function getEnvStrings(){if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":lang,"_":getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings}function stringToAscii(str,buffer){for(var i=0;i>0]=str.charCodeAt(i)}HEAP8[buffer>>0]=0}function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings().forEach(function(string,i){var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1});return 0}function _environ_sizes_get(penviron_count,penviron_buf_size){var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(function(string){bufSize+=string.length+1});HEAPU32[penviron_buf_size>>2]=bufSize;return 0}function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function doReadv(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function convertI32PairToI53Checked(lo,hi){return hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{var offset=convertI32PairToI53Checked(offset_low,offset_high);if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function doWritev(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!=="undefined"){offset+=curr}}return ret}function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _glAttachShader(program,shader){GLctx.attachShader(GL.programs[program],GL.shaders[shader])}function _glBindBuffer(target,buffer){if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,GL.buffers[buffer])}function _glBindTexture(target,texture){GLctx.bindTexture(target,GL.textures[texture])}function _glBindVertexArray(vao){GLctx.bindVertexArray(GL.vaos[vao])}var _glBindVertexArrayOES=_glBindVertexArray;function _glBlendFunc(x0,x1){GLctx.blendFunc(x0,x1)}function _glBufferData(target,size,data,usage){if(true){if(data&&size){GLctx.bufferData(target,HEAPU8,usage,data,size)}else{GLctx.bufferData(target,size,usage)}}else{GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)}}function _glClear(x0){GLctx.clear(x0)}function _glClearColor(x0,x1,x2,x3){GLctx.clearColor(x0,x1,x2,x3)}function _glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}function _glCreateProgram(){var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;program.maxUniformLength=program.maxAttributeLength=program.maxUniformBlockNameLength=0;program.uniformIdCounter=1;GL.programs[id]=program;return id}function _glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id}function _glDeleteProgram(id){if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null}function _glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null}function _glDeleteTextures(n,textures){for(var i=0;i>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}}function _glDrawArrays(mode,first,count){GLctx.drawArrays(mode,first,count)}function _glEnable(x0){GLctx.enable(x0)}function _glEnableVertexAttribArray(index){GLctx.enableVertexAttribArray(index)}function __glGenObject(n,buffers,createFunction,objectTable){for(var i=0;i>2]=id}}function _glGenBuffers(n,buffers){__glGenObject(n,buffers,"createBuffer",GL.buffers)}function _glGenTextures(n,textures){__glGenObject(n,textures,"createTexture",GL.textures)}function _glGenVertexArrays(n,arrays){__glGenObject(n,arrays,"createVertexArray",GL.vaos)}var _glGenVertexArraysOES=_glGenVertexArrays;function _glGetShaderInfoLog(shader,maxLength,length,infoLog){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _glLinkProgram(program){program=GL.programs[program];GLctx.linkProgram(program);program.uniformLocsById=0;program.uniformSizeAndIdsByName={}}function computeUnpackAlignedImageSize(width,height,sizePerPixel,alignment){function roundedToNextMultipleOf(x,y){return x+y-1&-y}var plainRowSize=width*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,alignment);return height*alignedRowSize}function colorChannelsInGlTextureFormat(format){var colorChannels={5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4};return colorChannels[format-6402]||1}function heapObjectForWebGLType(type){type-=5120;if(type==0)return HEAP8;if(type==1)return HEAPU8;if(type==2)return HEAP16;if(type==4)return HEAP32;if(type==6)return HEAPF32;if(type==5||type==28922||type==28520||type==30779||type==30782)return HEAPU32;return HEAPU16}function heapAccessShiftForWebGLHeap(heap){return 31-Math.clz32(heap.BYTES_PER_ELEMENT)}function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat){var heap=heapObjectForWebGLType(type);var shift=heapAccessShiftForWebGLHeap(heap);var byteSize=1<>shift,pixels+bytes>>shift)}function _glReadPixels(x,y,width,height,format,type,pixels){if(true){if(GLctx.currentPixelPackBufferBinding){GLctx.readPixels(x,y,width,height,format,type,pixels)}else{var heap=heapObjectForWebGLType(type);GLctx.readPixels(x,y,width,height,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}return}var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)}function _glShaderSource(shader,count,string,length){var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)}function _glTexImage2D(target,level,internalFormat,width,height,border,format,type,pixels){if(true){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,null)}return}GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null)}function _glTexParameteri(x0,x1,x2){GLctx.texParameteri(x0,x1,x2)}function _glUseProgram(program){program=GL.programs[program];GLctx.useProgram(program);GLctx.currentProgram=program}function _glVertexAttribPointer(index,size,type,normalized,stride,ptr){GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)}function _glViewport(x0,x1,x2,x3){GLctx.viewport(x0,x1,x2,x3)}function isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}function arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum}var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value=="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={"%a":function(date){return WEEKDAYS[date.tm_wday].substring(0,3)},"%A":function(date){return WEEKDAYS[date.tm_wday]},"%b":function(date){return MONTHS[date.tm_mon].substring(0,3)},"%B":function(date){return MONTHS[date.tm_mon]},"%C":function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":function(date){return leadingNulls(date.tm_mday,2)},"%e":function(date){return leadingSomething(date.tm_mday,2," ")},"%g":function(date){return getWeekBasedYear(date).toString().substring(2)},"%G":function(date){return getWeekBasedYear(date)},"%H":function(date){return leadingNulls(date.tm_hour,2)},"%I":function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":function(date){return leadingNulls(date.tm_mday+arraySum(isLeapYear(date.tm_year+1900)?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,date.tm_mon-1),3)},"%m":function(date){return leadingNulls(date.tm_mon+1,2)},"%M":function(date){return leadingNulls(date.tm_min,2)},"%n":function(){return"\n"},"%p":function(date){if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}return"PM"},"%S":function(date){return leadingNulls(date.tm_sec,2)},"%t":function(){return"\t"},"%u":function(date){return date.tm_wday||7},"%U":function(date){var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},"%V":function(date){var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},"%w":function(date){return date.tm_wday},"%W":function(date){var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},"%y":function(date){return(date.tm_year+1900).toString().substring(2)},"%Y":function(date){return date.tm_year+1900},"%z":function(date){var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":function(date){return date.tm_zone},"%%":function(){return"%"}};pattern=pattern.replace(/%%/g,"\0\0");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\0\0/g,"%");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _strftime_l(s,maxsize,format,tm,loc){return _strftime(s,maxsize,format,tm)}var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_unlink"]=FS.unlink;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;Module["requestFullscreen"]=function Module_requestFullscreen(lockPointer,resizeCanvas){Browser.requestFullscreen(lockPointer,resizeCanvas)};Module["requestAnimationFrame"]=function Module_requestAnimationFrame(func){Browser.requestAnimationFrame(func)};Module["setCanvasSize"]=function Module_setCanvasSize(width,height,noUpdates){Browser.setCanvasSize(width,height,noUpdates)};Module["pauseMainLoop"]=function Module_pauseMainLoop(){Browser.mainLoop.pause()};Module["resumeMainLoop"]=function Module_resumeMainLoop(){Browser.mainLoop.resume()};Module["getUserMedia"]=function Module_getUserMedia(){Browser.getUserMedia()};Module["createContext"]=function Module_createContext(canvas,useWebGL,setInModule,webGLContextAttributes){return Browser.createContext(canvas,useWebGL,setInModule,webGLContextAttributes)};var preloadedImages={};var preloadedAudios={};var GLctx;var decodeBase64=typeof atob=="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;run(); +var Module=typeof Module!="undefined"?Module:{};if(!Module.expectedDataFileDownloads){Module.expectedDataFileDownloads=0}Module.expectedDataFileDownloads++;(function(){if(Module["ENVIRONMENT_IS_PTHREAD"]||Module["$ww"])return;var loadPackage=function(metadata){var PACKAGE_PATH="";if(typeof window==="object"){PACKAGE_PATH=window["encodeURIComponent"](window.location.pathname.toString().substring(0,window.location.pathname.toString().lastIndexOf("/"))+"/")}else if(typeof process==="undefined"&&typeof location!=="undefined"){PACKAGE_PATH=encodeURIComponent(location.pathname.toString().substring(0,location.pathname.toString().lastIndexOf("/"))+"/")}var PACKAGE_NAME="pge.data";var REMOTE_PACKAGE_BASE="pge.data";if(typeof Module["locateFilePackage"]==="function"&&!Module["locateFile"]){Module["locateFile"]=Module["locateFilePackage"];err("warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)")}var REMOTE_PACKAGE_NAME=Module["locateFile"]?Module["locateFile"](REMOTE_PACKAGE_BASE,""):REMOTE_PACKAGE_BASE;var REMOTE_PACKAGE_SIZE=metadata["remote_package_size"];function fetchRemotePackage(packageName,packageSize,callback,errback){if(typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string"){require("fs").readFile(packageName,function(err,contents){if(err){errback(err)}else{callback(contents.buffer)}});return}var xhr=new XMLHttpRequest;xhr.open("GET",packageName,true);xhr.responseType="arraybuffer";xhr.onprogress=function(event){var url=packageName;var size=packageSize;if(event.total)size=event.total;if(event.loaded){if(!xhr.addedTotal){xhr.addedTotal=true;if(!Module.dataFileDownloads)Module.dataFileDownloads={};Module.dataFileDownloads[url]={loaded:event.loaded,total:size}}else{Module.dataFileDownloads[url].loaded=event.loaded}var total=0;var loaded=0;var num=0;for(var download in Module.dataFileDownloads){var data=Module.dataFileDownloads[download];total+=data.total;loaded+=data.loaded;num++}total=Math.ceil(total*Module.expectedDataFileDownloads/num);if(Module["setStatus"])Module["setStatus"](`Downloading data... (${loaded}/${total})`)}else if(!Module.dataFileDownloads){if(Module["setStatus"])Module["setStatus"]("Downloading data...")}};xhr.onerror=function(event){throw new Error("NetworkError for: "+packageName)};xhr.onload=function(event){if(xhr.status==200||xhr.status==304||xhr.status==206||xhr.status==0&&xhr.response){var packageData=xhr.response;callback(packageData)}else{throw new Error(xhr.statusText+" : "+xhr.responseURL)}};xhr.send(null)}function handleError(error){console.error("package error:",error)}var fetchedCallback=null;var fetched=Module["getPreloadedPackage"]?Module["getPreloadedPackage"](REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE):null;if(!fetched)fetchRemotePackage(REMOTE_PACKAGE_NAME,REMOTE_PACKAGE_SIZE,function(data){if(fetchedCallback){fetchedCallback(data);fetchedCallback=null}else{fetched=data}},handleError);function runWithFS(){function assert(check,msg){if(!check)throw msg+(new Error).stack}Module["FS_createPath"]("/","assets",true,true);Module["FS_createPath"]("/assets","Ability Icons",true,true);Module["FS_createPath"]("/assets","Campaigns",true,true);Module["FS_createPath"]("/assets","backgrounds",true,true);Module["FS_createPath"]("/assets","characters",true,true);Module["FS_createPath"]("/assets","config",true,true);Module["FS_createPath"]("/assets/config","classes",true,true);Module["FS_createPath"]("/assets/config","gfx",true,true);Module["FS_createPath"]("/assets/config","items",true,true);Module["FS_createPath"]("/assets/config","shops",true,true);Module["FS_createPath"]("/assets/config","story",true,true);Module["FS_createPath"]("/assets","items",true,true);Module["FS_createPath"]("/assets","maps",true,true);Module["FS_createPath"]("/assets/maps","commercial_assets",true,true);Module["FS_createPath"]("/assets","menus",true,true);Module["FS_createPath"]("/assets","monsters",true,true);Module["FS_createPath"]("/assets","themes",true,true);function DataRequest(start,end,audio){this.start=start;this.end=end;this.audio=audio}DataRequest.prototype={requests:{},open:function(mode,name){this.name=name;this.requests[name]=this;Module["addRunDependency"](`fp ${this.name}`)},send:function(){},onload:function(){var byteArray=this.byteArray.subarray(this.start,this.end);this.finish(byteArray)},finish:function(byteArray){var that=this;Module["FS_createDataFile"](this.name,null,byteArray,true,true,true);Module["removeRunDependency"](`fp ${that.name}`);this.requests[this.name]=null}};var files=metadata["files"];for(var i=0;i{throw toThrow};var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");if(ENVIRONMENT_IS_WORKER){scriptDirectory=nodePath.dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=(filename,binary)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return fs.readFileSync(filename,binary?undefined:"utf8")};readBinary=filename=>{var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}return ret};readAsync=(filename,onload,onerror,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)onerror(err);else onload(binary?data.buffer:data)})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);if(typeof module!="undefined"){module["exports"]=Module}process.on("uncaughtException",ex=>{if(ex!=="unwind"&&!(ex instanceof ExitStatus)&&!(ex.context instanceof ExitStatus)){throw ex}});var nodeMajor=process.versions.node.split(".")[0];if(nodeMajor<15){process.on("unhandledRejection",reason=>{throw reason})}quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow};Module["inspect"]=()=>"[Emscripten Module object]"}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort(text)}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeKeepaliveCounter=0;function keepRuntimeAlive(){return noExitRuntime||runtimeKeepaliveCounter>0}function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}function isFileURI(filename){return filename.startsWith("file://")}var wasmBinaryFile;wasmBinaryFile="pge.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}catch(err){abort(err)}}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"&&!isFileURI(binaryFile)){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{if(!response["ok"]){throw"failed to load wasm binary file at '"+binaryFile+"'"}return response["arrayBuffer"]()}).catch(()=>getBinary(binaryFile))}else{if(readAsync){return new Promise((resolve,reject)=>{readAsync(binaryFile,response=>resolve(new Uint8Array(response)),reject)})}}}return Promise.resolve().then(()=>getBinary(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>{return WebAssembly.instantiate(binary,imports)}).then(instance=>{return instance}).then(receiver,reason=>{err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}else{return instantiateArrayBuffer(binaryFile,imports,callback)}}function createWasm(){var info={"env":wasmImports,"wasi_snapshot_preview1":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["memory"];updateMemoryViews();wasmTable=Module["asm"]["__indirect_function_table"];addOnInit(Module["asm"]["__wasm_call_ctors"]);removeRunDependency("wasm-instantiate");return exports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}var tempDouble;var tempI64;var ASM_CONSTS={325348:()=>{window.onunload=Module._olc_OnPageUnload},325392:($0,$1)=>{Module.olc_AspectRatio=$0/$1;Module.olc_AssumeDefaultShells=document.querySelectorAll(".emscripten").length>=3?true:false;oncontextmenu=function(e){return false};var olc_ResizeHandler=function(){let isFullscreen=document.fullscreenElement!=null;let width=isFullscreen?window.innerWidth:Module.canvas.parentNode.clientWidth;let height=isFullscreen?window.innerHeight:Module.canvas.parentNode.clientHeight;let viewWidth=width;let viewHeight=width/Module.olc_AspectRatio;if(viewHeight>height){viewWidth=height*Module.olc_AspectRatio;viewHeight=height}viewWidth=parseInt(viewWidth);viewHeight=parseInt(viewHeight);setTimeout(function(){if(Module.olc_AssumeDefaultShells)Module.canvas.parentNode.setAttribute("style","width: 100%; height: 70vh; margin-left: auto; margin-right: auto;");Module.canvas.setAttribute("width",viewWidth);Module.canvas.setAttribute("height",viewHeight);Module.canvas.setAttribute("style",`width: ${viewWidth}px; height: ${viewHeight}px;`);Module._olc_PGE_UpdateWindowSize(viewWidth,viewHeight);Module.canvas.focus()},200)};var olc_Init=function(){if(Module.olc_AspectRatio===undefined){setTimeout(function(){Module.olc_Init()},50);return}let resizeObserver=new ResizeObserver(function(entries){Module.olc_ResizeHandler()}).observe(Module.canvas.parentNode);let mutationObserver=new MutationObserver(function(mutationsList,observer){setTimeout(function(){Module.olc_ResizeHandler()},200)}).observe(Module.canvas.parentNode,{attributes:false,childList:true,subtree:false});window.addEventListener("fullscreenchange",function(e){setTimeout(function(){Module.olc_ResizeHandler()},200)})};Module.olc_ResizeHandler=Module.olc_ResizeHandler!=undefined?Module.olc_ResizeHandler:olc_ResizeHandler;Module.olc_Init=Module.olc_Init!=undefined?Module.olc_Init:olc_Init;Module.olc_Init()},327365:()=>{return window.scrollX},327389:()=>{return window.scrollY},327413:()=>{return window.scrollX},327437:()=>{return window.scrollY},327461:()=>{return window.scrollX},327485:()=>{return window.scrollY},327509:()=>{return Module.canvas.getBoundingClientRect().left},327561:()=>{return Module.canvas.getBoundingClientRect().top},327612:()=>{return Module.canvas.getBoundingClientRect().left},327664:()=>{return Module.canvas.getBoundingClientRect().top}};function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){callbacks.shift()(Module)}}var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heapOrArray,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function ___assert_fail(condition,filename,line,func){abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])}var exceptionCaught=[];var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_rethrow(){var info=exceptionCaught.pop();if(!info){abort("no exception to throw")}var ptr=info.excPtr;if(!info.get_rethrown()){exceptionCaught.push(info);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}exceptionLast=ptr;throw exceptionLast}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast}function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:function(){var paths=Array.prototype.slice.call(arguments);return PATH.normalize(paths.join("/"))},join2:(l,r)=>{return PATH.normalize(l+"/"+r)}};function initRandomFill(){if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else if(ENVIRONMENT_IS_NODE){try{var crypto_module=require("crypto");var randomFillSync=crypto_module["randomFillSync"];if(randomFillSync){return view=>crypto_module["randomFillSync"](view)}var randomBytes=crypto_module["randomBytes"];return view=>(view.set(randomBytes(view.byteLength)),view)}catch(e){}}abort("initRandomDevice")}function randomFill(view){return(randomFill=initRandomFill())(view)}var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var TTY={ttys:[],init:function(){},shutdown:function(){},register:function(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open:function(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close:function(stream){stream.tty.ops.fsync(stream.tty)},fsync:function(stream){stream.tty.ops.fsync(stream.tty)},read:function(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};function mmapAlloc(size){abort()}var MEMFS={ops_table:null,mount:function(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode:function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray:function(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage:function(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr:function(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr:function(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup:function(parent,name){throw FS.genericErrors[44]},mknod:function(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename:function(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp;old_node.parent=new_dir},unlink:function(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir:function(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir:function(node){var entries=[".",".."];for(var key in node.contents){if(!node.contents.hasOwnProperty(key)){continue}entries.push(key)}return entries},symlink:function(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink:function(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read:function(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},event=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)}var preloadPlugins=Module["preloadPlugins"]||[];function FS_handledByPreloadPlugin(byteArray,fullname,finish,onerror){if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(function(plugin){if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled}function FS_createPreloadedFile(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish){var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){if(preFinish)preFinish();if(!dontCreateFile){FS.createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}if(onload)onload();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{if(onerror)onerror();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,byteArray=>processData(byteArray),onerror)}else{processData(url)}}function FS_modeStringToFlags(str){var flagModes={"r":0,"r+":2,"w":512|64|1,"w+":512|64|2,"a":1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags}function FS_getMode(canRead,canWrite){var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode}var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:(path,opts={})=>{path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:node=>{var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName:(parentid,name)=>{var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode:node=>{var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:node=>{var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:(parent,name)=>{var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:(parent,name,mode,rdev)=>{var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:node=>{FS.hashRemoveNode(node)},isRoot:node=>{return node===node.parent},isMountpoint:node=>{return!!node.mounted},isFile:mode=>{return(mode&61440)===32768},isDir:mode=>{return(mode&61440)===16384},isLink:mode=>{return(mode&61440)===40960},isChrdev:mode=>{return(mode&61440)===8192},isBlkdev:mode=>{return(mode&61440)===24576},isFIFO:mode=>{return(mode&61440)===4096},isSocket:mode=>{return(mode&49152)===49152},flagsToPermissionString:flag=>{var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:(node,perms)=>{if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup:dir=>{var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:(dir,name)=>{try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:(dir,name,isdir)=>{var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:(node,flags)=>{if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:()=>{for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStream:fd=>FS.streams[fd],createStream:(stream,fd=-1)=>{if(!FS.FSStream){FS.FSStream=function(){this.shared={}};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}},flags:{get:function(){return this.shared.flags},set:function(val){this.shared.flags=val}},position:{get:function(){return this.shared.position},set:function(val){this.shared.position=val}}})}stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:fd=>{FS.streams[fd]=null},chrdev_stream_ops:{open:stream=>{var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:()=>{throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice:(dev,ops)=>{FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts:mount=>{var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:(populate,callback)=>{if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:(type,opts,mountpoint)=>{var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:mountpoint=>{var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:(parent,name)=>{return parent.node_ops.lookup(parent,name)},mknod:(path,mode,dev)=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:(path,mode)=>{mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:(path,mode)=>{mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:(path,mode)=>{var dirs=path.split("/");var d="";for(var i=0;i{if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink:(oldpath,newpath)=>{if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename:(old_path,new_path)=>{var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir:path=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(54)}return node.node_ops.readdir(node)},unlink:path=>{var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink:path=>{var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return PATH_FS.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))},stat:(path,dontFollow)=>{var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(44)}if(!node.node_ops.getattr){throw new FS.ErrnoError(63)}return node.node_ops.getattr(node)},lstat:path=>{return FS.stat(path,true)},chmod:(path,mode,dontFollow)=>{var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})},lchmod:(path,mode)=>{FS.chmod(path,mode,true)},fchmod:(fd,mode)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}FS.chmod(stream.node,mode)},chown:(path,uid,gid,dontFollow)=>{var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{timestamp:Date.now()})},lchown:(path,uid,gid)=>{FS.chown(path,uid,gid,true)},fchown:(fd,uid,gid)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}FS.chown(stream.node,uid,gid)},truncate:(path,len)=>{if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})},ftruncate:(fd,len)=>{var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.truncate(stream.node,len)},utime:(path,atime,mtime)=>{var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})},open:(path,flags,mode)=>{if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;mode=typeof mode=="undefined"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path=="object"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module["logReadFiles"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close:stream=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed:stream=>{return stream.fd===null},llseek:(stream,offset,whence)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read:(stream,buffer,offset,length,position)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write:(stream,buffer,offset,length,position,canOwn)=>{if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate:(stream,offset,length)=>{if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap:(stream,length,position,prot,flags)=>{if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync:(stream,buffer,offset,length,mmapFlags)=>{if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:stream=>0,ioctl:(stream,cmd,arg)=>{if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile:(path,opts={})=>{opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile:(path,data,opts={})=>{opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir:path=>{var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories:()=>{FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices:()=>{FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories:()=>{FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount:()=>{var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup:(parent,name)=>{var fd=+name;var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams:()=>{if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},ensureErrnoError:()=>{if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.name="ErrnoError";this.node=node;this.setErrno=function(errno){this.errno=errno};this.setErrno(errno);this.message="FS error"};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""})},staticInit:()=>{FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={"MEMFS":MEMFS}},init:(input,output,error)=>{FS.init.initialized=true;FS.ensureErrnoError();Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit:()=>{FS.init.initialized=false;for(var i=0;i{var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath:(path,dontResolveLastLink)=>{try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath:(parent,path,canRead,canWrite)=>{parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current},createFile:(parent,name,properties,canRead,canWrite)=>{var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile:(parent,name,data,canRead,canWrite,canOwn)=>{var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;i{var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open:stream=>{stream.seekable=false},close:stream=>{if(output&&output.buffer&&output.buffer.length){output(10)}},read:(stream,buffer,offset,length,pos)=>{var bytesRead=0;for(var i=0;i{for(var i=0;i{if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;if(typeof XMLHttpRequest!="undefined"){throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")}else if(read_){try{obj.contents=intArrayFromString(read_(obj.url),true);obj.usedBytes=obj.contents.length}catch(e){throw new FS.ErrnoError(29)}}else{throw new Error("Cannot load without read() or XMLHttpRequest.")}},createLazyFile:(parent,name,url,canRead,canWrite)=>{function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt:function(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat:function(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-54}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAPU32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAP32[buf+48>>2]=4096;HEAP32[buf+52>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];HEAPU32[buf+64>>2]=atime%1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];HEAPU32[buf+80>>2]=mtime%1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];HEAPU32[buf+96>>2]=ctime%1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+104>>2]=tempI64[0],HEAP32[buf+108>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);return stream}};function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}var newStream;newStream=FS.createStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 5:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 6:case 7:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:case 21505:{if(!stream.tty)return-59;return 0}case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:{if(!stream.tty)return-59;return 0}case 21519:{if(!stream.tty)return-59;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;return 0}case 21524:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?SYSCALLS.get():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var nowIsMonotonic=true;function __emscripten_get_now_is_monotonic(){return nowIsMonotonic}function __emscripten_throw_longjmp(){throw Infinity}function _abort(){abort("")}function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.timingMode=mode;Browser.mainLoop.timingValue=value;if(!Browser.mainLoop.func){return 1}if(!Browser.mainLoop.running){Browser.mainLoop.running=true}if(mode==0){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setTimeout(){var timeUntilNextTick=Math.max(0,Browser.mainLoop.tickStartTime+value-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,timeUntilNextTick)};Browser.mainLoop.method="timeout"}else if(mode==1){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_rAF(){Browser.requestAnimationFrame(Browser.mainLoop.runner)};Browser.mainLoop.method="rAF"}else if(mode==2){if(typeof setImmediate=="undefined"){var setImmediates=[];var emscriptenMainLoopMessageId="setimmediate";var Browser_setImmediate_messageHandler=event=>{if(event.data===emscriptenMainLoopMessageId||event.data.target===emscriptenMainLoopMessageId){event.stopPropagation();setImmediates.shift()()}};addEventListener("message",Browser_setImmediate_messageHandler,true);setImmediate=function Browser_emulated_setImmediate(func){setImmediates.push(func);if(ENVIRONMENT_IS_WORKER){if(Module["setImmediates"]===undefined)Module["setImmediates"]=[];Module["setImmediates"].push(func);postMessage({target:emscriptenMainLoopMessageId})}else postMessage(emscriptenMainLoopMessageId,"*")}}Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setImmediate(){setImmediate(Browser.mainLoop.runner)};Browser.mainLoop.method="immediate"}return 0}var _emscripten_get_now;if(ENVIRONMENT_IS_NODE){global.performance=require("perf_hooks").performance}_emscripten_get_now=()=>performance.now();function setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg,noSetTiming){assert(!Browser.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.");Browser.mainLoop.func=browserIterationFunc;Browser.mainLoop.arg=arg;var thisMainLoopId=Browser.mainLoop.currentlyRunningMainloop;function checkIsRunning(){if(thisMainLoopId0){var start=Date.now();var blocker=Browser.mainLoop.queue.shift();blocker.func(blocker.arg);if(Browser.mainLoop.remainingBlockers){var remaining=Browser.mainLoop.remainingBlockers;var next=remaining%1==0?remaining-1:Math.floor(remaining);if(blocker.counted){Browser.mainLoop.remainingBlockers=next}else{next=next+.5;Browser.mainLoop.remainingBlockers=(8*remaining+next)/9}}out('main loop blocker "'+blocker.name+'" took '+(Date.now()-start)+" ms");Browser.mainLoop.updateStatus();if(!checkIsRunning())return;setTimeout(Browser.mainLoop.runner,0);return}if(!checkIsRunning())return;Browser.mainLoop.currentFrameNumber=Browser.mainLoop.currentFrameNumber+1|0;if(Browser.mainLoop.timingMode==1&&Browser.mainLoop.timingValue>1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else if(Browser.mainLoop.timingMode==0){Browser.mainLoop.tickStartTime=_emscripten_get_now()}Browser.mainLoop.runIter(browserIterationFunc);if(!checkIsRunning())return;if(typeof SDL=="object"&&SDL.audio&&SDL.audio.queueNewAudioData)SDL.audio.queueNewAudioData();Browser.mainLoop.scheduler()};if(!noSetTiming){if(fps&&fps>0){_emscripten_set_main_loop_timing(0,1e3/fps)}else{_emscripten_set_main_loop_timing(1,1)}Browser.mainLoop.scheduler()}if(simulateInfiniteLoop){throw"unwind"}}function handleException(e){if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)}function _proc_exit(code){EXITSTATUS=code;if(!keepRuntimeAlive()){if(Module["onExit"])Module["onExit"](code);ABORT=true}quit_(code,new ExitStatus(code))}function exitJS(status,implicit){EXITSTATUS=status;_proc_exit(status)}var _exit=exitJS;function maybeExit(){if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}}function callUserCallback(func){if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}}function safeSetTimeout(func,timeout){return setTimeout(()=>{callUserCallback(func)},timeout)}var Browser={mainLoop:{running:false,scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null;Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var timingMode=Browser.mainLoop.timingMode;var timingValue=Browser.mainLoop.timingValue;var func=Browser.mainLoop.func;Browser.mainLoop.func=null;setMainLoop(func,0,false,Browser.mainLoop.arg,true);_emscripten_set_main_loop_timing(timingMode,timingValue);Browser.mainLoop.scheduler()},updateStatus:function(){if(Module["setStatus"]){var message=Module["statusMessage"]||"Please wait...";var remaining=Browser.mainLoop.remainingBlockers;var expected=Browser.mainLoop.expectedBlockers;if(remaining){if(remaining{assert(img.complete,"Image "+name+" could not be decoded");var canvas=document.createElement("canvas");canvas.width=img.width;canvas.height=img.height;var ctx=canvas.getContext("2d");ctx.drawImage(img,0,0);preloadedImages[name]=canvas;URL.revokeObjectURL(url);if(onload)onload(byteArray)};img.onerror=event=>{out("Image "+url+" could not be decoded");if(onerror)onerror()};img.src=url};preloadPlugins.push(imagePlugin);var audioPlugin={};audioPlugin["canHandle"]=function audioPlugin_canHandle(name){return!Module.noAudioDecoding&&name.substr(-4)in{".ogg":1,".wav":1,".mp3":1}};audioPlugin["handle"]=function audioPlugin_handle(byteArray,name,onload,onerror){var done=false;function finish(audio){if(done)return;done=true;preloadedAudios[name]=audio;if(onload)onload(byteArray)}var b=new Blob([byteArray],{type:Browser.getMimetype(name)});var url=URL.createObjectURL(b);var audio=new Audio;audio.addEventListener("canplaythrough",()=>finish(audio),false);audio.onerror=function audio_onerror(event){if(done)return;err("warning: browser could not fully decode audio "+name+", trying slower base64 approach");function encode64(data){var BASE="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";var PAD="=";var ret="";var leftchar=0;var leftbits=0;for(var i=0;i=6){var curr=leftchar>>leftbits-6&63;leftbits-=6;ret+=BASE[curr]}}if(leftbits==2){ret+=BASE[(leftchar&3)<<4];ret+=PAD+PAD}else if(leftbits==4){ret+=BASE[(leftchar&15)<<2];ret+=PAD}return ret}audio.src="data:audio/x-"+name.substr(-3)+";base64,"+encode64(byteArray);finish(audio)};audio.src=url;safeSetTimeout(()=>{finish(audio)},1e4)};preloadPlugins.push(audioPlugin);function pointerLockChange(){Browser.pointerLock=document["pointerLockElement"]===Module["canvas"]||document["mozPointerLockElement"]===Module["canvas"]||document["webkitPointerLockElement"]===Module["canvas"]||document["msPointerLockElement"]===Module["canvas"]}var canvas=Module["canvas"];if(canvas){canvas.requestPointerLock=canvas["requestPointerLock"]||canvas["mozRequestPointerLock"]||canvas["webkitRequestPointerLock"]||canvas["msRequestPointerLock"]||(()=>{});canvas.exitPointerLock=document["exitPointerLock"]||document["mozExitPointerLock"]||document["webkitExitPointerLock"]||document["msExitPointerLock"]||(()=>{});canvas.exitPointerLock=canvas.exitPointerLock.bind(document);document.addEventListener("pointerlockchange",pointerLockChange,false);document.addEventListener("mozpointerlockchange",pointerLockChange,false);document.addEventListener("webkitpointerlockchange",pointerLockChange,false);document.addEventListener("mspointerlockchange",pointerLockChange,false);if(Module["elementPointerLock"]){canvas.addEventListener("click",ev=>{if(!Browser.pointerLock&&Module["canvas"].requestPointerLock){Module["canvas"].requestPointerLock();ev.preventDefault()}},false)}}},createContext:function(canvas,useWebGL,setInModule,webGLContextAttributes){if(useWebGL&&Module.ctx&&canvas==Module.canvas)return Module.ctx;var ctx;var contextHandle;if(useWebGL){var contextAttributes={antialias:false,alpha:false,majorVersion:2};if(webGLContextAttributes){for(var attribute in webGLContextAttributes){contextAttributes[attribute]=webGLContextAttributes[attribute]}}if(typeof GL!="undefined"){contextHandle=GL.createContext(canvas,contextAttributes);if(contextHandle){ctx=GL.getContext(contextHandle).GLctx}}}else{ctx=canvas.getContext("2d")}if(!ctx)return null;if(setInModule){if(!useWebGL)assert(typeof GLctx=="undefined","cannot set in module if GLctx is used, but we are a non-GL context that would replace it");Module.ctx=ctx;if(useWebGL)GL.makeContextCurrent(contextHandle);Module.useWebGL=useWebGL;Browser.moduleContextCreatedCallbacks.forEach(callback=>callback());Browser.init()}return ctx},destroyContext:function(canvas,useWebGL,setInModule){},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer,resizeCanvas){Browser.lockPointer=lockPointer;Browser.resizeCanvas=resizeCanvas;if(typeof Browser.lockPointer=="undefined")Browser.lockPointer=true;if(typeof Browser.resizeCanvas=="undefined")Browser.resizeCanvas=false;var canvas=Module["canvas"];function fullscreenChange(){Browser.isFullscreen=false;var canvasContainer=canvas.parentNode;if((document["fullscreenElement"]||document["mozFullScreenElement"]||document["msFullscreenElement"]||document["webkitFullscreenElement"]||document["webkitCurrentFullScreenElement"])===canvasContainer){canvas.exitFullscreen=Browser.exitFullscreen;if(Browser.lockPointer)canvas.requestPointerLock();Browser.isFullscreen=true;if(Browser.resizeCanvas){Browser.setFullscreenCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}else{canvasContainer.parentNode.insertBefore(canvas,canvasContainer);canvasContainer.parentNode.removeChild(canvasContainer);if(Browser.resizeCanvas){Browser.setWindowedCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}if(Module["onFullScreen"])Module["onFullScreen"](Browser.isFullscreen);if(Module["onFullscreen"])Module["onFullscreen"](Browser.isFullscreen)}if(!Browser.fullscreenHandlersInstalled){Browser.fullscreenHandlersInstalled=true;document.addEventListener("fullscreenchange",fullscreenChange,false);document.addEventListener("mozfullscreenchange",fullscreenChange,false);document.addEventListener("webkitfullscreenchange",fullscreenChange,false);document.addEventListener("MSFullscreenChange",fullscreenChange,false)}var canvasContainer=document.createElement("div");canvas.parentNode.insertBefore(canvasContainer,canvas);canvasContainer.appendChild(canvas);canvasContainer.requestFullscreen=canvasContainer["requestFullscreen"]||canvasContainer["mozRequestFullScreen"]||canvasContainer["msRequestFullscreen"]||(canvasContainer["webkitRequestFullscreen"]?()=>canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"]):null)||(canvasContainer["webkitRequestFullScreen"]?()=>canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"]):null);canvasContainer.requestFullscreen()},exitFullscreen:function(){if(!Browser.isFullscreen){return false}var CFS=document["exitFullscreen"]||document["cancelFullScreen"]||document["mozCancelFullScreen"]||document["msExitFullscreen"]||document["webkitCancelFullScreen"]||(()=>{});CFS.apply(document,[]);return true},nextRAF:0,fakeRequestAnimationFrame:function(func){var now=Date.now();if(Browser.nextRAF===0){Browser.nextRAF=now+1e3/60}else{while(now+2>=Browser.nextRAF){Browser.nextRAF+=1e3/60}}var delay=Math.max(Browser.nextRAF-now,0);setTimeout(func,delay)},requestAnimationFrame:function(func){if(typeof requestAnimationFrame=="function"){requestAnimationFrame(func);return}var RAF=Browser.fakeRequestAnimationFrame;RAF(func)},safeSetTimeout:function(func,timeout){return safeSetTimeout(func,timeout)},safeRequestAnimationFrame:function(func){return Browser.requestAnimationFrame(()=>{callUserCallback(func)})},getMimetype:function(name){return{"jpg":"image/jpeg","jpeg":"image/jpeg","png":"image/png","bmp":"image/bmp","ogg":"audio/ogg","wav":"audio/wav","mp3":"audio/mpeg"}[name.substr(name.lastIndexOf(".")+1)]},getUserMedia:function(func){if(!window.getUserMedia){window.getUserMedia=navigator["getUserMedia"]||navigator["mozGetUserMedia"]}window.getUserMedia(func)},getMovementX:function(event){return event["movementX"]||event["mozMovementX"]||event["webkitMovementX"]||0},getMovementY:function(event){return event["movementY"]||event["mozMovementY"]||event["webkitMovementY"]||0},getMouseWheelDelta:function(event){var delta=0;switch(event.type){case"DOMMouseScroll":delta=event.detail/3;break;case"mousewheel":delta=event.wheelDelta/120;break;case"wheel":delta=event.deltaY;switch(event.deltaMode){case 0:delta/=100;break;case 1:delta/=3;break;case 2:delta*=80;break;default:throw"unrecognized mouse wheel delta mode: "+event.deltaMode}break;default:throw"unrecognized mouse wheel event: "+event.type}return delta},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(event){if(Browser.pointerLock){if(event.type!="mousemove"&&"mozMovementX"in event){Browser.mouseMovementX=Browser.mouseMovementY=0}else{Browser.mouseMovementX=Browser.getMovementX(event);Browser.mouseMovementY=Browser.getMovementY(event)}if(typeof SDL!="undefined"){Browser.mouseX=SDL.mouseX+Browser.mouseMovementX;Browser.mouseY=SDL.mouseY+Browser.mouseMovementY}else{Browser.mouseX+=Browser.mouseMovementX;Browser.mouseY+=Browser.mouseMovementY}}else{var rect=Module["canvas"].getBoundingClientRect();var cw=Module["canvas"].width;var ch=Module["canvas"].height;var scrollX=typeof window.scrollX!="undefined"?window.scrollX:window.pageXOffset;var scrollY=typeof window.scrollY!="undefined"?window.scrollY:window.pageYOffset;if(event.type==="touchstart"||event.type==="touchend"||event.type==="touchmove"){var touch=event.touch;if(touch===undefined){return}var adjustedX=touch.pageX-(scrollX+rect.left);var adjustedY=touch.pageY-(scrollY+rect.top);adjustedX=adjustedX*(cw/rect.width);adjustedY=adjustedY*(ch/rect.height);var coords={x:adjustedX,y:adjustedY};if(event.type==="touchstart"){Browser.lastTouches[touch.identifier]=coords;Browser.touches[touch.identifier]=coords}else if(event.type==="touchend"||event.type==="touchmove"){var last=Browser.touches[touch.identifier];if(!last)last=coords;Browser.lastTouches[touch.identifier]=last;Browser.touches[touch.identifier]=coords}return}var x=event.pageX-(scrollX+rect.left);var y=event.pageY-(scrollY+rect.top);x=x*(cw/rect.width);y=y*(ch/rect.height);Browser.mouseMovementX=x-Browser.mouseX;Browser.mouseMovementY=y-Browser.mouseY;Browser.mouseX=x;Browser.mouseY=y}},resizeListeners:[],updateResizeListeners:function(){var canvas=Module["canvas"];Browser.resizeListeners.forEach(listener=>listener(canvas.width,canvas.height))},setCanvasSize:function(width,height,noUpdates){var canvas=Module["canvas"];Browser.updateCanvasDimensions(canvas,width,height);if(!noUpdates)Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen>>2];flags=flags|8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module["canvas"]);Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen>>2];flags=flags&~8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module["canvas"]);Browser.updateResizeListeners()},updateCanvasDimensions:function(canvas,wNative,hNative){if(wNative&&hNative){canvas.widthNative=wNative;canvas.heightNative=hNative}else{wNative=canvas.widthNative;hNative=canvas.heightNative}var w=wNative;var h=hNative;if(Module["forcedAspectRatio"]&&Module["forcedAspectRatio"]>0){if(w/h>2];if(param==12321){var alphaSize=HEAP32[attribList+4>>2];EGL.contextAttributes.alpha=alphaSize>0}else if(param==12325){var depthSize=HEAP32[attribList+4>>2];EGL.contextAttributes.depth=depthSize>0}else if(param==12326){var stencilSize=HEAP32[attribList+4>>2];EGL.contextAttributes.stencil=stencilSize>0}else if(param==12337){var samples=HEAP32[attribList+4>>2];EGL.contextAttributes.antialias=samples>0}else if(param==12338){var samples=HEAP32[attribList+4>>2];EGL.contextAttributes.antialias=samples==1}else if(param==12544){var requestedPriority=HEAP32[attribList+4>>2];EGL.contextAttributes.lowLatency=requestedPriority!=12547}else if(param==12344){break}attribList+=8}}if((!config||!config_size)&&!numConfigs){EGL.setErrorCode(12300);return 0}if(numConfigs){HEAP32[numConfigs>>2]=1}if(config&&config_size>0){HEAP32[config>>2]=62002}EGL.setErrorCode(12288);return 1}};function _eglChooseConfig(display,attrib_list,configs,config_size,numConfigs){return EGL.chooseConfig(display,attrib_list,configs,config_size,numConfigs)}function webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(ctx){return!!(ctx.dibvbi=ctx.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"))}function webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(ctx){return!!(ctx.mdibvbi=ctx.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance"))}function webgl_enable_WEBGL_multi_draw(ctx){return!!(ctx.multiDrawWebgl=ctx.getExtension("WEBGL_multi_draw"))}var GL={counter:1,buffers:[],programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:function(table){var ret=GL.counter++;for(var i=table.length;i>2]:-1;source+=UTF8ToString(HEAP32[string+i*4>>2],len<0?undefined:len)}return source},createContext:function(canvas,webGLContextAttributes){if(!canvas.getContextSafariWebGL2Fixed){canvas.getContextSafariWebGL2Fixed=canvas.getContext;function fixedGetContext(ver,attrs){var gl=canvas.getContextSafariWebGL2Fixed(ver,attrs);return ver=="webgl"==gl instanceof WebGLRenderingContext?gl:null}canvas.getContext=fixedGetContext}var ctx=canvas.getContext("webgl2",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:function(ctx,webGLContextAttributes){var handle=GL.getNewId(GL.contexts);var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault=="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context)}return handle},makeContextCurrent:function(contextHandle){GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext&&GL.currentContext.GLctx;return!(contextHandle&&!GLctx)},getContext:function(contextHandle){return GL.contexts[contextHandle]},deleteContext:function(contextHandle){if(GL.currentContext===GL.contexts[contextHandle])GL.currentContext=null;if(typeof JSEvents=="object")JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas);if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas)GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined;GL.contexts[contextHandle]=null},initExtensions:function(context){if(!context)context=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);if(context.version>=2){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query_webgl2")}if(context.version<2||!GLctx.disjointTimerQueryExt){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query")}webgl_enable_WEBGL_multi_draw(GLctx);var exts=GLctx.getSupportedExtensions()||[];exts.forEach(function(ext){if(!ext.includes("lose_context")&&!ext.includes("debug")){GLctx.getExtension(ext)}})}};function _eglCreateContext(display,config,hmm,contextAttribs){if(display!=62e3){EGL.setErrorCode(12296);return 0}var glesContextVersion=1;for(;;){var param=HEAP32[contextAttribs>>2];if(param==12440){glesContextVersion=HEAP32[contextAttribs+4>>2]}else if(param==12344){break}else{EGL.setErrorCode(12292);return 0}contextAttribs+=8}if(glesContextVersion<2||glesContextVersion>3){EGL.setErrorCode(12293);return 0}EGL.contextAttributes.majorVersion=glesContextVersion-1;EGL.contextAttributes.minorVersion=0;EGL.context=GL.createContext(Module["canvas"],EGL.contextAttributes);if(EGL.context!=0){EGL.setErrorCode(12288);GL.makeContextCurrent(EGL.context);Module.useWebGL=true;Browser.moduleContextCreatedCallbacks.forEach(function(callback){callback()});GL.makeContextCurrent(null);return 62004}else{EGL.setErrorCode(12297);return 0}}function _eglCreateWindowSurface(display,config,win,attrib_list){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(config!=62002){EGL.setErrorCode(12293);return 0}EGL.setErrorCode(12288);return 62006}function _eglDestroyContext(display,context){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(context!=62004){EGL.setErrorCode(12294);return 0}GL.deleteContext(EGL.context);EGL.setErrorCode(12288);if(EGL.currentContext==context){EGL.currentContext=0}return 1}function _eglDestroySurface(display,surface){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(surface!=62006){EGL.setErrorCode(12301);return 1}if(EGL.currentReadSurface==surface){EGL.currentReadSurface=0}if(EGL.currentDrawSurface==surface){EGL.currentDrawSurface=0}EGL.setErrorCode(12288);return 1}function _eglGetDisplay(nativeDisplayType){EGL.setErrorCode(12288);return 62e3}function _eglInitialize(display,majorVersion,minorVersion){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(majorVersion){HEAP32[majorVersion>>2]=1}if(minorVersion){HEAP32[minorVersion>>2]=4}EGL.defaultDisplayInitialized=true;EGL.setErrorCode(12288);return 1}function _eglMakeCurrent(display,draw,read,context){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(context!=0&&context!=62004){EGL.setErrorCode(12294);return 0}if(read!=0&&read!=62006||draw!=0&&draw!=62006){EGL.setErrorCode(12301);return 0}GL.makeContextCurrent(context?EGL.context:null);EGL.currentContext=context;EGL.currentDrawSurface=draw;EGL.currentReadSurface=read;EGL.setErrorCode(12288);return 1}function _eglSwapBuffers(dpy,surface){if(!EGL.defaultDisplayInitialized){EGL.setErrorCode(12289)}else if(!Module.ctx){EGL.setErrorCode(12290)}else if(Module.ctx.isContextLost()){EGL.setErrorCode(12302)}else{EGL.setErrorCode(12288);return 1}return 0}function _eglSwapInterval(display,interval){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(interval==0)_emscripten_set_main_loop_timing(0,0);else _emscripten_set_main_loop_timing(1,interval);EGL.setErrorCode(12288);return 1}function _eglTerminate(display){if(display!=62e3){EGL.setErrorCode(12296);return 0}EGL.currentContext=0;EGL.currentReadSurface=0;EGL.currentDrawSurface=0;EGL.defaultDisplayInitialized=false;EGL.setErrorCode(12288);return 1}var readEmAsmArgsArray=[];function readEmAsmArgs(sigPtr,buf){readEmAsmArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){buf+=ch!=105&buf;readEmAsmArgsArray.push(ch==105?HEAP32[buf]:HEAPF64[buf++>>1]);++buf}return readEmAsmArgsArray}function runEmAsmFunction(code,sigPtr,argbuf){var args=readEmAsmArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)}function _emscripten_asm_const_int(code,sigPtr,argbuf){return runEmAsmFunction(code,sigPtr,argbuf)}function _emscripten_cancel_main_loop(){Browser.mainLoop.pause();Browser.mainLoop.func=null}function _emscripten_date_now(){return Date.now()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function getHeapMax(){return 2147483648}function emscripten_realloc_buffer(size){var b=wasmMemory.buffer;try{wasmMemory.grow(size-b.byteLength+65535>>>16);updateMemoryViews();return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var JSEvents={inEventHandler:0,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i)}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[]},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){__ATEXIT__.push(JSEvents.removeAllEventListeners);JSEvents.removeEventListenersRegistered=true}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!="undefined"?document:0,typeof window!="undefined"?window:0];function findEventTarget(target){target=maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!="undefined"?document.querySelector(target):undefined);return domElement}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}var wasmTableMirror=[];function getWasmTableEntry(funcPtr){var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func}function registerFocusEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.focusEvent)JSEvents.focusEvent=_malloc(256);var focusEventHandlerFunc=function(e=event){var nodeName=JSEvents.getNodeNameForTarget(e.target);var id=e.target.id?e.target.id:"";var focusEvent=JSEvents.focusEvent;stringToUTF8(nodeName,focusEvent+0,128);stringToUTF8(id,focusEvent+128,128);if(getWasmTableEntry(callbackfunc)(eventTypeId,focusEvent,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:focusEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_blur_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerFocusEventCallback(target,userData,useCapture,callbackfunc,12,"blur",targetThread)}function findCanvasEventTarget(target){return findEventTarget(target)}function _emscripten_set_canvas_element_size(target,width,height){var canvas=findCanvasEventTarget(target);if(!canvas)return-4;canvas.width=width;canvas.height=height;return 0}function _emscripten_set_focus_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerFocusEventCallback(target,userData,useCapture,callbackfunc,13,"focus",targetThread)}function registerKeyEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.keyEvent)JSEvents.keyEvent=_malloc(176);var keyEventHandlerFunc=function(e){var keyEventData=JSEvents.keyEvent;HEAPF64[keyEventData>>3]=e.timeStamp;var idx=keyEventData>>2;HEAP32[idx+2]=e.location;HEAP32[idx+3]=e.ctrlKey;HEAP32[idx+4]=e.shiftKey;HEAP32[idx+5]=e.altKey;HEAP32[idx+6]=e.metaKey;HEAP32[idx+7]=e.repeat;HEAP32[idx+8]=e.charCode;HEAP32[idx+9]=e.keyCode;HEAP32[idx+10]=e.which;stringToUTF8(e.key||"",keyEventData+44,32);stringToUTF8(e.code||"",keyEventData+76,32);stringToUTF8(e.char||"",keyEventData+108,32);stringToUTF8(e.locale||"",keyEventData+140,32);if(getWasmTableEntry(callbackfunc)(eventTypeId,keyEventData,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:keyEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_keydown_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerKeyEventCallback(target,userData,useCapture,callbackfunc,2,"keydown",targetThread)}function _emscripten_set_keyup_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerKeyEventCallback(target,userData,useCapture,callbackfunc,3,"keyup",targetThread)}function _emscripten_set_main_loop(func,fps,simulateInfiniteLoop){var browserIterationFunc=getWasmTableEntry(func);setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop)}function getBoundingClientRect(e){return specialHTMLTargets.indexOf(e)<0?e.getBoundingClientRect():{"left":0,"top":0}}function fillMouseEventData(eventStruct,e,target){HEAPF64[eventStruct>>3]=e.timeStamp;var idx=eventStruct>>2;HEAP32[idx+2]=e.screenX;HEAP32[idx+3]=e.screenY;HEAP32[idx+4]=e.clientX;HEAP32[idx+5]=e.clientY;HEAP32[idx+6]=e.ctrlKey;HEAP32[idx+7]=e.shiftKey;HEAP32[idx+8]=e.altKey;HEAP32[idx+9]=e.metaKey;HEAP16[idx*2+20]=e.button;HEAP16[idx*2+21]=e.buttons;HEAP32[idx+11]=e["movementX"];HEAP32[idx+12]=e["movementY"];var rect=getBoundingClientRect(target);HEAP32[idx+13]=e.clientX-rect.left;HEAP32[idx+14]=e.clientY-rect.top}function registerMouseEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.mouseEvent)JSEvents.mouseEvent=_malloc(72);target=findEventTarget(target);var mouseEventHandlerFunc=function(e=event){fillMouseEventData(JSEvents.mouseEvent,e,target);if(getWasmTableEntry(callbackfunc)(eventTypeId,JSEvents.mouseEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString!="mousemove"&&eventTypeString!="mouseenter"&&eventTypeString!="mouseleave",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:mouseEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_mousedown_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerMouseEventCallback(target,userData,useCapture,callbackfunc,5,"mousedown",targetThread)}function _emscripten_set_mousemove_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerMouseEventCallback(target,userData,useCapture,callbackfunc,8,"mousemove",targetThread)}function _emscripten_set_mouseup_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerMouseEventCallback(target,userData,useCapture,callbackfunc,6,"mouseup",targetThread)}function registerTouchEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.touchEvent)JSEvents.touchEvent=_malloc(1696);target=findEventTarget(target);var touchEventHandlerFunc=function(e){var t,touches={},et=e.touches;for(var i=0;i>3]=e.timeStamp;var idx=touchEvent>>2;HEAP32[idx+3]=e.ctrlKey;HEAP32[idx+4]=e.shiftKey;HEAP32[idx+5]=e.altKey;HEAP32[idx+6]=e.metaKey;idx+=7;var targetRect=getBoundingClientRect(target);var numTouches=0;for(var i in touches){t=touches[i];HEAP32[idx+0]=t.identifier;HEAP32[idx+1]=t.screenX;HEAP32[idx+2]=t.screenY;HEAP32[idx+3]=t.clientX;HEAP32[idx+4]=t.clientY;HEAP32[idx+5]=t.pageX;HEAP32[idx+6]=t.pageY;HEAP32[idx+7]=t.isChanged;HEAP32[idx+8]=t.onTarget;HEAP32[idx+9]=t.clientX-targetRect.left;HEAP32[idx+10]=t.clientY-targetRect.top;idx+=13;if(++numTouches>31){break}}HEAP32[touchEvent+8>>2]=numTouches;if(getWasmTableEntry(callbackfunc)(eventTypeId,touchEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString=="touchstart"||eventTypeString=="touchend",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:touchEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_touchend_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerTouchEventCallback(target,userData,useCapture,callbackfunc,23,"touchend",targetThread)}function _emscripten_set_touchmove_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerTouchEventCallback(target,userData,useCapture,callbackfunc,24,"touchmove",targetThread)}function _emscripten_set_touchstart_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){return registerTouchEventCallback(target,userData,useCapture,callbackfunc,22,"touchstart",targetThread)}function registerWheelEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.wheelEvent)JSEvents.wheelEvent=_malloc(104);var wheelHandlerFunc=function(e=event){var wheelEvent=JSEvents.wheelEvent;fillMouseEventData(wheelEvent,e,target);HEAPF64[wheelEvent+72>>3]=e["deltaX"];HEAPF64[wheelEvent+80>>3]=e["deltaY"];HEAPF64[wheelEvent+88>>3]=e["deltaZ"];HEAP32[wheelEvent+96>>2]=e["deltaMode"];if(getWasmTableEntry(callbackfunc)(eventTypeId,wheelEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:wheelHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_wheel_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){target=findEventTarget(target);if(!target)return-4;if(typeof target.onwheel!="undefined"){return registerWheelEventCallback(target,userData,useCapture,callbackfunc,9,"wheel",targetThread)}else{return-1}}function _emscripten_set_window_title(title){setWindowTitle(UTF8ToString(title))}var ENV={};function getExecutableName(){return thisProgram||"./this.program"}function getEnvStrings(){if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":lang,"_":getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings}function stringToAscii(str,buffer){for(var i=0;i>0]=str.charCodeAt(i)}HEAP8[buffer>>0]=0}function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings().forEach(function(string,i){var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1});return 0}function _environ_sizes_get(penviron_count,penviron_buf_size){var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(function(string){bufSize+=string.length+1});HEAPU32[penviron_buf_size>>2]=bufSize;return 0}function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function doReadv(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function convertI32PairToI53Checked(lo,hi){return hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{var offset=convertI32PairToI53Checked(offset_low,offset_high);if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function doWritev(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!=="undefined"){offset+=curr}}return ret}function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _glAttachShader(program,shader){GLctx.attachShader(GL.programs[program],GL.shaders[shader])}function _glBindBuffer(target,buffer){if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,GL.buffers[buffer])}function _glBindTexture(target,texture){GLctx.bindTexture(target,GL.textures[texture])}function _glBindVertexArray(vao){GLctx.bindVertexArray(GL.vaos[vao])}var _glBindVertexArrayOES=_glBindVertexArray;function _glBlendFunc(x0,x1){GLctx.blendFunc(x0,x1)}function _glBufferData(target,size,data,usage){if(true){if(data&&size){GLctx.bufferData(target,HEAPU8,usage,data,size)}else{GLctx.bufferData(target,size,usage)}}else{GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)}}function _glClear(x0){GLctx.clear(x0)}function _glClearColor(x0,x1,x2,x3){GLctx.clearColor(x0,x1,x2,x3)}function _glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}function _glCreateProgram(){var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;program.maxUniformLength=program.maxAttributeLength=program.maxUniformBlockNameLength=0;program.uniformIdCounter=1;GL.programs[id]=program;return id}function _glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id}function _glDeleteProgram(id){if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null}function _glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null}function _glDeleteTextures(n,textures){for(var i=0;i>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}}function _glDrawArrays(mode,first,count){GLctx.drawArrays(mode,first,count)}function _glEnable(x0){GLctx.enable(x0)}function _glEnableVertexAttribArray(index){GLctx.enableVertexAttribArray(index)}function __glGenObject(n,buffers,createFunction,objectTable){for(var i=0;i>2]=id}}function _glGenBuffers(n,buffers){__glGenObject(n,buffers,"createBuffer",GL.buffers)}function _glGenTextures(n,textures){__glGenObject(n,textures,"createTexture",GL.textures)}function _glGenVertexArrays(n,arrays){__glGenObject(n,arrays,"createVertexArray",GL.vaos)}var _glGenVertexArraysOES=_glGenVertexArrays;function _glGetShaderInfoLog(shader,maxLength,length,infoLog){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _glLinkProgram(program){program=GL.programs[program];GLctx.linkProgram(program);program.uniformLocsById=0;program.uniformSizeAndIdsByName={}}function computeUnpackAlignedImageSize(width,height,sizePerPixel,alignment){function roundedToNextMultipleOf(x,y){return x+y-1&-y}var plainRowSize=width*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,alignment);return height*alignedRowSize}function colorChannelsInGlTextureFormat(format){var colorChannels={5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4};return colorChannels[format-6402]||1}function heapObjectForWebGLType(type){type-=5120;if(type==0)return HEAP8;if(type==1)return HEAPU8;if(type==2)return HEAP16;if(type==4)return HEAP32;if(type==6)return HEAPF32;if(type==5||type==28922||type==28520||type==30779||type==30782)return HEAPU32;return HEAPU16}function heapAccessShiftForWebGLHeap(heap){return 31-Math.clz32(heap.BYTES_PER_ELEMENT)}function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat){var heap=heapObjectForWebGLType(type);var shift=heapAccessShiftForWebGLHeap(heap);var byteSize=1<>shift,pixels+bytes>>shift)}function _glReadPixels(x,y,width,height,format,type,pixels){if(true){if(GLctx.currentPixelPackBufferBinding){GLctx.readPixels(x,y,width,height,format,type,pixels)}else{var heap=heapObjectForWebGLType(type);GLctx.readPixels(x,y,width,height,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}return}var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)}function _glShaderSource(shader,count,string,length){var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)}function _glTexImage2D(target,level,internalFormat,width,height,border,format,type,pixels){if(true){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,null)}return}GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null)}function _glTexParameteri(x0,x1,x2){GLctx.texParameteri(x0,x1,x2)}function _glUseProgram(program){program=GL.programs[program];GLctx.useProgram(program);GLctx.currentProgram=program}function _glVertexAttribPointer(index,size,type,normalized,stride,ptr){GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)}function _glViewport(x0,x1,x2,x3){GLctx.viewport(x0,x1,x2,x3)}function isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}function arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum}var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value=="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={"%a":function(date){return WEEKDAYS[date.tm_wday].substring(0,3)},"%A":function(date){return WEEKDAYS[date.tm_wday]},"%b":function(date){return MONTHS[date.tm_mon].substring(0,3)},"%B":function(date){return MONTHS[date.tm_mon]},"%C":function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":function(date){return leadingNulls(date.tm_mday,2)},"%e":function(date){return leadingSomething(date.tm_mday,2," ")},"%g":function(date){return getWeekBasedYear(date).toString().substring(2)},"%G":function(date){return getWeekBasedYear(date)},"%H":function(date){return leadingNulls(date.tm_hour,2)},"%I":function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":function(date){return leadingNulls(date.tm_mday+arraySum(isLeapYear(date.tm_year+1900)?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,date.tm_mon-1),3)},"%m":function(date){return leadingNulls(date.tm_mon+1,2)},"%M":function(date){return leadingNulls(date.tm_min,2)},"%n":function(){return"\n"},"%p":function(date){if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}return"PM"},"%S":function(date){return leadingNulls(date.tm_sec,2)},"%t":function(){return"\t"},"%u":function(date){return date.tm_wday||7},"%U":function(date){var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},"%V":function(date){var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},"%w":function(date){return date.tm_wday},"%W":function(date){var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},"%y":function(date){return(date.tm_year+1900).toString().substring(2)},"%Y":function(date){return date.tm_year+1900},"%z":function(date){var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":function(date){return date.tm_zone},"%%":function(){return"%"}};pattern=pattern.replace(/%%/g,"\0\0");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\0\0/g,"%");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _strftime_l(s,maxsize,format,tm,loc){return _strftime(s,maxsize,format,tm)}var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_unlink"]=FS.unlink;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;Module["requestFullscreen"]=function Module_requestFullscreen(lockPointer,resizeCanvas){Browser.requestFullscreen(lockPointer,resizeCanvas)};Module["requestAnimationFrame"]=function Module_requestAnimationFrame(func){Browser.requestAnimationFrame(func)};Module["setCanvasSize"]=function Module_setCanvasSize(width,height,noUpdates){Browser.setCanvasSize(width,height,noUpdates)};Module["pauseMainLoop"]=function Module_pauseMainLoop(){Browser.mainLoop.pause()};Module["resumeMainLoop"]=function Module_resumeMainLoop(){Browser.mainLoop.resume()};Module["getUserMedia"]=function Module_getUserMedia(){Browser.getUserMedia()};Module["createContext"]=function Module_createContext(canvas,useWebGL,setInModule,webGLContextAttributes){return Browser.createContext(canvas,useWebGL,setInModule,webGLContextAttributes)};var preloadedImages={};var preloadedAudios={};var GLctx;var decodeBase64=typeof atob=="function"?atob:function(input){var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";var output="";var chr1,chr2,chr3;var enc1,enc2,enc3,enc4;var i=0;input=input.replace(/[^A-Za-z0-9\+\/\=]/g,"");do{enc1=keyStr.indexOf(input.charAt(i++));enc2=keyStr.indexOf(input.charAt(i++));enc3=keyStr.indexOf(input.charAt(i++));enc4=keyStr.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;output=output+String.fromCharCode(chr1);if(enc3!==64){output=output+String.fromCharCode(chr2)}if(enc4!==64){output=output+String.fromCharCode(chr3)}}while(i0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;run(); diff --git a/Crawler/pge.wasm b/Crawler/pge.wasm index bf604dae..5bac178b 100644 Binary files a/Crawler/pge.wasm and b/Crawler/pge.wasm differ diff --git a/x64/Release/Crawler.exe b/x64/Release/Crawler.exe index bc4f2bee..1602acba 100644 Binary files a/x64/Release/Crawler.exe and b/x64/Release/Crawler.exe differ