mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-18 12:05:14 -04:00
Fix texture packs without content length header not decoding, on windows.
This commit is contained in:
parent
10e0a4ea2e
commit
348ca90306
@ -21,6 +21,7 @@ struct AsyncRequest {
|
||||
|
||||
TimeMS TimeAdded, TimeDownloaded;
|
||||
int StatusCode;
|
||||
uint32_t ContentLength;
|
||||
|
||||
ReturnCode Result;
|
||||
void* ResultData;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "ErrorHandler.h"
|
||||
#include "Stream.h"
|
||||
#include "Errors.h"
|
||||
#include "Utils.h"
|
||||
|
||||
BitmapCol BitmapCol_Scale(BitmapCol value, float t) {
|
||||
value.R = (uint8_t)(value.R * t);
|
||||
|
@ -307,8 +307,7 @@ STRING_REF String Block_UNSAFE_GetName(BlockID block) {
|
||||
}
|
||||
|
||||
void Block_SetName(BlockID block, const String* name) {
|
||||
String dst = { Block_NamePtr(block), 0, STRING_SIZE };
|
||||
Mem_Set(dst.buffer, 0, STRING_SIZE);
|
||||
String dst = String_InitAndClear(Block_NamePtr(block), STRING_SIZE);
|
||||
String_AppendString(&dst, name);
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ static char Chat_LogPathBuffer[FILENAME_SIZE];
|
||||
static String Chat_LogPath = String_FromArray(Chat_LogPathBuffer);
|
||||
|
||||
static struct Stream Chat_LogStream;
|
||||
static DateTime ChatLog_LastLogDate;
|
||||
static struct DateTime ChatLog_LastLogDate;
|
||||
|
||||
static void Chat_CloseLog(void) {
|
||||
ReturnCode res;
|
||||
@ -82,7 +82,7 @@ static void Chat_DisableLogging(void) {
|
||||
Chat_AddRaw("&cDisabling chat logging");
|
||||
}
|
||||
|
||||
static void Chat_OpenLog(DateTime* now) {
|
||||
static void Chat_OpenLog(struct DateTime* now) {
|
||||
void* file;
|
||||
int i;
|
||||
ReturnCode res;
|
||||
@ -119,7 +119,7 @@ static void Chat_OpenLog(DateTime* now) {
|
||||
|
||||
static void Chat_AppendLog(const String* text) {
|
||||
String str; char strBuffer[STRING_SIZE * 2];
|
||||
DateTime now;
|
||||
struct DateTime now;
|
||||
ReturnCode res;
|
||||
|
||||
if (!Chat_LogName.length || !Game_ChatLogging) return;
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "Platform.h"
|
||||
#include "Stream.h"
|
||||
#include "Errors.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#define Header_ReadU8(value) if ((res = s->ReadU8(s, &value))) return res;
|
||||
/*########################################################################################################################*
|
||||
|
@ -645,7 +645,7 @@ static void Game_DoScheduledTasks(double time) {
|
||||
void Game_TakeScreenshot(void) {
|
||||
String filename; char fileBuffer[STRING_SIZE];
|
||||
String path; char pathBuffer[FILENAME_SIZE];
|
||||
DateTime now;
|
||||
struct DateTime now;
|
||||
struct Stream stream;
|
||||
ReturnCode res;
|
||||
|
||||
|
@ -3259,7 +3259,7 @@ static void TexPackOverlay_Render(void* screen, double delta) {
|
||||
MenuScreen_Render(s, delta);
|
||||
if (!AsyncDownloader_Get(&s->Identifier, &item)) return;
|
||||
|
||||
s->ContentLength = item.ResultSize;
|
||||
s->ContentLength = item.ContentLength;
|
||||
if (!s->ContentLength) return;
|
||||
Elem_Recreate(s);
|
||||
}
|
||||
|
136
src/Platform.c
136
src/Platform.c
@ -258,7 +258,7 @@ TimeMS DateTime_CurrentUTC_MS(void) {
|
||||
return FileTime_TotalMS(raw);
|
||||
}
|
||||
|
||||
static void Platform_FromSysTime(DateTime* time, SYSTEMTIME* sysTime) {
|
||||
static void Platform_FromSysTime(struct DateTime* time, SYSTEMTIME* sysTime) {
|
||||
time->Year = sysTime->wYear;
|
||||
time->Month = sysTime->wMonth;
|
||||
time->Day = sysTime->wDay;
|
||||
@ -268,13 +268,13 @@ static void Platform_FromSysTime(DateTime* time, SYSTEMTIME* sysTime) {
|
||||
time->Milli = sysTime->wMilliseconds;
|
||||
}
|
||||
|
||||
void DateTime_CurrentUTC(DateTime* time) {
|
||||
void DateTime_CurrentUTC(struct DateTime* time) {
|
||||
SYSTEMTIME utcTime;
|
||||
GetSystemTime(&utcTime);
|
||||
Platform_FromSysTime(time, &utcTime);
|
||||
}
|
||||
|
||||
void DateTime_CurrentLocal(DateTime* time) {
|
||||
void DateTime_CurrentLocal(struct DateTime* time) {
|
||||
SYSTEMTIME localTime;
|
||||
GetLocalTime(&localTime);
|
||||
Platform_FromSysTime(time, &localTime);
|
||||
@ -308,7 +308,7 @@ TimeMS DateTime_CurrentUTC_MS(void) {
|
||||
return UnixTime_TotalMS(cur);
|
||||
}
|
||||
|
||||
static void Platform_FromSysTime(DateTime* time, struct tm* sysTime) {
|
||||
static void Platform_FromSysTime(struct DateTime* time, struct tm* sysTime) {
|
||||
time->Year = sysTime->tm_year + 1900;
|
||||
time->Month = sysTime->tm_mon + 1;
|
||||
time->Day = sysTime->tm_mday;
|
||||
@ -317,7 +317,7 @@ static void Platform_FromSysTime(DateTime* time, struct tm* sysTime) {
|
||||
time->Second = sysTime->tm_sec;
|
||||
}
|
||||
|
||||
void DateTime_CurrentUTC(DateTime* time_) {
|
||||
void DateTime_CurrentUTC(struct DateTime* time_) {
|
||||
struct timeval cur;
|
||||
struct tm utc_time;
|
||||
|
||||
@ -328,7 +328,7 @@ void DateTime_CurrentUTC(DateTime* time_) {
|
||||
time_->Milli = cur.tv_usec / 1000;
|
||||
}
|
||||
|
||||
void DateTime_CurrentLocal(DateTime* time_) {
|
||||
void DateTime_CurrentLocal(struct DateTime* time_) {
|
||||
struct timeval cur;
|
||||
struct tm loc_time;
|
||||
|
||||
@ -451,51 +451,51 @@ ReturnCode File_GetModifiedTime_MS(const String* path, TimeMS* time) {
|
||||
return res;
|
||||
}
|
||||
|
||||
ReturnCode File_Do(void** file, const String* path, DWORD access, DWORD createMode) {
|
||||
static ReturnCode File_Do(FileHandle* file, const String* path, DWORD access, DWORD createMode) {
|
||||
TCHAR str[300];
|
||||
Platform_ConvertString(str, path);
|
||||
*file = CreateFile(str, access, FILE_SHARE_READ, NULL, createMode, 0, NULL);
|
||||
return Win_Return(*file != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
ReturnCode File_Open(void** file, const String* path) {
|
||||
ReturnCode File_Open(FileHandle* file, const String* path) {
|
||||
return File_Do(file, path, GENERIC_READ, OPEN_EXISTING);
|
||||
}
|
||||
ReturnCode File_Create(void** file, const String* path) {
|
||||
ReturnCode File_Create(FileHandle* file, const String* path) {
|
||||
return File_Do(file, path, GENERIC_WRITE, CREATE_ALWAYS);
|
||||
}
|
||||
ReturnCode File_Append(void** file, const String* path) {
|
||||
ReturnCode File_Append(FileHandle* file, const String* path) {
|
||||
ReturnCode res = File_Do(file, path, GENERIC_WRITE, OPEN_ALWAYS);
|
||||
if (res) return res;
|
||||
return File_Seek(*file, 0, FILE_SEEKFROM_END);
|
||||
}
|
||||
|
||||
ReturnCode File_Read(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead) {
|
||||
BOOL success = ReadFile((HANDLE)file, buffer, count, bytesRead, NULL);
|
||||
ReturnCode File_Read(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead) {
|
||||
BOOL success = ReadFile(file, buffer, count, bytesRead, NULL);
|
||||
return Win_Return(success);
|
||||
}
|
||||
|
||||
ReturnCode File_Write(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote) {
|
||||
BOOL success = WriteFile((HANDLE)file, buffer, count, bytesWrote, NULL);
|
||||
ReturnCode File_Write(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote) {
|
||||
BOOL success = WriteFile(file, buffer, count, bytesWrote, NULL);
|
||||
return Win_Return(success);
|
||||
}
|
||||
|
||||
ReturnCode File_Close(void* file) {
|
||||
return Win_Return(CloseHandle((HANDLE)file));
|
||||
ReturnCode File_Close(FileHandle file) {
|
||||
return Win_Return(CloseHandle(file));
|
||||
}
|
||||
|
||||
ReturnCode File_Seek(void* file, int offset, int seekType) {
|
||||
ReturnCode File_Seek(FileHandle file, int offset, int seekType) {
|
||||
static uint8_t modes[3] = { FILE_BEGIN, FILE_CURRENT, FILE_END };
|
||||
DWORD pos = SetFilePointer(file, offset, NULL, modes[seekType]);
|
||||
return Win_Return(pos != INVALID_SET_FILE_POINTER);
|
||||
}
|
||||
|
||||
ReturnCode File_Position(void* file, uint32_t* position) {
|
||||
*position = SetFilePointer(file, 0, NULL, 1); /* SEEK_CUR */
|
||||
ReturnCode File_Position(FileHandle file, uint32_t* position) {
|
||||
*position = SetFilePointer(file, 0, NULL, FILE_CURRENT);
|
||||
return Win_Return(*position != INVALID_SET_FILE_POINTER);
|
||||
}
|
||||
|
||||
ReturnCode File_Length(void* file, uint32_t* length) {
|
||||
ReturnCode File_Length(FileHandle file, uint32_t* length) {
|
||||
*length = GetFileSize(file, NULL);
|
||||
return Win_Return(*length != INVALID_FILE_SIZE);
|
||||
}
|
||||
@ -577,52 +577,52 @@ ReturnCode File_GetModifiedTime_MS(const String* path, TimeMS* time) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ReturnCode File_Do(void** file, const String* path, int mode) {
|
||||
static ReturnCode File_Do(FileHandle* file, const String* path, int mode) {
|
||||
char str[600];
|
||||
Platform_ConvertString(str, path);
|
||||
*file = open(str, mode, (6 << 6) | (4 << 3) | 4); /* rw|r|r */
|
||||
return Nix_Return(*file != -1);
|
||||
}
|
||||
|
||||
ReturnCode File_Open(void** file, const String* path) {
|
||||
ReturnCode File_Open(FileHandle* file, const String* path) {
|
||||
return File_Do(file, path, O_RDONLY);
|
||||
}
|
||||
ReturnCode File_Create(void** file, const String* path) {
|
||||
ReturnCode File_Create(FileHandle* file, const String* path) {
|
||||
return File_Do(file, path, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
}
|
||||
ReturnCode File_Append(void** file, const String* path) {
|
||||
ReturnCode File_Append(FileHandle* file, const String* path) {
|
||||
ReturnCode res = File_Do(file, path, O_WRONLY | O_CREAT);
|
||||
if (res) return res;
|
||||
return File_Seek(*file, 0, FILE_SEEKFROM_END);
|
||||
}
|
||||
|
||||
ReturnCode File_Read(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead) {
|
||||
*bytesRead = read((int)file, buffer, count);
|
||||
ReturnCode File_Read(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead) {
|
||||
*bytesRead = read(file, buffer, count);
|
||||
return Nix_Return(*bytesRead != -1);
|
||||
}
|
||||
|
||||
ReturnCode File_Write(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote) {
|
||||
*bytesWrote = write((int)file, buffer, count);
|
||||
ReturnCode File_Write(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote) {
|
||||
*bytesWrote = write(file, buffer, count);
|
||||
return Nix_Return(*bytesWrote != -1);
|
||||
}
|
||||
|
||||
ReturnCode File_Close(void* file) {
|
||||
return Nix_Return(close((int)file) != -1);
|
||||
ReturnCode File_Close(FileHandle file) {
|
||||
return Nix_Return(close(file) != -1);
|
||||
}
|
||||
|
||||
ReturnCode File_Seek(void* file, int offset, int seekType) {
|
||||
ReturnCode File_Seek(FileHandle file, int offset, int seekType) {
|
||||
static uint8_t modes[3] = { SEEK_SET, SEEK_CUR, SEEK_END };
|
||||
return Nix_Return(lseek((int)file, offset, modes[seekType]) != -1);
|
||||
return Nix_Return(lseek(file, offset, modes[seekType]) != -1);
|
||||
}
|
||||
|
||||
ReturnCode File_Position(void* file, uint32_t* position) {
|
||||
*position = lseek((int)file, 0, SEEK_CUR);
|
||||
ReturnCode File_Position(FileHandle file, uint32_t* position) {
|
||||
*position = lseek(file, 0, SEEK_CUR);
|
||||
return Nix_Return(*position != -1);
|
||||
}
|
||||
|
||||
ReturnCode File_Length(void* file, uint32_t* length) {
|
||||
ReturnCode File_Length(FileHandle file, uint32_t* length) {
|
||||
struct stat st;
|
||||
if (fstat((int)file, &st) == -1) { *length = -1; return errno; }
|
||||
if (fstat(file, &st) == -1) { *length = -1; return errno; }
|
||||
*length = st.st_size; return 0;
|
||||
}
|
||||
#endif
|
||||
@ -1113,14 +1113,14 @@ static void Font_Init(void) {
|
||||
/*########################################################################################################################*
|
||||
*---------------------------------------------------------Socket----------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Socket_Create(SocketPtr* socketResult) {
|
||||
void Socket_Create(SocketHandle* socketResult) {
|
||||
*socketResult = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (*socketResult == -1) {
|
||||
ErrorHandler_Fail2(Socket__Error(), "Failed to create socket");
|
||||
}
|
||||
}
|
||||
|
||||
static ReturnCode Socket_ioctl(SocketPtr socket, uint32_t cmd, int* data) {
|
||||
static ReturnCode Socket_ioctl(SocketHandle socket, uint32_t cmd, int* data) {
|
||||
#ifdef CC_BUILD_WIN
|
||||
return ioctlsocket(socket, cmd, data);
|
||||
#else
|
||||
@ -1128,20 +1128,20 @@ static ReturnCode Socket_ioctl(SocketPtr socket, uint32_t cmd, int* data) {
|
||||
#endif
|
||||
}
|
||||
|
||||
ReturnCode Socket_Available(SocketPtr socket, uint32_t* available) {
|
||||
ReturnCode Socket_Available(SocketHandle socket, uint32_t* available) {
|
||||
return Socket_ioctl(socket, FIONREAD, available);
|
||||
}
|
||||
ReturnCode Socket_SetBlocking(SocketPtr socket, bool blocking) {
|
||||
ReturnCode Socket_SetBlocking(SocketHandle socket, bool blocking) {
|
||||
int blocking_raw = blocking ? 0 : -1;
|
||||
return Socket_ioctl(socket, FIONBIO, &blocking_raw);
|
||||
}
|
||||
|
||||
ReturnCode Socket_GetError(SocketPtr socket, ReturnCode* result) {
|
||||
ReturnCode Socket_GetError(SocketHandle socket, ReturnCode* result) {
|
||||
int resultSize = sizeof(ReturnCode);
|
||||
return getsockopt(socket, SOL_SOCKET, SO_ERROR, result, &resultSize);
|
||||
}
|
||||
|
||||
ReturnCode Socket_Connect(SocketPtr socket, const String* ip, int port) {
|
||||
ReturnCode Socket_Connect(SocketHandle socket, const String* ip, int port) {
|
||||
struct { int16_t Family; uint8_t Port[2], IP[4], Pad[8]; } addr;
|
||||
ReturnCode res;
|
||||
|
||||
@ -1153,19 +1153,19 @@ ReturnCode Socket_Connect(SocketPtr socket, const String* ip, int port) {
|
||||
return res == -1 ? Socket__Error() : 0;
|
||||
}
|
||||
|
||||
ReturnCode Socket_Read(SocketPtr socket, uint8_t* buffer, uint32_t count, uint32_t* modified) {
|
||||
ReturnCode Socket_Read(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified) {
|
||||
int recvCount = recv(socket, buffer, count, 0);
|
||||
if (recvCount != -1) { *modified = recvCount; return 0; }
|
||||
*modified = 0; return Socket__Error();
|
||||
}
|
||||
|
||||
ReturnCode Socket_Write(SocketPtr socket, uint8_t* buffer, uint32_t count, uint32_t* modified) {
|
||||
ReturnCode Socket_Write(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified) {
|
||||
int sentCount = send(socket, buffer, count, 0);
|
||||
if (sentCount != -1) { *modified = sentCount; return 0; }
|
||||
*modified = 0; return Socket__Error();
|
||||
}
|
||||
|
||||
ReturnCode Socket_Close(SocketPtr socket) {
|
||||
ReturnCode Socket_Close(SocketHandle socket) {
|
||||
ReturnCode res = 0;
|
||||
ReturnCode res1, res2;
|
||||
|
||||
@ -1185,7 +1185,7 @@ ReturnCode Socket_Close(SocketPtr socket) {
|
||||
return res;
|
||||
}
|
||||
|
||||
ReturnCode Socket_Select(SocketPtr socket, int selectMode, bool* success) {
|
||||
ReturnCode Socket_Select(SocketHandle socket, int selectMode, bool* success) {
|
||||
fd_set set;
|
||||
struct timeval time = { 0 };
|
||||
int selectCount, nfds;
|
||||
@ -1270,12 +1270,12 @@ static ReturnCode Http_GetHeaders(struct AsyncRequest* req, HINTERNET handle) {
|
||||
if (!HttpQueryInfoA(handle, FLAG_STATUS, &req->StatusCode, &len, NULL)) return GetLastError();
|
||||
|
||||
len = sizeof(DWORD);
|
||||
HttpQueryInfoA(handle, FLAG_LENGTH, &req->ResultSize, &len, NULL);
|
||||
HttpQueryInfoA(handle, FLAG_LENGTH, &req->ContentLength, &len, NULL);
|
||||
|
||||
SYSTEMTIME sysTime;
|
||||
len = sizeof(SYSTEMTIME);
|
||||
if (HttpQueryInfoA(handle, FLAG_LASTMOD, &sysTime, &len, NULL)) {
|
||||
DateTime time;
|
||||
struct DateTime time;
|
||||
Platform_FromSysTime(&time, &sysTime);
|
||||
req->LastModified = DateTime_TotalMs(&time);
|
||||
}
|
||||
@ -1288,27 +1288,37 @@ static ReturnCode Http_GetHeaders(struct AsyncRequest* req, HINTERNET handle) {
|
||||
}
|
||||
|
||||
static ReturnCode Http_GetData(struct AsyncRequest* req, HINTERNET handle, volatile int* progress) {
|
||||
uint32_t size = req->ResultSize;
|
||||
if (!size) return ERROR_NOT_SUPPORTED;
|
||||
uint8_t* buffer;
|
||||
uint32_t size, totalRead;
|
||||
uint32_t read, avail;
|
||||
bool success;
|
||||
|
||||
*progress = 0;
|
||||
size = req->ContentLength ? req->ContentLength : 1;
|
||||
buffer = Mem_Alloc(size, 1, "http get data");
|
||||
totalRead = 0;
|
||||
|
||||
uint8_t* buffer = Mem_Alloc(size, 1, "http get data");
|
||||
uint32_t left = size, read, totalRead = 0;
|
||||
req->ResultData = buffer;
|
||||
req->ResultSize = 0;
|
||||
|
||||
while (left) {
|
||||
uint32_t toRead = left, avail = 0;
|
||||
/* only read as much data that is pending */
|
||||
if (InternetQueryDataAvailable(handle, &avail, 0, 0)) {
|
||||
toRead = min(toRead, avail);
|
||||
for (;;) {
|
||||
if (!InternetQueryDataAvailable(handle, &avail, 0, 0)) break;
|
||||
if (!avail) break;
|
||||
|
||||
/* expand if buffer is too small (some servers don't give content length) */
|
||||
if (totalRead + avail > size) {
|
||||
size = totalRead + avail;
|
||||
buffer = Mem_Realloc(buffer, size, 1, "http inc data");
|
||||
req->ResultData = buffer;
|
||||
}
|
||||
|
||||
bool success = InternetReadFile(handle, buffer, toRead, &read);
|
||||
success = InternetReadFile(handle, &buffer[totalRead], avail, &read);
|
||||
if (!success) { Mem_Free(buffer); return GetLastError(); }
|
||||
|
||||
if (!read) break;
|
||||
buffer += read; totalRead += read; left -= read;
|
||||
*progress = (int)(100.0f * totalRead / size);
|
||||
|
||||
totalRead += read;
|
||||
if (req->ContentLength) *progress = (int)(100.0f * totalRead / size);
|
||||
req->ResultSize += read;
|
||||
}
|
||||
|
||||
*progress = 100;
|
||||
@ -1393,7 +1403,9 @@ static size_t Http_GetHeaders(char *buffer, size_t size, size_t nitems, struct A
|
||||
tmp = String_ClearedArray(req->Etag);
|
||||
String_AppendString(&tmp, &value);
|
||||
} else if (String_CaselessEqualsConst(&name, "Content-Length")) {
|
||||
Convert_TryParseInt(&value, &req->ResultSize);
|
||||
Convert_TryParseInt(&value, &req->ContentLength);
|
||||
/* TODO: Fix when ContentLength isn't RequestSize */
|
||||
req->RequestSize = req->ContentLength;
|
||||
} else if (String_CaselessEqualsConst(&name, "Last-Modified")) {
|
||||
String_InitArray_NT(tmp, tmpBuffer);
|
||||
String_AppendString(&tmp, &value);
|
||||
|
@ -1,6 +1,5 @@
|
||||
#ifndef CC_PLATFORM_H
|
||||
#define CC_PLATFORM_H
|
||||
#include "Utils.h"
|
||||
#include "PackedCol.h"
|
||||
#include "Bitmap.h"
|
||||
/* Abstracts platform specific memory management, I/O, etc.
|
||||
@ -8,16 +7,19 @@
|
||||
*/
|
||||
struct DrawTextArgs;
|
||||
struct AsyncRequest;
|
||||
struct DateTime;
|
||||
|
||||
enum SOCKET_SELECT { SOCKET_SELECT_READ, SOCKET_SELECT_WRITE };
|
||||
enum Socket_Select { SOCKET_SELECT_READ, SOCKET_SELECT_WRITE };
|
||||
#ifdef CC_BUILD_WIN
|
||||
typedef uintptr_t SocketPtr;
|
||||
typedef uintptr_t SocketHandle;
|
||||
typedef void* FileHandle;
|
||||
#else
|
||||
typedef int SocketPtr;
|
||||
typedef int SocketHandle;
|
||||
typedef int FileHandle;
|
||||
#endif
|
||||
|
||||
/* Origin points for when seeking in a file. */
|
||||
enum FILE_SEEKFROM { FILE_SEEKFROM_BEGIN, FILE_SEEKFROM_CURRENT, FILE_SEEKFROM_END };
|
||||
enum File_SeekFrom { FILE_SEEKFROM_BEGIN, FILE_SEEKFROM_CURRENT, FILE_SEEKFROM_END };
|
||||
|
||||
/* Newline for console and text files. */
|
||||
extern char* Platform_NewLine;
|
||||
@ -95,9 +97,9 @@ void Platform_Log4(const char* format, const void* a1, const void* a2, const voi
|
||||
TimeMS DateTime_CurrentUTC_MS(void);
|
||||
/* Returns the current UTC Time. */
|
||||
/* NOTE: Generally DateTime_CurrentUTC_MS should be used instead. */
|
||||
void DateTime_CurrentUTC(DateTime* time);
|
||||
void DateTime_CurrentUTC(struct DateTime* time);
|
||||
/* Returns the current local Time. */
|
||||
void DateTime_CurrentLocal(DateTime* time);
|
||||
void DateTime_CurrentLocal(struct DateTime* time);
|
||||
/* Takes a platform-specific stopwatch measurement. */
|
||||
/* NOTE: The value returned is platform-specific - do NOT try to interpret the value. */
|
||||
uint64_t Stopwatch_Measure(void);
|
||||
@ -118,23 +120,23 @@ bool File_Exists(const String* path);
|
||||
ReturnCode File_GetModifiedTime_MS(const String* path, TimeMS* ms);
|
||||
|
||||
/* Attempts to create a new (or overwrite) file for writing. */
|
||||
ReturnCode File_Create(void** file, const String* path);
|
||||
ReturnCode File_Create(FileHandle* file, const String* path);
|
||||
/* Attempts to open an existing file for reading. */
|
||||
ReturnCode File_Open(void** file, const String* path);
|
||||
ReturnCode File_Open(FileHandle* file, const String* path);
|
||||
/* Attempts to open (or create) a file, for appending data to the end of the file. */
|
||||
ReturnCode File_Append(void** file, const String* path);
|
||||
ReturnCode File_Append(FileHandle* file, const String* path);
|
||||
/* Attempts to read data from the file. */
|
||||
ReturnCode File_Read(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead);
|
||||
ReturnCode File_Read(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesRead);
|
||||
/* Attempts to write data to the file. */
|
||||
ReturnCode File_Write(void* file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote);
|
||||
ReturnCode File_Write(FileHandle file, uint8_t* buffer, uint32_t count, uint32_t* bytesWrote);
|
||||
/* Attempts to close the given file. */
|
||||
ReturnCode File_Close(void* file);
|
||||
ReturnCode File_Close(FileHandle file);
|
||||
/* Attempts to seek to a position in the given file. */
|
||||
ReturnCode File_Seek(void* file, int offset, int seekType);
|
||||
ReturnCode File_Seek(FileHandle file, int offset, int seekType);
|
||||
/* Attempts to get the current position in the given file. */
|
||||
ReturnCode File_Position(void* file, uint32_t* position);
|
||||
ReturnCode File_Position(FileHandle file, uint32_t* position);
|
||||
/* Attempts to retrieve the length of the given file. */
|
||||
ReturnCode File_Length(void* file, uint32_t* length);
|
||||
ReturnCode File_Length(FileHandle file, uint32_t* length);
|
||||
|
||||
/* Blocks the current thread for the given number of milliseconds. */
|
||||
CC_EXPORT void Thread_Sleep(uint32_t milliseconds);
|
||||
@ -180,25 +182,25 @@ CC_EXPORT Size2D Platform_TextMeasure(struct DrawTextArgs* args);
|
||||
CC_EXPORT Size2D Platform_TextDraw(struct DrawTextArgs* args, Bitmap* bmp, int x, int y, BitmapCol col);
|
||||
|
||||
/* Allocates a new socket. */
|
||||
void Socket_Create(SocketPtr* socket);
|
||||
void Socket_Create(SocketHandle* socket);
|
||||
/* Returns how much data is available to be read from the given socket. */
|
||||
ReturnCode Socket_Available(SocketPtr socket, uint32_t* available);
|
||||
ReturnCode Socket_Available(SocketHandle socket, uint32_t* available);
|
||||
/* Sets whether operations on this socket block the calling thread. */
|
||||
/* e.g. if blocking is on, calling Connect() blocks until a response is received. */
|
||||
ReturnCode Socket_SetBlocking(SocketPtr socket, bool blocking);
|
||||
ReturnCode Socket_SetBlocking(SocketHandle socket, bool blocking);
|
||||
/* Returns (and resets) the last error generated by this socket. */
|
||||
ReturnCode Socket_GetError(SocketPtr socket, ReturnCode* result);
|
||||
ReturnCode Socket_GetError(SocketHandle socket, ReturnCode* result);
|
||||
|
||||
/* Attempts to initalise a TCP connection to the given IP address:port. */
|
||||
ReturnCode Socket_Connect(SocketPtr socket, const String* ip, int port);
|
||||
ReturnCode Socket_Connect(SocketHandle socket, const String* ip, int port);
|
||||
/* Attempts to read data from the given socket. */
|
||||
ReturnCode Socket_Read(SocketPtr socket, uint8_t* buffer, uint32_t count, uint32_t* modified);
|
||||
ReturnCode Socket_Read(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified);
|
||||
/* Attempts to write data to the given socket. */
|
||||
ReturnCode Socket_Write(SocketPtr socket, uint8_t* buffer, uint32_t count, uint32_t* modified);
|
||||
ReturnCode Socket_Write(SocketHandle socket, uint8_t* buffer, uint32_t count, uint32_t* modified);
|
||||
/* Attempts to close the given socket. */
|
||||
ReturnCode Socket_Close(SocketPtr socket);
|
||||
ReturnCode Socket_Close(SocketHandle socket);
|
||||
/* Attempts to poll the socket for reading or writing. */
|
||||
ReturnCode Socket_Select(SocketPtr socket, int selectMode, bool* success);
|
||||
ReturnCode Socket_Select(SocketHandle socket, int selectMode, bool* success);
|
||||
|
||||
/* Initalises the platform specific http library state. */
|
||||
void Http_Init(void);
|
||||
|
@ -240,7 +240,7 @@ void ServerConnection_InitSingleplayer(void) {
|
||||
/*########################################################################################################################*
|
||||
*--------------------------------------------------Multiplayer connection-------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
static SocketPtr net_socket;
|
||||
static SocketHandle net_socket;
|
||||
static uint8_t net_readBuffer[4096 * 5];
|
||||
static uint8_t net_writeBuffer[131];
|
||||
static uint8_t* net_readCurrent;
|
||||
|
@ -108,19 +108,19 @@ static ReturnCode Stream_FileLength(struct Stream* s, uint32_t* length) {
|
||||
}
|
||||
|
||||
ReturnCode Stream_OpenFile(struct Stream* s, const String* path) {
|
||||
void* file;
|
||||
FileHandle file;
|
||||
ReturnCode res = File_Open(&file, path);
|
||||
Stream_FromFile(s, file);
|
||||
return res;
|
||||
}
|
||||
ReturnCode Stream_CreateFile(struct Stream* s, const String* path) {
|
||||
void* file;
|
||||
FileHandle file;
|
||||
ReturnCode res = File_Create(&file, path);
|
||||
Stream_FromFile(s, file);
|
||||
return res;
|
||||
}
|
||||
|
||||
void Stream_FromFile(struct Stream* s, void* file) {
|
||||
void Stream_FromFile(struct Stream* s, FileHandle file) {
|
||||
Stream_Init(s);
|
||||
s->Meta.File = file;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef CC_STREAM_H
|
||||
#define CC_STREAM_H
|
||||
#include "String.h"
|
||||
#include "Constants.h"
|
||||
#include "Platform.h"
|
||||
/* Defines an abstract way of reading and writing data in a streaming manner.
|
||||
Also provides common helper methods for reading/writing data to/from streams.
|
||||
Copyright 2017 ClassicalSharp | Licensed under BSD-3
|
||||
@ -29,7 +29,7 @@ struct Stream {
|
||||
ReturnCode (*Close)(struct Stream* s);
|
||||
|
||||
union {
|
||||
void* File;
|
||||
FileHandle File;
|
||||
void* Inflate;
|
||||
/* NOTE: These structs rely on overlapping Meta_Mem fields being the same! Don't change them */
|
||||
struct { uint8_t* Cur; uint32_t Left, Length; uint8_t* Base; } Mem;
|
||||
@ -54,7 +54,7 @@ CC_EXPORT ReturnCode Stream_OpenFile(struct Stream* s, const String* path);
|
||||
/* Wrapper for File_Create() then Stream_FromFile() */
|
||||
CC_EXPORT ReturnCode Stream_CreateFile(struct Stream* s, const String* path);
|
||||
/* Wraps a file, allowing reading from/writing to/seeking in the file. */
|
||||
CC_EXPORT void Stream_FromFile(struct Stream* s, void* file);
|
||||
CC_EXPORT void Stream_FromFile(struct Stream* s, FileHandle file);
|
||||
|
||||
/* Wraps another Stream, only allows reading up to 'len' bytes from the wrapped stream. */
|
||||
CC_EXPORT void Stream_ReadonlyPortion(struct Stream* s, struct Stream* source, uint32_t len);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "ErrorHandler.h"
|
||||
#include "Platform.h"
|
||||
#include "Stream.h"
|
||||
#include "Utils.h"
|
||||
|
||||
String String_Init(STRING_REF char* buffer, int length, int capacity) {
|
||||
String s;
|
||||
|
@ -21,7 +21,7 @@ static bool DateTime_IsLeapYear(int year) {
|
||||
return (year % 400) == 0;
|
||||
}
|
||||
|
||||
int DateTime_TotalDays(const DateTime* time) {
|
||||
int DateTime_TotalDays(const struct DateTime* time) {
|
||||
/* Days from before this year */
|
||||
int y = time->Year - 1, days = 365 * y;
|
||||
/* A year is a leap year when the year is: */
|
||||
@ -38,7 +38,7 @@ int DateTime_TotalDays(const DateTime* time) {
|
||||
return days;
|
||||
}
|
||||
|
||||
TimeMS DateTime_TotalMs(const DateTime* time) {
|
||||
TimeMS DateTime_TotalMs(const struct DateTime* time) {
|
||||
int days = DateTime_TotalDays(time);
|
||||
uint64_t seconds =
|
||||
(uint64_t)days * DATETIME_SECONDS_PER_DAY +
|
||||
@ -48,7 +48,7 @@ TimeMS DateTime_TotalMs(const DateTime* time) {
|
||||
return seconds * DATETIME_MILLIS_PER_SEC + time->Milli;
|
||||
}
|
||||
|
||||
void DateTime_FromTotalMs(DateTime* time, TimeMS ms) {
|
||||
void DateTime_FromTotalMs(struct DateTime* time, TimeMS ms) {
|
||||
int dayMS, days, year;
|
||||
int daysInYear, month;
|
||||
uint16_t* totalDays;
|
||||
@ -90,7 +90,7 @@ void DateTime_FromTotalMs(DateTime* time, TimeMS ms) {
|
||||
void DateTime_HttpDate(TimeMS ms, String* str) {
|
||||
static char* days_of_week[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
|
||||
static char* month_names[13] = { NULL, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
DateTime t;
|
||||
struct DateTime t;
|
||||
int days;
|
||||
|
||||
DateTime_FromTotalMs(&t, ms);
|
||||
|
10
src/Utils.h
10
src/Utils.h
@ -8,7 +8,7 @@
|
||||
|
||||
/* Represents a particular instance in time in some timezone. Not necessarily UTC time. */
|
||||
/* NOTE: This is not an efficiently sized struct. Store DateTime_TotalMs instead for that. */
|
||||
typedef struct DateTime_ {
|
||||
struct DateTime {
|
||||
int Year; /* Year, ranges from 0 to 65535 */
|
||||
int Month; /* Month, ranges from 1 to 12 */
|
||||
int Day; /* Day, ranges from 1 to 31 */
|
||||
@ -16,12 +16,12 @@ typedef struct DateTime_ {
|
||||
int Minute; /* Minute, ranges from 0 to 59 */
|
||||
int Second; /* Second, ranges from 0 to 59 */
|
||||
int Milli; /* Milliseconds, ranges from 0 to 999 */
|
||||
} DateTime;
|
||||
};
|
||||
|
||||
#define DATETIME_MILLIS_PER_SEC 1000
|
||||
int DateTime_TotalDays(const DateTime* time);
|
||||
TimeMS DateTime_TotalMs(const DateTime* time);
|
||||
void DateTime_FromTotalMs(DateTime* time, TimeMS ms);
|
||||
int DateTime_TotalDays(const struct DateTime* time);
|
||||
TimeMS DateTime_TotalMs(const struct DateTime* time);
|
||||
void DateTime_FromTotalMs(struct DateTime* time, TimeMS ms);
|
||||
void DateTime_HttpDate(TimeMS ms, String* str);
|
||||
|
||||
CC_NOINLINE int Utils_ParseEnum(const String* text, int defValue, const char** names, int namesCount);
|
||||
|
@ -1916,21 +1916,25 @@ static void PlayerListWidget_SetColumnPos(struct PlayerListWidget* w, int column
|
||||
}
|
||||
|
||||
static void PlayerListWidget_RepositionColumns(struct PlayerListWidget* w) {
|
||||
int width = 0, centreX = Game_Width / 2;
|
||||
w->YHeight = 0;
|
||||
int x, y, width = 0, height;
|
||||
int col, columns;
|
||||
|
||||
w->YHeight = 0;
|
||||
columns = Math_CeilDiv(w->NamesCount, LIST_NAMES_PER_COLUMN);
|
||||
|
||||
int col, columns = Math_CeilDiv(w->NamesCount, LIST_NAMES_PER_COLUMN);
|
||||
for (col = 0; col < columns; col++) {
|
||||
width += PlayerListWidget_GetColumnWidth(w, col);
|
||||
int colHeight = PlayerListWidget_GetColumnHeight(w, col);
|
||||
w->YHeight = max(colHeight, w->YHeight);
|
||||
height = PlayerListWidget_GetColumnHeight(w, col);
|
||||
w->YHeight = max(height, w->YHeight);
|
||||
}
|
||||
|
||||
if (width < 480) width = 480;
|
||||
w->XMin = centreX - width / 2;
|
||||
w->XMax = centreX + width / 2;
|
||||
w->XMin = Game_Width / 2 - width / 2;
|
||||
w->XMax = Game_Width / 2 + width / 2;
|
||||
|
||||
x = w->XMin;
|
||||
y = Game_Height / 2 - w->YHeight / 2;
|
||||
|
||||
int x = w->XMin, y = Game_Height / 2 - w->YHeight / 2;
|
||||
for (col = 0; col < columns; col++) {
|
||||
PlayerListWidget_SetColumnPos(w, col, x, y);
|
||||
x += PlayerListWidget_GetColumnWidth(w, col);
|
||||
|
@ -115,12 +115,14 @@ static void Window_ResetWindowState(void) {
|
||||
|
||||
static bool win_hiddenBorder;
|
||||
static void Window_DoSetHiddenBorder(bool value) {
|
||||
bool wasVisible;
|
||||
RECT rect;
|
||||
if (win_hiddenBorder == value) return;
|
||||
|
||||
/* We wish to avoid making an invisible window visible just to change the border.
|
||||
However, it's a good idea to make a visible window invisible temporarily, to
|
||||
avoid garbage caused by the border change. */
|
||||
bool was_visible = Window_GetVisible();
|
||||
wasVisible = Window_GetVisible();
|
||||
|
||||
/* To ensure maximized/minimized windows work correctly, reset state to normal,
|
||||
change the border, then go back to maximized/minimized. */
|
||||
@ -130,14 +132,13 @@ static void Window_DoSetHiddenBorder(bool value) {
|
||||
style |= (value ? WS_POPUP : WS_OVERLAPPEDWINDOW);
|
||||
|
||||
/* Make sure client size doesn't change when changing the border style.*/
|
||||
RECT rect;
|
||||
rect.left = Window_Bounds.X; rect.top = Window_Bounds.Y;
|
||||
rect.right = rect.left + Window_Bounds.Width;
|
||||
rect.bottom = rect.top + Window_Bounds.Height;
|
||||
AdjustWindowRect(&rect, style, false);
|
||||
|
||||
/* This avoids leaving garbage on the background window. */
|
||||
if (was_visible) Window_SetVisible(false);
|
||||
if (wasVisible) Window_SetVisible(false);
|
||||
|
||||
SetWindowLong(win_handle, GWL_STYLE, style);
|
||||
SetWindowPos(win_handle, NULL, 0, 0, Rect_Width(rect), Rect_Height(rect),
|
||||
@ -146,7 +147,7 @@ static void Window_DoSetHiddenBorder(bool value) {
|
||||
/* Force window to redraw update its borders, but only if it's
|
||||
already visible (invisible windows will change borders when
|
||||
they become visible, so no need to make them visiable prematurely).*/
|
||||
if (was_visible) Window_SetVisible(true);
|
||||
if (wasVisible) Window_SetVisible(true);
|
||||
|
||||
Window_SetWindowState(state);
|
||||
}
|
||||
@ -166,15 +167,19 @@ static void Window_UpdateClientSize(HWND handle) {
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
char keyChar;
|
||||
bool wasFocused;
|
||||
float wheelDelta;
|
||||
|
||||
switch (message) {
|
||||
case WM_ACTIVATE:
|
||||
{
|
||||
bool wasFocused = Window_Focused;
|
||||
wasFocused = Window_Focused;
|
||||
Window_Focused = LOWORD(wParam) != 0;
|
||||
|
||||
if (Window_Focused != wasFocused) {
|
||||
Event_RaiseVoid(&WindowEvents_FocusChanged);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
|
||||
case WM_ENTERMENULOOP:
|
||||
case WM_ENTERSIZEMOVE:
|
||||
@ -238,31 +243,24 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara
|
||||
|
||||
|
||||
case WM_CHAR:
|
||||
{
|
||||
char keyChar;
|
||||
if (Convert_TryUnicodeToCP437((Codepoint)wParam, &keyChar)) {
|
||||
Event_RaiseInt(&KeyEvents_Press, keyChar);
|
||||
}
|
||||
} break;
|
||||
break;
|
||||
|
||||
case WM_MOUSEMOVE:
|
||||
{
|
||||
/* set before position change, in case mouse buttons changed when outside window */
|
||||
Mouse_SetPressed(MouseButton_Left, (wParam & 0x01) != 0);
|
||||
Mouse_SetPressed(MouseButton_Right, (wParam & 0x02) != 0);
|
||||
Mouse_SetPressed(MouseButton_Middle, (wParam & 0x10) != 0);
|
||||
/* TODO: do we need to set XBUTTON1/XBUTTON2 here */
|
||||
|
||||
WORD mouse_x = LOWORD(lParam);
|
||||
WORD mouse_y = HIWORD(lParam);
|
||||
Mouse_SetPosition(mouse_x, mouse_y);
|
||||
} break;
|
||||
Mouse_SetPosition(LOWORD(lParam), HIWORD(lParam));
|
||||
break;
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
{
|
||||
float wheel_delta = ((short)HIWORD(wParam)) / (float)WHEEL_DELTA;
|
||||
Mouse_SetWheel(Mouse_Wheel + wheel_delta);
|
||||
} return 0;
|
||||
wheelDelta = ((short)HIWORD(wParam)) / (float)WHEEL_DELTA;
|
||||
Mouse_SetWheel(Mouse_Wheel + wheelDelta);
|
||||
return 0;
|
||||
|
||||
case WM_LBUTTONDOWN:
|
||||
Mouse_SetPressed(MouseButton_Left, true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user