log errors instead of immediately dying in C client

This commit is contained in:
UnknownShadow200 2018-08-15 23:36:14 +10:00
parent 8fc1db2b68
commit 1d6e422c3f
22 changed files with 210 additions and 169 deletions

View File

@ -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")) {

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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,12 +74,15 @@ void Chat_SetLogName(STRING_PURE String* name) {
}
}
static void Chat_OpenLog(DateTime* now) {
String logsDir = String_FromConst("logs");
if (!Directory_Exists(&logsDir)) {
Directory_Create(&logsDir);
static void Chat_DisableLogging(void) {
Game_ChatLogging = false;
Chat_AddRaw("&cDisabling chat logging as a result");
}
static void Chat_OpenLog(DateTime* now) {
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;
for (i = 0; i < 20; i++) {
@ -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) {

View File

@ -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");
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);
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 = 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; }

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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,21 +293,29 @@ 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")) {
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");
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);
}
}
}
static void Game_ExtractInitialTexturePack(void) {
UChar texPackBuffer[String_BufferSize(STRING_SIZE)];
@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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; }
}

View File

@ -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);

View File

@ -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 */

View File

@ -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);
}

View File

@ -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--) {

View File

@ -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)))