From 946fb1f77362a710be1c40b52cfaa3383c216291 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 14 Jun 2023 21:49:41 +1000 Subject: [PATCH] WIP on redesigning how asset checking/downloading works in the launcher --- src/Game.c | 3 +- src/Game.h | 6 +- src/GameVersion.c | 15 ++-- src/Menus.c | 7 +- src/Protocol.c | 6 +- src/Resources.c | 214 +++++++++++++++++++++++++++++++--------------- src/Server.c | 2 +- 7 files changed, 166 insertions(+), 87 deletions(-) diff --git a/src/Game.c b/src/Game.c index 67aebd3ae..42697075a 100644 --- a/src/Game.c +++ b/src/Game.c @@ -50,7 +50,7 @@ int Game_FpsLimit, Game_Vertices; cc_bool Game_SimpleArmsAnim; cc_bool Game_ClassicMode, Game_ClassicHacks; -cc_bool Game_AllowCustomBlocks, Game_UseCPE; +cc_bool Game_AllowCustomBlocks; cc_bool Game_AllowServerTextures; cc_bool Game_ViewBobbing, Game_HideGui, Game_DefaultZipMissing; @@ -304,7 +304,6 @@ static void LoadOptions(void) { Game_ClassicMode = Options_GetBool(OPT_CLASSIC_MODE, false); Game_ClassicHacks = Options_GetBool(OPT_CLASSIC_HACKS, false); Game_AllowCustomBlocks = Options_GetBool(OPT_CUSTOM_BLOCKS, true); - Game_UseCPE = !Game_ClassicMode && Options_GetBool(OPT_CPE, true); Game_SimpleArmsAnim = Options_GetBool(OPT_SIMPLE_ARMS_ANIM, false); Game_ViewBobbing = Options_GetBool(OPT_VIEW_BOBBING, true); diff --git a/src/Game.h b/src/Game.h index 2eb1c38e2..9c905e649 100644 --- a/src/Game.h +++ b/src/Game.h @@ -38,7 +38,6 @@ extern cc_bool Game_ClassicMode; extern cc_bool Game_ClassicHacks; #define Game_PureClassic (Game_ClassicMode && !Game_ClassicHacks) extern cc_bool Game_AllowCustomBlocks; -extern cc_bool Game_UseCPE; extern cc_bool Game_AllowServerTextures; extern cc_bool Game_ViewBobbing; @@ -51,8 +50,9 @@ extern cc_bool Game_DefaultZipMissing; enum GAME_VERSION_ { VERSION_0017 = 27, VERSION_0019 = 28, VERSION_0023 = 29, VERSION_0030 = 30, VERSION_CPE = 31 }; -struct GameVersion { - const char* Name; +struct GameVersion { + const char* Name; + cc_bool HasCPE; cc_uint8 Version, Protocol, MaxCoreBlock; cc_uint8 BlocksPerRow, InventorySize; const cc_uint8* Inventory; diff --git a/src/GameVersion.c b/src/GameVersion.c index 77ca52a5c..8c88209e1 100644 --- a/src/GameVersion.c +++ b/src/GameVersion.c @@ -40,36 +40,37 @@ static const cc_uint8 v4_hotbar[INVENTORY_BLOCKS_PER_HOTBAR] = { }; static const struct GameVersion version_cpe = { - "0.30", VERSION_CPE, + "0.30", true, VERSION_CPE, PROTOCOL_0030, BLOCK_MAX_CPE, 10, sizeof(v7_inventory), NULL, v7_hotbar }; static const struct GameVersion version_0030 = { - "0.30", VERSION_0030, + "0.30", false, VERSION_0030, PROTOCOL_0030, BLOCK_OBSIDIAN, 9, sizeof(v7_inventory), v7_inventory, v7_hotbar }; static const struct GameVersion version_0023 = { - "0.0.23a", VERSION_0023, + "0.0.23a", false, VERSION_0023, PROTOCOL_0020, BLOCK_GOLD, 8, sizeof(v6_inventory), v6_inventory, v6_hotbar }; static const struct GameVersion version_0019 = { - "0.0.19a", VERSION_0019, + "0.0.19a", false, VERSION_0019, PROTOCOL_0019, BLOCK_GLASS, 6, sizeof(v5_inventory), v5_inventory, v5_hotbar }; static const struct GameVersion version_0017 = { - "0.0.17a", VERSION_0017, + "0.0.17a", false, VERSION_0017, PROTOCOL_0017, BLOCK_LEAVES, 6, sizeof(v4_inventory), v4_inventory, v4_hotbar }; void GameVersion_Load(void) { - int version = Options_GetInt(OPT_GAME_VERSION, VERSION_0017, VERSION_0030, VERSION_0030); + cc_bool hasCPE = !Game_ClassicMode && Options_GetBool(OPT_CPE, true); + int version = Options_GetInt(OPT_GAME_VERSION, VERSION_0017, VERSION_0030, VERSION_0030); const struct GameVersion* ver = &version_cpe; - if (Game_UseCPE) { + if (hasCPE) { /* defaults to CPE already */ } else if (version == VERSION_0030) { ver = &version_0030; diff --git a/src/Menus.c b/src/Menus.c index 01ca938e7..c07bf370d 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -3233,7 +3233,7 @@ void NostalgiaAppearanceScreen_Show(void) { *----------------------------------------------NostalgiaFunctionalityScreen-----------------------------------------------* *#########################################################################################################################*/ static void NostalgiaScreen_UpdateVersionDisabled(void) { - MenuOptionsScreen_Instance.buttons[3].disabled = Game_UseCPE; + MenuOptionsScreen_Instance.buttons[3].disabled = Game_Version.HasCPE; } static void NostalgiaScreen_GetTexs(cc_string* v) { Menu_GetBool(v, Game_AllowServerTextures); } @@ -3242,9 +3242,10 @@ static void NostalgiaScreen_SetTexs(const cc_string* v) { Game_AllowServerTextur static void NostalgiaScreen_GetCustom(cc_string* v) { Menu_GetBool(v, Game_AllowCustomBlocks); } static void NostalgiaScreen_SetCustom(const cc_string* v) { Game_AllowCustomBlocks = Menu_SetBool(v, OPT_CUSTOM_BLOCKS); } -static void NostalgiaScreen_GetCPE(cc_string* v) { Menu_GetBool(v, Game_UseCPE); } +static void NostalgiaScreen_GetCPE(cc_string* v) { Menu_GetBool(v, Game_Version.HasCPE); } static void NostalgiaScreen_SetCPE(const cc_string* v) { - Game_UseCPE = Menu_SetBool(v, OPT_CPE); + Menu_SetBool(v, OPT_CPE); + GameVersion_Load(); NostalgiaScreen_UpdateVersionDisabled(); } diff --git a/src/Protocol.c b/src/Protocol.c index f9f8bae54..4c1266247 100644 --- a/src/Protocol.c +++ b/src/Protocol.c @@ -386,7 +386,7 @@ void Classic_SendLogin(void) { /* and will get stuck waiting for data if client connects using version 5 and only sends 130 bytes */ /* To workaround this, include a 'ping packet' after 'version 5 handshake packet' - version 5 server software */ /* will do nothing with the ping packet, and the aforementioned server software will be happy with 131 bytes */ - data[130] = Game_UseCPE ? 0x42 : (Game_Version.Protocol <= PROTOCOL_0019 ? OPCODE_PING : 0x00); + data[130] = Game_Version.HasCPE ? 0x42 : (Game_Version.Protocol <= PROTOCOL_0019 ? OPCODE_PING : 0x00); } Server.SendData(data, 131); } @@ -1588,7 +1588,7 @@ static void CPE_Reset(void) { cpe_needD3Fix = false; cpe_extEntityPos = false; cpe_twoWayPing = false; cpe_pluginMessages = false; cpe_extTextures = false; cpe_fastMap = false; cpe_extBlocks = false; Game_UseCPEBlocks = false; cpe_blockPerms = false; - if (!Game_UseCPE) return; + if (!Game_Version.HasCPE) return; Net_Set(OPCODE_EXT_INFO, CPE_ExtInfo, 67); Net_Set(OPCODE_EXT_ENTRY, CPE_ExtEntry, 69); @@ -1760,7 +1760,7 @@ static void BlockDefs_DefineBlockExt(cc_uint8* data) { } static void BlockDefs_Reset(void) { - if (!Game_UseCPE || !Game_AllowCustomBlocks) return; + if (!Game_Version.HasCPE || !Game_AllowCustomBlocks) return; Net_Set(OPCODE_DEFINE_BLOCK, BlockDefs_DefineBlock, 80); Net_Set(OPCODE_UNDEFINE_BLOCK, BlockDefs_UndefineBlock, 2); Net_Set(OPCODE_DEFINE_BLOCK_EXT, BlockDefs_DefineBlockExt, 85); diff --git a/src/Resources.c b/src/Resources.c index 14532e345..98072b52a 100644 --- a/src/Resources.c +++ b/src/Resources.c @@ -13,6 +13,18 @@ #include "Logger.h" #include "LWeb.h" #include "Http.h" + +/* Represents a set of assets/resources */ +/* E.g. music set, sounds set, textures set */ +struct AssetSet { + /* Checks whether all assets in this asset set exist on disc */ + void (*CheckExistence)(void); + /* Begins asynchronously downloading the missing assets in this asset set */ + void (*DownloadAssets)(void); + /* Checks if any assets have been downloaded, and processes them if so */ + void (*CheckStatus)(void); +}; + int Resources_Count, Resources_Size; union ResourceValue { @@ -31,17 +43,19 @@ struct ResourceZipEntry { #define RESOURCE_TYPE_PNG 2 #define RESOURCE_TYPE_CONST 3 +static CC_NOINLINE cc_bool Fetcher_Get(int reqID, struct HttpRequest* item); + /*########################################################################################################################* -*--------------------------------------------------------Music resources--------------------------------------------------* +*---------------------------------------------------------Music assets----------------------------------------------------* *#########################################################################################################################*/ -static struct MusicResource { +static struct MusicAsset { const char* name; const char* hash; short size; cc_bool downloaded; int reqID; -} musicResources[] = { +} musicAssets[] = { { "calm1.ogg", "50a59a4f56e4046701b758ddbb1c1587efa4cadf", 2472 }, { "calm2.ogg", "74da65c99aa578486efa7b69983d3533e14c0d6e", 1931 }, { "calm3.ogg", "14ae57a6bce3d4254daa8be2b098c2d99743cc3f", 2181 }, @@ -51,25 +65,51 @@ static struct MusicResource { { "hal4.ogg", "5e7d63e75c6e042f452bc5e151276911ef92fed8", 2499 } }; -static void MusicResources_CheckExistence(void) { +static void MusicAssets_CheckExistence(void) { cc_string path; char pathBuffer[FILENAME_SIZE]; int i; String_InitArray(path, pathBuffer); - for (i = 0; i < Array_Elems(musicResources); i++) { + for (i = 0; i < Array_Elems(musicAssets); i++) + { path.length = 0; - String_Format1(&path, "audio/%c", musicResources[i].name); + String_Format1(&path, "audio/%c", musicAssets[i].name); - musicResources[i].downloaded = File_Exists(&path); - if (musicResources[i].downloaded) continue; + musicAssets[i].downloaded = File_Exists(&path); + if (musicAssets[i].downloaded) continue; - Resources_Size += musicResources[i].size; + Resources_Size += musicAssets[i].size; Resources_Count++; } } -static void MusicResource_Save(const char* name, struct HttpRequest* req) { +/*########################################################################################################################* +*-----------------------------------------------------Music asset fetching -----------------------------------------------* +*#########################################################################################################################*/ +CC_NOINLINE static int MusicAsset_Download(const char* hash) { + cc_string url; char urlBuffer[URL_MAX_SIZE]; + + String_InitArray(url, urlBuffer); + String_Format3(&url, "https://resources.download.minecraft.net/%r%r/%c", + &hash[0], &hash[1], hash); + return Http_AsyncGetData(&url, 0); +} + +static void MusicAssets_DownloadResources(void) { + int i; + for (i = 0; i < Array_Elems(musicAssets); i++) + { + if (musicAssets[i].downloaded) continue; + musicAssets[i].reqID = MusicAsset_Download(musicAssets[i].hash); + } +} + + +/*########################################################################################################################* +*----------------------------------------------------Music asset processing ----------------------------------------------* +*#########################################################################################################################*/ +static void MusicAsset_Save(const char* name, struct HttpRequest* req) { cc_string path; char pathBuffer[STRING_SIZE]; cc_result res; @@ -80,24 +120,39 @@ static void MusicResource_Save(const char* name, struct HttpRequest* req) { if (res) Logger_SysWarn(res, "saving music file"); } -CC_NOINLINE static int MusicResource_Download(const char* hash) { - cc_string url; char urlBuffer[URL_MAX_SIZE]; +static void MusicAsset_Check(struct MusicAsset* music) { + struct HttpRequest item; + if (!Fetcher_Get(music->reqID, &item)) return; - String_InitArray(url, urlBuffer); - String_Format3(&url, "https://resources.download.minecraft.net/%r%r/%c", - &hash[0], &hash[1], hash); - return Http_AsyncGetData(&url, 0); + music->downloaded = true; + MusicAsset_Save(music->name, &item); + HttpRequest_Free(&item); } +static void MusicAssets_CheckStatus(void) { + int i; + for (i = 0; i < Array_Elems(musicAssets); i++) + { + if (musicAssets[i].downloaded) continue; + MusicAsset_Check(&musicAssets[i]); + } +} + +static const struct AssetSet musicAssetSet = { + MusicAssets_CheckExistence, + MusicAssets_DownloadResources, + MusicAssets_CheckStatus +}; + /*########################################################################################################################* -*--------------------------------------------------------Sound resources--------------------------------------------------* +*---------------------------------------------------------Sound assets----------------------------------------------------* *#########################################################################################################################*/ -static struct SoundResource { +static struct SoundAsset { const char* name; const char* hash; int reqID; -} soundResources[] = { +} soundAssets[] = { { "dig_cloth1", "5fd568d724ba7d53911b6cccf5636f859d2662e8" }, { "dig_cloth2", "56c1d0ac0de2265018b2c41cb571cc6631101484" }, { "dig_cloth3", "9c63f2a3681832dc32d206f6830360bfe94b5bfc" }, { "dig_cloth4", "55da1856e77cfd31a7e8c3d358e1f856c5583198" }, { "dig_grass1", "41cbf5dd08e951ad65883854e74d2e034929f572" }, { "dig_grass2", "86cb1bb0c45625b18e00a64098cd425a38f6d3f2" }, @@ -132,26 +187,44 @@ static struct SoundResource { }; static cc_bool allSoundsExist; -static void SoundResources_CheckExistence(void) { +static void SoundAssets_CheckExistence(void) { cc_string path; char pathBuffer[FILENAME_SIZE]; int i; String_InitArray(path, pathBuffer); - for (i = 0; i < Array_Elems(soundResources); i++) { + for (i = 0; i < Array_Elems(soundAssets); i++) + { path.length = 0; - String_Format1(&path, "audio/%c.wav", soundResources[i].name); + String_Format1(&path, "audio/%c.wav", soundAssets[i].name); if (File_Exists(&path)) continue; allSoundsExist = false; - Resources_Count += Array_Elems(soundResources); + Resources_Count += Array_Elems(soundAssets); Resources_Size += 417; return; } allSoundsExist = true; } +/*########################################################################################################################* +*-----------------------------------------------------Sound asset fetching -----------------------------------------------* +*#########################################################################################################################*/ +#define SoundAsset_Download(hash) MusicAsset_Download(hash) +static void SoundAssets_DownloadAssets(void) { + int i; + for (i = 0; i < Array_Elems(soundAssets); i++) + { + if (allSoundsExist) continue; + soundAssets[i].reqID = SoundAsset_Download(soundAssets[i].hash); + } +} + + +/*########################################################################################################################* +*----------------------------------------------------Sound asset processing ----------------------------------------------* +*#########################################################################################################################*/ #define WAV_FourCC(a, b, c, d) (((cc_uint32)a << 24) | ((cc_uint32)b << 16) | ((cc_uint32)c << 8) | (cc_uint32)d) #define WAV_HDR_SIZE 44 @@ -238,7 +311,28 @@ static void SoundPatcher_Save(const char* name, struct HttpRequest* req) { Vorbis_Free(&ctx); } -#define SoundResource_Download(hash) MusicResource_Download(hash) + +static void SoundAsset_Check(const struct SoundAsset* sound) { + struct HttpRequest item; + if (!Fetcher_Get(sound->reqID, &item)) return; + + SoundPatcher_Save(sound->name, &item); + HttpRequest_Free(&item); +} + +static void SoundAssets_CheckStatus(void) { + int i; + for (i = 0; i < Array_Elems(soundAssets); i++) + { + SoundAsset_Check(&soundAssets[i]); + } +} + +static const struct AssetSet soundAssetSet = { + SoundAssets_CheckExistence, + SoundAssets_DownloadAssets, + SoundAssets_CheckStatus +}; /*########################################################################################################################* @@ -764,15 +858,6 @@ static void DefaultZip_CheckExistence(void) { } } -void Resources_CheckExistence(void) { - Resources_Count = 0; - Resources_Size = 0; - - DefaultZip_CheckExistence(); - MusicResources_CheckExistence(); - SoundResources_CheckExistence(); -} - /*########################################################################################################################* *-----------------------------------------------------------Fetcher-------------------------------------------------------* @@ -781,17 +866,35 @@ cc_bool Fetcher_Working, Fetcher_Completed, Fetcher_Failed; int Fetcher_Downloaded; FetcherErrorCallback Fetcher_ErrorCallback; +/* TODO: array of asset sets */ +static const struct AssetSet* const asset_sets[] = { + &musicAssetSet, + &soundAssetSet +}; + +void Resources_CheckExistence(void) { + int i; + Resources_Count = 0; + Resources_Size = 0; + + DefaultZip_CheckExistence(); + for (i = 0; i < Array_Elems(asset_sets); i++) + { + asset_sets[i]->CheckExistence(); + } +} + const char* Fetcher_RequestName(int reqID) { int i; for (i = 0; i < Array_Elems(defaultZipSources); i++) { if (reqID == defaultZipSources[i].reqID) return defaultZipSources[i].name; } - for (i = 0; i < Array_Elems(musicResources); i++) { - if (reqID == musicResources[i].reqID) return musicResources[i].name; + for (i = 0; i < Array_Elems(musicAssets); i++) { + if (reqID == musicAssets[i].reqID) return musicAssets[i].name; } - for (i = 0; i < Array_Elems(soundResources); i++) { - if (reqID == soundResources[i].reqID) return soundResources[i].name; + for (i = 0; i < Array_Elems(soundAssets); i++) { + if (reqID == soundAssets[i].reqID) return soundAssets[i].name; } return NULL; } @@ -812,13 +915,9 @@ void Fetcher_Run(void) { defaultZipSources[i].reqID = Http_AsyncGetData(&url, 0); } - for (i = 0; i < Array_Elems(musicResources); i++) { - if (musicResources[i].downloaded) continue; - musicResources[i].reqID = MusicResource_Download(musicResources[i].hash); - } - for (i = 0; i < Array_Elems(soundResources); i++) { - if (allSoundsExist) continue; - soundResources[i].reqID = SoundResource_Download(soundResources[i].hash); + for (i = 0; i < Array_Elems(asset_sets); i++) + { + asset_sets[i]->DownloadAssets(); } } @@ -871,23 +970,6 @@ static void Fetcher_CheckFile(struct ZipfileSource* file) { if (file->last) DefaultZip_Create(); } -static void Fetcher_CheckMusic(struct MusicResource* music) { - struct HttpRequest item; - if (!Fetcher_Get(music->reqID, &item)) return; - - music->downloaded = true; - MusicResource_Save(music->name, &item); - HttpRequest_Free(&item); -} - -static void Fetcher_CheckSound(const struct SoundResource* sound) { - struct HttpRequest item; - if (!Fetcher_Get(sound->reqID, &item)) return; - - SoundPatcher_Save(sound->name, &item); - HttpRequest_Free(&item); -} - /* TODO: Implement this.. */ /* TODO: How expensive is it to constantly do 'Get' over and over */ void Fetcher_Update(void) { @@ -898,13 +980,9 @@ void Fetcher_Update(void) { Fetcher_CheckFile(&defaultZipSources[i]); } - for (i = 0; i < Array_Elems(musicResources); i++) { - if (musicResources[i].downloaded) continue; - Fetcher_CheckMusic(&musicResources[i]); - } - - for (i = 0; i < Array_Elems(soundResources); i++) { - Fetcher_CheckSound(&soundResources[i]); + for (i = 0; i < Array_Elems(asset_sets); i++) + { + asset_sets[i]->CheckStatus(); } if (Fetcher_Downloaded != Resources_Count) return; diff --git a/src/Server.c b/src/Server.c index 4a4b53978..67ca68b8e 100644 --- a/src/Server.c +++ b/src/Server.c @@ -118,7 +118,7 @@ static void SPConnection_BeginConnect(void) { static const cc_string logName = String_FromConst("Singleplayer"); RNGState rnd; Chat_SetLogName(&logName); - Game_UseCPEBlocks = Game_UseCPE; + Game_UseCPEBlocks = Game_Version.HasCPE; /* For when user drops a map file onto ClassiCube.exe */ if (SP_AutoloadMap.length) {