mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 19:45:23 -04:00
log errors instead of immediately dying in C client
This commit is contained in:
parent
8fc1db2b68
commit
1d6e422c3f
@ -188,8 +188,9 @@ static void Animations_ReadDescription(struct Stream* stream) {
|
||||
}
|
||||
|
||||
if (anims_count == Array_Elems(anims_list)) {
|
||||
ErrorHandler_Fail("Too many animations in animations.txt");
|
||||
Chat_AddRaw("&cCannot show over 256 animations"); return;
|
||||
}
|
||||
|
||||
data.TexLoc = tileX + (tileY * ATLAS2D_TILES_PER_ROW);
|
||||
anims_list[anims_count++] = data;
|
||||
}
|
||||
@ -320,7 +321,10 @@ static void Animations_FileChanged(void* obj, struct Stream* stream) {
|
||||
String* name = &stream->Name;
|
||||
if (String_CaselessEqualsConst(name, "animation.png") || String_CaselessEqualsConst(name, "animations.png")) {
|
||||
ReturnCode result = Bitmap_DecodePng(&anims_bmp, stream);
|
||||
ErrorHandler_CheckOrFail(result, "Decoding animations bitmap");
|
||||
if (!result) return;
|
||||
|
||||
ErrorHandler_LogError_Path(result, "decoding", name);
|
||||
Mem_Free(&anims_bmp.Scan0);
|
||||
} else if (String_CaselessEqualsConst(name, "animation.txt") || String_CaselessEqualsConst(name, "animations.txt")) {
|
||||
Animations_ReadDescription(stream);
|
||||
} else if (String_CaselessEqualsConst(name, "uselavaanim")) {
|
||||
|
@ -198,7 +198,7 @@ static void AsyncDownloader_ProcessRequest(struct AsyncRequest* request) {
|
||||
result = Http_MakeRequest(request, &handle);
|
||||
elapsedMS = Stopwatch_ElapsedMicroseconds(&stopwatch) / 1000;
|
||||
Platform_Log2("HTTP make request: ret code %i, in %i ms", &result, &elapsedMS);
|
||||
if (!ErrorHandler_Check(result)) return;
|
||||
if (result) return;
|
||||
|
||||
async_curProgress = ASYNC_PROGRESS_FETCHING_DATA;
|
||||
UInt32 size = 0;
|
||||
@ -208,7 +208,7 @@ static void AsyncDownloader_ProcessRequest(struct AsyncRequest* request) {
|
||||
UInt32 status = request->StatusCode;
|
||||
Platform_Log3("HTTP get headers: ret code %i (http %i), in %i ms", &result, &status, &elapsedMS);
|
||||
|
||||
if (!ErrorHandler_Check(result) || request->StatusCode != 200) {
|
||||
if (result || request->StatusCode != 200) {
|
||||
Http_FreeRequest(handle); return;
|
||||
}
|
||||
|
||||
@ -221,7 +221,7 @@ static void AsyncDownloader_ProcessRequest(struct AsyncRequest* request) {
|
||||
}
|
||||
|
||||
Http_FreeRequest(handle);
|
||||
if (!ErrorHandler_Check(result)) return;
|
||||
if (result) return;
|
||||
|
||||
UInt64 addr = (UInt64)data;
|
||||
Platform_Log2("OK I got the DATA! %i bytes at %x", &size, &addr);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "GameStructs.h"
|
||||
#include "Errors.h"
|
||||
#include "Vorbis.h"
|
||||
#include "Chat.h"
|
||||
|
||||
StringsBuffer files;
|
||||
/*########################################################################################################################*
|
||||
@ -117,19 +118,26 @@ static void Soundboard_Init(struct Soundboard* board, STRING_PURE String* boardN
|
||||
|
||||
struct SoundGroup* group = Soundboard_Find(board, &name);
|
||||
if (group == NULL) {
|
||||
if (board->Count == Array_Elems(board->Groups)) ErrorHandler_Fail("Soundboard - too many groups");
|
||||
if (board->Count == Array_Elems(board->Groups)) {
|
||||
Chat_AddRaw("&cCannot have more than 10 sound groups"); return;
|
||||
}
|
||||
|
||||
group = &board->Groups[board->Count++];
|
||||
group->Name = String_InitAndClearArray(group->NameBuffer);
|
||||
String_Set(&group->Name, &name);
|
||||
}
|
||||
|
||||
if (group->Count == Array_Elems(group->Sounds)) ErrorHandler_Fail("Soundboard - too many sounds");
|
||||
if (group->Count == Array_Elems(group->Sounds)) {
|
||||
Chat_AddRaw("&cCannot have more than 10 sounds in a group"); return;
|
||||
}
|
||||
|
||||
struct Sound* snd = &group->Sounds[group->Count];
|
||||
ReturnCode result = Sound_ReadWave(&file, snd);
|
||||
|
||||
ErrorHandler_CheckOrFail(result, "Soundboard - reading WAV");
|
||||
group->Count++;
|
||||
if (result) {
|
||||
ErrorHandler_LogError_Path(result, "decoding", &file);
|
||||
Mem_Free(&snd->Data);
|
||||
} else { group->Count++; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,6 +345,7 @@ static void Music_RunLoop(void) {
|
||||
if (!count) return;
|
||||
Random rnd; Random_InitFromCurrentTime(&rnd);
|
||||
UInt8 pathBuffer[String_BufferSize(FILENAME_SIZE)];
|
||||
ReturnCode result;
|
||||
|
||||
while (!music_pendingStop) {
|
||||
Int32 idx = Random_Range(&rnd, 0, count);
|
||||
@ -345,17 +354,17 @@ static void Music_RunLoop(void) {
|
||||
String_Format2(&path, "audio%r%s", &Directory_Separator, &filename);
|
||||
Platform_Log1("playing music file: %s", &filename);
|
||||
|
||||
void* file; ReturnCode result = File_Open(&file, &path);
|
||||
ErrorHandler_CheckOrFail(result, "Music_RunLoop - opening file");
|
||||
void* file; result = File_Open(&file, &path);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "opening", &path); return; }
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
{
|
||||
result = Music_PlayOgg(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "Music_RunLoop - playing ogg");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "playing", &path); }
|
||||
}
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "Music_RunLoop - closing file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing", &path); }
|
||||
|
||||
if (music_pendingStop) break;
|
||||
if (music_pendingStop) return;
|
||||
Int32 delay = 1000 * 120 + Random_Range(&rnd, 0, 1000 * 300);
|
||||
Waitable_WaitFor(music_waitable, delay);
|
||||
}
|
||||
|
@ -458,8 +458,8 @@ ReturnCode Bitmap_DecodePng(struct Bitmap* bmp, struct Stream* stream) {
|
||||
UInt32 bufferLeft = bufferLen - bufferIdx, read;
|
||||
if (bufferLeft > bufferMax) bufferLeft = bufferMax;
|
||||
|
||||
ReturnCode code = compStream.Read(&compStream, &buffer[bufferIdx], bufferLeft, &read);
|
||||
ErrorHandler_CheckOrFail(code, "PNG - reading image bulk data");
|
||||
result = compStream.Read(&compStream, &buffer[bufferIdx], bufferLeft, &read);
|
||||
if (result) return result;
|
||||
if (!read) break;
|
||||
|
||||
UInt32 startY = bufferIdx / scanlineBytes, rowY;
|
||||
|
@ -48,8 +48,8 @@ DateTime ChatLog_LastLogDate;
|
||||
|
||||
static void Chat_CloseLog(void) {
|
||||
if (!Chat_LogStream.Meta.File) return;
|
||||
ReturnCode code = Chat_LogStream.Close(&Chat_LogStream);
|
||||
ErrorHandler_CheckOrFail(code, "Chat - closing log file");
|
||||
ReturnCode result = Chat_LogStream.Close(&Chat_LogStream);
|
||||
if (result) ErrorHandler_LogError(result, "closing chat log file");
|
||||
}
|
||||
|
||||
static bool Chat_AllowedLogChar(UChar c) {
|
||||
@ -74,11 +74,14 @@ void Chat_SetLogName(STRING_PURE String* name) {
|
||||
}
|
||||
}
|
||||
|
||||
static void Chat_DisableLogging(void) {
|
||||
Game_ChatLogging = false;
|
||||
Chat_AddRaw("&cDisabling chat logging as a result");
|
||||
}
|
||||
|
||||
static void Chat_OpenLog(DateTime* now) {
|
||||
String logsDir = String_FromConst("logs");
|
||||
if (!Directory_Exists(&logsDir)) {
|
||||
Directory_Create(&logsDir);
|
||||
}
|
||||
ReturnCode result;
|
||||
if (!Utils_EnsureDirectory("logs")) { Chat_DisableLogging(); return; }
|
||||
|
||||
/* Ensure multiple instances do not end up overwriting each other's log entries. */
|
||||
Int32 i, year = now->Year, month = now->Month, day = now->Day;
|
||||
@ -93,9 +96,10 @@ static void Chat_OpenLog(DateTime* now) {
|
||||
String_Format1(&path, "%s.log", &Chat_LogName);
|
||||
}
|
||||
|
||||
void* file; ReturnCode result = File_Append(&file, &path);
|
||||
void* file; result = File_Append(&file, &path);
|
||||
if (result && result != ReturnCode_FileShareViolation) {
|
||||
ErrorHandler_FailWithCode(result, "Chat - opening log file");
|
||||
ErrorHandler_LogError_Path(result, "appending to", &path);
|
||||
Chat_DisableLogging(); return;
|
||||
}
|
||||
|
||||
if (result == ReturnCode_FileShareViolation) continue;
|
||||
@ -104,8 +108,8 @@ static void Chat_OpenLog(DateTime* now) {
|
||||
}
|
||||
|
||||
Chat_LogStream.Meta.File = NULL;
|
||||
String failedMsg = String_FromConst("Failed to open chat log file after 20 tries, giving up");
|
||||
ErrorHandler_Log(&failedMsg);
|
||||
ErrorHandler_Log1("Failed to open a chat log file after %i tries, giving up", &i);
|
||||
Chat_DisableLogging();
|
||||
}
|
||||
|
||||
static void Chat_AppendLog(STRING_PURE String* text) {
|
||||
|
@ -73,7 +73,7 @@ static void D3D9_FindCompatibleFormat(void) {
|
||||
for (i = 0; i < count; i++) {
|
||||
d3d9_viewFormat = d3d9_viewFormats[i];
|
||||
res = IDirect3D9_CheckDeviceType(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3d9_viewFormat, d3d9_viewFormat, true);
|
||||
if (ErrorHandler_Check(res)) break;
|
||||
if (!res) break;
|
||||
|
||||
if (i == count - 1) {
|
||||
ErrorHandler_Fail("Unable to create a back buffer with sufficient precision.");
|
||||
@ -84,7 +84,7 @@ static void D3D9_FindCompatibleFormat(void) {
|
||||
for (i = 0; i < count; i++) {
|
||||
d3d9_depthFormat = d3d9_depthFormats[i];
|
||||
res = IDirect3D9_CheckDepthStencilMatch(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3d9_viewFormat, d3d9_viewFormat, d3d9_depthFormat);
|
||||
if (ErrorHandler_Check(res)) break;
|
||||
if (!res) break;
|
||||
|
||||
if (i == count - 1) {
|
||||
ErrorHandler_Fail("Unable to create a depth buffer with sufficient precision.");
|
||||
@ -130,11 +130,11 @@ void Gfx_Init(void) {
|
||||
|
||||
/* Try to create a device with as much hardware usage as possible. */
|
||||
res = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winHandle, createFlags, &args, &device);
|
||||
if (!ErrorHandler_Check(res)) {
|
||||
if (res) {
|
||||
createFlags = D3DCREATE_MIXED_VERTEXPROCESSING;
|
||||
res = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winHandle, createFlags, &args, &device);
|
||||
}
|
||||
if (!ErrorHandler_Check(res)) {
|
||||
if (res) {
|
||||
createFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
||||
res = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, winHandle, createFlags, &args, &device);
|
||||
}
|
||||
@ -565,32 +565,33 @@ void Gfx_CalcPerspectiveMatrix(Real32 fov, Real32 aspect, Real32 zNear, Real32 z
|
||||
}
|
||||
|
||||
|
||||
void Gfx_TakeScreenshot(struct Stream* output, Int32 width, Int32 height) {
|
||||
IDirect3DSurface9* backbuffer;
|
||||
IDirect3DSurface9* temp;
|
||||
ReturnCode hresult;
|
||||
ReturnCode Gfx_TakeScreenshot(struct Stream* output, Int32 width, Int32 height) {
|
||||
IDirect3DSurface9* backbuffer = NULL;
|
||||
IDirect3DSurface9* temp = NULL;
|
||||
ReturnCode result;
|
||||
|
||||
hresult = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
|
||||
ErrorHandler_CheckOrFail(hresult, "Gfx_TakeScreenshot - Get back buffer");
|
||||
hresult = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &temp, NULL);
|
||||
ErrorHandler_CheckOrFail(hresult, "Gfx_TakeScreenshot - Create temp surface");
|
||||
/* For DX 8 use IDirect3DDevice8::CreateImageSurface */
|
||||
result = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
|
||||
if (result) goto finished;
|
||||
result = IDirect3DDevice9_CreateOffscreenPlainSurface(device, width, height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &temp, NULL);
|
||||
if (result) goto finished; /* TODO: For DX 8 use IDirect3DDevice8::CreateImageSurface */
|
||||
result = IDirect3DDevice9_GetRenderTargetData(device, backbuffer, temp);
|
||||
if (result) goto finished;
|
||||
|
||||
hresult = IDirect3DDevice9_GetRenderTargetData(device, backbuffer, temp);
|
||||
ErrorHandler_CheckOrFail(hresult, "Gfx_TakeScreenshot - Copying back buffer");
|
||||
D3DLOCKED_RECT rect;
|
||||
hresult = IDirect3DSurface9_LockRect(temp, &rect, NULL, D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE);
|
||||
ErrorHandler_CheckOrFail(hresult, "Gfx_TakeScreenshot - Lock temp surface");
|
||||
|
||||
struct Bitmap bmp; Bitmap_Create(&bmp, width, height, rect.pBits);
|
||||
hresult = Bitmap_EncodePng(&bmp, output);
|
||||
ErrorHandler_CheckOrFail(hresult, "Gfx_TakeScreenshot - Writing .png");
|
||||
|
||||
hresult = IDirect3DSurface9_UnlockRect(temp);
|
||||
ErrorHandler_CheckOrFail(hresult, "Gfx_TakeScreenshot - Unlock temp surface");
|
||||
result = IDirect3DSurface9_LockRect(temp, &rect, NULL, D3DLOCK_READONLY | D3DLOCK_NO_DIRTY_UPDATE);
|
||||
if (result) goto finished;
|
||||
{
|
||||
struct Bitmap bmp; Bitmap_Create(&bmp, width, height, rect.pBits);
|
||||
result = Bitmap_EncodePng(&bmp, output);
|
||||
if (result) { IDirect3DSurface9_UnlockRect(temp); goto finished; }
|
||||
}
|
||||
result = IDirect3DSurface9_UnlockRect(temp);
|
||||
if (result) goto finished;
|
||||
|
||||
finished:
|
||||
D3D9_FreeResource(&backbuffer);
|
||||
D3D9_FreeResource(&temp);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Gfx_WarnIfNecessary(void) { return false; }
|
||||
|
@ -656,8 +656,6 @@ static void Player_EnsurePow2(struct Player* player, struct Bitmap* bmp) {
|
||||
if (width == bmp->Width && height == bmp->Height) return;
|
||||
|
||||
struct Bitmap scaled; Bitmap_Allocate(&scaled, width, height);
|
||||
if (!scaled.Scan0) ErrorHandler_Fail("Failed to allocate memory for resizing player skin");
|
||||
|
||||
Int32 y;
|
||||
UInt32 stride = (UInt32)(bmp->Width) * BITMAP_SIZEOF_PIXEL;
|
||||
for (y = 0; y < bmp->Height; y++) {
|
||||
@ -695,8 +693,13 @@ static void Player_CheckSkin(struct Player* player) {
|
||||
String url = String_FromRawArray(item.URL);
|
||||
struct Stream mem; struct Bitmap bmp;
|
||||
Stream_ReadonlyMemory(&mem, item.ResultData, item.ResultSize, &url);
|
||||
|
||||
ReturnCode result = Bitmap_DecodePng(&bmp, &mem);
|
||||
ErrorHandler_CheckOrFail(result, "Decoding player skin");
|
||||
if (result) {
|
||||
ErrorHandler_LogError_Path(result, "decoding", &url);
|
||||
Mem_Free(&bmp.Scan0);
|
||||
return;
|
||||
}
|
||||
|
||||
Gfx_DeleteTexture(&entity->TextureId);
|
||||
Player_SetSkinAll(player, true);
|
||||
|
@ -30,6 +30,10 @@ void ErrorHandler_LogError(ReturnCode result, const UChar* place) {
|
||||
ErrorHandler_Log4("&cError %y when %c", &result, place, NULL, NULL);
|
||||
}
|
||||
|
||||
void ErrorHandler_LogError_Path(ReturnCode result, const UChar* place, STRING_PURE String* path) {
|
||||
ErrorHandler_Log4("&cError %y when %c '%s'", &result, place, path, NULL);
|
||||
}
|
||||
|
||||
void ErrorHandler_FailWithCode(ReturnCode result, const UChar* raw_msg) {
|
||||
UChar logMsgBuffer[String_BufferSize(3071)];
|
||||
String logMsg = String_InitAndClearArray(logMsgBuffer);
|
||||
|
@ -13,11 +13,11 @@ void ErrorHandler_Log2(const UChar* format, const void* a1, const void* a2);
|
||||
void ErrorHandler_Log3(const UChar* format, const void* a1, const void* a2, const void* a3);
|
||||
void ErrorHandler_Log4(const UChar* format, const void* a1, const void* a2, const void* a3, const void* a4);
|
||||
void ErrorHandler_LogError(ReturnCode result, const UChar* place);
|
||||
void ErrorHandler_LogError_Path(ReturnCode result, const UChar* place, STRING_PURE String* path);
|
||||
|
||||
#define ErrorHandler_Check(returnCode) ((returnCode) == 0)
|
||||
void ErrorHandler_Fail(const UChar* raw_msg);
|
||||
void ErrorHandler_FailWithCode(ReturnCode returnCode, const UChar* raw_msg);
|
||||
#define ErrorHandler_CheckOrFail(returnCode, raw_msg) if (returnCode != 0) { ErrorHandler_FailWithCode(returnCode, raw_msg); }
|
||||
#define ErrorHandler_CheckOrFail(returnCode, raw_msg) if (returnCode) { ErrorHandler_FailWithCode(returnCode, raw_msg); }
|
||||
void ErrorHandler_ShowDialog(const UChar* title, const UChar* msg);
|
||||
void ErrorHandler_Backtrace(STRING_TRANSIENT String* str);
|
||||
#endif
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
static ReturnCode Map_ReadBlocks(struct Stream* stream) {
|
||||
World_BlocksSize = World_Width * World_Length * World_Height;
|
||||
World_Blocks = Mem_Alloc(World_BlocksSize, sizeof(BlockID), "map blocks for load");
|
||||
World_Blocks = Mem_Alloc(World_BlocksSize, sizeof(BlockID), "map blocks");
|
||||
return Stream_TryRead(stream, World_Blocks, World_BlocksSize);
|
||||
}
|
||||
|
||||
|
@ -207,9 +207,9 @@ bool Game_CanPick(BlockID block) {
|
||||
bool Game_UpdateTexture(GfxResourceID* texId, struct Stream* src, UInt8* skinType) {
|
||||
struct Bitmap bmp;
|
||||
ReturnCode result = Bitmap_DecodePng(&bmp, src);
|
||||
ErrorHandler_CheckOrFail(result, "Decoding texture");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "decoding", &src->Name); }
|
||||
|
||||
bool success = Game_ValidateBitmap(&src->Name, &bmp);
|
||||
bool success = !result && Game_ValidateBitmap(&src->Name, &bmp);
|
||||
if (success) {
|
||||
Gfx_DeleteTexture(texId);
|
||||
if (skinType != NULL) { *skinType = Utils_GetSkinType(&bmp); }
|
||||
@ -293,19 +293,27 @@ static void Game_OnNewMapLoadedCore(void* obj) {
|
||||
}
|
||||
|
||||
static void Game_TextureChangedCore(void* obj, struct Stream* src) {
|
||||
if (String_CaselessEqualsConst(&src->Name, "terrain.png")) {
|
||||
struct Bitmap atlas;
|
||||
ReturnCode result = Bitmap_DecodePng(&atlas, src);
|
||||
ErrorHandler_CheckOrFail(result, "Decoding terrain bitmap");
|
||||
|
||||
if (Game_ChangeTerrainAtlas(&atlas)) return;
|
||||
Mem_Free(&atlas.Scan0);
|
||||
} else if (String_CaselessEqualsConst(&src->Name, "default.png")) {
|
||||
struct Bitmap bmp;
|
||||
String* name = &src->Name;
|
||||
struct Bitmap bmp;
|
||||
if (String_CaselessEqualsConst(name, "terrain.png")) {
|
||||
ReturnCode result = Bitmap_DecodePng(&bmp, src);
|
||||
ErrorHandler_CheckOrFail(result, "Decoding font bitmap");
|
||||
Drawer2D_SetFontBitmap(&bmp);
|
||||
Event_RaiseVoid(&ChatEvents_FontChanged);
|
||||
|
||||
if (result) {
|
||||
ErrorHandler_LogError_Path(result, "decoding", name);
|
||||
Mem_Free(&bmp.Scan0);
|
||||
} else if (!Game_ChangeTerrainAtlas(&bmp)) {
|
||||
Mem_Free(&bmp.Scan0);
|
||||
}
|
||||
} else if (String_CaselessEqualsConst(name, "default.png")) {
|
||||
ReturnCode result = Bitmap_DecodePng(&bmp, src);
|
||||
|
||||
if (result) {
|
||||
ErrorHandler_LogError_Path(result, "decoding", name);
|
||||
Mem_Free(&bmp.Scan0);
|
||||
} else {
|
||||
Drawer2D_SetFontBitmap(&bmp);
|
||||
Event_RaiseVoid(&ChatEvents_FontChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -616,11 +624,9 @@ static void Game_DoScheduledTasks(Real64 time) {
|
||||
}
|
||||
|
||||
void Game_TakeScreenshot(void) {
|
||||
String dir = String_FromConst("screenshots");
|
||||
if (!Directory_Exists(&dir)) {
|
||||
ReturnCode result = Directory_Create(&dir);
|
||||
ErrorHandler_CheckOrFail(result, "Creating screenshots directory");
|
||||
}
|
||||
ReturnCode result;
|
||||
Game_ScreenshotRequested = false;
|
||||
if (!Utils_EnsureDirectory("screenshots")) return;
|
||||
|
||||
DateTime now; DateTime_CurrentLocal(&now);
|
||||
Int32 year = now.Year, month = now.Month, day = now.Day;
|
||||
@ -635,16 +641,20 @@ void Game_TakeScreenshot(void) {
|
||||
String path = String_InitAndClearArray(pathBuffer);
|
||||
String_Format2(&path, "screenshots%r%s", &Directory_Separator, &filename);
|
||||
|
||||
void* file; ReturnCode result = File_Create(&file, &path);
|
||||
ErrorHandler_CheckOrFail(result, "Taking screenshot - opening file");
|
||||
void* file; result = File_Create(&file, &path);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "creating", &path); return; }
|
||||
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
{
|
||||
Gfx_TakeScreenshot(&stream, Game_Width, Game_Height);
|
||||
result = Gfx_TakeScreenshot(&stream, Game_Width, Game_Height);
|
||||
if (result) {
|
||||
ErrorHandler_LogError(result, "saving screenshot");
|
||||
stream.Close(&stream); return;
|
||||
}
|
||||
}
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "Taking screenshot - closing file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing", &path); return; }
|
||||
|
||||
Game_ScreenshotRequested = false;
|
||||
String_Clear(&path);
|
||||
String_Format1(&path, "&eTaken screenshot as: %s", &filename);
|
||||
Chat_Add(&path);
|
||||
|
@ -96,7 +96,7 @@ void Gfx_CalcOrthoMatrix(Real32 width, Real32 height, struct Matrix* matrix);
|
||||
void Gfx_CalcPerspectiveMatrix(Real32 fov, Real32 aspect, Real32 zNear, Real32 zFar, struct Matrix* matrix);
|
||||
|
||||
/* Outputs a .png screenshot of the backbuffer */
|
||||
void Gfx_TakeScreenshot(struct Stream* output, Int32 width, Int32 height);
|
||||
ReturnCode Gfx_TakeScreenshot(struct Stream* output, Int32 width, Int32 height);
|
||||
/* Adds a warning to game's chat if this graphics API has problems with the current user's GPU.
|
||||
Returns boolean of whether legacy rendering mode is needed. */
|
||||
bool Gfx_WarnIfNecessary(void);
|
||||
|
@ -156,7 +156,7 @@ void Gui_RefreshHud(void) { Elem_Recreate(Gui_HUD); }
|
||||
|
||||
void Gui_ShowOverlay(struct Screen* overlay, bool atFront) {
|
||||
if (Gui_OverlaysCount == GUI_MAX_OVERLAYS) {
|
||||
ErrorHandler_Fail("Cannot have more than 6 overlays");
|
||||
ErrorHandler_Fail("Gui_ShowOverlay - hit max count");
|
||||
}
|
||||
|
||||
if (atFront) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "Utils.h"
|
||||
#include "ErrorHandler.h"
|
||||
#include "Platform.h"
|
||||
#include "Chat.h"
|
||||
|
||||
#define Key_Function_Names \
|
||||
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10",\
|
||||
@ -223,7 +224,8 @@ void Hotkeys_AddNewHotkey(Key trigger, UInt8 flags, STRING_PURE String* text, bo
|
||||
hKey.StaysOpen = more;
|
||||
|
||||
if (HotkeysText.Count == HOTKEYS_MAX_COUNT) {
|
||||
ErrorHandler_Fail("Cannot define more than 256 hotkeys");
|
||||
Chat_AddRaw("&cCannot define more than 256 hotkeys");
|
||||
return;
|
||||
}
|
||||
|
||||
HotkeysList[HotkeysText.Count] = hKey;
|
||||
|
@ -1336,9 +1336,10 @@ static void SaveLevelScreen_Render(struct GuiElem* elem, Real64 delta) {
|
||||
struct SaveLevelScreen* screen = (struct SaveLevelScreen*)elem;
|
||||
if (!screen->TextPath.length) return;
|
||||
String path = screen->TextPath;
|
||||
ReturnCode result;
|
||||
|
||||
void* file; ReturnCode result = File_Create(&file, &path);
|
||||
ErrorHandler_CheckOrFail(result, "Saving map - opening file");
|
||||
void* file; result = File_Create(&file, &path);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "creating", &path); return; }
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
{
|
||||
String cw = String_FromConst(".cw");
|
||||
@ -1349,7 +1350,7 @@ static void SaveLevelScreen_Render(struct GuiElem* elem, Real64 delta) {
|
||||
}
|
||||
}
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "Saving map - closing file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing", &path); return; }
|
||||
|
||||
UChar msgBuffer[String_BufferSize(STRING_SIZE * 2)];
|
||||
String msg = String_InitAndClearArray(msgBuffer);
|
||||
@ -1619,7 +1620,7 @@ void LoadLevelScreen_LoadMap(STRING_PURE String* path) {
|
||||
Inventory_SetDefaultMapping();
|
||||
|
||||
void* file; ReturnCode result = File_Open(&file, path);
|
||||
ErrorHandler_CheckOrFail(result, "Loading map - open file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "opening", path); return; }
|
||||
struct Stream stream; Stream_FromFile(&stream, file, path);
|
||||
{
|
||||
String cw = String_FromConst(".cw"); String lvl = String_FromConst(".lvl");
|
||||
@ -1634,10 +1635,15 @@ void LoadLevelScreen_LoadMap(STRING_PURE String* path) {
|
||||
} else if (String_CaselessEnds(path, &lvl)) {
|
||||
result = Lvl_Load(&stream);
|
||||
}
|
||||
ErrorHandler_CheckOrFail(result, "Loading map - reading data");
|
||||
|
||||
if (result) {
|
||||
ErrorHandler_LogError_Path(result, "decoding", path);
|
||||
Mem_Free(&World_Blocks); World_BlocksSize = 0;
|
||||
stream.Close(&stream); return;
|
||||
}
|
||||
}
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "Loading map - close file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing", path); }
|
||||
|
||||
World_SetNewMap(World_Blocks, World_BlocksSize, World_Width, World_Height, World_Length);
|
||||
Event_RaiseVoid(&WorldEvents_MapLoaded);
|
||||
|
@ -516,7 +516,7 @@ void Gfx_CalcPerspectiveMatrix(Real32 fov, Real32 aspect, Real32 zNear, Real32 z
|
||||
}
|
||||
|
||||
|
||||
void Gfx_TakeScreenshot(struct Stream* output, Int32 width, Int32 height) {
|
||||
ReturnCode Gfx_TakeScreenshot(struct Stream* output, Int32 width, Int32 height) {
|
||||
struct Bitmap bmp; Bitmap_Allocate(&bmp, width, height);
|
||||
glReadPixels(0, 0, width, height, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bmp.Scan0);
|
||||
UInt8 tmp[PNG_MAX_DIMS * BITMAP_SIZEOF_PIXEL];
|
||||
@ -536,9 +536,9 @@ void Gfx_TakeScreenshot(struct Stream* output, Int32 width, Int32 height) {
|
||||
}*/
|
||||
}
|
||||
|
||||
ReturnCode hresult = Bitmap_EncodePng(&bmp, output);
|
||||
ErrorHandler_CheckOrFail(hresult, "Gfx_TakeScreenshot - Writing .png");
|
||||
ReturnCode result = Bitmap_EncodePng(&bmp, output);
|
||||
Mem_Free(&bmp.Scan0);
|
||||
return result;
|
||||
}
|
||||
|
||||
void Gfx_MakeApiInfo(void) {
|
||||
|
@ -158,15 +158,11 @@ void Options_Set(const UChar* keyRaw, STRING_PURE String* value) {
|
||||
|
||||
void Options_Load(void) {
|
||||
String path = String_FromConst("options.txt");
|
||||
void* file; ReturnCode result = File_Open(&file, &path);
|
||||
ReturnCode result;
|
||||
|
||||
void* file; result = File_Open(&file, &path);
|
||||
if (result == ReturnCode_FileNotFound) return;
|
||||
/* TODO: Should we just log failure to open? */
|
||||
ErrorHandler_CheckOrFail(result, "Options - Loading");
|
||||
|
||||
UChar lineBuffer[String_BufferSize(768)];
|
||||
String line = String_InitAndClearArray(lineBuffer);
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "opening", &path); return; }
|
||||
|
||||
/* Remove all the unchanged options */
|
||||
UInt32 i;
|
||||
@ -176,6 +172,10 @@ void Options_Load(void) {
|
||||
Options_Remove(i - 1);
|
||||
}
|
||||
|
||||
UChar lineBuffer[String_BufferSize(768)];
|
||||
String line = String_InitAndClearArray(lineBuffer);
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
|
||||
/* ReadLine reads single byte at a time */
|
||||
UInt8 buffer[2048]; struct Stream buffered;
|
||||
Stream_ReadonlyBuffered(&buffered, &stream, buffer, sizeof(buffer));
|
||||
@ -197,15 +197,15 @@ void Options_Load(void) {
|
||||
}
|
||||
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "Options load - close file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing", &path); return; }
|
||||
}
|
||||
|
||||
void Options_Save(void) {
|
||||
String path = String_FromConst("options.txt");
|
||||
void* file; ReturnCode result = File_Create(&file, &path);
|
||||
ReturnCode result;
|
||||
|
||||
/* TODO: Should we just log failure to save? */
|
||||
ErrorHandler_CheckOrFail(result, "Options - Saving");
|
||||
void* file; result = File_Create(&file, &path);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "creating", &path); return; }
|
||||
|
||||
UChar lineBuffer[String_BufferSize(1024)];
|
||||
String line = String_InitAndClearArray(lineBuffer);
|
||||
@ -221,7 +221,7 @@ void Options_Save(void) {
|
||||
String_Clear(&line);
|
||||
}
|
||||
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "Options save - close file");
|
||||
StringsBuffer_Free(&Options_Changed);
|
||||
result = stream.Close(&stream);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing", &path); return; }
|
||||
}
|
||||
|
@ -11,8 +11,8 @@
|
||||
#include "Game.h"
|
||||
#include "Funcs.h"
|
||||
#include "AsyncDownloader.h"
|
||||
#include "Audio.h"
|
||||
#include "ExtMath.h"
|
||||
#include "Utils.h"
|
||||
|
||||
//#define CC_TEST_VORBIS
|
||||
#ifdef CC_TEST_VORBIS
|
||||
@ -61,23 +61,9 @@ int main(void) {
|
||||
ReturnCode ret2 = Http_FreeRequest(reqHandle);
|
||||
ReturnCode ret3 = Http_Free();*/
|
||||
|
||||
String maps = String_FromConst("maps");
|
||||
if (!Directory_Exists(&maps)) {
|
||||
ReturnCode result = Directory_Create(&maps);
|
||||
ErrorHandler_CheckOrFail(result, "Program - creating maps directory");
|
||||
}
|
||||
|
||||
String texPacks = String_FromConst("texpacks");
|
||||
if (!Directory_Exists(&texPacks)) {
|
||||
ReturnCode result = Directory_Create(&texPacks);
|
||||
ErrorHandler_CheckOrFail(result, "Program - creating texpacks directory");
|
||||
}
|
||||
|
||||
String texCache = String_FromConst("texturecache");
|
||||
if (!Directory_Exists(&texCache)) {
|
||||
ReturnCode result = Directory_Create(&texCache);
|
||||
ErrorHandler_CheckOrFail(result, "Program - creating texturecache directory");
|
||||
}
|
||||
Utils_EnsureDirectory("maps");
|
||||
Utils_EnsureDirectory("texpacks");
|
||||
Utils_EnsureDirectory("texturecache");
|
||||
|
||||
UChar defPathBuffer[String_BufferSize(STRING_SIZE)];
|
||||
String defPath = String_InitAndClearArray(defPathBuffer);
|
||||
|
@ -9,7 +9,7 @@
|
||||
*#########################################################################################################################*/
|
||||
#define Stream_SafeWriteBlock(stream, buffer, count, write)\
|
||||
ReturnCode result = stream->Write(stream, buffer, count, &write);\
|
||||
if (!write || !ErrorHandler_Check(result)) {\
|
||||
if (!write || result) {\
|
||||
Stream_Fail(stream, result, "writing to");\
|
||||
}
|
||||
|
||||
@ -24,7 +24,7 @@ void Stream_Read(struct Stream* stream, UInt8* buffer, UInt32 count) {
|
||||
UInt32 read;
|
||||
while (count) {
|
||||
ReturnCode result = stream->Read(stream, buffer, count, &read);
|
||||
if (!read || !ErrorHandler_Check(result)) { Stream_Fail(stream, result, "reading from"); }
|
||||
if (!read || result) { Stream_Fail(stream, result, "reading from"); }
|
||||
|
||||
buffer += read;
|
||||
count -= read;
|
||||
@ -123,9 +123,9 @@ static ReturnCode Stream_FileWrite(struct Stream* stream, UInt8* data, UInt32 co
|
||||
return File_Write(stream->Meta.File, data, count, modified);
|
||||
}
|
||||
static ReturnCode Stream_FileClose(struct Stream* stream) {
|
||||
ReturnCode code = File_Close(stream->Meta.File);
|
||||
ReturnCode result = File_Close(stream->Meta.File);
|
||||
stream->Meta.File = NULL;
|
||||
return code;
|
||||
return result;
|
||||
}
|
||||
static ReturnCode Stream_FileSeek(struct Stream* stream, Int32 offset, Int32 seekType) {
|
||||
return File_Seek(stream->Meta.File, offset, seekType);
|
||||
@ -422,7 +422,7 @@ bool Stream_ReadLine(struct Stream* stream, STRING_TRANSIENT String* text) {
|
||||
ReturnCode result = Stream_ReadUtf8Char(stream, &codepoint);
|
||||
if (result == ERR_END_OF_STREAM) break;
|
||||
|
||||
if (!ErrorHandler_Check(result)) { Stream_Fail(stream, result, "reading utf8 from"); }
|
||||
if (result) { Stream_Fail(stream, result, "reading utf8 from"); }
|
||||
readAny = true;
|
||||
|
||||
/* Handle \r\n or \n line endings */
|
||||
|
@ -189,13 +189,14 @@ static void EntryList_Load(struct EntryList* list) {
|
||||
String folder = String_FromRawArray(list->FolderBuffer);
|
||||
String filename = String_FromRawArray(list->FileBuffer);
|
||||
UChar pathBuffer[String_BufferSize(FILENAME_SIZE)];
|
||||
|
||||
String path = String_InitAndClearArray(pathBuffer);
|
||||
String_Format3(&path, "%s%r%s", &folder, &Directory_Separator, &filename);
|
||||
ReturnCode result;
|
||||
|
||||
void* file; ReturnCode result = File_Open(&file, &path);
|
||||
void* file; result = File_Open(&file, &path);
|
||||
if (result == ReturnCode_FileNotFound) return;
|
||||
/* TODO: Should we just log failure to save? */
|
||||
ErrorHandler_CheckOrFail(result, "EntryList_Load - open file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "opening", &path); return; }
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
{
|
||||
/* ReadLine reads single byte at a time */
|
||||
@ -211,24 +212,25 @@ static void EntryList_Load(struct EntryList* list) {
|
||||
}
|
||||
}
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "EntryList_Load - close file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing", &path); }
|
||||
}
|
||||
|
||||
static void EntryList_Save(struct EntryList* list) {
|
||||
String folder = String_FromRawArray(list->FolderBuffer);
|
||||
String filename = String_FromRawArray(list->FileBuffer);
|
||||
UChar pathBuffer[String_BufferSize(FILENAME_SIZE)];
|
||||
|
||||
String path = String_InitAndClearArray(pathBuffer);
|
||||
String_Format3(&path, "%s%r%s", &folder, &Directory_Separator, &filename);
|
||||
ReturnCode result;
|
||||
|
||||
if (!Directory_Exists(&folder)) {
|
||||
ReturnCode dirResult = Directory_Create(&folder);
|
||||
ErrorHandler_CheckOrFail(dirResult, "EntryList_Save - create directory");
|
||||
result = Directory_Create(&folder);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "creating", &folder); return; }
|
||||
}
|
||||
|
||||
void* file; ReturnCode result = File_Create(&file, &path);
|
||||
/* TODO: Should we just log failure to save? */
|
||||
ErrorHandler_CheckOrFail(result, "EntryList_Save - open file");
|
||||
void* file; result = File_Create(&file, &path);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "creating", &path); return; }
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
{
|
||||
Int32 i;
|
||||
@ -238,7 +240,7 @@ static void EntryList_Save(struct EntryList* list) {
|
||||
}
|
||||
}
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "EntryList_Save - close file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing", &path); }
|
||||
}
|
||||
|
||||
static void EntryList_Add(struct EntryList* list, STRING_PURE String* entry) {
|
||||
@ -312,7 +314,7 @@ bool TextureCache_GetStream(STRING_PURE String* url, struct Stream* stream) {
|
||||
void* file; ReturnCode result = File_Open(&file, &path);
|
||||
if (result == ReturnCode_FileNotFound) return false;
|
||||
|
||||
ErrorHandler_CheckOrFail(result, "TextureCache - GetStream");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "opening cache for", url); return false; }
|
||||
Stream_FromFile(stream, file, &path);
|
||||
return true;
|
||||
}
|
||||
@ -338,12 +340,16 @@ void TextureCache_GetLastModified(STRING_PURE String* url, DateTime* time) {
|
||||
TexturePack_GetFromTags(url, &entry, &cache_lastModified);
|
||||
|
||||
Int64 ticks;
|
||||
DateTime temp;
|
||||
|
||||
if (entry.length && Convert_TryParseInt64(&entry, &ticks)) {
|
||||
DateTime_FromTotalMs(time, ticks / TEXCACHE_TICKS_PER_MS);
|
||||
} else {
|
||||
String path; TexCache_InitAndMakePath(url);
|
||||
ReturnCode result = File_GetModifiedTime(&path, time);
|
||||
ErrorHandler_CheckOrFail(result, "TextureCache - get file last modified time")
|
||||
ReturnCode result = File_GetModifiedTime(&path, &temp);
|
||||
|
||||
if (result) { ErrorHandler_LogError_Path(result, "getting last modified time of", url); return; }
|
||||
*time = temp;
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,22 +360,17 @@ void TextureCache_GetETag(STRING_PURE String* url, STRING_PURE String* etag) {
|
||||
void TextureCache_AddData(STRING_PURE String* url, UInt8* data, UInt32 length) {
|
||||
String path; TexCache_InitAndMakePath(url);
|
||||
ReturnCode result;
|
||||
|
||||
String folder = String_FromConst(TEXCACHE_FOLDER);
|
||||
if (!Directory_Exists(&folder)) {
|
||||
result = Directory_Create(&folder);
|
||||
ErrorHandler_CheckOrFail(result, "TextureCache_AddData - create directory");
|
||||
}
|
||||
if (!Utils_EnsureDirectory(TEXCACHE_FOLDER)) return;
|
||||
|
||||
void* file; result = File_Create(&file, &path);
|
||||
/* TODO: Should we just log failure to save? */
|
||||
ErrorHandler_CheckOrFail(result, "TextureCache_AddData - open file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "creating cache for", url); return; }
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
{
|
||||
Stream_Write(&stream, data, length);
|
||||
result = Stream_TryWrite(&stream, data, length);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "saving data for", url); }
|
||||
}
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "TextureCache_AddData - close file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing cache for", url); }
|
||||
}
|
||||
|
||||
void TextureCache_AddToTags(STRING_PURE String* url, STRING_PURE String* data, struct EntryList* list) {
|
||||
@ -429,23 +430,24 @@ void TexturePack_ExtractZip_File(STRING_PURE String* filename) {
|
||||
UChar pathBuffer[String_BufferSize(FILENAME_SIZE)];
|
||||
String path = String_InitAndClearArray(pathBuffer);
|
||||
String_Format2(&path, "texpacks%r%s", &Directory_Separator, filename);
|
||||
ReturnCode result;
|
||||
|
||||
void* file; ReturnCode result = File_Open(&file, &path);
|
||||
ErrorHandler_CheckOrFail(result, "TexturePack_Extract - opening file");
|
||||
void* file; result = File_Open(&file, &path);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "opening", &path); return; }
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
{
|
||||
result = TexturePack_ExtractZip(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "TexturePack_Extract - extract content");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "extracting", &path); }
|
||||
}
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "TexturePack_Extract - closing file");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing", &path); }
|
||||
}
|
||||
|
||||
ReturnCode TexturePack_ExtractTerrainPng(struct Stream* stream) {
|
||||
struct Bitmap bmp;
|
||||
ReturnCode result = Bitmap_DecodePng(&bmp, stream);
|
||||
|
||||
if (result == 0) {
|
||||
if (!result) {
|
||||
Event_RaiseVoid(&TextureEvents_PackChanged);
|
||||
if (Game_ChangeTerrainAtlas(&bmp)) return 0;
|
||||
}
|
||||
@ -475,17 +477,18 @@ void TexturePack_ExtractCurrent(STRING_PURE String* url) {
|
||||
ReturnCode result = 0;
|
||||
|
||||
if (String_Equals(url, &World_TextureUrl)) {
|
||||
} else if (String_ContainsString(url, &zip)) {
|
||||
String_Set(&World_TextureUrl, url);
|
||||
result = TexturePack_ExtractZip(&stream);
|
||||
} else {
|
||||
bool zip = String_ContainsString(url, &zip);
|
||||
String_Set(&World_TextureUrl, url);
|
||||
result = TexturePack_ExtractTerrainPng(&stream);
|
||||
const UChar* operation = zip ? "extracting" : "decoding";
|
||||
|
||||
ReturnCode result = zip ? TexturePack_ExtractZip(&stream) :
|
||||
TexturePack_ExtractTerrainPng(&stream);
|
||||
if (result) { ErrorHandler_LogError_Path(result, operation, &url); }
|
||||
}
|
||||
ErrorHandler_CheckOrFail(result, "TexturePack_ExtractCurrent - extract content");
|
||||
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "TexturePack_ExtractCurrent - close stream");
|
||||
if (result) { ErrorHandler_LogError_Path(result, "closing cache for", url); }
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,13 +506,10 @@ void TexturePack_Extract_Req(struct AsyncRequest* item) {
|
||||
String id = String_FromRawArray(item->ID);
|
||||
struct Stream mem; Stream_ReadonlyMemory(&mem, data, len, &id);
|
||||
|
||||
ReturnCode result;
|
||||
if (Bitmap_DetectPng(data, len)) {
|
||||
result = TexturePack_ExtractTerrainPng(&mem);
|
||||
} else {
|
||||
result = TexturePack_ExtractZip(&mem);
|
||||
}
|
||||
bool png = Bitmap_DetectPng(data, len);
|
||||
ReturnCode result = png ? TexturePack_ExtractTerrainPng(&mem) : TexturePack_ExtractZip(&mem);
|
||||
const UChar* operation = png ? "decoding" : "extracting";
|
||||
|
||||
ErrorHandler_CheckOrFail(result, "TexturePack_Extract_Req - extract content");
|
||||
if (result) { ErrorHandler_LogError_Path(result, operation, &url); }
|
||||
ASyncRequest_Free(item);
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
#include "Constants.h"
|
||||
#include "Bitmap.h"
|
||||
#include "PackedCol.h"
|
||||
#include "ErrorHandler.h"
|
||||
#include "Platform.h"
|
||||
|
||||
#define DATETIME_SECONDS_PER_MINUTE 60
|
||||
#define DATETIME_SECONDS_PER_HOUR (60 * 60)
|
||||
@ -119,6 +121,15 @@ bool Utils_IsUrlPrefix(STRING_PURE String* value, Int32 index) {
|
||||
|| String_IndexOfString(value, &https) == index;
|
||||
}
|
||||
|
||||
bool Utils_EnsureDirectory(STRING_PURE const UChar* dirName) {
|
||||
String dir = String_FromReadonly(dirName);
|
||||
if (Directory_Exists(&dir)) return true;
|
||||
|
||||
ReturnCode result = Directory_Create(&dir);
|
||||
if (result) { ErrorHandler_LogError_Path(result, "creating directory", &dir); }
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
void Utils_UNSAFE_GetFilename(STRING_TRANSIENT String* str) {
|
||||
Int32 i;
|
||||
for (i = str->length - 1; i >= 0; i--) {
|
||||
|
@ -27,6 +27,7 @@ UInt32 Utils_ParseEnum(STRING_PURE String* text, UInt32 defValue, const UChar**
|
||||
bool Utils_IsValidInputChar(UChar c, bool supportsCP437);
|
||||
bool Utils_IsUrlPrefix(STRING_PURE String* value, Int32 index);
|
||||
|
||||
bool Utils_EnsureDirectory(STRING_PURE const UChar* dirName);
|
||||
void Utils_UNSAFE_GetFilename(STRING_TRANSIENT String* str);
|
||||
Int32 Utils_AccumulateWheelDelta(Real32* accmulator, Real32 delta);
|
||||
#define Utils_AdjViewDist(value) ((Int32)(1.4142135f * (value)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user