diff --git a/src/Entity.c b/src/Entity.c index 7cbbac7ed..8e79577c6 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -468,6 +468,7 @@ static void Entity_CheckSkin(struct Entity* e) { struct Stream mem; struct Bitmap bmp; cc_string skin; + cc_uint8 flags; cc_result res; /* Don't check skin if don't have to */ @@ -477,8 +478,10 @@ static void Entity_CheckSkin(struct Entity* e) { if (!e->SkinFetchState) { first = Entity_FirstOtherWithSameSkinAndFetchedSkin(e); + flags = e == &LocalPlayer_Instance ? HTTP_FLAG_NOCACHE : 0; + if (!first) { - e->_skinReqID = Http_AsyncGetSkin(&skin); + e->_skinReqID = Http_AsyncGetSkin(&skin, flags); e->SkinFetchState = SKIN_FETCH_DOWNLOADING; } else { Entity_CopySkin(e, first); diff --git a/src/Http.h b/src/Http.h index fe36314dc..eff04a8ac 100644 --- a/src/Http.h +++ b/src/Http.h @@ -12,6 +12,7 @@ struct StringsBuffer; #define URL_MAX_SIZE (STRING_SIZE * 2) #define HTTP_FLAG_PRIORITY 0x01 +#define HTTP_FLAG_NOCACHE 0x02 extern struct IGameComponent Http_Component; @@ -45,7 +46,7 @@ struct HttpRequest { /* Aschronously performs a http GET request to download a skin. */ /* If url is a skin, downloads from there. (if not, downloads from SKIN_SERVER/[skinName].png) */ -int Http_AsyncGetSkin(const cc_string* skinName); +int Http_AsyncGetSkin(const cc_string* skinName, cc_uint8 flags); /* Asynchronously performs a http GET request. (e.g. to download data) */ int Http_AsyncGetData(const cc_string* url, cc_uint8 flags); /* Asynchronously performs a http HEAD request. (e.g. to get Content-Length header) */ diff --git a/src/Http_Web.c b/src/Http_Web.c index 6b4e35eea..c1e9b4084 100644 --- a/src/Http_Web.c +++ b/src/Http_Web.c @@ -6,6 +6,7 @@ extern int interop_DownloadAsync(const char* url, int method, int reqID); extern int interop_IsHttpsOnly(void); static struct RequestList workingReqs, queuedReqs; +static cc_uint64 startTime; /*########################################################################################################################* @@ -117,6 +118,13 @@ EMSCRIPTEN_KEEPALIVE void Http_OnFinishedAsync(int reqID, void* data, int len, i /* Adds a req to the list of pending requests, waking up worker thread if needed */ static void HttpBackend_Add(struct HttpRequest* req, cc_uint8 flags) { + /* Add time based query string parameter to bypass browser cache */ + if (flags & HTTP_FLAG_NOCACHE) { + cc_string url = String_FromRawArray(req->url); + int lo = (int)(startTime), hi = (int)(startTime >> 32); + String_Format2(&url, "?t=%i%i", &hi, &lo); + } + RequestList_Append(&queuedReqs, req, flags); Http_StartNextDownload(); } @@ -129,6 +137,7 @@ static void Http_Init(void) { Http_InitCommon(); /* If this webpage is https://, browsers deny any http:// downloading */ httpsOnly = interop_IsHttpsOnly(); + startTime = DateTime_CurrentUTC_MS(); RequestList_Init(&queuedReqs); RequestList_Init(&workingReqs); diff --git a/src/_HttpBase.h b/src/_HttpBase.h index a06e6ada9..72739e0e1 100644 --- a/src/_HttpBase.h +++ b/src/_HttpBase.h @@ -208,7 +208,7 @@ static void Http_CleanCacheTask(struct ScheduledTask* task) { /*########################################################################################################################* *----------------------------------------------------Http public api------------------------------------------------------* *#########################################################################################################################*/ -int Http_AsyncGetSkin(const cc_string* skinName) { +int Http_AsyncGetSkin(const cc_string* skinName, cc_uint8 flags) { cc_string url; char urlBuffer[URL_MAX_SIZE]; String_InitArray(url, urlBuffer); @@ -217,7 +217,7 @@ int Http_AsyncGetSkin(const cc_string* skinName) { } else { String_Format2(&url, "%s/%s.png", &skinServer, skinName); } - return Http_AsyncGetData(&url, 0); + return Http_AsyncGetData(&url, flags); } int Http_AsyncGetData(const cc_string* url, cc_uint8 flags) {