mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 19:45:23 -04:00
fix terrain.png in C client being cached discarding alpha channel
This commit is contained in:
parent
0086f047f8
commit
d60472be45
@ -6,17 +6,7 @@
|
||||
#include "GameStructs.h"
|
||||
|
||||
void ASyncRequest_Free(struct 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;
|
||||
}
|
||||
Platform_MemFree(&request->ResultData);
|
||||
}
|
||||
|
||||
#define ASYNCREQUESTLIST_DEFELEMS 10
|
||||
@ -127,37 +117,25 @@ void AsyncDownloader_GetSkin(STRING_PURE String* id, STRING_PURE String* skinNam
|
||||
String_AppendConst(&url, ".png");
|
||||
}
|
||||
|
||||
AsyncDownloader_Add(&url, false, id, REQUEST_TYPE_IMAGE, NULL, NULL, NULL);
|
||||
AsyncDownloader_Add(&url, false, id, REQUEST_TYPE_DATA, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetData(STRING_PURE String* url, bool priority, STRING_PURE String* id) {
|
||||
AsyncDownloader_Add(url, priority, id, REQUEST_TYPE_DATA, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetImage(STRING_PURE String* url, bool priority, STRING_PURE String* id) {
|
||||
AsyncDownloader_Add(url, priority, id, REQUEST_TYPE_IMAGE, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetString(STRING_PURE String* url, bool priority, STRING_PURE String* id) {
|
||||
AsyncDownloader_Add(url, priority, id, REQUEST_TYPE_STRING, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetContentLength(STRING_PURE String* url, bool priority, STRING_PURE String* id) {
|
||||
AsyncDownloader_Add(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) {
|
||||
AsyncDownloader_Add(url, priority, id, REQUEST_TYPE_STRING, NULL, NULL, contents);
|
||||
AsyncDownloader_Add(url, priority, id, REQUEST_TYPE_DATA, NULL, NULL, contents);
|
||||
}
|
||||
|
||||
void AsyncDownloader_GetDataEx(STRING_PURE String* url, bool priority, STRING_PURE String* id, DateTime* lastModified, STRING_PURE String* etag) {
|
||||
AsyncDownloader_Add(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) {
|
||||
AsyncDownloader_Add(url, priority, id, REQUEST_TYPE_IMAGE, lastModified, etag, NULL);
|
||||
}
|
||||
|
||||
void AsyncDownloader_PurgeOldEntriesTask(struct ScheduledTask* task) {
|
||||
Platform_MutexLock(async_processedMutex);
|
||||
{
|
||||
@ -247,27 +225,8 @@ static void AsyncDownloader_ProcessRequest(struct AsyncRequest* request) {
|
||||
|
||||
UInt64 addr = (UInt64)data;
|
||||
Platform_Log2("OK I got the DATA! %i bytes at %x", &size, &addr);
|
||||
|
||||
struct Stream memStream;
|
||||
switch (request->RequestType) {
|
||||
case REQUEST_TYPE_DATA:
|
||||
request->ResultData.Ptr = data;
|
||||
request->ResultData.Size = size;
|
||||
break;
|
||||
|
||||
case REQUEST_TYPE_IMAGE:
|
||||
Stream_ReadonlyMemory(&memStream, data, size, &url);
|
||||
Bitmap_DecodePng(&request->ResultBitmap, &memStream);
|
||||
break;
|
||||
|
||||
case REQUEST_TYPE_STRING:
|
||||
request->ResultString = String_Init(data, size, size);
|
||||
break;
|
||||
|
||||
case REQUEST_TYPE_CONTENT_LENGTH:
|
||||
request->ResultContentLength = size;
|
||||
break;
|
||||
}
|
||||
request->ResultData = data;
|
||||
request->ResultSize = size;
|
||||
}
|
||||
|
||||
static void AsyncDownloader_CompleteResult(struct AsyncRequest* request) {
|
||||
|
@ -9,10 +9,7 @@
|
||||
struct IGameComponent;
|
||||
struct ScheduledTask;
|
||||
|
||||
enum REQUEST_TYPE {
|
||||
REQUEST_TYPE_DATA, REQUEST_TYPE_IMAGE,
|
||||
REQUEST_TYPE_STRING, REQUEST_TYPE_CONTENT_LENGTH,
|
||||
};
|
||||
enum REQUEST_TYPE { REQUEST_TYPE_DATA, REQUEST_TYPE_CONTENT_LENGTH };
|
||||
#define ASYNC_PROGRESS_NOTHING -3
|
||||
#define ASYNC_PROGRESS_MAKING_REQUEST -2
|
||||
#define ASYNC_PROGRESS_FETCHING_DATA -1
|
||||
@ -25,12 +22,8 @@ struct AsyncRequest {
|
||||
DateTime TimeDownloaded;
|
||||
UInt16 StatusCode;
|
||||
|
||||
union {
|
||||
struct { void* Ptr; UInt32 Size; } ResultData;
|
||||
struct Bitmap ResultBitmap;
|
||||
String ResultString;
|
||||
UInt32 ResultContentLength;
|
||||
};
|
||||
void* ResultData;
|
||||
UInt32 ResultSize;
|
||||
|
||||
DateTime LastModified; /* Time item cached at (if at all) */
|
||||
UInt8 Etag[String_BufferSize(STRING_SIZE)]; /* ETag of cached item (if any) */
|
||||
@ -42,13 +35,10 @@ void ASyncRequest_Free(struct AsyncRequest* request);
|
||||
void AsyncDownloader_MakeComponent(struct IGameComponent* comp);
|
||||
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);
|
||||
/* TODO: Implement post */
|
||||
//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, struct AsyncRequest* item);
|
||||
bool AsyncDownloader_GetCurrent(struct AsyncRequest* request, Int32* progress);
|
||||
|
@ -63,13 +63,20 @@ enum PNG_FILTER {
|
||||
typedef void(*Png_RowExpander)(UInt8 bpp, Int32 width, UInt32* palette, UInt8* src, UInt32* dst);
|
||||
UInt8 png_sig[PNG_SIG_SIZE] = { 137, 80, 78, 71, 13, 10, 26, 10 };
|
||||
|
||||
bool Bitmap_DetectPng(UInt8* data, UInt32 len) {
|
||||
if (len < PNG_SIG_SIZE) return false;
|
||||
Int32 i;
|
||||
|
||||
for (i = 0; i < PNG_SIG_SIZE; i++) {
|
||||
if (data[i] != png_sig[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Png_CheckHeader(struct Stream* stream) {
|
||||
UInt8 header[PNG_SIG_SIZE];
|
||||
Stream_Read(stream, header, PNG_SIG_SIZE);
|
||||
Int32 i;
|
||||
for (i = 0; i < PNG_SIG_SIZE; i++) {
|
||||
if (header[i] != png_sig[i]) ErrorHandler_Fail("Invalid PNG header");
|
||||
}
|
||||
if (!Bitmap_DetectPng(header, PNG_SIG_SIZE)) ErrorHandler_Fail("Invalid PNG header");
|
||||
}
|
||||
|
||||
static void Png_Reconstruct(UInt8 type, UInt8 bytesPerPixel, UInt8* line, UInt8* prior, UInt32 lineLen) {
|
||||
|
@ -25,6 +25,7 @@ void Bitmap_Allocate(struct Bitmap* bmp, Int32 width, Int32 height);
|
||||
/* Allocates a power-of-2 sized bitmap larger or equal to to the given size, and clears it to 0. You are responsible for freeing its memory! */
|
||||
void Bitmap_AllocateClearedPow2(struct Bitmap* bmp, Int32 width, Int32 height);
|
||||
|
||||
bool Bitmap_DetectPng(UInt8* data, UInt32 len);
|
||||
/*
|
||||
Partially based off information from
|
||||
https://handmade.network/forums/wip/t/2363-implementing_a_basic_png_reader_the_handmade_way
|
||||
|
@ -697,8 +697,12 @@ static void Player_CheckSkin(struct Player* player) {
|
||||
|
||||
struct AsyncRequest item;
|
||||
if (!AsyncDownloader_Get(&skin, &item)) return;
|
||||
struct Bitmap bmp = item.ResultBitmap;
|
||||
if (bmp.Scan0 == NULL) { Player_SetSkinAll(player, true); return; }
|
||||
if (item.ResultData == NULL) { Player_SetSkinAll(player, true); return; }
|
||||
|
||||
String url = String_FromRawArray(item.URL);
|
||||
struct Stream mem; struct Bitmap bmp;
|
||||
Stream_ReadonlyMemory(&mem, item.ResultData, item.ResultSize, &url);
|
||||
Bitmap_DecodePng(&bmp, &mem);
|
||||
|
||||
Gfx_DeleteTexture(&entity->TextureId);
|
||||
Player_SetSkinAll(player, true);
|
||||
|
@ -3324,7 +3324,7 @@ static void TexPackOverlay_Render(struct GuiElem* elem, Real64 delta) {
|
||||
struct AsyncRequest item;
|
||||
if (!AsyncDownloader_Get(&identifier, &item)) return;
|
||||
|
||||
screen->ContentLength = item.ResultContentLength;
|
||||
screen->ContentLength = item.ResultSize;
|
||||
if (screen->ContentLength == 0) return;
|
||||
|
||||
screen->ContextLost(elem);
|
||||
|
@ -200,7 +200,7 @@ static 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_GetString(&url, true, &wom_identifier);
|
||||
AsyncDownloader_GetData(&url, true, &wom_identifier);
|
||||
wom_sendId = true;
|
||||
}
|
||||
|
||||
@ -288,11 +288,13 @@ static void WoM_Reset(void) {
|
||||
|
||||
static void WoM_Tick(void) {
|
||||
struct AsyncRequest item;
|
||||
bool success = AsyncDownloader_Get(&wom_identifier, &item);
|
||||
if (success && item.ResultString.length > 0) {
|
||||
Wom_ParseConfig(&item.ResultString);
|
||||
ASyncRequest_Free(&item);
|
||||
if (!AsyncDownloader_Get(&wom_identifier, &item)) return;
|
||||
|
||||
if (item.ResultData) {
|
||||
String str = String_Init(item.ResultData, item.ResultSize, item.ResultSize);
|
||||
Wom_ParseConfig(&str);
|
||||
}
|
||||
ASyncRequest_Free(&item);
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,47 +60,27 @@ void ServerConnection_DownloadTexturePack(STRING_PURE String* url) {
|
||||
TextureCache_GetLastModified(url, &lastModified);
|
||||
TextureCache_GetETag(url, &etag);
|
||||
}
|
||||
|
||||
TexturePack_ExtractCurrent(url);
|
||||
|
||||
String zip = String_FromConst(".zip");
|
||||
if (String_ContainsString(url, &zip)) {
|
||||
String texPack = String_FromConst("texturePack");
|
||||
AsyncDownloader_GetDataEx(url, true, &texPack, &lastModified, &etag);
|
||||
} else {
|
||||
String terrain = String_FromConst("terrain");
|
||||
AsyncDownloader_GetImageEx(url, true, &terrain, &lastModified, &etag);
|
||||
}
|
||||
}
|
||||
|
||||
void ServerConnection_LogResourceFail(struct AsyncRequest* item) {
|
||||
Int32 status = item->StatusCode;
|
||||
if (status == 0 || status == 304) return;
|
||||
|
||||
UChar msgBuffer[String_BufferSize(STRING_SIZE)];
|
||||
String msg = String_InitAndClearArray(msgBuffer);
|
||||
String_Format1(&msg, "&c%i error when trying to download texture pack", &status);
|
||||
Chat_Add(&msg);
|
||||
String texPack = String_FromConst("texturePack");
|
||||
AsyncDownloader_GetDataEx(url, true, &texPack, &lastModified, &etag);
|
||||
}
|
||||
|
||||
void ServerConnection_CheckAsyncResources(void) {
|
||||
struct AsyncRequest item;
|
||||
String terrain = String_FromConst("terrain");
|
||||
String texPack = String_FromConst("texturePack");
|
||||
if (!AsyncDownloader_Get(&texPack, &item)) return;
|
||||
|
||||
if (AsyncDownloader_Get(&terrain, &item)) {
|
||||
if (item.ResultBitmap.Scan0 != NULL) {
|
||||
TexturePack_ExtractTerrainPng_Req(&item);
|
||||
} else {
|
||||
ServerConnection_LogResourceFail(&item);
|
||||
}
|
||||
}
|
||||
if (item.ResultData) {
|
||||
TexturePack_Extract_Req(&item);
|
||||
} else {
|
||||
Int32 status = item.StatusCode;
|
||||
if (status == 0 || status == 304) return;
|
||||
|
||||
if (AsyncDownloader_Get(&texPack, &item)) {
|
||||
if (item.ResultData.Ptr != NULL) {
|
||||
TexturePack_ExtractTexturePack_Req(&item);
|
||||
} else {
|
||||
ServerConnection_LogResourceFail(&item);
|
||||
}
|
||||
UChar msgBuffer[String_BufferSize(STRING_SIZE)];
|
||||
String msg = String_InitAndClearArray(msgBuffer);
|
||||
String_Format1(&msg, "&c%i error when trying to download texture pack", &status);
|
||||
Chat_Add(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ ReturnCode Platform_SocketConnect(SocketPtr socket, STRING_PURE String* ip, Int3
|
||||
|
||||
ReturnCode Platform_SocketRead(SocketPtr socket, UInt8* buffer, UInt32 count, UInt32* modified) {
|
||||
Int32 recvCount = recv(socket, buffer, count, 0);
|
||||
if (recvCount == -1) { *modified = recvCount; return 0; }
|
||||
if (recvCount != -1) { *modified = recvCount; return 0; }
|
||||
*modified = 0; return Socket__Error();
|
||||
}
|
||||
|
||||
|
@ -354,39 +354,24 @@ void TextureCache_GetETag(STRING_PURE String* url, STRING_PURE String* etag) {
|
||||
TexturePack_GetFromTags(url, etag, &cache_eTags);
|
||||
}
|
||||
|
||||
static void* TextureCache_CreateFile(STRING_PURE String* path) {
|
||||
String folder = String_FromConst(TEXCACHE_FOLDER);
|
||||
if (!Platform_DirectoryExists(&folder)) {
|
||||
ReturnCode dirResult = Platform_DirectoryCreate(&folder);
|
||||
ErrorHandler_CheckOrFail(dirResult, "TextureCache_CreateFile - create directory");
|
||||
}
|
||||
|
||||
void* file;
|
||||
ReturnCode result = Platform_FileCreate(&file, path);
|
||||
/* TODO: Should we just log failure to save? */
|
||||
ErrorHandler_CheckOrFail(result, "TextureCache_CreateFile - open file");
|
||||
return file;
|
||||
}
|
||||
|
||||
void TextureCache_AddImage(STRING_PURE String* url, struct Bitmap* bmp) {
|
||||
String path; TexCache_InitAndMakePath(url);
|
||||
void* file = TextureCache_CreateFile(&path);
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
{
|
||||
Bitmap_EncodePng(bmp, &stream);
|
||||
}
|
||||
ReturnCode result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "TextureCache_AddImage - close file");
|
||||
}
|
||||
|
||||
void TextureCache_AddData(STRING_PURE String* url, UInt8* data, UInt32 length) {
|
||||
String path; TexCache_InitAndMakePath(url);
|
||||
void* file = TextureCache_CreateFile(&path);
|
||||
ReturnCode result;
|
||||
|
||||
String folder = String_FromConst(TEXCACHE_FOLDER);
|
||||
if (!Platform_DirectoryExists(&folder)) {
|
||||
result = Platform_DirectoryCreate(&folder);
|
||||
ErrorHandler_CheckOrFail(result, "TextureCache_AddData - create directory");
|
||||
}
|
||||
|
||||
void* file; result = Platform_FileCreate(&file, &path);
|
||||
/* TODO: Should we just log failure to save? */
|
||||
ErrorHandler_CheckOrFail(result, "TextureCache_AddData - open file");
|
||||
struct Stream stream; Stream_FromFile(&stream, file, &path);
|
||||
{
|
||||
Stream_Write(&stream, data, length);
|
||||
}
|
||||
ReturnCode result = stream.Close(&stream);
|
||||
result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "TextureCache_AddData - close file");
|
||||
}
|
||||
|
||||
@ -495,29 +480,15 @@ void TexturePack_ExtractCurrent(STRING_PURE String* url) {
|
||||
}
|
||||
|
||||
ReturnCode result = stream.Close(&stream);
|
||||
ErrorHandler_CheckOrFail(result, "TexturePack_ExtractCurrent - slow stream");
|
||||
ErrorHandler_CheckOrFail(result, "TexturePack_ExtractCurrent - close stream");
|
||||
}
|
||||
}
|
||||
|
||||
void TexturePack_ExtractTerrainPng_Req(struct AsyncRequest* item) {
|
||||
void TexturePack_Extract_Req(struct AsyncRequest* item) {
|
||||
String url = String_FromRawArray(item->URL);
|
||||
String_Set(&World_TextureUrl, &url);
|
||||
struct Bitmap bmp = item->ResultBitmap;
|
||||
|
||||
String etag = String_FromRawArray(item->Etag);
|
||||
TextureCache_AddImage(&url, &bmp);
|
||||
TextureCache_AddETag(&url, &etag);
|
||||
TextureCache_AddLastModified(&url, &item->LastModified);
|
||||
|
||||
Event_RaiseVoid(&TextureEvents_PackChanged);
|
||||
if (!Game_ChangeTerrainAtlas(&bmp)) ASyncRequest_Free(item);
|
||||
}
|
||||
|
||||
void TexturePack_ExtractTexturePack_Req(struct AsyncRequest* item) {
|
||||
String url = String_FromRawArray(item->URL);
|
||||
String_Set(&World_TextureUrl, &url);
|
||||
void* data = item->ResultData.Ptr;
|
||||
UInt32 len = item->ResultData.Size;
|
||||
void* data = item->ResultData;
|
||||
UInt32 len = item->ResultSize;
|
||||
|
||||
String etag = String_FromRawArray(item->Etag);
|
||||
TextureCache_AddData(&url, data, len);
|
||||
@ -525,7 +496,14 @@ void TexturePack_ExtractTexturePack_Req(struct AsyncRequest* item) {
|
||||
TextureCache_AddLastModified(&url, &item->LastModified);
|
||||
|
||||
String id = String_FromRawArray(item->ID);
|
||||
struct Stream stream; Stream_ReadonlyMemory(&stream, data, len, &id);
|
||||
TexturePack_ExtractZip(&stream);
|
||||
struct Stream mem; Stream_ReadonlyMemory(&mem, data, len, &id);
|
||||
|
||||
if (Bitmap_DetectPng(data, len)) {
|
||||
struct Bitmap bmp; Bitmap_DecodePng(&bmp, &mem);
|
||||
Event_RaiseVoid(&TextureEvents_PackChanged);
|
||||
if (!Game_ChangeTerrainAtlas(&bmp)) Platform_MemFree(&bmp.Scan0);
|
||||
} else {
|
||||
TexturePack_ExtractZip(&mem);
|
||||
}
|
||||
ASyncRequest_Free(item);
|
||||
}
|
@ -35,7 +35,6 @@ bool TextureCache_HasUrl(STRING_PURE String* url);
|
||||
bool TextureCache_GetStream(STRING_PURE String* url, struct Stream* stream);
|
||||
void TextureCache_GetLastModified(STRING_PURE String* url, DateTime* time);
|
||||
void TextureCache_GetETag(STRING_PURE String* url, STRING_PURE String* etag);
|
||||
void TextureCache_AddImage(STRING_PURE String* url, struct Bitmap* bmp);
|
||||
void TextureCache_AddData(STRING_PURE String* url, UInt8* data, UInt32 length);
|
||||
void TextureCache_AddETag(STRING_PURE String* url, STRING_PURE String* etag);
|
||||
void TextureCache_AddLastModified(STRING_PURE String* url, DateTime* lastModified);
|
||||
@ -43,6 +42,5 @@ void TextureCache_AddLastModified(STRING_PURE String* url, DateTime* lastModifie
|
||||
void TexturePack_ExtractZip_File(STRING_PURE String* filename);
|
||||
void TexturePack_ExtractDefault(void);
|
||||
void TexturePack_ExtractCurrent(STRING_PURE String* url);
|
||||
void TexturePack_ExtractTerrainPng_Req(struct AsyncRequest* item);
|
||||
void TexturePack_ExtractTexturePack_Req(struct AsyncRequest* item);
|
||||
void TexturePack_Extract_Req(struct AsyncRequest* item);
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user