mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 19:45:23 -04:00
Start porting AsyncDownloader to C
This commit is contained in:
parent
fd1c9354c2
commit
206eb88036
@ -39,11 +39,7 @@ namespace ClassicalSharp.Network {
|
||||
#if !LAUNCHER
|
||||
void IGameComponent.Init(Game game) { Init(game.skinServer); }
|
||||
void IGameComponent.Ready(Game game) { }
|
||||
void IGameComponent.Reset(Game game) {
|
||||
lock (pendingLocker)
|
||||
pending.Clear();
|
||||
handle.Set();
|
||||
}
|
||||
void IGameComponent.Reset(Game game) { Clear(); }
|
||||
|
||||
void IGameComponent.OnNewMap(Game game) { }
|
||||
void IGameComponent.OnNewMapLoaded(Game game) { }
|
||||
|
353
src/Client/AsyncDownloader.c
Normal file
353
src/Client/AsyncDownloader.c
Normal file
@ -0,0 +1,353 @@
|
||||
#include "AsyncDownloader.h"
|
||||
#include "Platform.h"
|
||||
|
||||
void ASyncRequest_Free(AsyncRequest* request) {
|
||||
switch (request->RequestType) {
|
||||
case REQUEST_TYPE_IMAGE:
|
||||
Platform_MemFree(&request->ResultBitmap.Scan0);
|
||||
break;
|
||||
case REQUEST_TYPE_DATA:
|
||||
Platform_MemFree(&request->ResultData.Ptr);
|
||||
break;
|
||||
case REQUEST_TYPE_STRING:
|
||||
Platform_MemFree(&request->ResultString.buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct AsyncRequestList_ {
|
||||
UInt32 Count;
|
||||
AsyncRequest* Requests;
|
||||
AsyncRequest DefaultRequests[10];
|
||||
} AsyncRequestList;
|
||||
|
||||
void AsyncRequestList_Append(AsyncRequestList* list, AsyncRequest* item);
|
||||
void AsyncRequestList_Prepend(AsyncRequestList* list, AsyncRequest* item);
|
||||
void AsyncRequestList_RemoveAt(AsyncRequestList* list, UInt32 i);
|
||||
|
||||
void AsyncRequestList_Init(AsyncRequestList* list) {
|
||||
list->Count = 0;
|
||||
list->Requests = list->DefaultRequests;
|
||||
}
|
||||
|
||||
void AsyncRequestList_Free(AsyncRequestList* list) {
|
||||
if (list->Requests != list->DefaultRequests) {
|
||||
Platform_MemFree(&list->Requests);
|
||||
}
|
||||
AsyncDownloader_Init(list);
|
||||
}
|
||||
|
||||
void* async_eventHandle;
|
||||
void* async_workerThread;
|
||||
void* async_pendingMutex;
|
||||
void* async_processedMutex;
|
||||
void* async_curRequestMutex;
|
||||
volatile bool async_terminate;
|
||||
|
||||
AsyncRequestList async_pending;
|
||||
AsyncRequestList async_processed;
|
||||
String async_skinServer = String_FromConst("http://static.classicube.net/skins/");
|
||||
AsyncRequest async_curRequest;
|
||||
volatile Int32 async_curRequestProgress = -3;
|
||||
bool ManageCookies;
|
||||
bool KeepAlive;
|
||||
|
||||
void AsyncDownloader_Init(void) {
|
||||
AsyncRequestList_Init(&async_pending);
|
||||
AsyncRequestList_Init(&async_processed);
|
||||
async_eventHandle = Platform_EventCreate();
|
||||
async_pendingMutex = Platform_MutexCreate();
|
||||
async_processedMutex = Platform_MutexCreate();
|
||||
async_curRequestMutex = Platform_MutexCreate();
|
||||
async_workerThread = Platform_ThreadStart(DownloadThreadWorker);
|
||||
}
|
||||
|
||||
void AsyncDownloader_Reset(void) {
|
||||
Platform_MutexLock(async_pendingMutex);
|
||||
{
|
||||
AsyncRequestList_Free(&async_pending);
|
||||
}
|
||||
Platform_MutexUnlock(async_pendingMutex);
|
||||
Platform_EventSet(async_eventHandle);
|
||||
}
|
||||
|
||||
void AsyncDownloader_Free(void) {
|
||||
async_terminate = true;
|
||||
AsyncDownloader_Reset();
|
||||
Platform_ThreadJoin(async_workerThread);
|
||||
Platform_ThreadFreeHandle(async_workerThread);
|
||||
|
||||
Platform_EventFree(async_eventHandle);
|
||||
Platform_MutexFree(async_pendingMutex);
|
||||
Platform_MutexFree(async_processedMutex);
|
||||
Platform_MutexFree(async_curRequestMutex);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetSkin(STRING_PURE String* id, STRING_PURE String* skinName) {
|
||||
UInt8 urlBuffer[String_BufferSize(STRING_SIZE)];
|
||||
String url = String_InitAndClearArray(urlBuffer);
|
||||
|
||||
if (Utils_IsUrlPrefix(skinName, 0)) {
|
||||
String_Set(&url, &skinName);
|
||||
} else {
|
||||
String_AppendString(&url, &async_skinServer);
|
||||
String_AppendColorless(&url, skinName);
|
||||
String_AppendConst(&url, ".png");
|
||||
}
|
||||
|
||||
AddRequest(&url, false, id, REQUEST_TYPE_IMAGE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetData(STRING_PURE String* url, bool priority, STRING_PURE String* id) {
|
||||
AddRequest(url, priority, id, REQUEST_TYPE_DATA, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetImage(STRING_PURE String* url, bool priority, STRING_PURE String* id) {
|
||||
AddRequest(url, priority, id, REQUEST_TYPE_IMAGE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetString(STRING_PURE String* url, bool priority, STRING_PURE String* id) {
|
||||
AddRequest(url, priority, id, REQUEST_TYPE_STRING, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetContentLength(STRING_PURE String* url, bool priority, STRING_PURE String* id) {
|
||||
AddRequest(url, priority, id, REQUEST_TYPE_CONTENT_LENGTH, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_PostString(STRING_PURE String* url, bool priority, STRING_PURE String* id, STRING_PURE String* contents) {
|
||||
AddRequest(url, priority, id, REQUEST_TYPE_STRING, NULL, NULL, contents);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetDataEx(STRING_PURE String* url, bool priority, STRING_PURE String* id, DateTime* lastModified, STRING_PURE String* etag) {
|
||||
AddRequest(url, priority, id, REQUEST_TYPE_DATA, lastModified, etag, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetImageEx(STRING_PURE String* url, bool priority, STRING_PURE String* id, DateTime* lastModified, STRING_PURE String* etag) {
|
||||
AddRequest(url, priority, id, REQUEST_TYPE_IMAGE, lastModified, etag, NULL);
|
||||
}
|
||||
|
||||
void AddRequest(String* url, bool priority, String* id, UInt8 type, DateTime* lastModified, String* etag, object data) {
|
||||
Platform_MutexLock(async_pendingMutex);
|
||||
{
|
||||
AsyncRequest request = { 0 };
|
||||
String reqUrl = String_FromEmptyArray(request.URL); String_Set(&reqUrl, url);
|
||||
String reqID = String_FromEmptyArray(request.ID); String_Set(&reqID, id);
|
||||
request.RequestType = type;
|
||||
request.LastModified = lastModified; // can be null
|
||||
request.ETag = etag; // can be null
|
||||
request.Data = data;
|
||||
|
||||
Platform_CurrentUTCTime(&request.TimeAdded);
|
||||
if (priority) {
|
||||
AsyncRequestList_Prepend(&async_pending, &request);
|
||||
} else {
|
||||
AsyncRequestList_Append(&async_pending, &request);
|
||||
}
|
||||
}
|
||||
Platform_MutexUnlock(async_pendingMutex);
|
||||
Platform_EventSet(async_eventHandle);
|
||||
}
|
||||
|
||||
void PurgeOldEntriesTask(ScheduledTask* task) {
|
||||
Platform_MutexLock(async_processedMutex);
|
||||
{
|
||||
DateTime now; Platform_CurrentUTCTime(&now);
|
||||
Int32 i;
|
||||
for (i = async_processed.Count - 1; i >= 0; i--) {
|
||||
AsyncRequest* item = &async_processed.Requests[i];
|
||||
if ((now - item.TimeDownloaded).TotalSeconds < 10) continue;
|
||||
|
||||
ASyncRequest_Free(item);
|
||||
AsyncRequestList_RemoveAt(&async_processed, i);
|
||||
}
|
||||
}
|
||||
Platform_MutexUnlock(async_processedMutex);
|
||||
}
|
||||
|
||||
bool AsyncDownloader_Get(STRING_PURE String* id, AsyncRequest* item) {
|
||||
bool success = false;
|
||||
|
||||
Platform_MutexLock(async_processedMutex);
|
||||
{
|
||||
Int32 i = FindRequest(id, item);
|
||||
success = i >= 0;
|
||||
if (success) AsyncRequestList_RemoveAt(&async_processed, i);
|
||||
}
|
||||
Platform_MutexUnlock(async_processedMutex);
|
||||
return success;
|
||||
}
|
||||
|
||||
void DownloadThreadWorker() {
|
||||
while (true) {
|
||||
AsyncRequest request;
|
||||
bool hasRequest = false;
|
||||
|
||||
Platform_MutexLock(async_pendingMutex);
|
||||
{
|
||||
if (async_terminate) return;
|
||||
if (async_pending.Count > 0) {
|
||||
request = async_pending.Requests[0];
|
||||
hasRequest = true;
|
||||
AsyncRequestList_RemoveAt(&async_pending, 0);
|
||||
}
|
||||
}
|
||||
Platform_MutexUnlock(async_pendingMutex);
|
||||
|
||||
if (hasRequest) {
|
||||
Platform_MutexLock(async_curRequestMutex);
|
||||
{
|
||||
async_curRequest = request;
|
||||
async_curRequestProgress = -2;
|
||||
}
|
||||
Platform_MutexUnlock(async_curRequestMutex);
|
||||
|
||||
ProcessRequest(request);
|
||||
|
||||
Platform_MutexLock(async_curRequestMutex);
|
||||
{
|
||||
async_curRequest.ID[0] = NULL;
|
||||
async_curRequestProgress = -3;
|
||||
}
|
||||
Platform_MutexUnlock(async_curRequestMutex);
|
||||
} else {
|
||||
Platform_EventWait(async_eventHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Int32 FindRequest(STRING_PURE String* id, AsyncRequest* item) {
|
||||
Int32 i;
|
||||
for (i = 0; i < async_processed.Count; i++) {
|
||||
String requestID = String_FromRawArray(async_processed.Requests[i].ID);
|
||||
if (!String_Equals(&requestID, id)) continue;
|
||||
|
||||
*item = async_processed.Requests[i];
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ProcessRequest(AsyncRequest* request) {
|
||||
String url = String_FromRawArray(request->URL);
|
||||
Platform_Log2("Downloading from %s (type %b)", &url, &request->RequestType);
|
||||
HttpStatusCode status = HttpStatusCode.OK;
|
||||
|
||||
try {
|
||||
HttpWebRequest req = MakeRequest(request);
|
||||
using (HttpWebResponse response = (HttpWebResponse)req.GetResponse()) {
|
||||
request.ETag = response.Headers.Get("ETag");
|
||||
if (response.Headers.Get("Last-Modified") != null) {
|
||||
request.LastModified = response.LastModified;
|
||||
}
|
||||
request.Data = DownloadContent(request, response);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (!(ex is WebException || ex is ArgumentException || ex is UriFormatException || ex is IOException)) throw;
|
||||
|
||||
if (ex is WebException) {
|
||||
WebException webEx = (WebException)ex;
|
||||
if (webEx.Response != null) {
|
||||
status = ((HttpWebResponse)webEx.Response).StatusCode;
|
||||
webEx.Response.Close();
|
||||
}
|
||||
request.WebEx = webEx;
|
||||
}
|
||||
|
||||
if (status != HttpStatusCode.OK) {
|
||||
Utils.LogDebug("Failed to download (" + (int)status + ") from: " + url);
|
||||
} else {
|
||||
Utils.LogDebug("Failed to download from: " + url);
|
||||
}
|
||||
}
|
||||
request.TimeDownloaded = DateTime.UtcNow;
|
||||
|
||||
Platform_MutexLock(async_processedMutex);
|
||||
{
|
||||
AsyncRequest older;
|
||||
String id = String_FromRawArray(request->ID);
|
||||
Int32 index = FindRequest(&id, &older);
|
||||
|
||||
if (index >= 0) {
|
||||
/* very rare case - priority item was inserted, then inserted again (so put before first item), */
|
||||
/* and both items got downloaded before an external function removed them from the queue */
|
||||
if (older.TimeAdded > request.TimeAdded) {
|
||||
AsyncRequest tmp = older; older = *request; *request = tmp;
|
||||
}
|
||||
|
||||
ASyncRequest_Free(&older);
|
||||
async_processed.Requests[index] = *request;
|
||||
} else {
|
||||
AsyncRequestList_Append(&async_processed, request);
|
||||
}
|
||||
}
|
||||
Platform_MutexUnlock(async_processedMutex);
|
||||
}
|
||||
/*
|
||||
object DownloadContent(Request request, HttpWebResponse response) {
|
||||
if (request.Type == RequestType.Bitmap) {
|
||||
MemoryStream data = DownloadBytes(response);
|
||||
Bitmap bmp = Platform.ReadBmp32Bpp(drawer, data);
|
||||
|
||||
if (bmp == null) {
|
||||
Utils.LogDebug("Failed to download from: " + request.Url);
|
||||
}
|
||||
return bmp;
|
||||
} else if (request.Type == RequestType.String) {
|
||||
MemoryStream data = DownloadBytes(response);
|
||||
byte[] rawBuffer = data.GetBuffer();
|
||||
return Encoding.UTF8.GetString(rawBuffer, 0, (int)data.Length);
|
||||
} else if (request.Type == RequestType.ByteArray) {
|
||||
MemoryStream data = DownloadBytes(response);
|
||||
return data.ToArray();
|
||||
} else if (request.Type == RequestType.ContentLength) {
|
||||
return response.ContentLength;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
HttpWebRequest MakeRequest(Request request) {
|
||||
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(request.Url);
|
||||
req.AutomaticDecompression = DecompressionMethods.GZip;
|
||||
req.ReadWriteTimeout = 90 * 1000;
|
||||
req.Timeout = 90 * 1000;
|
||||
req.Proxy = null;
|
||||
req.UserAgent = Program.AppName;
|
||||
req.CookieContainer = Cookies;
|
||||
req.KeepAlive = KeepAlive;
|
||||
|
||||
if (request.LastModified != DateTime.MinValue) {
|
||||
req.IfModifiedSince = request.LastModified;
|
||||
}
|
||||
if (request.ETag != null) {
|
||||
req.Headers["If-None-Match"] = request.ETag;
|
||||
}
|
||||
|
||||
if (request.Data != null) {
|
||||
req.Method = "POST";
|
||||
req.ContentType = "application/x-www-form-urlencoded; charset=UTF-8;";
|
||||
byte[] encodedData = Encoding.UTF8.GetBytes((string)request.Data);
|
||||
req.ContentLength = encodedData.Length;
|
||||
using (Stream stream = req.GetRequestStream()) {
|
||||
stream.Write(encodedData, 0, encodedData.Length);
|
||||
}
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
static byte[] buffer = new byte[4096 * 8];
|
||||
MemoryStream DownloadBytes(HttpWebResponse response) {
|
||||
int length = (int)response.ContentLength;
|
||||
MemoryStream dst = length > 0 ? new MemoryStream(length) : new MemoryStream();
|
||||
CurrentItemProgress = length > 0 ? 0 : -1;
|
||||
|
||||
using (Stream src = response.GetResponseStream()) {
|
||||
int read = 0;
|
||||
while ((read = src.Read(buffer, 0, buffer.Length)) > 0) {
|
||||
dst.Write(buffer, 0, read);
|
||||
if (length <= 0) continue;
|
||||
CurrentItemProgress = (int)(100 * (float)dst.Length / length);
|
||||
}
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
}*/
|
@ -8,11 +8,10 @@
|
||||
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
#define REQUEST_TYPE_BITMAP 0
|
||||
#define REQUEST_TYPE_STRING 1
|
||||
#define REQUEST_TYPE_DATA 2
|
||||
#define REQUEST_TYPE_CONTENT_LENGTH 3
|
||||
|
||||
enum REQUEST_TYPE {
|
||||
REQUEST_TYPE_DATA, REQUEST_TYPE_IMAGE,
|
||||
REQUEST_TYPE_STRING, REQUEST_TYPE_CONTENT_LENGTH,
|
||||
};
|
||||
typedef struct AsyncRequest_ {
|
||||
UInt8 URL[String_BufferSize(STRING_SIZE)];
|
||||
UInt8 ID[String_BufferSize(STRING_SIZE)];
|
||||
@ -35,12 +34,19 @@ typedef struct AsyncRequest_ {
|
||||
void ASyncRequest_Free(AsyncRequest* request);
|
||||
|
||||
IGameComponent AsyncDownloader_MakeComponent(void);
|
||||
void AsyncDownloader_Init(STRING_PURE String* skinServer);
|
||||
void AsyncDownloader_DownloadSkin(STRING_PURE String* identifier, STRING_PURE String* skinName);
|
||||
void AsyncDownloader_Download(STRING_PURE String* url, bool priority, UInt8 type, STRING_PURE String* identifier);
|
||||
void AsyncDownloader_Download2(STRING_PURE String* url, bool priority, UInt8 type, STRING_PURE String* identifier, DateTime* lastModified, STRING_PURE String* etag);
|
||||
void AsyncDownloader_Init(void);
|
||||
void AsyncDownloader_Free(void);
|
||||
bool AsyncDownloader_Get(STRING_PURE String* identifier, AsyncRequest* item);
|
||||
bool AsyncDownloader_GetInProgress(AsyncRequest* request, Int32* progress);
|
||||
|
||||
void AsyncDownloader_GetSkin(STRING_PURE String* id, STRING_PURE String* skinName);
|
||||
void AsyncDownloader_GetData(STRING_PURE String* url, bool priority, STRING_PURE String* id);
|
||||
void AsyncDownloader_GetImage(STRING_PURE String* url, bool priority, STRING_PURE String* id);
|
||||
void AsyncDownloader_GetString(STRING_PURE String* url, bool priority, STRING_PURE String* id);
|
||||
void AsyncDownloader_GetContentLength(STRING_PURE String* url, bool priority, STRING_PURE String* id);
|
||||
void AsyncDownloader_PostString(STRING_PURE String* url, bool priority, STRING_PURE String* id, STRING_PURE String* contents);
|
||||
void AsyncDownloader_GetDataEx(STRING_PURE String* url, bool priority, STRING_PURE String* id, DateTime* lastModified, STRING_PURE String* etag);
|
||||
void AsyncDownloader_GetImageEx(STRING_PURE String* url, bool priority, STRING_PURE String* id, DateTime* lastModified, STRING_PURE String* etag);
|
||||
|
||||
bool AsyncDownloader_Get(STRING_PURE String* id, AsyncRequest* item);
|
||||
bool AsyncDownloader_GetCurrent(AsyncRequest* request, Int32* progress);
|
||||
void AsyncDownloader_PurgeOldEntriesTask(ScheduledTask* task);
|
||||
#endif
|
@ -255,6 +255,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="2DStructs.c" />
|
||||
<ClCompile Include="AsyncDownloader.c" />
|
||||
<ClCompile Include="Camera.c" />
|
||||
<ClCompile Include="AxisLinesRenderer.c" />
|
||||
<ClCompile Include="Block.c" />
|
||||
|
@ -572,5 +572,8 @@
|
||||
<ClCompile Include="PacketHandlers.c">
|
||||
<Filter>Source Files\Network</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AsyncDownloader.c">
|
||||
<Filter>Source Files\Network</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -454,8 +454,7 @@ void TabList_Reset(void) {
|
||||
Platform_MemSet(TabList_ListNames, 0, sizeof(TabList_ListNames));
|
||||
Platform_MemSet(TabList_GroupNames, 0, sizeof(TabList_GroupNames));
|
||||
Platform_MemSet(TabList_GroupRanks, 0, sizeof(TabList_GroupRanks));
|
||||
/* TODO: Should we be trying to free the buffer here? */
|
||||
StringsBuffer_UNSAFE_Reset(&TabList_Buffer);
|
||||
StringsBuffer_Free(&TabList_Buffer);
|
||||
}
|
||||
|
||||
IGameComponent TabList_MakeComponent(void) {
|
||||
@ -692,7 +691,7 @@ void Player_CheckSkin(Player* player) {
|
||||
if (!player->FetchedSkin && entity->Model->UsesSkin) {
|
||||
Player* first = Player_FirstOtherWithSameSkinAndFetchedSkin(player);
|
||||
if (first == NULL) {
|
||||
AsyncDownloader_DownloadSkin(&skin, &skin);
|
||||
AsyncDownloader_GetSkin(&skin, &skin);
|
||||
} else {
|
||||
Player_ApplySkin(player, first);
|
||||
}
|
||||
|
@ -767,16 +767,7 @@ void Audio_SetSounds(Int32 volume) { }
|
||||
void Audio_PlayDigSound(UInt8 type) { }
|
||||
void Audio_PlayStepSound(UInt8 type) { }
|
||||
|
||||
void ASyncRequest_Free(AsyncRequest* request) { }
|
||||
IGameComponent AsyncDownloader_MakeComponent(void) { return IGameComponent_MakeEmpty(); }
|
||||
void AsyncDownloader_Init(STRING_PURE String* skinServer) { }
|
||||
void AsyncDownloader_DownloadSkin(STRING_PURE String* identifier, STRING_PURE String* skinName) { }
|
||||
void AsyncDownloader_Download(STRING_PURE String* url, bool priority, UInt8 type, STRING_PURE String* identifier) { }
|
||||
void AsyncDownloader_Download2(STRING_PURE String* url, bool priority, UInt8 type, STRING_PURE String* identifier, DateTime* lastModified, STRING_PURE String* etag) { }
|
||||
void AsyncDownloader_Free(void) { }
|
||||
bool AsyncDownloader_Get(STRING_PURE String* identifier, AsyncRequest* item) { return false; }
|
||||
bool AsyncDownloader_GetInProgress(AsyncRequest* request, Int32* progress) { return false; }
|
||||
void AsyncDownloader_PurgeOldEntriesTask(ScheduledTask* task) { }
|
||||
/* TODO: needed for async downloading */
|
||||
DateTime DateTime_FromTotalMs(Int64 ms) { DateTime time; return time; }
|
||||
|
||||
void Bitmap_EncodePng(Bitmap* bmp, Stream* stream) { }
|
||||
|
@ -214,14 +214,14 @@ void WoM_CheckMotd(void) {
|
||||
applied in the new world if the async 'get env request' didn't complete before the old world was unloaded */
|
||||
wom_counter++;
|
||||
WoM_UpdateIdentifier();
|
||||
AsyncDownloader_Download(&url, true, REQUEST_TYPE_STRING, &wom_identifier);
|
||||
AsyncDownloader_GetString(&url, true, &wom_identifier);
|
||||
wom_sendId = true;
|
||||
}
|
||||
|
||||
void WoM_CheckSendWomID(void) {
|
||||
if (wom_sendId && !wom_sentId) {
|
||||
String msg = String_FromConst("/womid WoMClient-2.0.7")
|
||||
ServerConnection_SendChat(&msg);
|
||||
String msg = String_FromConst("/womid WoMClient-2.0.7");
|
||||
ServerConnection_SendChat(&msg);
|
||||
wom_sentId = true;
|
||||
}
|
||||
}
|
||||
|
@ -52,9 +52,20 @@ UInt32 Platform_FileLength(void* file);
|
||||
void Platform_ThreadSleep(UInt32 milliseconds);
|
||||
typedef void Platform_ThreadFunc(void);
|
||||
void* Platform_ThreadStart(Platform_ThreadFunc* func);
|
||||
void Platform_ThreadJoin(void* handle);
|
||||
/* Frees handle to thread - NOT THE THREAD ITSELF */
|
||||
void Platform_ThreadFreeHandle(void* handle);
|
||||
|
||||
void* Platform_MutexCreate(void);
|
||||
void Platform_MutexFree(void* handle);
|
||||
void Platform_MutexLock(void* handle);
|
||||
void Platform_MutexUnlock(void* handle);
|
||||
|
||||
void* Platform_EventCreate(void);
|
||||
void Platform_EventFree(void* handle);
|
||||
void Platform_EventSet(void* handle);
|
||||
void Platform_EventWait(void* handle);
|
||||
|
||||
typedef Int64 Stopwatch;
|
||||
void Stopwatch_Start(Stopwatch* timer);
|
||||
Int32 Stopwatch_ElapsedMicroseconds(Stopwatch* timer);
|
||||
|
@ -767,7 +767,7 @@ void ChatScreen_SetInitialMessages(ChatScreen* screen) {
|
||||
void ChatScreen_CheckOtherStatuses(ChatScreen* screen) {
|
||||
AsyncRequest request;
|
||||
Int32 progress;
|
||||
bool hasRequest = AsyncDownloader_GetInProgress(&request, &progress);
|
||||
bool hasRequest = AsyncDownloader_GetCurrent(&request, &progress);
|
||||
|
||||
String id = String_FromRawArray(request.ID);
|
||||
String terrain = String_FromConst("terrain");
|
||||
|
@ -63,10 +63,10 @@ void ServerConnection_DownloadTexturePack(STRING_PURE String* url) {
|
||||
String zip = String_FromConst(".zip");
|
||||
if (String_ContainsString(url, &zip)) {
|
||||
String texPack = String_FromConst("texturePack");
|
||||
AsyncDownloader_Download2(url, true, REQUEST_TYPE_DATA, &texPack, &lastModified, &etag);
|
||||
AsyncDownloader_GetDataEx(url, true, &texPack, &lastModified, &etag);
|
||||
} else {
|
||||
String terrain = String_FromConst("terrain");
|
||||
AsyncDownloader_Download2(url, true, REQUEST_TYPE_BITMAP, &terrain, &lastModified, &etag);
|
||||
AsyncDownloader_GetImageEx(url, true, &terrain, &lastModified, &etag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -641,7 +641,8 @@ bool Convert_TryParseBool(STRING_PURE String* str, bool* value) {
|
||||
#define STRINGSBUFFER_LEN_SHIFT 9
|
||||
#define STRINGSBUFFER_LEN_MASK 0x1FFUL
|
||||
void StringsBuffer_Init(StringsBuffer* buffer) {
|
||||
StringsBuffer_UNSAFE_Reset(buffer);
|
||||
buffer->Count = 0;
|
||||
buffer->UsedElems = 0;
|
||||
buffer->TextBuffer = buffer->DefaultBuffer;
|
||||
buffer->FlagsBuffer = buffer->DefaultFlags;
|
||||
buffer->TextBufferElems = STRINGSBUFFER_BUFFER_DEF_SIZE;
|
||||
@ -655,12 +656,7 @@ void StringsBuffer_Free(StringsBuffer* buffer) {
|
||||
if (buffer->FlagsBuffer != buffer->DefaultFlags) {
|
||||
Platform_MemFree(&buffer->FlagsBuffer);
|
||||
}
|
||||
StringsBuffer_UNSAFE_Reset(buffer);
|
||||
}
|
||||
|
||||
void StringsBuffer_UNSAFE_Reset(StringsBuffer* buffer) {
|
||||
buffer->Count = 0;
|
||||
buffer->UsedElems = 0;
|
||||
StringsBuffer_Init(buffer);
|
||||
}
|
||||
|
||||
void StringsBuffer_Get(StringsBuffer* buffer, UInt32 index, STRING_TRANSIENT String* text) {
|
||||
|
@ -115,7 +115,6 @@ typedef struct StringsBuffer_ {
|
||||
|
||||
void StringsBuffer_Init(StringsBuffer* buffer);
|
||||
void StringsBuffer_Free(StringsBuffer* buffer);
|
||||
void StringsBuffer_UNSAFE_Reset(StringsBuffer* buffer);
|
||||
void StringsBuffer_Get(StringsBuffer* buffer, UInt32 index, STRING_TRANSIENT String* text);
|
||||
STRING_REF String StringsBuffer_UNSAFE_Get(StringsBuffer* buffer, UInt32 index);
|
||||
void StringsBuffer_Resize(void** buffer, UInt32* elems, UInt32 elemSize, UInt32 defElems, UInt32 expandElems);
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "ExtMath.h"
|
||||
#include "ErrorHandler.h"
|
||||
#include "Drawer2D.h"
|
||||
#include "Funcs.h"
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOSERVICE
|
||||
#define NOMCX
|
||||
@ -297,12 +298,63 @@ void* Platform_ThreadStart(Platform_ThreadFunc* func) {
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Platform_ThreadJoin(void* handle) {
|
||||
WaitForSingleObject((HANDLE)handle, INFINITE);
|
||||
}
|
||||
|
||||
void Platform_ThreadFreeHandle(void* handle) {
|
||||
if (!CloseHandle((HANDLE)handle)) {
|
||||
ErrorHandler_FailWithCode(GetLastError(), "Freeing thread handle");
|
||||
}
|
||||
}
|
||||
|
||||
CRITICAL_SECTION mutexList[3];
|
||||
Int32 mutexIndex;
|
||||
void* Platform_MutexCreate(void) {
|
||||
if (mutexIndex == Array_Elems(mutexList)) {
|
||||
ErrorHandler_Fail("Cannot allocate another mutex");
|
||||
return NULL;
|
||||
} else {
|
||||
CRITICAL_SECTION* ptr = &mutexList[mutexIndex];
|
||||
InitializeCriticalSection(ptr); mutexIndex++;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Platform_MutexFree(void* handle) {
|
||||
DeleteCriticalSection((CRITICAL_SECTION*)handle);
|
||||
}
|
||||
|
||||
void Platform_MutexLock(void* handle) {
|
||||
EnterCriticalSection((CRITICAL_SECTION*)handle);
|
||||
}
|
||||
|
||||
void Platform_MutexUnlock(void* handle) {
|
||||
LeaveCriticalSection((CRITICAL_SECTION*)handle);
|
||||
}
|
||||
|
||||
void* Platform_EventCreate(void) {
|
||||
void* handle = CreateEventA(NULL, false, false, NULL);
|
||||
if (handle == NULL) {
|
||||
ErrorHandler_FailWithCode(GetLastError(), "Creating event");
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Platform_EventFree(void* handle) {
|
||||
if (!CloseHandle((HANDLE)handle)) {
|
||||
ErrorHandler_FailWithCode(GetLastError(), "Freeing event");
|
||||
}
|
||||
}
|
||||
|
||||
void Platform_EventSet(void* handle) {
|
||||
SetEvent((HANDLE)handle);
|
||||
}
|
||||
|
||||
void Platform_EventWait(void* handle) {
|
||||
WaitForSingleObject((HANDLE)handle, INFINITE);
|
||||
}
|
||||
|
||||
void Stopwatch_Start(Stopwatch* timer) {
|
||||
if (stopwatch_highResolution) {
|
||||
QueryPerformanceCounter(timer);
|
||||
|
Loading…
x
Reference in New Issue
Block a user