Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-toolchain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ jobs:
vcpkg-bincache-v2-${{ runner.os }}-

- name: Setup vcpkg
if: startsWith(inputs.preset, 'win32')
uses: lukka/run-vcpkg@v11
with:
runVcpkgInstall: false
Expand Down
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,8 @@ cmake-build-*/
## Ninja
.ninja_deps
.ninja_log
build.ninja
build.ninja

## vcpkg
vcpkg_installed/
vcpkg_installed
30 changes: 30 additions & 0 deletions Core/GameEngine/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ set(GAMEENGINE_SRC
# Include/Common/GameType.h
Include/Common/GameUtility.h
# Include/Common/Geometry.h
# Include/Common/JSONChunkInput.h
# Include/Common/JSONChunkOutput.h
# Include/Common/GlobalData.h
# Include/Common/Handicap.h
# Include/Common/IgnorePreferences.h
Expand Down Expand Up @@ -647,6 +649,8 @@ set(GAMEENGINE_SRC
# Source/Common/System/CriticalSection.cpp
# Source/Common/System/DataChunk.cpp
Source/Common/System/Debug.cpp
# Source/Common/System/JSONChunkInput.cpp
# Source/Common/System/JSONChunkOutput.cpp
# Source/Common/System/Directory.cpp
# Source/Common/System/DisabledTypes.cpp
# Source/Common/System/encrypt.cpp
Expand Down Expand Up @@ -1146,6 +1150,15 @@ set(GAMEENGINE_SRC
# Source/Precompiled/PreRTS.cpp
)

if(NOT IS_VS6_BUILD)
list(APPEND GAMEENGINE_SRC
${CMAKE_CURRENT_SOURCE_DIR}/Include/Common/JSONChunkInput.h
${CMAKE_CURRENT_SOURCE_DIR}/Include/Common/JSONChunkOutput.h
${CMAKE_CURRENT_SOURCE_DIR}/Source/Common/System/JSONChunkInput.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Source/Common/System/JSONChunkOutput.cpp
)
endif()

if(RTS_GAMEMEMORY_ENABLE)
# Uses the original Game Memory implementation.
list(APPEND GAMEENGINE_SRC
Expand All @@ -1165,6 +1178,21 @@ else()
endif()


if (NOT IS_VS6_BUILD)
find_package(nlohmann_json CONFIG)
if (TARGET nlohmann_json::nlohmann_json)
# Uses nlohmann-json from vcpkg
set(NLOHMANN_JSON_TARGET nlohmann_json::nlohmann_json)
else()
# Uses nlohmann-json from github repository
include(${CMAKE_SOURCE_DIR}/cmake/nlohmann-json.cmake)
set(NLOHMANN_JSON_TARGET nlohmann_json)
endif()
else()
# VC6 doesn't support C++11, so nlohmann-json is not available
set(NLOHMANN_JSON_TARGET "")
endif()

add_library(corei_gameengine_private INTERFACE)
add_library(corei_gameengine_public INTERFACE)

Expand All @@ -1180,6 +1208,7 @@ target_link_libraries(corei_gameengine_private INTERFACE

target_compile_definitions(corei_gameengine_private INTERFACE
IG_DEBUG_STACKTRACE
$<$<NOT:$<BOOL:${IS_VS6_BUILD}>>:RTS_HAS_JSON_CHUNK>
)

target_precompile_headers(corei_gameengine_private INTERFACE
Expand All @@ -1199,4 +1228,5 @@ target_link_libraries(corei_gameengine_public INTERFACE
d3d8lib
gamespy::gamespy
stlport
$<$<NOT:$<BOOL:${IS_VS6_BUILD}>>:${NLOHMANN_JSON_TARGET}>
)
137 changes: 137 additions & 0 deletions Core/GameEngine/Include/Common/JSONChunkInput.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 TheSuperHackers
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#ifdef RTS_HAS_JSON_CHUNK

#include "Common/GameMemory.h"
#include "Common/Dict.h"
#include <nlohmann/json.hpp>

typedef unsigned short DataChunkVersionType;

class JSONChunkInput;

struct JSONChunkInfo
{
AsciiString label;
AsciiString parentLabel;
DataChunkVersionType version;
Int dataSize;
};

typedef Bool (*JSONChunkParserPtr)( JSONChunkInput &file, JSONChunkInfo *info, void *userData );

class JSONParser : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(JSONParser, "JSONParser")
public:
JSONParser *next;

JSONChunkParserPtr parser;
AsciiString label;
AsciiString parentLabel;
void *userData;
};
EMPTY_DTOR(JSONParser)

class JSONInputChunk : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(JSONInputChunk, "JSONInputChunk")
public:
JSONInputChunk* next;
AsciiString label;
DataChunkVersionType version;
nlohmann::json* data;
size_t childIndex; // Index into _children array for nested chunks
size_t itemIndex; // Index into _items array for reading values
};
EMPTY_DTOR(JSONInputChunk)

class JSONChunkInput
{
protected:
nlohmann::json m_root;
JSONParser* m_parserList;
JSONInputChunk* m_chunkStack;
std::vector<nlohmann::json*> m_chunkArray;
size_t m_currentChunkIndex;

void clearChunkStack( void );

public:
void *m_currentObject;
void *m_userData;

public:
JSONChunkInput( const char* jsonData, size_t jsonSize );
~JSONChunkInput();

void registerParser( const AsciiString& label, const AsciiString& parentLabel, JSONChunkParserPtr parser, void *userData = NULL );

Bool parse( void *userData = NULL );

Bool isValidFileType(void);
AsciiString openDataChunk(DataChunkVersionType *ver );
void closeDataChunk( void );

Bool atEndOfFile( void );
Bool atEndOfChunk( void );

void reset( void );

AsciiString getChunkLabel( void );
DataChunkVersionType getChunkVersion( void );
unsigned int getChunkDataSize( void );
unsigned int getChunkDataSizeLeft( void );

// Unnamed reads (for backwards compatibility - reads from positional array)
Real readReal(void);
Int readInt(void);
Byte readByte(void);

AsciiString readAsciiString(void);
UnicodeString readUnicodeString(void);
Dict readDict(void);
void readArrayOfBytes(char *ptr, Int len);

NameKeyType readNameKey(void);

// Named reads (reads from object with field names for human-readable JSON)
Real readReal(const char* name);
Int readInt(const char* name);
Byte readByte(const char* name);
Bool readBool(const char* name);

AsciiString readAsciiString(const char* name);
UnicodeString readUnicodeString(const char* name);
Dict readDict(const char* name);
void readArrayOfBytes(const char* name, char *ptr, Int len);

NameKeyType readNameKey(const char* name);

// Type-converting reads
Bool readBool(); // Read boolean from _items array

// Read int that may be stored as string enum - returns the value if int, or -1 if string
// If string, the enum string is stored in outEnumStr (caller must convert it)
Int readIntOrEnumString(AsciiString& outEnumStr);
};

#endif // RTS_HAS_JSON_CHUNK
97 changes: 97 additions & 0 deletions Core/GameEngine/Include/Common/JSONChunkOutput.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
** Command & Conquer Generals(tm)
** Copyright 2025 TheSuperHackers
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#ifdef RTS_HAS_JSON_CHUNK

#include "Common/GameMemory.h"
#include "Common/Dict.h"
#include "Common/DataChunk.h"
#include <nlohmann/json.hpp>
#include <string>

class JSONOutputChunk : public MemoryPoolObject
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(JSONOutputChunk, "JSONOutputChunk")
public:
JSONOutputChunk* next;
AsciiString label;
nlohmann::json* data;
};
EMPTY_DTOR(JSONOutputChunk)

class JSONChunkOutput : public ChunkOutputStream
{
protected:
nlohmann::json m_root;
nlohmann::json m_toc;
JSONOutputChunk* m_chunkStack;
UnsignedInt m_nextID;

public:
JSONChunkOutput( void );
~JSONChunkOutput();

void openDataChunk( const char *name, DataChunkVersionType ver );
void closeDataChunk( void );

// Unnamed writes (for backwards compatibility - writes to positional array)
void writeReal(Real r);
void writeInt(Int i);
void writeByte(Byte b);
void writeAsciiString(const AsciiString& string);
void writeUnicodeString(UnicodeString string);
void writeArrayOfBytes(char *ptr, Int len);
void writeDict(const Dict& d);
void writeNameKey(const NameKeyType key);

// Named writes (writes to object with field names for human-readable JSON)
void writeReal(const char* name, Real r);
void writeInt(const char* name, Int i);
void writeByte(const char* name, Byte b);
void writeAsciiString(const char* name, const AsciiString& string);
void writeUnicodeString(const char* name, UnicodeString string);
void writeArrayOfBytes(const char* name, char *ptr, Int len);
void writeDict(const char* name, const Dict& d);
void writeNameKey(const char* name, const NameKeyType key);

// Binary-only writes (no-op for JSON output)
void writeBinaryOnlyInt(Int i) { (void)i; }
void writeBinaryOnlyReal(Real r) { (void)r; }
void writeBinaryOnlyString(const AsciiString& s) { (void)s; }
void writeBinaryOnlyNameKey(NameKeyType key) { (void)key; }

// JSON-only writes (writes to JSON field)
void writeJSONOnlyString(const char* name, const AsciiString& value);
void writeJSONOnlyInt(const char* name, Int i);
void writeJSONOnlyBool(const char* name, Bool b);

// Type-converting writes (JSON writes string to _items)
void writeParameterType(Int type, const char* typeName);
void writeBoolAsByte(Bool b);
void writeBoolAsByte(const char* name, Bool b);
void writeBoolAsInt(Bool b); // JSON writes true/false to _items

// Enum writes (JSON writes string to _items, ignores int value)
void writeEnumAsInt(Int value, const char* enumStr);

std::string getJSONString( void );
};

#endif // RTS_HAS_JSON_CHUNK
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,9 @@ static PoolSizeRec PoolSizes[] =
{ "Mapping", 128, 32 },
{ "OutputChunk", 32, 32 },
{ "InputChunk", 32, 32 },
{ "JSONOutputChunk", 128, 32 },
{ "JSONParser", 128, 32 },
{ "JSONInputChunk", 128, 32 },
{ "AnimateWindow", 32, 32 },
{ "GameFont", 32, 32 },
{ "NetCommandRef", 256, 32 },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,9 @@ static PoolSizeRec PoolSizes[] =
{ "Mapping", 384, 64 },
{ "OutputChunk", 32, 32 },
{ "InputChunk", 32, 32 },
{ "JSONOutputChunk", 128, 32 },
{ "JSONParser", 128, 32 },
{ "JSONInputChunk", 128, 32 },
{ "AnimateWindow", 32, 32 },
{ "GameFont", 32, 32 },
{ "NetCommandRef", 256, 32 },
Expand Down
Loading
Loading