mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 11:35:08 -04:00
C client: Simplify audio/http API
This commit is contained in:
parent
cac5978407
commit
e0e0326a98
@ -39,19 +39,20 @@ namespace SharpWave {
|
|||||||
Play();
|
Play();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferBlock(AudioChunk tmp, AudioFormat fmt, IEnumerator<AudioChunk> chunks) {
|
bool BufferBlock(int i, AudioChunk tmp, int size, IEnumerator<AudioChunk> chunks) {
|
||||||
// decode up to around a second
|
|
||||||
int secondSize = fmt.SampleRate * fmt.Channels * sizeof(short);
|
|
||||||
tmp.Length = 0;
|
tmp.Length = 0;
|
||||||
|
bool end = false;
|
||||||
|
|
||||||
while (tmp.Length < secondSize) {
|
while (tmp.Length < size) {
|
||||||
if (!chunks.MoveNext()) return true;
|
if (!chunks.MoveNext()) { end = true; break; }
|
||||||
AudioChunk src = chunks.Current;
|
AudioChunk src = chunks.Current;
|
||||||
|
|
||||||
Buffer.BlockCopy(src.Data, 0, tmp.Data, tmp.Length, src.Length);
|
Buffer.BlockCopy(src.Data, 0, tmp.Data, tmp.Length, src.Length);
|
||||||
tmp.Length += src.Length;
|
tmp.Length += src.Length;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
BufferData(i, tmp);
|
||||||
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PlayStreaming(Stream stream) {
|
public void PlayStreaming(Stream stream) {
|
||||||
@ -65,18 +66,18 @@ namespace SharpWave {
|
|||||||
// largest possible vorbis frame decodes to blocksize1 samples
|
// largest possible vorbis frame decodes to blocksize1 samples
|
||||||
// so we may end up decoding slightly over a second of audio
|
// so we may end up decoding slightly over a second of audio
|
||||||
int chunkSize = (fmt.SampleRate + 8192) * fmt.Channels * sizeof(short);
|
int chunkSize = (fmt.SampleRate + 8192) * fmt.Channels * sizeof(short);
|
||||||
|
int secondSize = fmt.SampleRate * fmt.Channels * sizeof(short);
|
||||||
byte[][] data = new byte[NumBuffers][];
|
byte[][] data = new byte[NumBuffers][];
|
||||||
for (int i = 0; i < NumBuffers; i++) { data[i] = new byte[chunkSize]; }
|
for (int i = 0; i < NumBuffers; i++) { data[i] = new byte[chunkSize]; }
|
||||||
|
|
||||||
bool reachedEnd = false;
|
bool end = false;
|
||||||
for (int i = 0; i < NumBuffers && !reachedEnd; i++) {
|
for (int i = 0; i < NumBuffers && !end; i++) {
|
||||||
tmp.Data = data[i];
|
tmp.Data = data[i];
|
||||||
reachedEnd = BufferBlock(tmp, fmt, chunks);
|
end = BufferBlock(i, tmp, secondSize, chunks);
|
||||||
BufferData(i, tmp);
|
|
||||||
}
|
}
|
||||||
Play();
|
Play();
|
||||||
|
|
||||||
for (; !reachedEnd;) {
|
for (; !end;) {
|
||||||
int next = -1;
|
int next = -1;
|
||||||
for (int i = 0; i < NumBuffers; i++) {
|
for (int i = 0; i < NumBuffers; i++) {
|
||||||
if (IsCompleted(i)) { next = i; break; }
|
if (IsCompleted(i)) { next = i; break; }
|
||||||
@ -86,8 +87,7 @@ namespace SharpWave {
|
|||||||
if (pendingStop) break;
|
if (pendingStop) break;
|
||||||
|
|
||||||
tmp.Data = data[next];
|
tmp.Data = data[next];
|
||||||
reachedEnd = BufferBlock(tmp, fmt, chunks);
|
end = BufferBlock(next, tmp, secondSize, chunks);
|
||||||
BufferData(next, tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!IsFinished()) { Thread.Sleep(10); }
|
while (!IsFinished()) { Thread.Sleep(10); }
|
||||||
|
@ -82,8 +82,8 @@ static void AsyncDownloader_Add(String* url, bool priority, String* id, UInt8 ty
|
|||||||
Mutex_Lock(async_pendingMutex);
|
Mutex_Lock(async_pendingMutex);
|
||||||
{
|
{
|
||||||
struct AsyncRequest req = { 0 };
|
struct AsyncRequest req = { 0 };
|
||||||
String reqUrl = String_FromArray(req.URL); String_Set(&reqUrl, url);
|
String reqUrl = String_FromArray(req.URL); String_Copy(&reqUrl, url);
|
||||||
String reqID = String_FromArray(req.ID); String_Set(&reqID, id);
|
String reqID = String_FromArray(req.ID); String_Copy(&reqID, id);
|
||||||
req.RequestType = type;
|
req.RequestType = type;
|
||||||
|
|
||||||
Platform_Log2("Adding %s (type %b)", &reqUrl, &type);
|
Platform_Log2("Adding %s (type %b)", &reqUrl, &type);
|
||||||
@ -92,7 +92,7 @@ static void AsyncDownloader_Add(String* url, bool priority, String* id, UInt8 ty
|
|||||||
req.LastModified = *lastModified;
|
req.LastModified = *lastModified;
|
||||||
}
|
}
|
||||||
if (etag) {
|
if (etag) {
|
||||||
String reqEtag = String_FromArray(req.Etag); String_Set(&reqEtag, etag);
|
String reqEtag = String_FromArray(req.Etag); String_Copy(&reqEtag, etag);
|
||||||
}
|
}
|
||||||
/* request.Data = data; TODO: Implement this. do we need to copy or expect caller to malloc it? */
|
/* request.Data = data; TODO: Implement this. do we need to copy or expect caller to malloc it? */
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ void AsyncDownloader_GetSkin(STRING_PURE String* id, STRING_PURE String* skinNam
|
|||||||
String url = String_FromArray(urlBuffer);
|
String url = String_FromArray(urlBuffer);
|
||||||
|
|
||||||
if (Utils_IsUrlPrefix(skinName, 0)) {
|
if (Utils_IsUrlPrefix(skinName, 0)) {
|
||||||
String_Set(&url, skinName);
|
String_Copy(&url, skinName);
|
||||||
} else {
|
} else {
|
||||||
String_AppendString(&url, &async_skinServer);
|
String_AppendString(&url, &async_skinServer);
|
||||||
String_AppendColorless(&url, skinName);
|
String_AppendColorless(&url, skinName);
|
||||||
@ -192,43 +192,20 @@ bool AsyncDownloader_GetCurrent(struct AsyncRequest* request, Int32* progress) {
|
|||||||
static void AsyncDownloader_ProcessRequest(struct AsyncRequest* request) {
|
static void AsyncDownloader_ProcessRequest(struct AsyncRequest* request) {
|
||||||
String url = String_FromRawArray(request->URL);
|
String url = String_FromRawArray(request->URL);
|
||||||
Platform_Log2("Downloading from %s (type %b)", &url, &request->RequestType);
|
Platform_Log2("Downloading from %s (type %b)", &url, &request->RequestType);
|
||||||
struct Stopwatch stopwatch; UInt32 elapsedMS;
|
struct Stopwatch stopwatch;
|
||||||
|
|
||||||
void* handle;
|
|
||||||
ReturnCode res;
|
|
||||||
Stopwatch_Start(&stopwatch);
|
Stopwatch_Start(&stopwatch);
|
||||||
res = Http_MakeRequest(request, &handle);
|
ReturnCode res = Http_Do(request, &async_curProgress);
|
||||||
elapsedMS = Stopwatch_ElapsedMicroseconds(&stopwatch) / 1000;
|
UInt32 elapsed = Stopwatch_ElapsedMicroseconds(&stopwatch) / 1000;
|
||||||
Platform_Log2("HTTP make request: ret code %i, in %i ms", &res, &elapsedMS);
|
|
||||||
if (res) return;
|
|
||||||
|
|
||||||
async_curProgress = ASYNC_PROGRESS_FETCHING_DATA;
|
|
||||||
UInt32 size = 0;
|
|
||||||
Stopwatch_Start(&stopwatch);
|
|
||||||
res = Http_GetRequestHeaders(request, handle, &size);
|
|
||||||
elapsedMS = Stopwatch_ElapsedMicroseconds(&stopwatch) / 1000;
|
|
||||||
UInt32 status = request->StatusCode;
|
UInt32 status = request->StatusCode;
|
||||||
Platform_Log3("HTTP get headers: ret code %i (http %i), in %i ms", &res, &status, &elapsedMS);
|
Platform_Log3("HTTP: return code %i (http %i), in %i ms", &res, &status, &elapsed);
|
||||||
|
|
||||||
if (res || request->StatusCode != 200) {
|
if (request->ResultData) {
|
||||||
Http_FreeRequest(handle); return;
|
UInt32 size = request->ResultSize;
|
||||||
|
UInt64 addr = (UInt64)request->ResultData;
|
||||||
|
Platform_Log2("HTTP returned data: %i bytes at %x", &size, &addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* data = NULL;
|
|
||||||
if (request->RequestType != REQUEST_TYPE_CONTENT_LENGTH) {
|
|
||||||
Stopwatch_Start(&stopwatch);
|
|
||||||
res = Http_GetRequestData(request, handle, &data, size, &async_curProgress);
|
|
||||||
elapsedMS = Stopwatch_ElapsedMicroseconds(&stopwatch) / 1000;
|
|
||||||
Platform_Log3("HTTP get data: ret code %i (size %i), in %i ms", &res, &size, &elapsedMS);
|
|
||||||
}
|
|
||||||
|
|
||||||
Http_FreeRequest(handle);
|
|
||||||
if (res) return;
|
|
||||||
|
|
||||||
UInt64 addr = (UInt64)data;
|
|
||||||
Platform_Log2("OK I got the DATA! %i bytes at %x", &size, &addr);
|
|
||||||
request->ResultData = data;
|
|
||||||
request->ResultSize = size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AsyncDownloader_CompleteResult(struct AsyncRequest* request) {
|
static void AsyncDownloader_CompleteResult(struct AsyncRequest* request) {
|
||||||
|
47
src/Audio.c
47
src/Audio.c
@ -148,7 +148,7 @@ static void Soundboard_Init(struct Soundboard* board, STRING_PURE String* boardN
|
|||||||
|
|
||||||
group = &board->Groups[board->Count++];
|
group = &board->Groups[board->Count++];
|
||||||
group->Name = String_ClearedArray(group->NameBuffer);
|
group->Name = String_ClearedArray(group->NameBuffer);
|
||||||
String_Set(&group->Name, &name);
|
String_Copy(&group->Name, &name);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group->Count == Array_Elems(group->Sounds)) {
|
if (group->Count == Array_Elems(group->Sounds)) {
|
||||||
@ -211,7 +211,8 @@ static void Sounds_PlayRaw(struct SoundOutput* output, struct Sound* snd, struct
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Audio_PlayData(output->Handle, 0, buffer, snd->DataSize);
|
Audio_BufferData(output->Handle, 0, buffer, snd->DataSize);
|
||||||
|
Audio_Play(output->Handle);
|
||||||
/* TODO: handle errors here */
|
/* TODO: handle errors here */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -320,6 +321,23 @@ void* music_thread;
|
|||||||
void* music_waitable;
|
void* music_waitable;
|
||||||
volatile bool music_pendingStop;
|
volatile bool music_pendingStop;
|
||||||
|
|
||||||
|
static ReturnCode Music_BufferBlock(Int32 i, Int16* data, Int32 maxSamples, struct VorbisState* ctx) {
|
||||||
|
Int32 samples = 0;
|
||||||
|
ReturnCode res = 0;
|
||||||
|
|
||||||
|
while (samples < maxSamples) {
|
||||||
|
res = Vorbis_DecodeFrame(ctx);
|
||||||
|
if (res) break;
|
||||||
|
|
||||||
|
Int16* cur = &data[samples];
|
||||||
|
samples += Vorbis_OutputFrame(ctx, cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Game_MusicVolume < 100) { Volume_Mix16(data, samples, Game_MusicVolume); }
|
||||||
|
Audio_BufferData(music_out, i, data, samples * sizeof(Int16));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static ReturnCode Music_PlayOgg(struct Stream* source) {
|
static ReturnCode Music_PlayOgg(struct Stream* source) {
|
||||||
UInt8 buffer[OGG_BUFFER_SIZE];
|
UInt8 buffer[OGG_BUFFER_SIZE];
|
||||||
struct Stream stream;
|
struct Stream stream;
|
||||||
@ -338,12 +356,19 @@ static ReturnCode Music_PlayOgg(struct Stream* source) {
|
|||||||
|
|
||||||
/* largest possible vorbis frame decodes to blocksize1 * channels samples */
|
/* largest possible vorbis frame decodes to blocksize1 * channels samples */
|
||||||
/* so we may end up decoding slightly over a second of audio */
|
/* so we may end up decoding slightly over a second of audio */
|
||||||
Int32 chunkSize = fmt.Channels * (fmt.SampleRate + vorbis.BlockSizes[1]);
|
Int32 i, chunkSize = fmt.Channels * (fmt.SampleRate + vorbis.BlockSizes[1]);
|
||||||
Int32 samplesPerSecond = fmt.Channels * fmt.SampleRate;
|
Int32 samplesPerSecond = fmt.Channels * fmt.SampleRate;
|
||||||
Int16* data = Mem_Alloc(chunkSize * AUDIO_MAX_CHUNKS, sizeof(Int16), "Ogg - final PCM output");
|
Int16* data = Mem_Alloc(chunkSize * AUDIO_MAX_CHUNKS, sizeof(Int16), "Ogg - final PCM output");
|
||||||
|
|
||||||
|
/* fill up with some samples before playing */
|
||||||
|
for (i = 0; i < AUDIO_MAX_CHUNKS && !res; i++) {
|
||||||
|
Int16* base = data + (chunkSize * i);
|
||||||
|
res = Music_BufferBlock(i, base, samplesPerSecond, &vorbis);
|
||||||
|
}
|
||||||
|
Audio_Play(music_out);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Int32 i, next = -1;
|
Int32 next = -1;
|
||||||
for (i = 0; i < AUDIO_MAX_CHUNKS; i++) {
|
for (i = 0; i < AUDIO_MAX_CHUNKS; i++) {
|
||||||
if (Audio_IsCompleted(music_out, i)) { next = i; break; }
|
if (Audio_IsCompleted(music_out, i)) { next = i; break; }
|
||||||
}
|
}
|
||||||
@ -351,20 +376,8 @@ static ReturnCode Music_PlayOgg(struct Stream* source) {
|
|||||||
if (next == -1) { Thread_Sleep(10); continue; }
|
if (next == -1) { Thread_Sleep(10); continue; }
|
||||||
if (music_pendingStop) break;
|
if (music_pendingStop) break;
|
||||||
|
|
||||||
/* decode up to around a second */
|
|
||||||
Int16* base = data + (chunkSize * next);
|
Int16* base = data + (chunkSize * next);
|
||||||
Int32 samples = 0;
|
res = Music_BufferBlock(next, base, samplesPerSecond, &vorbis);
|
||||||
|
|
||||||
while (samples < samplesPerSecond) {
|
|
||||||
res = Vorbis_DecodeFrame(&vorbis);
|
|
||||||
if (res) break;
|
|
||||||
|
|
||||||
Int16* cur = &base[samples];
|
|
||||||
samples += Vorbis_OutputFrame(&vorbis, cur);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Game_MusicVolume < 100) { Volume_Mix16(base, samples, Game_MusicVolume); }
|
|
||||||
Audio_PlayData(music_out, next, base, samples * sizeof(Int16));
|
|
||||||
/* need to specially handle last bit of audio */
|
/* need to specially handle last bit of audio */
|
||||||
if (res) break;
|
if (res) break;
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ void Game_GetDefaultTexturePack(STRING_TRANSIENT String* texPack) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Game_SetDefaultTexturePack(STRING_PURE String* texPack) {
|
void Game_SetDefaultTexturePack(STRING_PURE String* texPack) {
|
||||||
String_Set(&game_defTexPack, texPack);
|
String_Copy(&game_defTexPack, texPack);
|
||||||
Options_Set(OPT_DEFAULT_TEX_PACK, texPack);
|
Options_Set(OPT_DEFAULT_TEX_PACK, texPack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
src/Menus.c
12
src/Menus.c
@ -1307,7 +1307,7 @@ static void SaveLevelScreen_DoSave(struct GuiElem* elem, struct GuiElem* widget,
|
|||||||
String warnMsg = String_FromConst("Saving..");
|
String warnMsg = String_FromConst("Saving..");
|
||||||
SaveLevelScreen_MakeDesc(screen, &warnMsg);
|
SaveLevelScreen_MakeDesc(screen, &warnMsg);
|
||||||
|
|
||||||
String_Set(&screen->TextPath, &path);
|
String_Copy(&screen->TextPath, &path);
|
||||||
SaveLevelScreen_RemoveOverwrites(screen);
|
SaveLevelScreen_RemoveOverwrites(screen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1495,7 +1495,7 @@ static void FontListScreen_EntryClick(struct GuiElem* elem, struct GuiElem* w) {
|
|||||||
String fontName = ListScreen_UNSAFE_GetCur(screen, w);
|
String fontName = ListScreen_UNSAFE_GetCur(screen, w);
|
||||||
if (String_CaselessEqualsConst(&fontName, LIST_SCREEN_EMPTY)) return;
|
if (String_CaselessEqualsConst(&fontName, LIST_SCREEN_EMPTY)) return;
|
||||||
|
|
||||||
String_Set(&Game_FontName, &fontName);
|
String_Copy(&Game_FontName, &fontName);
|
||||||
Options_Set(OPT_FONT_NAME, &fontName);
|
Options_Set(OPT_FONT_NAME, &fontName);
|
||||||
|
|
||||||
Int32 cur = screen->CurrentIndex;
|
Int32 cur = screen->CurrentIndex;
|
||||||
@ -2494,14 +2494,14 @@ static void GraphicsOptionsScreen_SetMipmaps(STRING_PURE String* v) {
|
|||||||
Gfx_Mipmaps = Menu_SetBool(v, OPT_MIPMAPS);
|
Gfx_Mipmaps = Menu_SetBool(v, OPT_MIPMAPS);
|
||||||
char urlBuffer[STRING_SIZE];
|
char urlBuffer[STRING_SIZE];
|
||||||
String url = String_FromArray(urlBuffer);
|
String url = String_FromArray(urlBuffer);
|
||||||
String_Set(&url, &World_TextureUrl);
|
String_Copy(&url, &World_TextureUrl);
|
||||||
|
|
||||||
/* always force a reload from cache */
|
/* always force a reload from cache */
|
||||||
World_TextureUrl.length = 0;
|
World_TextureUrl.length = 0;
|
||||||
String_AppendConst(&World_TextureUrl, "~`#$_^*()@");
|
String_AppendConst(&World_TextureUrl, "~`#$_^*()@");
|
||||||
TexturePack_ExtractCurrent(&url);
|
TexturePack_ExtractCurrent(&url);
|
||||||
|
|
||||||
String_Set(&World_TextureUrl, &url);
|
String_Copy(&World_TextureUrl, &url);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GraphicsOptionsScreen_ContextRecreated(void* obj) {
|
static void GraphicsOptionsScreen_ContextRecreated(void* obj) {
|
||||||
@ -3237,7 +3237,7 @@ struct Screen* UrlWarningOverlay_MakeInstance(STRING_PURE String* url) {
|
|||||||
Array_Elems(widgets), UrlWarningOverlay_ContextRecreated);
|
Array_Elems(widgets), UrlWarningOverlay_ContextRecreated);
|
||||||
|
|
||||||
String dstUrl = String_FromArray(screen->__UrlBuffer);
|
String dstUrl = String_FromArray(screen->__UrlBuffer);
|
||||||
String_Set(&dstUrl, url);
|
String_Copy(&dstUrl, url);
|
||||||
screen->Url = dstUrl;
|
screen->Url = dstUrl;
|
||||||
|
|
||||||
Overlay_UseVTABLE((struct MenuScreen*)screen, &WarningOverlay_VTABLE);
|
Overlay_UseVTABLE((struct MenuScreen*)screen, &WarningOverlay_VTABLE);
|
||||||
@ -3294,7 +3294,7 @@ struct Screen* ConfirmDenyOverlay_MakeInstance(STRING_PURE String* url, bool alw
|
|||||||
Array_Elems(widgets), ConfirmDenyOverlay_ContextRecreated);
|
Array_Elems(widgets), ConfirmDenyOverlay_ContextRecreated);
|
||||||
|
|
||||||
String dstUrl = String_FromArray(screen->__UrlBuffer);
|
String dstUrl = String_FromArray(screen->__UrlBuffer);
|
||||||
String_Set(&dstUrl, url);
|
String_Copy(&dstUrl, url);
|
||||||
screen->Url = dstUrl;
|
screen->Url = dstUrl;
|
||||||
screen->AlwaysDeny = alwaysDeny;
|
screen->AlwaysDeny = alwaysDeny;
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ void Window_GetClipboardText(STRING_TRANSIENT String* value) {
|
|||||||
for (i = 0; i < 10; i++) {
|
for (i = 0; i < 10; i++) {
|
||||||
Window_ProcessEvents();
|
Window_ProcessEvents();
|
||||||
if (clipboard_paste_text.length) {
|
if (clipboard_paste_text.length) {
|
||||||
String_Set(value, &clipboard_paste_text);
|
String_Copy(value, &clipboard_paste_text);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
Thread_Sleep(100);
|
Thread_Sleep(100);
|
||||||
@ -231,7 +231,7 @@ void Window_GetClipboardText(STRING_TRANSIENT String* value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Window_SetClipboardText(STRING_PURE String* value) {
|
void Window_SetClipboardText(STRING_PURE String* value) {
|
||||||
String_Set(&clipboard_paste_text, value);
|
String_Copy(&clipboard_paste_text, value);
|
||||||
XSetSelectionOwner(win_display, xa_clipboard, win_handle, 0);
|
XSetSelectionOwner(win_display, xa_clipboard, win_handle, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,8 +102,8 @@ static void Handlers_CheckName(EntityID id, STRING_TRANSIENT String* displayName
|
|||||||
String nameNoCols = String_FromArray(nameNoColsBuffer);
|
String nameNoCols = String_FromArray(nameNoColsBuffer);
|
||||||
String_AppendColorless(&nameNoCols, displayName);
|
String_AppendColorless(&nameNoCols, displayName);
|
||||||
|
|
||||||
if (!String_Equals(&nameNoCols, &Game_Username)) { String_Set(displayName, &Game_Username); }
|
if (!String_Equals(&nameNoCols, &Game_Username)) { String_Copy(displayName, &Game_Username); }
|
||||||
if (!skinName->length) { String_Set(skinName, &Game_Username); }
|
if (!skinName->length) { String_Copy(skinName, &Game_Username); }
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Classic_ReadAbsoluteLocation(UInt8* data, EntityID id, bool interpolate);
|
static void Classic_ReadAbsoluteLocation(UInt8* data, EntityID id, bool interpolate);
|
||||||
@ -125,9 +125,9 @@ static void Handlers_AddEntity(UInt8* data, EntityID id, STRING_TRANSIENT String
|
|||||||
p->FetchedSkin = false;
|
p->FetchedSkin = false;
|
||||||
|
|
||||||
String player_name = String_ClearedArray(p->DisplayNameRaw);
|
String player_name = String_ClearedArray(p->DisplayNameRaw);
|
||||||
String_Set(&player_name, displayName);
|
String_Copy(&player_name, displayName);
|
||||||
String player_skin = String_ClearedArray(p->SkinNameRaw);
|
String player_skin = String_ClearedArray(p->SkinNameRaw);
|
||||||
String_Set(&player_skin, skinName);
|
String_Copy(&player_skin, skinName);
|
||||||
Player_UpdateName((struct Player*)p);
|
Player_UpdateName((struct Player*)p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +381,7 @@ static void Classic_Handshake(UInt8* data) {
|
|||||||
struct HacksComp* hacks = &LocalPlayer_Instance.Hacks;
|
struct HacksComp* hacks = &LocalPlayer_Instance.Hacks;
|
||||||
HacksComp_SetUserType(hacks, *data, !cpe_blockPerms);
|
HacksComp_SetUserType(hacks, *data, !cpe_blockPerms);
|
||||||
|
|
||||||
String_Set(&hacks->HacksFlags, &ServerConnection_ServerName);
|
String_Copy(&hacks->HacksFlags, &ServerConnection_ServerName);
|
||||||
String_AppendString(&hacks->HacksFlags, &ServerConnection_ServerMOTD);
|
String_AppendString(&hacks->HacksFlags, &ServerConnection_ServerMOTD);
|
||||||
HacksComp_UpdateState(hacks);
|
HacksComp_UpdateState(hacks);
|
||||||
}
|
}
|
||||||
|
@ -862,28 +862,33 @@ ReturnCode Socket_Select(SocketPtr socket, Int32 selectMode, bool* success) {
|
|||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
#if CC_BUILD_WIN
|
#if CC_BUILD_WIN
|
||||||
HINTERNET hInternet;
|
HINTERNET hInternet;
|
||||||
|
/* TODO: Test last modified and etag even work */
|
||||||
|
#define FLAG_STATUS HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER
|
||||||
|
#define FLAG_LENGTH HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER
|
||||||
|
#define FLAG_LASTMOD HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME
|
||||||
|
|
||||||
void Http_Init(void) {
|
void Http_Init(void) {
|
||||||
/* TODO: Should we use INTERNET_OPEN_TYPE_PRECONFIG instead? */
|
/* TODO: Should we use INTERNET_OPEN_TYPE_PRECONFIG instead? */
|
||||||
hInternet = InternetOpenA(PROGRAM_APP_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
hInternet = InternetOpenA(PROGRAM_APP_NAME, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
|
||||||
if (!hInternet) ErrorHandler_FailWithCode(GetLastError(), "Failed to init WinINet");
|
if (!hInternet) ErrorHandler_FailWithCode(GetLastError(), "Failed to init WinINet");
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode Http_MakeRequest(struct AsyncRequest* request, void** handle) {
|
static ReturnCode Http_Make(struct AsyncRequest* req, HINTERNET* handle) {
|
||||||
String url = String_FromRawArray(request->URL);
|
String url = String_FromRawArray(req->URL);
|
||||||
char headersBuffer[STRING_SIZE * 2];
|
char headersBuffer[STRING_SIZE * 2];
|
||||||
String headers = String_MakeNull();
|
String headers = String_MakeNull();
|
||||||
|
|
||||||
/* https://stackoverflow.com/questions/25308488/c-wininet-custom-http-headers */
|
/* https://stackoverflow.com/questions/25308488/c-wininet-custom-http-headers */
|
||||||
if (request->Etag[0] || request->LastModified.Year) {
|
if (req->Etag[0] || req->LastModified.Year) {
|
||||||
headers = String_ClearedArray(headersBuffer);
|
headers = String_ClearedArray(headersBuffer);
|
||||||
if (request->LastModified.Year) {
|
if (req->LastModified.Year) {
|
||||||
String_AppendConst(&headers, "If-Modified-Since: ");
|
String_AppendConst(&headers, "If-Modified-Since: ");
|
||||||
DateTime_HttpDate(&request->LastModified, &headers);
|
DateTime_HttpDate(&req->LastModified, &headers);
|
||||||
String_AppendConst(&headers, "\r\n");
|
String_AppendConst(&headers, "\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request->Etag[0]) {
|
if (req->Etag[0]) {
|
||||||
String etag = String_FromRawArray(request->Etag);
|
String etag = String_FromRawArray(req->Etag);
|
||||||
String_AppendConst(&headers, "If-None-Match: ");
|
String_AppendConst(&headers, "If-None-Match: ");
|
||||||
String_AppendString(&headers, &etag);
|
String_AppendString(&headers, &etag);
|
||||||
String_AppendConst(&headers, "\r\n");
|
String_AppendConst(&headers, "\r\n");
|
||||||
@ -896,39 +901,38 @@ ReturnCode Http_MakeRequest(struct AsyncRequest* request, void** handle) {
|
|||||||
return Win_Return(*handle);
|
return Win_Return(*handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Test last modified and etag even work */
|
static ReturnCode Http_GetHeaders(struct AsyncRequest* req, HINTERNET handle) {
|
||||||
#define Http_Query(flags, result) HttpQueryInfoA(handle, flags, result, &bufferLen, NULL)
|
DWORD len;
|
||||||
ReturnCode Http_GetRequestHeaders(struct AsyncRequest* request, void* handle, UInt32* size) {
|
|
||||||
DWORD bufferLen;
|
|
||||||
|
|
||||||
UInt32 status;
|
UInt32 status;
|
||||||
bufferLen = sizeof(DWORD);
|
len = sizeof(DWORD);
|
||||||
if (!Http_Query(HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status)) return GetLastError();
|
if (!HttpQueryInfoA(handle, FLAG_STATUS, &status, &len, NULL)) return GetLastError();
|
||||||
request->StatusCode = status;
|
req->StatusCode = status;
|
||||||
|
|
||||||
bufferLen = sizeof(DWORD);
|
len = sizeof(DWORD);
|
||||||
if (!Http_Query(HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, size)) return GetLastError();
|
if (!HttpQueryInfoA(handle, FLAG_LENGTH, &req->ResultSize, &len, NULL)) return GetLastError();
|
||||||
|
|
||||||
SYSTEMTIME lastModified;
|
SYSTEMTIME time;
|
||||||
bufferLen = sizeof(SYSTEMTIME);
|
len = sizeof(SYSTEMTIME);
|
||||||
if (Http_Query(HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME, &lastModified)) {
|
if (HttpQueryInfoA(handle, FLAG_LASTMOD, &time, &len, NULL)) {
|
||||||
Platform_FromSysTime(&request->LastModified, &lastModified);
|
Platform_FromSysTime(&req->LastModified, &time);
|
||||||
}
|
}
|
||||||
|
|
||||||
String etag = String_ClearedArray(request->Etag);
|
String etag = String_ClearedArray(req->Etag);
|
||||||
bufferLen = etag.capacity;
|
len = etag.capacity;
|
||||||
Http_Query(HTTP_QUERY_ETAG, etag.buffer);
|
HttpQueryInfoA(handle, HTTP_QUERY_ETAG, etag.buffer, &len, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode Http_GetRequestData(struct AsyncRequest* request, void* handle, void** data, UInt32 size, volatile Int32* progress) {
|
static ReturnCode Http_GetData(struct AsyncRequest* req, HINTERNET handle, volatile Int32* progress) {
|
||||||
if (!size) return ERROR_NOT_SUPPORTED;
|
UInt32 size = req->ResultSize;
|
||||||
|
if (size) return ERROR_NOT_SUPPORTED;
|
||||||
*progress = 0;
|
*progress = 0;
|
||||||
|
|
||||||
UInt8* buffer = Mem_Alloc(size, sizeof(UInt8), "http get data");
|
UInt8* buffer = Mem_Alloc(size, sizeof(UInt8), "http get data");
|
||||||
UInt32 left = size, read, totalRead = 0;
|
UInt32 left = size, read, totalRead = 0;
|
||||||
*data = buffer;
|
req->ResultData = buffer;
|
||||||
|
|
||||||
while (left) {
|
while (left) {
|
||||||
UInt32 toRead = left, avail = 0;
|
UInt32 toRead = left, avail = 0;
|
||||||
@ -949,7 +953,23 @@ ReturnCode Http_GetRequestData(struct AsyncRequest* request, void* handle, void*
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode Http_FreeRequest(void* handle) { return Win_Return(InternetCloseHandle(handle)); }
|
ReturnCode Http_Do(struct AsyncRequest* req, volatile Int32* progress) {
|
||||||
|
HINTERNET handle;
|
||||||
|
ReturnCode res = Http_Make(req, &handle);
|
||||||
|
if (res) return res;
|
||||||
|
|
||||||
|
*progress = ASYNC_PROGRESS_FETCHING_DATA;
|
||||||
|
res = Http_GetHeaders(req, handle);
|
||||||
|
if (res) { InternetCloseHandle(handle); return res; }
|
||||||
|
|
||||||
|
if (req->RequestType != REQUEST_TYPE_CONTENT_LENGTH && req->StatusCode == 200) {
|
||||||
|
res = Http_GetData(req, handle, progress);
|
||||||
|
if (res) { InternetCloseHandle(handle); return res; }
|
||||||
|
}
|
||||||
|
|
||||||
|
return Win_Return(InternetCloseHandle(handle));
|
||||||
|
}
|
||||||
|
|
||||||
ReturnCode Http_Free(void) { return Win_Return(InternetCloseHandle(hInternet)); }
|
ReturnCode Http_Free(void) { return Win_Return(InternetCloseHandle(hInternet)); }
|
||||||
#elif CC_BUILD_NIX
|
#elif CC_BUILD_NIX
|
||||||
void Http_Init(void) { }
|
void Http_Init(void) { }
|
||||||
@ -1028,7 +1048,7 @@ void Audio_SetFormat(AudioHandle handle, struct AudioFormat* format) {
|
|||||||
ctx->Format = *format;
|
ctx->Format = *format;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio_PlayData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize) {
|
void Audio_BufferData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize) {
|
||||||
struct AudioContext* ctx = &Audio_Contexts[handle];
|
struct AudioContext* ctx = &Audio_Contexts[handle];
|
||||||
WAVEHDR* hdr = &ctx->Headers[idx];
|
WAVEHDR* hdr = &ctx->Headers[idx];
|
||||||
Mem_Set(hdr, 0, sizeof(WAVEHDR));
|
Mem_Set(hdr, 0, sizeof(WAVEHDR));
|
||||||
@ -1043,6 +1063,8 @@ void Audio_PlayData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize)
|
|||||||
ErrorHandler_CheckOrFail(result, "Audio - write header");
|
ErrorHandler_CheckOrFail(result, "Audio - write header");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Audio_Play(AudioHandle handle) { }
|
||||||
|
|
||||||
bool Audio_IsCompleted(AudioHandle handle, Int32 idx) {
|
bool Audio_IsCompleted(AudioHandle handle, Int32 idx) {
|
||||||
struct AudioContext* ctx = &Audio_Contexts[handle];
|
struct AudioContext* ctx = &Audio_Contexts[handle];
|
||||||
WAVEHDR* hdr = &ctx->Headers[idx];
|
WAVEHDR* hdr = &ctx->Headers[idx];
|
||||||
|
@ -110,10 +110,7 @@ ReturnCode Socket_Close(SocketPtr socket);
|
|||||||
ReturnCode Socket_Select(SocketPtr socket, Int32 selectMode, bool* success);
|
ReturnCode Socket_Select(SocketPtr socket, Int32 selectMode, bool* success);
|
||||||
|
|
||||||
void Http_Init(void);
|
void Http_Init(void);
|
||||||
ReturnCode Http_MakeRequest(struct AsyncRequest* request, void** handle);
|
ReturnCode Http_Do(struct AsyncRequest* req, volatile Int32* progress);
|
||||||
ReturnCode Http_GetRequestHeaders(struct AsyncRequest* request, void* handle, UInt32* size);
|
|
||||||
ReturnCode Http_GetRequestData(struct AsyncRequest* request, void* handle, void** data, UInt32 size, volatile Int32* progress);
|
|
||||||
ReturnCode Http_FreeRequest(void* handle);
|
|
||||||
ReturnCode Http_Free(void);
|
ReturnCode Http_Free(void);
|
||||||
|
|
||||||
#define AUDIO_MAX_CHUNKS 4
|
#define AUDIO_MAX_CHUNKS 4
|
||||||
@ -126,7 +123,8 @@ void Audio_Free(AudioHandle handle);
|
|||||||
struct AudioFormat* Audio_GetFormat(AudioHandle handle);
|
struct AudioFormat* Audio_GetFormat(AudioHandle handle);
|
||||||
void Audio_SetFormat(AudioHandle handle, struct AudioFormat* format);
|
void Audio_SetFormat(AudioHandle handle, struct AudioFormat* format);
|
||||||
void Audio_SetVolume(AudioHandle handle, Real32 volume);
|
void Audio_SetVolume(AudioHandle handle, Real32 volume);
|
||||||
void Audio_PlayData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize);
|
void Audio_BufferData(AudioHandle handle, Int32 idx, void* data, UInt32 dataSize);
|
||||||
|
void Audio_Play(AudioHandle handle);
|
||||||
bool Audio_IsCompleted(AudioHandle handle, Int32 idx);
|
bool Audio_IsCompleted(AudioHandle handle, Int32 idx);
|
||||||
bool Audio_IsFinished(AudioHandle handle);
|
bool Audio_IsFinished(AudioHandle handle);
|
||||||
#endif
|
#endif
|
||||||
|
@ -92,7 +92,7 @@ int main(void) {
|
|||||||
String title = String_FromConst(PROGRAM_APP_NAME);
|
String title = String_FromConst(PROGRAM_APP_NAME);
|
||||||
String rawArgs = Platform_GetCommandLineArgs();
|
String rawArgs = Platform_GetCommandLineArgs();
|
||||||
/* NOTE: Make sure to comment this out before pushing a commit */
|
/* NOTE: Make sure to comment this out before pushing a commit */
|
||||||
rawArgs = String_FromReadonly("UnknownShadow200 fff 127.0.0.1 25565");
|
//rawArgs = String_FromReadonly("UnknownShadow200 fff 127.0.0.1 25565");
|
||||||
|
|
||||||
String args[5]; Int32 argsCount = Array_Elems(args);
|
String args[5]; Int32 argsCount = Array_Elems(args);
|
||||||
String_UNSAFE_Split(&rawArgs, ' ', args, &argsCount);
|
String_UNSAFE_Split(&rawArgs, ' ', args, &argsCount);
|
||||||
@ -100,14 +100,14 @@ int main(void) {
|
|||||||
if (argsCount == 1) {
|
if (argsCount == 1) {
|
||||||
String name = args[0];
|
String name = args[0];
|
||||||
if (!name.length) name = String_FromReadonly("Singleplayer");
|
if (!name.length) name = String_FromReadonly("Singleplayer");
|
||||||
String_Set(&Game_Username, &name);
|
String_Copy(&Game_Username, &name);
|
||||||
} else if (argsCount < 4) {
|
} else if (argsCount < 4) {
|
||||||
Platform_LogConst("ClassiCube.exe is only the raw client. You must either use the launcher or provide command line arguments to start the client.");
|
Platform_LogConst("ClassiCube.exe is only the raw client. You must either use the launcher or provide command line arguments to start the client.");
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
String_Set(&Game_Username, &args[0]);
|
String_Copy(&Game_Username, &args[0]);
|
||||||
String_Set(&Game_Mppass, &args[1]);
|
String_Copy(&Game_Mppass, &args[1]);
|
||||||
String_Set(&Game_IPAddress, &args[2]);
|
String_Copy(&Game_IPAddress, &args[2]);
|
||||||
|
|
||||||
UInt8 ip[4];
|
UInt8 ip[4];
|
||||||
if (!Utils_ParseIP(&args[2], ip)) {
|
if (!Utils_ParseIP(&args[2], ip)) {
|
||||||
|
@ -743,7 +743,7 @@ static void ChatScreen_OpenInput(struct ChatScreen* screen, STRING_PURE String*
|
|||||||
ChatScreen_SetHandlesAllInput(screen, true);
|
ChatScreen_SetHandlesAllInput(screen, true);
|
||||||
Key_KeyRepeat = true;
|
Key_KeyRepeat = true;
|
||||||
|
|
||||||
String_Set(&screen->Input.Base.Text, initialText);
|
String_Copy(&screen->Input.Base.Text, initialText);
|
||||||
Elem_Recreate(&screen->Input.Base);
|
Elem_Recreate(&screen->Input.Base);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1071,7 +1071,7 @@ static void ChatScreen_ChatReceived(void* obj, String* msg, Int32 type) {
|
|||||||
static void ChatScreen_ContextLost(void* obj) {
|
static void ChatScreen_ContextLost(void* obj) {
|
||||||
struct ChatScreen* screen = (struct ChatScreen*)obj;
|
struct ChatScreen* screen = (struct ChatScreen*)obj;
|
||||||
if (screen->HandlesAllInput) {
|
if (screen->HandlesAllInput) {
|
||||||
String_Set(&screen->ChatInInputStr, &screen->Input.Base.Text);
|
String_Copy(&screen->ChatInInputStr, &screen->Input.Base.Text);
|
||||||
Gui_CalcCursorVisible();
|
Gui_CalcCursorVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,8 +321,8 @@ static void MPConnection_TickConnect(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void MPConnection_BeginConnect(void) {
|
static void MPConnection_BeginConnect(void) {
|
||||||
Socket_Create(&net_socket);
|
|
||||||
Event_RegisterBlock(&UserEvents_BlockChanged, NULL, MPConnection_BlockChanged);
|
Event_RegisterBlock(&UserEvents_BlockChanged, NULL, MPConnection_BlockChanged);
|
||||||
|
Socket_Create(&net_socket);
|
||||||
ServerConnection_Disconnected = false;
|
ServerConnection_Disconnected = false;
|
||||||
|
|
||||||
Socket_SetBlocking(net_socket, false);
|
Socket_SetBlocking(net_socket, false);
|
||||||
|
@ -49,9 +49,9 @@ void String_StripCols(STRING_TRANSIENT String* str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void String_Set(STRING_TRANSIENT String* str, STRING_PURE String* value) {
|
void String_Copy(STRING_TRANSIENT String* dst, STRING_PURE String* src) {
|
||||||
str->length = 0;
|
dst->length = 0;
|
||||||
String_AppendString(str, value);
|
String_AppendString(dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length) {
|
String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length) {
|
||||||
@ -684,7 +684,7 @@ void StringsBuffer_Clear(StringsBuffer* buffer) {
|
|||||||
|
|
||||||
void StringsBuffer_Get(StringsBuffer* buffer, Int32 index, STRING_TRANSIENT String* text) {
|
void StringsBuffer_Get(StringsBuffer* buffer, Int32 index, STRING_TRANSIENT String* text) {
|
||||||
String raw = StringsBuffer_UNSAFE_Get(buffer, index);
|
String raw = StringsBuffer_UNSAFE_Get(buffer, index);
|
||||||
String_Set(text, &raw);
|
String_Copy(text, &raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
String StringsBuffer_UNSAFE_Get(StringsBuffer* buffer, Int32 index) {
|
String StringsBuffer_UNSAFE_Get(StringsBuffer* buffer, Int32 index) {
|
||||||
|
@ -42,7 +42,7 @@ String String_FromReadonly(STRING_REF const char* buffer);
|
|||||||
#define String_FromRawArray(buffer) String_FromRaw(buffer, (UInt16)sizeof(buffer))
|
#define String_FromRawArray(buffer) String_FromRaw(buffer, (UInt16)sizeof(buffer))
|
||||||
|
|
||||||
void String_StripCols(STRING_TRANSIENT String* str);
|
void String_StripCols(STRING_TRANSIENT String* str);
|
||||||
void String_Set(STRING_TRANSIENT String* str, STRING_PURE String* value);
|
void String_Copy(STRING_TRANSIENT String* dst, STRING_PURE String* src);
|
||||||
/* Returns a string that points directly to a substring of the given string.
|
/* Returns a string that points directly to a substring of the given string.
|
||||||
NOTE: THIS IS UNSAFE - IT MAINTAINS A REFERENCE TO THE ORIGINAL BUFFER, AND THE SUBSTRING IS NOT NULL TERMINATED */
|
NOTE: THIS IS UNSAFE - IT MAINTAINS A REFERENCE TO THE ORIGINAL BUFFER, AND THE SUBSTRING IS NOT NULL TERMINATED */
|
||||||
String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length);
|
String String_UNSAFE_Substring(STRING_REF String* str, Int32 offset, Int32 length);
|
||||||
|
@ -478,7 +478,7 @@ void TexturePack_ExtractCurrent(STRING_PURE String* url) {
|
|||||||
if (String_Equals(url, &World_TextureUrl)) {
|
if (String_Equals(url, &World_TextureUrl)) {
|
||||||
} else {
|
} else {
|
||||||
bool zip = String_ContainsString(url, &zipExt);
|
bool zip = String_ContainsString(url, &zipExt);
|
||||||
String_Set(&World_TextureUrl, url);
|
String_Copy(&World_TextureUrl, url);
|
||||||
const char* operation = zip ? "extracting" : "decoding";
|
const char* operation = zip ? "extracting" : "decoding";
|
||||||
|
|
||||||
res = zip ? TexturePack_ExtractZip(&stream) :
|
res = zip ? TexturePack_ExtractZip(&stream) :
|
||||||
@ -493,7 +493,7 @@ void TexturePack_ExtractCurrent(STRING_PURE String* url) {
|
|||||||
|
|
||||||
void TexturePack_Extract_Req(struct AsyncRequest* item) {
|
void TexturePack_Extract_Req(struct AsyncRequest* item) {
|
||||||
String url = String_FromRawArray(item->URL);
|
String url = String_FromRawArray(item->URL);
|
||||||
String_Set(&World_TextureUrl, &url);
|
String_Copy(&World_TextureUrl, &url);
|
||||||
void* data = item->ResultData;
|
void* data = item->ResultData;
|
||||||
UInt32 len = item->ResultSize;
|
UInt32 len = item->ResultSize;
|
||||||
|
|
||||||
|
@ -1693,7 +1693,7 @@ static void ChatInputWidget_UpKey(struct GuiElem* elem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (widget->TypingLogPos == Chat_InputLog.Count) {
|
if (widget->TypingLogPos == Chat_InputLog.Count) {
|
||||||
String_Set(&widget->OrigStr, &input->Text);
|
String_Copy(&widget->OrigStr, &input->Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Chat_InputLog.Count) return;
|
if (!Chat_InputLog.Count) return;
|
||||||
@ -2213,7 +2213,7 @@ String TextGroupWidget_UNSAFE_Get(struct TextGroupWidget* widget, Int32 i) {
|
|||||||
|
|
||||||
void TextGroupWidget_GetText(struct TextGroupWidget* widget, Int32 index, STRING_TRANSIENT String* text) {
|
void TextGroupWidget_GetText(struct TextGroupWidget* widget, Int32 index, STRING_TRANSIENT String* text) {
|
||||||
String line = TextGroupWidget_UNSAFE_Get(widget, index);
|
String line = TextGroupWidget_UNSAFE_Get(widget, index);
|
||||||
String_Set(text, &line);
|
String_Copy(text, &line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextGroupWidget_PushUpAndReplaceLast(struct TextGroupWidget* widget, STRING_PURE String* text) {
|
void TextGroupWidget_PushUpAndReplaceLast(struct TextGroupWidget* widget, STRING_PURE String* text) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user