Skip to content

Commit fbdc1b4

Browse files
committed
Basic custom resource
1 parent 99da4fe commit fbdc1b4

21 files changed

Lines changed: 676 additions & 42 deletions

File tree

CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,7 @@ set_src(GAME_SHARED GLOB src/game
13061306
layers.cpp
13071307
layers.h
13081308
mapitems.h
1309+
resource.h
13091310
tuning.h
13101311
variables.h
13111312
version.h
@@ -1415,6 +1416,8 @@ if(CLIENT)
14151416
components/particles.h
14161417
components/players.cpp
14171418
components/players.h
1419+
components/resource.cpp
1420+
components/resource.h
14181421
components/scoreboard.cpp
14191422
components/scoreboard.h
14201423
components/skins.cpp
@@ -1559,6 +1562,8 @@ set_src(GAME_SERVER GLOB_RECURSE src/game/server
15591562
gameworld.h
15601563
player.cpp
15611564
player.h
1565+
resource.cpp
1566+
resource.h
15621567
)
15631568
set(GAME_GENERATED_SERVER
15641569
src/generated/server_data.cpp

datasrc/datatypes.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,33 @@ def emit_unpack(self):
304304
def emit_unpack_check(self):
305305
return []
306306

307+
308+
class NetRawData(NetVariable):
309+
def emit_declaration(self):
310+
return [f"const void *{self.name};", f"int {self.name}Size;"]
311+
def emit_unpack(self):
312+
return [f"pMsg->{self.name}Size = pUnpacker->GetInt();", f"pMsg->{self.name} = pUnpacker->GetRaw(pMsg->{self.name}Size);"]
313+
def emit_pack(self):
314+
return [f"pPacker->AddInt({self.name}Size);", f"pPacker->AddRaw({self.name}, {self.name}Size);"]
315+
316+
class NetRawDataFixed(NetVariable):
317+
def __init__(self, name, data_size, default=None):
318+
NetVariable.__init__(self,name,default=default)
319+
self.data_size = data_size
320+
def emit_declaration(self):
321+
return [f"const void *{self.name};"]
322+
def emit_unpack(self):
323+
return [f"pMsg->{self.name} = pUnpacker->GetRaw({self.data_size});"]
324+
def emit_pack(self):
325+
return [f"pPacker->AddRaw({self.name}, {self.data_size});"]
326+
327+
class NetRawDataFixedSnapshot(NetVariable):
328+
def __init__(self, name, data_size, default=None):
329+
NetVariable.__init__(self,name,default=default)
330+
self.data_size = data_size
331+
def emit_declaration(self):
332+
return [f"unsigned char {self.name}[{self.data_size}];"]
333+
307334
class NetString(NetVariable):
308335
def emit_declaration(self):
309336
return ["const char *%s;"%self.name]

datasrc/network.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,12 @@
2222

2323
GamePredictionFlags = Flags("GAMEPREDICTIONFLAG", ["EVENT", "INPUT"])
2424

25+
Resources = Enum("RESOURCE", ["SOUND", "IMAGE"])
26+
2527
RawHeader = '''
2628
29+
#include <base/hash.h>
30+
#include <base/uuid.h>
2731
#include <engine/message.h>
2832
#include <engine/shared/protocol_ex.h>
2933
@@ -75,6 +79,7 @@
7579
Votes,
7680
ChatModes,
7781
GameMsgIDs,
82+
Resources,
7883
]
7984

8085
Flags = [
@@ -274,6 +279,10 @@
274279

275280
NetObjectEx("GameDataPrediction", "game-data-prediction@netobj.teeworlds.wiki", [
276281
NetFlag("m_PredictionFlags", GamePredictionFlags),
282+
]),
283+
284+
NetEventEx("CustomSoundWorld:Common", "custom-sound-world@netevent.teeworlds.wiki", [
285+
NetRawDataFixedSnapshot("m_Uuid", "sizeof(Uuid)")
277286
])
278287
]
279288

@@ -490,4 +499,19 @@
490499
NetStringStrict("m_Arguments")
491500
]),
492501

502+
NetMessageEx("Sv_CustomRes", "custom-res@netmsg.teeworlds.wiki", [
503+
NetRawDataFixed("m_Uuid", "sizeof(Uuid)"),
504+
NetEnum("m_Type", Resources),
505+
NetStringStrict("m_Name"),
506+
NetIntAny("m_Crc"),
507+
NetIntRange("m_Size", 0, 'max_int'),
508+
NetRawDataFixed("m_Sha256", "sizeof(SHA256_DIGEST)"),
509+
]),
510+
NetMessageEx("Sv_CustomResData", "custom-res-data@netmsg.teeworlds.wiki", [
511+
NetRawDataFixed("m_Uuid", "sizeof(Uuid)"),
512+
NetRawData("m_Data"),
513+
]),
514+
NetMessageEx("Cl_ReqeustCustomRes", "request-custom-res@netmsg.teeworlds.wiki", [
515+
NetRawDataFixed("m_Uuid", "sizeof(Uuid)"),
516+
]),
493517
]

src/base/uuid.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ inline bool operator!=(const Uuid &that, const Uuid &other)
4646
{
4747
return !(that == other);
4848
}
49+
50+
inline bool operator<(const Uuid &that, const Uuid &other)
51+
{
52+
return uuid_comp(that, other) < 0;
53+
}
54+
55+
inline bool operator<=(const Uuid &that, const Uuid &other)
56+
{
57+
return uuid_comp(that, other) < 1;
58+
}
4959
#endif
5060

5161
#endif // BASE_UUID_H

src/engine/client/sound.cpp

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -332,11 +332,10 @@ void CSound::RateConvert(int SampleID)
332332
pSample->m_NumFrames = NumFrames;
333333
}
334334

335-
ISound::CSampleHandle CSound::LoadOpus(const char *pFilename)
335+
ISound::CSampleHandle CSound::LoadOpusMemory(const char *pContext, const unsigned char *pData, int DataSize)
336336
{
337337
CSample *pSample;
338338
int SampleID = -1;
339-
340339
// don't waste memory on sound when we are stress testing
341340
#ifdef CONF_DEBUG
342341
if(m_pConfig->m_DbgStress)
@@ -349,23 +348,16 @@ ISound::CSampleHandle CSound::LoadOpus(const char *pFilename)
349348

350349
if(!m_pStorage)
351350
return CSampleHandle();
352-
353-
lock_wait(m_SoundLock);
354-
unsigned char *pFileData;
355-
unsigned FileSize;
356-
if(!m_pStorage->ReadFile(pFilename, IStorage::TYPE_ALL, (void **) &pFileData, &FileSize))
357-
{
358-
dbg_msg("sound/opus", "failed to open file. filename='%s'", pFilename);
359-
lock_unlock(m_SoundLock);
351+
352+
if(!pContext || !pData || DataSize <= 0)
360353
return CSampleHandle();
361-
}
362354

355+
lock_wait(m_SoundLock);
363356
int Error = 0;
364-
OggOpusFile *pOpusFile = op_open_memory(pFileData, FileSize, &Error);
357+
OggOpusFile *pOpusFile = op_open_memory(pData, DataSize, &Error);
365358
if(!pOpusFile)
366359
{
367-
dbg_msg("sound/opus", "failed to open opus file '%s': error %d", pFilename, Error);
368-
mem_free(pFileData);
360+
dbg_msg("sound/opus", "failed to open opus '%s': error %d", pContext, Error);
369361
lock_unlock(m_SoundLock);
370362
return CSampleHandle();
371363
}
@@ -374,19 +366,17 @@ ISound::CSampleHandle CSound::LoadOpus(const char *pFilename)
374366
;
375367
if(NumChannels < 0 || NumChannels > 2)
376368
{
377-
dbg_msg("sound/opus", "only mono/stereo supported. channels=%d, file='%s'", NumChannels, pFilename);
369+
dbg_msg("sound/opus", "only mono/stereo supported. channels=%d, file='%s'", NumChannels, pContext);
378370
op_free(pOpusFile);
379-
mem_free(pFileData);
380371
lock_unlock(m_SoundLock);
381372
return CSampleHandle();
382373
}
383374

384375
int TotalSamples = op_pcm_total(pOpusFile, -1);
385376
if(TotalSamples < 0)
386377
{
387-
dbg_msg("sound/opus", "failed to get number of samples, error %d. file='%s'", TotalSamples, pFilename);
378+
dbg_msg("sound/opus", "failed to get number of samples, error %d. file='%s'", TotalSamples, pContext);
388379
op_free(pOpusFile);
389-
mem_free(pFileData);
390380
lock_unlock(m_SoundLock);
391381
return CSampleHandle();
392382
}
@@ -395,7 +385,6 @@ ISound::CSampleHandle CSound::LoadOpus(const char *pFilename)
395385
if(SampleID < 0)
396386
{
397387
op_free(pOpusFile);
398-
mem_free(pFileData);
399388
lock_unlock(m_SoundLock);
400389
return CSampleHandle();
401390
}
@@ -404,7 +393,6 @@ ISound::CSampleHandle CSound::LoadOpus(const char *pFilename)
404393
if(!pSample->m_pData)
405394
{
406395
op_free(pOpusFile);
407-
mem_free(pFileData);
408396
lock_unlock(m_SoundLock);
409397
return CSampleHandle();
410398
}
@@ -417,8 +405,7 @@ ISound::CSampleHandle CSound::LoadOpus(const char *pFilename)
417405
{
418406
mem_free(pSample->m_pData);
419407
op_free(pOpusFile);
420-
mem_free(pFileData);
421-
dbg_msg("sound/opus", "op_read error %d at %d. file='%s'", Read, Pos, pFilename);
408+
dbg_msg("sound/opus", "op_read error %d at %d. file='%s'", Read, Pos, pContext);
422409
return CSampleHandle();
423410
}
424411
else if(Read == 0) // EOF
@@ -428,7 +415,6 @@ ISound::CSampleHandle CSound::LoadOpus(const char *pFilename)
428415
}
429416

430417
op_free(pOpusFile);
431-
mem_free(pFileData);
432418

433419
pSample->m_Channels = NumChannels;
434420
pSample->m_Rate = 48000;
@@ -438,13 +424,56 @@ ISound::CSampleHandle CSound::LoadOpus(const char *pFilename)
438424
pSample->m_PausedAt = 0;
439425

440426
if(m_pConfig->m_Debug)
441-
dbg_msg("sound/opus", "loaded %s (%d samples, %d channels)", pFilename, TotalSamples, NumChannels);
427+
dbg_msg("sound/opus", "loaded %s (%d samples, %d channels)", pContext, TotalSamples, NumChannels);
442428

443429
RateConvert(SampleID);
444430
lock_unlock(m_SoundLock);
445431
return CreateSampleHandle(SampleID);
446432
}
447433

434+
ISound::CSampleHandle CSound::LoadOpus(const char *pFilename)
435+
{
436+
// don't waste memory on sound when we are stress testing
437+
#ifdef CONF_DEBUG
438+
if(m_pConfig->m_DbgStress)
439+
return CSampleHandle();
440+
#endif
441+
442+
// no need to load sound when we are running with no sound
443+
if(!m_SoundEnabled)
444+
return CSampleHandle();
445+
446+
if(!m_pStorage)
447+
return CSampleHandle();
448+
449+
unsigned char *pFileData;
450+
unsigned FileSize;
451+
if(!m_pStorage->ReadFile(pFilename, IStorage::TYPE_ALL, (void **) &pFileData, &FileSize))
452+
{
453+
dbg_msg("sound/opus", "failed to open file. filename='%s'", pFilename);
454+
return CSampleHandle();
455+
}
456+
457+
ISound::CSampleHandle Sample = LoadOpusMemory(pFilename, pFileData, FileSize);
458+
mem_free(pFileData);
459+
return Sample;
460+
}
461+
462+
bool CSound::UnloadSample(CSampleHandle *pSampleID)
463+
{
464+
if(!pSampleID)
465+
return false;
466+
467+
if(m_aSamples[pSampleID->Id()].m_pData)
468+
{
469+
mem_free(m_aSamples[pSampleID->Id()].m_pData);
470+
m_aSamples[pSampleID->Id()].m_pData = 0;
471+
pSampleID->Invalidate();
472+
return true;
473+
}
474+
return false;
475+
}
476+
448477
void CSound::SetListenerPos(float x, float y)
449478
{
450479
m_CenterX = (int) x;

src/engine/client/sound.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ class CSound : public IEngineSound
2424

2525
virtual bool IsSoundEnabled() { return m_SoundEnabled != 0; }
2626

27+
virtual CSampleHandle LoadOpusMemory(const char *pContext, const unsigned char *pData, int DataSize);
2728
virtual CSampleHandle LoadOpus(const char *pFilename);
29+
virtual bool UnloadSample(CSampleHandle *pSampleID);
2830

2931
virtual void SetListenerPos(float x, float y);
3032
virtual void SetChannelVolume(int ChannelID, float Vol);

src/engine/shared/storage.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class CStorage : public IStorage
6969
fs_makedir(GetPath(TYPE_SAVE, "screenshots/auto", aPath, sizeof(aPath)));
7070
fs_makedir(GetPath(TYPE_SAVE, "maps", aPath, sizeof(aPath)));
7171
fs_makedir(GetPath(TYPE_SAVE, "downloadedmaps", aPath, sizeof(aPath)));
72+
fs_makedir(GetPath(TYPE_SAVE, "downloadedres", aPath, sizeof(aPath)));
7273
fs_makedir(GetPath(TYPE_SAVE, "skins", aPath, sizeof(aPath)));
7374
fs_makedir(GetPath(TYPE_SAVE, "editor", aPath, sizeof(aPath)));
7475
}

src/engine/sound.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ class ISound : public IInterface
2828

2929
bool IsValid() const { return Id() >= 0; }
3030
int Id() const { return m_Id; }
31+
void Invalidate() { m_Id = -1; }
3132
};
3233

3334
virtual bool IsSoundEnabled() = 0;
3435

36+
virtual CSampleHandle LoadOpusMemory(const char *pContext, const unsigned char *pData, int DataSize) = 0;
3537
virtual CSampleHandle LoadOpus(const char *pFilename) = 0;
38+
virtual bool UnloadSample(CSampleHandle *pSampleID) = 0;
3639

3740
virtual void SetChannelVolume(int ChannelID, float Volume) = 0;
3841
virtual void SetListenerPos(float x, float y) = 0;

0 commit comments

Comments
 (0)