diff --git a/src/Platform.h b/src/Platform.h index 7300962d1..6355eaf3e 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -172,7 +172,7 @@ typedef void (*Directory_EnumCallback)(const cc_string* filename, void* obj); CC_API cc_result Directory_Enum(const cc_string* path, void* obj, Directory_EnumCallback callback); /* Returns non-zero if the given file exists. */ CC_API int File_Exists(const cc_string* path); -void Directory_GetCachePath(cc_string* path, const char* folder); +void Directory_GetCachePath(cc_string* path); /* Attempts to create a new (or overwrite) file for writing. */ /* NOTE: If the file already exists, its contents are discarded. */ diff --git a/src/Platform_Android.c b/src/Platform_Android.c index 442cd3b2d..98d330f60 100644 --- a/src/Platform_Android.c +++ b/src/Platform_Android.c @@ -93,14 +93,9 @@ void Platform_ShareScreenshot(const cc_string* filename) { Chat_Add1(" &c%s", &path); } -void Directory_GetCachePath(cc_string* path, const char* folder) { - cc_string dir; char dirBuffer[FILENAME_SIZE]; - String_InitArray(dir, dirBuffer); +void Directory_GetCachePath(cc_string* path) { // TODO cache method ID - JavaCall_Void_String("getGameCacheDirectory", &dir); - - String_Format2(path, "%s/%c", &dir, folder); - Directory_Create(path); + JavaCall_Void_String("getGameCacheDirectory", path); } diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index 8fc60516f..ba6863719 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -148,9 +148,7 @@ cc_uint64 Stopwatch_Measure(void) { #elif defined CC_BUILD_IOS /* implemented in interop_ios.m */ #else -void Directory_GetCachePath(cc_string* path, const char* folder) { - String_AppendConst(path, folder); -} +void Directory_GetCachePath(cc_string* path) { } #endif cc_result Directory_Create(const cc_string* path) { diff --git a/src/Platform_Web.c b/src/Platform_Web.c index 626eba7de..3f25a1146 100644 --- a/src/Platform_Web.c +++ b/src/Platform_Web.c @@ -98,9 +98,7 @@ cc_uint64 Stopwatch_Measure(void) { /*########################################################################################################################* *-----------------------------------------------------Directory/File------------------------------------------------------* *#########################################################################################################################*/ -void Directory_GetCachePath(cc_string* path, const char* folder) { - String_AppendConst(path, folder); -} +void Directory_GetCachePath(cc_string* path) { } extern void interop_InitFilesystem(void); cc_result Directory_Create(const cc_string* path) { diff --git a/src/Platform_WinApi.c b/src/Platform_WinApi.c index fc123f00e..e7a5a09fa 100644 --- a/src/Platform_WinApi.c +++ b/src/Platform_WinApi.c @@ -137,9 +137,7 @@ cc_uint64 Stopwatch_Measure(void) { /*########################################################################################################################* *-----------------------------------------------------Directory/File------------------------------------------------------* *#########################################################################################################################*/ -void Directory_GetCachePath(cc_string* path, const char* folder) { - String_AppendConst(path, folder); -} +void Directory_GetCachePath(cc_string* path) { } cc_result Directory_Create(const cc_string* path) { WCHAR str[NATIVE_STR_LEN]; diff --git a/src/Screens.c b/src/Screens.c index f9db602ab..6fe3a9c71 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -1851,7 +1851,7 @@ static struct DisconnectScreen { struct FontDesc titleFont, messageFont; struct TextWidget title, message; - char _titleBuffer[STRING_SIZE]; + char _titleBuffer[STRING_SIZE * 2]; char _messageBuffer[STRING_SIZE]; cc_string titleStr, messageStr; } DisconnectScreen; diff --git a/src/TexturePack.c b/src/TexturePack.c index 41f297d2b..992ad31b7 100644 --- a/src/TexturePack.c +++ b/src/TexturePack.c @@ -192,32 +192,68 @@ CC_INLINE static void HashUrl(cc_string* key, const cc_string* url) { String_AppendUInt32(key, Utils_CRC32((const cc_uint8*)url->buffer, url->length)); } -CC_NOINLINE static void MakeCachePath(cc_string* path, const cc_string* url) { +static cc_bool createdCache, cacheInvalid; +static cc_bool UseDedicatedCache(cc_string* path, const cc_string* key) { + cc_result res; + Directory_GetCachePath(path); + if (!path->length || cacheInvalid) return false; + + String_AppendConst(path, "/texturecache"); + res = Directory_Create(path); + + /* Check if something is deleting the cache directory behind our back */ + /* (Several users have reported this happening on some Android devices) */ + if (createdCache && res == 0) { + Chat_AddRaw("&cSomething has deleted system managed cache folder"); + Chat_AddRaw(" &cFalling back to caching to game folder instead.."); + cacheInvalid = true; + } + if (res == 0) createdCache = true; + + String_Format1(path, "/%s", key); + return !cacheInvalid; +} + +CC_NOINLINE static void MakeCachePath(cc_string* mainPath, cc_string* altPath, const cc_string* url) { cc_string key; char keyBuffer[STRING_INT_CHARS]; String_InitArray(key, keyBuffer); - HashUrl(&key, url); - Directory_GetCachePath(path, "texturecache"); - String_Format1(path, "/%s", &key); + + if (UseDedicatedCache(mainPath, &key)) { + /* If using dedicated cache directory, also fallback to default cache directory */ + String_Format1(altPath, "texturecache/%s", &key); + } else { + mainPath->length = 0; + String_Format1(mainPath, "texturecache/%s", &key); + } } /* Returns non-zero if given URL has been cached */ static int IsCached(const cc_string* url) { - cc_string path; char pathBuffer[FILENAME_SIZE]; - String_InitArray(path, pathBuffer); + cc_string mainPath; char mainBuffer[FILENAME_SIZE]; + cc_string altPath; char altBuffer[FILENAME_SIZE]; + String_InitArray(mainPath, mainBuffer); + String_InitArray(altPath, altBuffer); - MakeCachePath(&path, url); - return File_Exists(&path); + MakeCachePath(&mainPath, &altPath, url); + return File_Exists(&mainPath) || (altPath.length && File_Exists(&altPath)); } /* Attempts to open the cached data stream for the given url */ static cc_bool OpenCachedData(const cc_string* url, struct Stream* stream) { - cc_string path; char pathBuffer[FILENAME_SIZE]; + cc_string mainPath; char mainBuffer[FILENAME_SIZE]; + cc_string altPath; char altBuffer[FILENAME_SIZE]; cc_result res; + String_InitArray(mainPath, mainBuffer); + String_InitArray(altPath, altBuffer); + - String_InitArray(path, pathBuffer); - MakeCachePath(&path, url); - res = Stream_OpenFile(stream, &path); + MakeCachePath(&mainPath, &altPath, url); + res = Stream_OpenFile(stream, &mainPath); + + /* try fallback cache if can't find in main cache */ + if (res == ReturnCode_FileNotFound && altPath.length) + res = Stream_OpenFile(stream, &altPath); if (res == ReturnCode_FileNotFound) return false; if (res) { Logger_SysWarn2(res, "opening cache for", url); return false; } @@ -262,17 +298,20 @@ CC_NOINLINE static void SetCachedTag(const cc_string* url, struct StringsBuffer* /* Updates cached data, ETag, and Last-Modified for the given URL */ static void UpdateCache(struct HttpRequest* req) { - cc_string path, url; char pathBuffer[FILENAME_SIZE]; + cc_string url, altPath, value; + cc_string path; char pathBuffer[FILENAME_SIZE]; cc_result res; url = String_FromRawArray(req->url); - path = String_FromRawArray(req->etag); - SetCachedTag(&url, &etagCache, &path, ETAGS_TXT); - path = String_FromRawArray(req->lastModified); - SetCachedTag(&url, &lastModCache, &path, LASTMOD_TXT); + value = String_FromRawArray(req->etag); + SetCachedTag(&url, &etagCache, &value, ETAGS_TXT); + value = String_FromRawArray(req->lastModified); + SetCachedTag(&url, &lastModCache, &value, LASTMOD_TXT); String_InitArray(path, pathBuffer); - MakeCachePath(&path, &url); + altPath = String_Empty; + MakeCachePath(&path, &altPath, &url); + res = Stream_WriteAllTo(&path, req->data, req->size); if (res) { Logger_SysWarn2(res, "caching", &url); } } diff --git a/src/interop_ios.m b/src/interop_ios.m index e6638135b..58251fb38 100644 --- a/src/interop_ios.m +++ b/src/interop_ios.m @@ -784,20 +784,16 @@ void GetDeviceUUID(cc_string* str) { String_AppendUtf8(str, src, String_Length(src)); } -void Directory_GetCachePath(cc_string* path, const char* folder) { +void Directory_GetCachePath(cc_string* path) { NSArray* array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); - if (array.count > 0) { - // try to use iOS app cache folder if possible - // https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html - NSString* str = [array objectAtIndex:0]; - const char* utf8 = [str UTF8String]; + if (array.count <= 0) return; + + // try to use iOS app cache folder if possible + // https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html + NSString* str = [array objectAtIndex:0]; + const char* utf8 = [str UTF8String]; - String_AppendUtf8(path, utf8, String_Length(utf8)); - String_Format1(path, "/%c", folder); - Directory_Create(path); - } else { - String_AppendConst(path, folder); - } + String_AppendUtf8(path, utf8, String_Length(utf8)); }