Compare commits

...

2 Commits

Author SHA1 Message Date
Asuro
155339917d static puzzle data! 2025-03-13 00:41:38 +01:00
Asuro
f3f994fd8b add hashes 2025-03-12 22:29:52 +01:00
21 changed files with 368 additions and 145 deletions

View File

@@ -26,9 +26,10 @@ namespace Generated
{
)END";
constexpr char StructHeader1[] =
constexpr char StructHeader2[] =
R"END( struct %s
{
static constexpr uint32_t Hash = %u;
)END";
constexpr char StructField4[] =
@@ -39,9 +40,10 @@ namespace Generated
R"END( };
)END";
constexpr char EnumHeader3[] =
constexpr char EnumHeader4[] =
R"END( struct %s
{
static constexpr uint32_t Hash = %u;
static constexpr int32_t EntryCount = %u;
enum Enum : %s
{
@@ -100,7 +102,7 @@ namespace Generated
)END";
constexpr char LoadFuncBodyType3[] = R"END( isOk = Load(%sobj[i].%s, %u, serializer) && isOk;
)END";
constexpr char LoadFuncBodyEnum1[] = R"END( auto val = (%s)obj[i];
constexpr char LoadFuncBodyEnum2[] = R"END( %s& val = (%s&)obj[i];
isOk = Load(&val, 1, serializer) && isOk;
)END";
constexpr char LoadFuncBodyEnd[] = R"END( }
@@ -192,8 +194,11 @@ void CppFileWriter::WriteEnums(const Def::DefinitionFile& definitions)
{
const Def::Enum& e = definitions.Enums[enumIdx];
Write(
WriteTemplates::EnumHeader3, e.Name, e.EntryCount, Generated::KnownType::CName[(int32_t)e.EnumType.Native]);
Write(WriteTemplates::EnumHeader4,
e.Name,
e.Hash,
e.EntryCount,
Generated::KnownType::CName[(int32_t)e.EnumType.Native]);
for (int32_t entryIdx = 0; entryIdx < e.EntryCount; ++entryIdx)
{
Write(WriteTemplates::EnumField1, e.EntryNames[entryIdx]);
@@ -223,7 +228,7 @@ void CppFileWriter::WriteTypes(const Def::DefinitionFile& definitions)
{
const Def::Type& t = definitions.Types[typeIdx];
Write(WriteTemplates::StructHeader1, t.Name);
Write(WriteTemplates::StructHeader2, t.Name, t.Hash);
for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx)
{
char Type[64]{0};
@@ -234,7 +239,7 @@ void CppFileWriter::WriteTypes(const Def::DefinitionFile& definitions)
{
bx::snprintf(Array, sizeof(Array), "[%u]", ArraySize);
}
Write(WriteTemplates::StructField4, Type, t.FieldNames[fieldIdx], Array, t.FieldVaules[fieldIdx]);
Write(WriteTemplates::StructField4, Type, t.FieldNames[fieldIdx], Array, t.FieldValues[fieldIdx]);
}
Write(WriteTemplates::StructEnd);
}
@@ -257,7 +262,7 @@ void CppFileWriter::WriteSaveLoadMethods(const Def::DefinitionFile& definitions)
WriteCpp(WriteTemplates::SaveFuncBodyEnd);
WriteCpp(WriteTemplates::LoadFuncBodyStart1, nameBuf);
WriteCpp(WriteTemplates::LoadFuncBodyEnum1, fieldBuf);
WriteCpp(WriteTemplates::LoadFuncBodyEnum2, fieldBuf, fieldBuf);
WriteCpp(WriteTemplates::LoadFuncBodyEnd);
}
for (int32_t typeIdx = 0; typeIdx < definitions.TypeCount; ++typeIdx)

View File

@@ -3,6 +3,8 @@
#include "Logging.h"
#include "MiniDef.h"
#include "TypeDef.h"
#include "bx/hash.h"
#include "bx/string.h"
#include <bx/filepath.h>
#include <ctype.h>
@@ -165,7 +167,7 @@ Parser::Result Parser::HandleType()
Def::Type& t = Definitions.Types[Definitions.TypeCount];
for (int32_t i = 0; i < Def::MaxFields; ++i)
{
bx::strCopy(t.FieldVaules[i], sizeof(t.FieldVaules[i]), "{}");
bx::strCopy(t.FieldValues[i], sizeof(t.FieldValues[i]), "{}");
}
CHECK(ReadName(t.Name));
@@ -203,11 +205,11 @@ Parser::Result Parser::HandleType()
CHECK(ExpectChar("("));
CHECK(ExpectChar("\""));
int32_t Remaining = bx::min(GetRemaining(), (int32_t)BX_COUNTOF(Def::Type::FieldVaules[0]));
int32_t Remaining = bx::min(GetRemaining(), (int32_t)BX_COUNTOF(Def::Type::FieldValues[0]));
for (int32_t i = 0; i < Remaining; ++i)
{
if (*ReadPtr != '\\' && CmpAdvance("\"", Res)) break;
t.FieldVaules[t.FieldCount][i] = *ReadPtr;
t.FieldValues[t.FieldCount][i] = *ReadPtr;
ReadPtr++;
}
if (Res != OK) return Res;
@@ -404,7 +406,7 @@ Parser::Result Parser::ReadOptionalEnumValues(Def::Enum& Enum, int32_t EntryIdx)
for (int32_t i = 0; i < Remaining; ++i)
{
if (CmpAdvance("\"", Res)) break;
Enum.ExtraStringFields[extraIdx][EntryIdx][i] = *ReadPtr;
Enum.ExtraStringFields[EntryIdx][extraIdx][i] = *ReadPtr;
ReadPtr++;
}
if (Res != OK) return Res;
@@ -425,6 +427,59 @@ int32_t Parser::GetRemaining()
{
return &Buffer[BufferSize] - ReadPtr;
}
uint32_t Parser::CalculateTypeHash(const Def::Type& t)
{
bx::HashMurmur2A hash;
hash.begin();
for (int32_t i = 0; i < t.FieldCount; ++i)
{
hash.add(t.FieldNames[i]);
hash.add(t.FieldArraySizes[i]);
Def::EFieldType fieldType = t.FieldTypes[i].FieldKind;
if (fieldType == Def::EFieldType::Native)
{
hash.add(t.FieldTypes[i].Native);
}
else if (fieldType == Def::EFieldType::DefinedClass)
{
Def::Type& dependType = Definitions.Types[t.FieldTypes[i].TypeIdx];
if (dependType.Hash == 0)
{
CalculateTypeHash(dependType);
}
hash.add(dependType.Hash);
}
else if (fieldType == Def::EFieldType::DefinedEnum)
{
hash.add(Definitions.Enums[t.FieldTypes[i].TypeIdx].Hash);
}
else
{
LOG_ERROR(0, "TODO!");
}
}
return hash.end();
}
void Parser::CalculateHashes()
{
for (int32_t i = 0; i < Definitions.EnumCount; ++i)
{
Def::Enum& e = Definitions.Enums[i];
bx::HashMurmur2A hash;
hash.begin();
hash.add(e.EnumType.Native);
e.Hash = hash.end();
}
for (int32_t i = 0; i < Definitions.TypeCount; ++i)
{
Def::Type& t = Definitions.Types[i];
if (t.Hash == 0)
{
t.Hash = CalculateTypeHash(t);
}
}
}
Parser FileParser;
CppFileWriter Writer;
@@ -460,6 +515,8 @@ int main(int argc, const char** argv)
return 1;
}
LOG(0, "Finished parsing!");
FileParser.CalculateHashes();
Writer.GenerateCpp(outPath, FileParser.Definitions);
return 0;

View File

@@ -76,6 +76,7 @@ class Parser
public:
Result Parse();
void CalculateHashes();
private:
int32_t GetRemaining();
@@ -94,6 +95,8 @@ class Parser
Result ReadTypeToken();
Result ReadOptionalEnumValues(Def::Enum& Enum, int32_t EntryIdx);
uint32_t CalculateTypeHash(const Def::Type& t);
void ErrorLine()
{
char line[64]{0};

View File

@@ -6,7 +6,7 @@ namespace Def
{
constexpr int32_t MaxNameLength = 64;
constexpr int32_t MaxFields = 64;
constexpr int32_t MaxExtraEnumFields = 1;
constexpr int32_t MaxExtraEnumFields = 2;
enum class EFieldType
{
Native,
@@ -26,8 +26,9 @@ namespace Def
FieldType FieldTypes[MaxFields];
char FieldNames[MaxFields][MaxNameLength];
uint32_t FieldArraySizes[MaxFields]{0};
char FieldVaules[MaxFields][128]{0};
char FieldValues[MaxFields][128]{0};
char Name[MaxNameLength]{0};
uint32_t Hash = 0;
};
struct Enum
@@ -39,6 +40,7 @@ namespace Def
char ExtraStringFieldNames[MaxExtraEnumFields][MaxNameLength];
char ExtraStringFields[MaxFields][MaxExtraEnumFields][MaxNameLength];
char Name[MaxNameLength]{0};
uint32_t Hash = 0;
};
struct DefinitionFile

View File

@@ -43,6 +43,10 @@ namespace Game
uint16_t SelectedDebugLevel = UINT16_MAX;
uint64_t ImguiIniSize = 0;
char ImguiIni[4096]{0};
static constexpr uint32_t MaxAssets = 128;
uint32_t AssetCount = 0;
uint32_t AssetHandles[MaxAssets]{0};
char AssetHandlePaths[MaxAssets][128];
};
struct GameInstance

View File

@@ -74,7 +74,7 @@ namespace Game
needReset |= PuzzleTiles.Setup(storagePtr, needReset);
needReset |= UIQuads.Setup(storagePtr, needReset);
Generated::Setup(PuzzleData);
Generated::Setup();
bx::Error err;
bx::DirectoryReader dirIter;

View File

@@ -1,3 +1,4 @@
#include "Global.h"
#include "Log.h"
#include "Mesh.h"
#include "bx/bx.h"
@@ -8,6 +9,8 @@
#include "bx/string.h"
#include "rendering/Rendering.h"
#include "Instance.h"
#define TINYGLTF_IMPLEMENTATION
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
@@ -139,6 +142,15 @@ namespace Game
if (LoadMesh(mod, fullPath.getCPtr(), modelFileIsBinary[i]))
{
mod.AssetHandle = CrcPath(fullPath.getCPtr());
auto& inst = GetInstance();
if (inst.DebugData.AssetCount < inst.DebugData.MaxAssets)
{
inst.DebugData.AssetHandles[inst.DebugData.AssetCount] = mod.AssetHandle;
bx::strCopy(inst.DebugData.AssetHandlePaths[inst.DebugData.AssetCount],
sizeof(inst.DebugData.AssetHandlePaths[inst.DebugData.AssetCount]),
fullPath.getCPtr());
++inst.DebugData.AssetCount;
}
++writeI;
}
else

View File

@@ -1,10 +1,9 @@
#include "Log.h"
#include "Puzzle.h"
#include "bx/string.h"
#include "imgui.h"
#include "rendering/Rendering.h"
#include "bx/bx.h"
#include "imgui.h"
#include <cassert>
namespace
@@ -16,25 +15,43 @@ namespace
{1, 0},
};
Generated::StaticPuzzleData* StaticDataInstance = nullptr;
Generated::StaticPuzzleData StaticData;
} // namespace
namespace Generated
{
void Setup(StaticPuzzleData& data)
void Setup()
{
StaticDataInstance = &data;
LOG("Setting up static puzzle data");
for (int32_t i = 0; i < BX_COUNTOF(data.Cards); ++i)
{
data.Cards[i].ModelHandle = Game::GameRendering::Get().GetModelHandleFromPath("models/w straight.glb");
}
LoadStaticPuzzleData();
}
StaticPuzzleData& GetStaticPuzzleData()
{
assert(StaticDataInstance != nullptr);
return *StaticDataInstance;
return StaticData;
}
void LoadStaticPuzzleData()
{
Deserializer ser;
ser.Init("game/data/static/puzzle.dat");
if (ser.ReadT("SPUZ", StaticData))
{
LOG("Successfully loaded static puzzle data!");
}
ser.Finish();
}
void SaveStaticPuzzleData()
{
auto& data = GetStaticPuzzleData();
Serializer ser;
ser.Init("game/data/static/puzzle.dat");
if (ser.WriteT("SPUZ", GetStaticPuzzleData()))
{
LOG("Successfully saved static puzzle data!");
}
ser.Finish();
}
const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H)
{
@@ -167,6 +184,18 @@ namespace Generated
namespace Generated
{
constexpr float UIPuzBoxSize = 26;
const char* GetShortNodeName(const PuzzleNode& node)
{
PuzzleElementType::Enum elemMax = PuzzleElementType::None;
for (int32_t i = 0; i < BX_COUNTOF(node.PlacedTypes); ++i)
{
if (node.PlacedTypes[i] > elemMax) elemMax = node.PlacedTypes[i];
}
return PuzzleElementType::ShortName[elemMax];
}
bool RenderDebugUI(PuzzleData& obj)
{
bool dataChanged = false;
@@ -197,6 +226,47 @@ namespace Generated
dataChanged = true;
}
ImGui::PopID();
ImVec2 puzCursorStart = ImGui::GetCursorScreenPos();
auto& drawList = *ImGui::GetWindowDrawList();
for (int32_t y = 0; y < obj.HeightTiles; ++y)
{
for (int32_t x = 0; x < obj.WidthTiles; ++x)
{
PuzzleNode& node = obj.PlacedNodes[Puzzle::Config::MaxPuzzleSizeTiles * y + x];
ImVec2 pos = ImVec2{puzCursorStart.x + x * UIPuzBoxSize + 5, puzCursorStart.y + y * UIPuzBoxSize};
ImGui::SetCursorScreenPos(pos);
ImGui::Text("%s", GetShortNodeName(node));
}
}
for (int32_t y = 0; y <= obj.HeightTiles; ++y)
{
ImVec2 linePos = {puzCursorStart.x, puzCursorStart.y + y * UIPuzBoxSize};
drawList.AddLine(linePos,
{linePos.x + obj.WidthTiles * UIPuzBoxSize, linePos.y},
y % Puzzle::Config::CardSize == 0 ? 0xFFFFFFFF : 0x11FFFFFF);
}
for (int32_t x = 0; x <= obj.WidthTiles; ++x)
{
ImVec2 linePos = {puzCursorStart.x + x * UIPuzBoxSize, puzCursorStart.y};
drawList.AddLine(linePos,
{linePos.x, linePos.y + obj.HeightTiles * UIPuzBoxSize},
x % Puzzle::Config::CardSize == 0 ? 0xFFFFFFFF : 0x11FFFFFF);
}
ImGui::Spacing();
ImGui::Spacing();
if (ImGui::TreeNodeEx("Available Cards", ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_Framed))
{
for (int32_t i = 0; i < obj.AvailableCardCount; ++i)
{
ImGui::Text("Card");
}
ImGui::TreePop();
}
}
ImGui::End();

View File

@@ -18,112 +18,6 @@ namespace Puzzle
static constexpr uint32_t MaxAvailableStacks = 16;
static constexpr uint32_t MaxGoalPositions = 16;
};
// struct PuzPos
// {
// int8_t X = 0;
// int8_t Y = 0;
// PuzPos& operator+=(const PuzPos& rhs)
// {
// X += rhs.X;
// Y += rhs.Y;
// return *this;
// }
// friend PuzPos operator+(PuzPos lhs, const PuzPos& rhs)
// {
// lhs += rhs;
// return lhs;
// }
// };
// struct ElemPos
// {
// PuzPos Position;
// uint8_t ElemIdx = 0;
// };
// enum class PuzzleElementType : uint8_t
// {
// None,
// WaterIn,
// WaterGoal,
// WaterChannel,
// ElectricIn,
// ElectricGoal,
// Blocked,
// Bridge,
// };
// struct PuzzleNode
// {
// PuzzleElementType PlacedTypes[Config::MaxElementsPerTile]{PuzzleElementType::None};
// bool HasElement(PuzzleElementType search) const;
// bool IsEmpty() const;
// };
// struct StaticPuzzleCard
// {
// PuzzleNode Nodes[Config::NodesPerCard];
// uint16_t ModelHandle = 0;
// };
// struct StaticPuzzleCardHandle
// {
// uint16_t Idx = UINT16_MAX;
// bool IsValid()
// {
// return Idx != UINT16_MAX;
// }
// };
// struct StaticPuzzleData
// {
// StaticPuzzleCard Cards[64];
// void Setup();
// static StaticPuzzleData& Get();
// const StaticPuzzleCard& GetCard(StaticPuzzleCardHandle H) const;
// };
// struct PlacedPuzzleCard
// {
// StaticPuzzleCardHandle RefCard;
// PuzPos Position;
// uint8_t Rotation = 0;
// bool IsLocked = false;
// };
// struct PuzzleCardStack
// {
// StaticPuzzleCardHandle RefCard;
// uint8_t MaxAvailableCount = 0;
// uint8_t UsedCount = 0;
// uint8_t GetRemainingCount();
// };
// struct PuzzleData
// {
// uint32_t AvailableCardCount = 0;
// PuzzleCardStack AvailableCards[Config::MaxAvailableStacks];
// uint32_t PlacedCardCount = 0;
// PlacedPuzzleCard PlacedCards[Config::MaxCardsInPuzzle];
// // Indexed by board position
// PuzzleNode PlacedNodes[Config::MaxTilesInPuzzle];
// uint32_t GoalPositionCount = 0;
// ElemPos GoalPositions[Config::MaxGoalPositions];
// const PuzzleNode& GetNodeAt(PuzPos pos) const;
// PuzzleElementType GetElementAt(ElemPos pos) const;
// char PuzzleName[32]{"Unnamed"};
// bool RenderDebugUI();
// };
} // namespace Puzzle
namespace Generated
@@ -131,8 +25,10 @@ namespace Generated
PuzPos operator+=(PuzPos lhs, const PuzPos& rhs);
PuzPos operator+(PuzPos lhs, const PuzPos& rhs);
void Setup(StaticPuzzleData& data);
void Setup();
StaticPuzzleData& GetStaticPuzzleData();
void LoadStaticPuzzleData();
void SaveStaticPuzzleData();
const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H);
bool HasElement(const PuzzleNode& node, PuzzleElementType::Enum search);
bool IsEmpty(const PuzzleNode& node);

View File

@@ -48,6 +48,7 @@ namespace Game
instance.UsedScratchAmount = 0;
SetShared(shared);
SetInstance(instance);
Generated::LoadStaticPuzzleData();
SetupInstance.Rendering.Setup();
instance.GameLevel.Setup(shared.Game);
instance.IsInitialized = true;

39
src/game/Tools.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include "Global.h"
#include "Instance.h"
#include "Tools.h"
#include "rendering/Rendering.h"
#include <imgui.h>
namespace Tools
{
const char* GetAssetPath(uint32_t assetHandle)
{
const auto& inst = Game::GetInstance();
for (int32_t j = 0; j < inst.DebugData.AssetCount; ++j)
{
if (inst.DebugData.AssetHandles[j] == assetHandle)
{
return inst.DebugData.AssetHandlePaths[j];
}
}
return "---";
}
void ModelDropdown(uint16_t& modelHandle)
{
auto& R = Game::GameRendering::Get();
const char* name = GetAssetPath(R.Models[modelHandle].AssetHandle);
if (ImGui::BeginCombo("Models", name))
{
for (int32_t i = 0; i < R.ModelCount; ++i)
{
if (ImGui::Selectable(GetAssetPath(R.Models[i].AssetHandle), i == modelHandle))
{
modelHandle = i;
}
}
ImGui::EndCombo();
}
}
} // namespace Tools

7
src/game/Tools.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include <cstdint>
namespace Tools
{
void ModelDropdown(uint16_t& modelHandle);
} // namespace Tools

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -12,14 +12,14 @@ type ElemPos
enum PuzzleElementType(u8)
{
None GameName("Empty")
WaterIn GameName("Water Source")
WaterGoal GameName("Water Goal")
WaterChannel GameName("Water Channel")
ElectricIn GameName("Electricity Source")
ElectricGoal GameName("Electricity Goal")
Blocked GameName("Blocked")
Bridge GameName("Bridge")
None GameName("Empty") ShortName(" ")
WaterIn GameName("Water Source") ShortName("~+")
WaterGoal GameName("Water Goal") ShortName("~-")
WaterChannel GameName("Water Channel") ShortName("~")
ElectricIn GameName("Electricity Source") ShortName("e+")
ElectricGoal GameName("Electricity Goal") ShortName("e-")
Blocked GameName("Blocked") ShortName("B")
Bridge GameName("Bridge") ShortName("#")
}
type PuzzleNode

View File

@@ -3,6 +3,7 @@
#include "../Instance.h"
#include "../Log.h"
#include "../Mesh.h"
#include "../Tools.h"
#include "Rendering.h"
#include "SDL3/SDL_events.h"
@@ -515,6 +516,8 @@ namespace Game
for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i)
{
auto& puzzleData = level.Puzzles[i].Data;
if (puzzleData.PuzzleName[0] == 0) continue;
bool isSelected = debug.SelectedDebugLevel == i;
ImGui::PushID("selectable");
if (ImGui::Selectable(puzzleData.PuzzleName, isSelected))
@@ -525,6 +528,7 @@ namespace Game
if (isSelected)
{
ImGui::PushID("edit field");
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
ImGui::InputText("", puzzleData.PuzzleName, sizeof(Generated::PuzzleData::PuzzleName));
ImGui::PopID();
@@ -536,6 +540,53 @@ namespace Game
}
}
ImGui::End();
if (ImGui::Begin("Cards"))
{
Generated::StaticPuzzleData& staticData = Generated::GetStaticPuzzleData();
if (ImGui::Button("Save"))
{
Generated::SaveStaticPuzzleData();
}
ImGui::SameLine();
if (ImGui::Button("Reload"))
{
Generated::LoadStaticPuzzleData();
}
for (int32_t i = 0; i < BX_COUNTOF(staticData.Cards); ++i)
{
ImGui::Separator();
Generated::StaticPuzzleCard& card = staticData.Cards[i];
ImGui::PushID(i);
ImGui::Text("%i", i);
Tools::ModelDropdown(card.ModelHandle);
for (int32_t y = 0; y < Puzzle::Config::CardSize; ++y)
{
ImGui::PushID(y);
for (int32_t x = 0; x < Puzzle::Config::CardSize; ++x)
{
if (x > 0) ImGui::SameLine();
ImGui::PushID(x);
auto& node = card.Nodes[y * Puzzle::Config::CardSize + x];
if (ImGui::Button(Generated::PuzzleElementType::ShortName[node.PlacedTypes[0]], {26, 24}))
{
int32_t newVal = int32_t(node.PlacedTypes[0]) + 1;
if (newVal >= Generated::PuzzleElementType::EntryCount)
{
newVal = 0;
}
node.PlacedTypes[0] = Generated::PuzzleElementType::Enum(newVal);
}
ImGui::PopID();
}
ImGui::PopID();
}
ImGui::PopID();
}
}
ImGui::End();
}
GetInstance().GameLevel.Update();

View File

@@ -96,7 +96,7 @@ namespace Game
UIVisibilityState UIVisible = UIVisibilityState::Game;
DitherData DitherTextures;
private:
public:
bgfx::UniformHandle DefaultSampler;
Texture Textures[8];
Material Materials[8];

View File

@@ -1,4 +1,7 @@
#pragma once
#include "../game/Log.h"
#include "bx/string.h"
#include <bx/file.h>
#include <cstdint>
@@ -17,9 +20,23 @@ namespace Generated
return Err.isOk();
}
template <typename T> bool WriteT(const char* _4cc, const T& data)
{
if (!Write(_4cc, 4)) return false;
uint32_t hash = data.Hash;
if (!Write(&hash, sizeof(hash))) return false;
uint32_t size = sizeof(T);
if (!Write(&size, sizeof(size))) return false;
return Save(&data, 1, *this);
}
bool Write(const void* data, uint32_t size)
{
Writer.write(data, size, &Err);
if (!Err.isOk()) LOG_ERROR("Write error: %s", Err.getMessage().getCPtr());
return Err.isOk();
}
@@ -45,9 +62,47 @@ namespace Generated
bool Read(void* data, uint32_t size)
{
Reader.read(data, size, &Err);
if (!Err.isOk()) LOG_ERROR("Read error: %s", Err.getMessage().getCPtr());
return Err.isOk();
}
template <typename T> bool ReadT(const char* _4cc, T& data)
{
char magic[5]{0};
if (!Read(magic, 4)) return false;
bx::StringView given{_4cc, 4};
bx::StringView loaded{magic, 4};
if (bx::strCmp(given, loaded) != 0)
{
LOG_ERROR("Magic mismatch! %s != %s", _4cc, magic);
return false;
}
uint32_t hash = 0;
if (!Read(&hash, sizeof(hash))) return false;
if (data.Hash != hash)
{
LOG_ERROR("Hash mismatch! %u != %u", data.Hash, hash);
return false;
}
uint32_t size = 0;
if (!Read(&size, sizeof(size))) return false;
if (sizeof(T) != size)
{
LOG_ERROR("Size mismatch! %u != %u", sizeof(T), size);
return false;
}
if (!Load(&data, 1, *this))
{
LOG_ERROR("Failed to load: %s", Err.getMessage().getCPtr());
return false;
}
return true;
}
void Finish()
{
Reader.close();

View File

@@ -17,7 +17,7 @@ namespace Generated
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
auto val = (int32_t)obj[i];
int32_t& val = (int32_t&)obj[i];
isOk = Load(&val, 1, serializer) && isOk;
}
return isOk;

View File

@@ -5,6 +5,7 @@ namespace Generated
{
struct PuzzleElementType
{
static constexpr uint32_t Hash = 2024002654;
static constexpr int32_t EntryCount = 8;
enum Enum : int32_t
{
@@ -39,42 +40,61 @@ namespace Generated
"Blocked",
"Bridge",
};
static constexpr char ShortName[EntryCount][64]
{
" ",
"~+",
"~-",
"~",
"e+",
"e-",
"B",
"#",
};
};
struct PuzPos
{
static constexpr uint32_t Hash = 1834398141;
int8_t X = {};
int8_t Y = {};
};
struct ElemPos
{
static constexpr uint32_t Hash = 3966109730;
PuzPos Position = {};
uint8_t ElemIdx = {};
};
struct PuzzleNode
{
static constexpr uint32_t Hash = 1417779061;
PuzzleElementType::Enum PlacedTypes[4] = {};
};
struct StaticPuzzleCard
{
static constexpr uint32_t Hash = 110653106;
PuzzleNode Nodes[4] = {};
uint16_t ModelHandle = {};
};
struct StaticPuzzleCardHandle
{
static constexpr uint32_t Hash = 1742502768;
uint16_t Idx = UINT16_MAX;
};
struct StaticPuzzleData
{
static constexpr uint32_t Hash = 1881743597;
StaticPuzzleCard Cards[64] = {};
};
struct PuzzleCardStack
{
static constexpr uint32_t Hash = 53538532;
StaticPuzzleCardHandle RefCard = {};
uint8_t MaxAvailableCount = {};
uint8_t UsedCount = {};
};
struct PlacedPuzzleCard
{
static constexpr uint32_t Hash = 3555575973;
StaticPuzzleCardHandle RefCard = {};
PuzPos Position = {};
uint8_t Rotation = {};
@@ -82,6 +102,7 @@ namespace Generated
};
struct PuzzleData
{
static constexpr uint32_t Hash = 2015691597;
uint8_t WidthTiles = {};
uint8_t HeightTiles = {};
uint32_t AvailableCardCount = {};