Compare commits

...

2 Commits

Author SHA1 Message Date
Asuro
ffad8f8460 loading works!! 2025-03-11 01:19:13 +01:00
Asuro
c7377c3452 save works! 2025-03-10 22:45:15 +01:00
15 changed files with 806 additions and 217 deletions

1
.gitattributes vendored
View File

@@ -4,3 +4,4 @@
*.png filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text *.jpg filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text *.blend filter=lfs diff=lfs merge=lfs -text
*.pzl filter=lfs diff=lfs merge=lfs -text

View File

@@ -1,8 +1,10 @@
#include "CppGen.h" #include "CppGen.h"
#include "Logging.h" #include "Logging.h"
#include "TypeDef.h" #include "TypeDef.h"
#include "bx/string.h"
#include <bx/file.h> #include <bx/file.h>
#include <cstdarg>
#include <memoryapi.h> #include <memoryapi.h>
#include <winnt.h> #include <winnt.h>
@@ -11,10 +13,15 @@
namespace WriteTemplates namespace WriteTemplates
{ {
constexpr char FileHeader[] = constexpr char FileHeaderStart[] =
R"END(#pragma once R"END(#pragma once
#include "Def.h" #include "Def.h"
namespace Generated
{
)END";
constexpr char FileCppStart[] = R"END(#include "Generated.h"
namespace Generated namespace Generated
{ {
)END"; )END";
@@ -36,7 +43,7 @@ namespace Generated
R"END( struct %s R"END( struct %s
{ {
static constexpr int32_t EntryCount = %u; static constexpr int32_t EntryCount = %u;
enum class Enum : %s enum Enum : %s
{ {
)END"; )END";
@@ -62,8 +69,96 @@ namespace Generated
constexpr char FileEnd[] = constexpr char FileEnd[] =
R"END(} R"END(}
)END"; )END";
constexpr char SaveFuncHeader1[] =
R"END( bool Save(const %s* obj, uint32_t count, Serializer& serializer);
)END";
constexpr char SaveFuncBodyStart1[] = R"END( bool Save(const %s* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
)END";
constexpr char SaveFuncBodyType3[] = R"END( isOk = Save(%sobj[i].%s, %u, serializer) && isOk;
)END";
constexpr char SaveFuncBodyEnum1[] = R"END( auto val = (%s)obj[i];
isOk = Save(&val, 1, serializer) && isOk;
)END";
constexpr char SaveFuncBodyEnd[] = R"END( }
return isOk;
}
)END";
constexpr char LoadFuncHeader1[] =
R"END( bool Load(%s* obj, uint32_t count, Deserializer& serializer);
)END";
constexpr char LoadFuncBodyStart1[] = R"END( bool Load(%s* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
)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];
isOk = Load(&val, 1, serializer) && isOk;
)END";
constexpr char LoadFuncBodyEnd[] = R"END( }
return isOk;
}
)END";
} // namespace WriteTemplates } // namespace WriteTemplates
void CppFileWriter::InitBuffer(WriteBuffer& buf)
{
if (buf.Data != nullptr)
{
LOG_ERROR(0, "Multiple writes not supported yet!");
return;
}
buf.Data =
reinterpret_cast<char*>(VirtualAlloc(nullptr, BufferRequestSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
if (buf.Data == nullptr)
{
LOG_ERROR(0, "Failed to allocate write memory!");
return;
}
buf.WrittenBytes = 0;
}
bool CppFileWriter::WriteBufferToDisk(const bx::FilePath& path, const WriteBuffer& buf)
{
bx::Error error;
bx::FileWriter writer;
LOG(0, "Writing to %s", path.getCPtr());
if (!writer.open(path, false, &error))
{
LOG_ERROR(0, "Failed to open output file: %s", error.getMessage().getCPtr());
return false;
}
writer.write(buf.Data, buf.WrittenBytes, &error);
if (!error.isOk())
{
LOG_ERROR(0, "Failed to write to output file: %s", error.getMessage().getCPtr());
}
writer.close();
LOG(0, "Finished writing!");
return true;
}
void CppFileWriter::WriteInternal(WriteBuffer& buf, const char* templateStr, va_list args)
{
if (buf.Data == nullptr)
{
LOG_ERROR(0, "Wrote too early!");
return;
}
buf.WrittenBytes += bx::vsnprintf(&buf.Data[buf.WrittenBytes], BufferRequestSize, templateStr, args);
}
void CppFileWriter::PrintTypeName(char* buf, void CppFileWriter::PrintTypeName(char* buf,
int32_t bufSize, int32_t bufSize,
const Def::FieldType& type, const Def::FieldType& type,
@@ -87,6 +182,7 @@ void CppFileWriter::PrintTypeName(char* buf,
else if (type.FieldKind == Def::EFieldType::DefinedEnum) else if (type.FieldKind == Def::EFieldType::DefinedEnum)
{ {
bx::strCopy(buf, bufSize, definitions.Enums[type.TypeIdx].Name); bx::strCopy(buf, bufSize, definitions.Enums[type.TypeIdx].Name);
bx::strCat(buf, bufSize, "::Enum");
} }
} }
@@ -143,64 +239,90 @@ void CppFileWriter::WriteTypes(const Def::DefinitionFile& definitions)
Write(WriteTemplates::StructEnd); Write(WriteTemplates::StructEnd);
} }
} }
void CppFileWriter::WriteSaveLoadMethods(const Def::DefinitionFile& definitions)
{
char nameBuf[64]{0};
char fieldBuf[64]{0};
for (int32_t enumIdx = 0; enumIdx < definitions.EnumCount; ++enumIdx)
{
const Def::Enum& e = definitions.Enums[enumIdx];
bx::snprintf(nameBuf, sizeof(nameBuf), "%s::Enum", e.Name);
PrintTypeName(fieldBuf, sizeof(fieldBuf), e.EnumType, definitions);
Write(WriteTemplates::SaveFuncHeader1, nameBuf);
Write(WriteTemplates::LoadFuncHeader1, nameBuf);
WriteCpp(WriteTemplates::SaveFuncBodyStart1, nameBuf);
WriteCpp(WriteTemplates::SaveFuncBodyEnum1, fieldBuf);
WriteCpp(WriteTemplates::SaveFuncBodyEnd);
WriteCpp(WriteTemplates::LoadFuncBodyStart1, nameBuf);
WriteCpp(WriteTemplates::LoadFuncBodyEnum1, fieldBuf);
WriteCpp(WriteTemplates::LoadFuncBodyEnd);
}
for (int32_t typeIdx = 0; typeIdx < definitions.TypeCount; ++typeIdx)
{
const Def::Type& t = definitions.Types[typeIdx];
Write(WriteTemplates::SaveFuncHeader1, t.Name);
Write(WriteTemplates::LoadFuncHeader1, t.Name);
WriteCpp(WriteTemplates::SaveFuncBodyStart1, t.Name);
for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx)
{
WriteCpp(WriteTemplates::SaveFuncBodyType3,
t.FieldArraySizes[fieldIdx] > 0 ? "" : "&",
t.FieldNames[fieldIdx],
bx::max(1, t.FieldArraySizes[fieldIdx]));
}
WriteCpp(WriteTemplates::SaveFuncBodyEnd);
WriteCpp(WriteTemplates::LoadFuncBodyStart1, t.Name);
for (int32_t fieldIdx = 0; fieldIdx < t.FieldCount; ++fieldIdx)
{
WriteCpp(WriteTemplates::LoadFuncBodyType3,
t.FieldArraySizes[fieldIdx] > 0 ? "" : "&",
t.FieldNames[fieldIdx],
bx::max(1, t.FieldArraySizes[fieldIdx]));
}
WriteCpp(WriteTemplates::LoadFuncBodyEnd);
}
}
void CppFileWriter::GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions) void CppFileWriter::GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions)
{ {
LOG(0, "Generating..."); LOG(0, "Generating output files...");
// Allocate write buffer InitBuffer(HeaderWrite);
if (FileWriteBuffer != nullptr) InitBuffer(CppWrite);
{
LOG_ERROR(0, "Multiple writes not supported yet!");
return;
}
FileWriteBuffer =
reinterpret_cast<char*>(VirtualAlloc(nullptr, BufferRequestSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE));
if (FileWriteBuffer == nullptr)
{
LOG_ERROR(0, "Failed to allocate write memory!");
return;
}
FileWriterWritten = 0;
// Write text to buffer Write(WriteTemplates::FileHeaderStart);
Write(WriteTemplates::FileHeader); WriteCpp(WriteTemplates::FileCppStart);
WriteEnums(definitions); WriteEnums(definitions);
WriteTypes(definitions); WriteTypes(definitions);
WriteSaveLoadMethods(definitions);
Write(WriteTemplates::FileEnd); Write(WriteTemplates::FileEnd);
WriteCpp(WriteTemplates::FileEnd);
// Write buffer to disk
bx::Error error;
bx::FileWriter writer;
bx::FilePath writePath = outDir;
// std::filesystem::create_directory(outDir.getCPtr()); // std::filesystem::create_directory(outDir.getCPtr());
writePath.join("Generated.h"); bx::FilePath writePathHeader = outDir;
bx::FilePath writePathCpp = outDir;
LOG(0, "Writing to %s", writePath.getCPtr()); writePathHeader.join("Generated.h");
if (!writer.open(writePath, false, &error)) writePathCpp.join("Generated.cpp");
{ WriteBufferToDisk(writePathHeader, HeaderWrite);
LOG_ERROR(0, "Failed to open output file: %s", error.getMessage().getCPtr()); WriteBufferToDisk(writePathCpp, CppWrite);
return;
} }
writer.write(FileWriteBuffer, FileWriterWritten, &error); void CppFileWriter::Write(const char* templateStr, ...)
if (!error.isOk())
{ {
LOG_ERROR(0, "Failed to write to output file: %s", error.getMessage().getCPtr()); va_list args;
} va_start(args, templateStr);
writer.close(); WriteInternal(HeaderWrite, templateStr, args);
LOG(0, "Finished writing!"); va_end(args);
} }
void CppFileWriter::Write(const char* Template, ...) void CppFileWriter::WriteCpp(const char* templateStr, ...)
{ {
if (FileWriteBuffer == nullptr) va_list args;
{ va_start(args, templateStr);
LOG_ERROR(0, "Wrote too early!"); WriteInternal(CppWrite, templateStr, args);
return; va_end(args);
}
va_list ArgList;
va_start(ArgList, Template);
FileWriterWritten += bx::vsnprintf(&FileWriteBuffer[FileWriterWritten], BufferRequestSize, Template, ArgList);
va_end(ArgList);
} }

View File

@@ -4,17 +4,29 @@
#include "bx/filepath.h" #include "bx/filepath.h"
struct WriteBuffer
{
char* Data = nullptr;
uint64_t WrittenBytes = 0;
};
struct CppFileWriter struct CppFileWriter
{ {
private: private:
static constexpr size_t BufferRequestSize = 1024 * 1024 * 1024; static constexpr size_t BufferRequestSize = 1024 * 1024 * 1024;
char* FileWriteBuffer = nullptr; WriteBuffer HeaderWrite;
uint64_t FileWriterWritten = 0; WriteBuffer CppWrite;
void InitBuffer(WriteBuffer& buf);
bool WriteBufferToDisk(const bx::FilePath& path, const WriteBuffer& buf);
void WriteInternal(WriteBuffer& buf, const char* templateStr, va_list args);
public: public:
void PrintTypeName(char* buf, int32_t bufSize, const Def::FieldType& type, const Def::DefinitionFile& definitions); void PrintTypeName(char* buf, int32_t bufSize, const Def::FieldType& type, const Def::DefinitionFile& definitions);
void WriteEnums(const Def::DefinitionFile& definitions); void WriteEnums(const Def::DefinitionFile& definitions);
void WriteTypes(const Def::DefinitionFile& definitions); void WriteTypes(const Def::DefinitionFile& definitions);
void WriteSaveLoadMethods(const Def::DefinitionFile& definitions);
void GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions); void GenerateCpp(const bx::FilePath& outDir, const Def::DefinitionFile& definitions);
void Write(const char* Template, ...); void Write(const char* templateStr, ...);
void WriteCpp(const char* templateStr, ...);
}; };

View File

@@ -6,6 +6,10 @@
#include "Puzzle.h" #include "Puzzle.h"
#include "SDL3/SDL_mouse.h" #include "SDL3/SDL_mouse.h"
#include "bgfx/bgfx.h" #include "bgfx/bgfx.h"
#include "bx/error.h"
#include "bx/file.h"
#include "bx/filepath.h"
#include "bx/string.h"
#include "imgui.h" #include "imgui.h"
#include "rendering/Rendering.h" #include "rendering/Rendering.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
@@ -70,7 +74,58 @@ namespace Game
needReset |= PuzzleTiles.Setup(storagePtr, needReset); needReset |= PuzzleTiles.Setup(storagePtr, needReset);
needReset |= UIQuads.Setup(storagePtr, needReset); needReset |= UIQuads.Setup(storagePtr, needReset);
PuzzleData.Setup(); Generated::Setup(PuzzleData);
bx::Error err;
bx::DirectoryReader dirIter;
bx::FileInfo info;
bx::FilePath puzzleDirPath{"game/data/puzzles"};
uint32_t puzIdx = 0;
if (dirIter.open(puzzleDirPath, &err))
{
while (true)
{
int32_t readCount = dirIter.read(&info, sizeof(info), &err);
if (readCount == 0) break;
if (err.isOk())
{
if (info.type != bx::FileType::File) continue;
bx::StringView pathEnd = info.filePath.getExt();
if (bx::strCmpI(pathEnd, ".pzl") != 0) continue;
if (puzIdx >= BX_COUNTOF(Puzzles))
{
LOG_WARN("Too many puzzles!");
break;
}
bx::FilePath fullPath = puzzleDirPath;
fullPath.join(info.filePath);
LOG("Loading %s", fullPath.getCPtr());
Generated::Deserializer ser;
ser.Init(fullPath);
if (Generated::Load(&Puzzles[puzIdx].Data, 1, ser))
{
Puzzles[puzIdx].Setup();
++puzIdx;
}
else
{
LOG_WARN("Failed to load puzzle!");
}
ser.Finish();
}
else
{
LOG_ERROR("Failed parsing file name at %s:\n%s", puzzleDirPath.getCPtr(), err.getMessage());
break;
}
}
}
else
{
LOG_ERROR("Failed to open puzzle dir at %s:\n%s", puzzleDirPath.getCPtr(), err.getMessage().getCPtr());
}
if (Cubes.Count == 0) if (Cubes.Count == 0)
{ {
@@ -255,7 +310,7 @@ namespace Game
for (uint32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI) for (uint32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI)
{ {
const Puzzle::PlacedPuzzleCard& card = Data.PlacedCards[cardI]; const Generated::PlacedPuzzleCard& card = Data.PlacedCards[cardI];
Level& level = GetInstance().GameLevel; Level& level = GetInstance().GameLevel;
TileHandles[cardI] = level.PuzzleTiles.New(); TileHandles[cardI] = level.PuzzleTiles.New();
UIPlacedCards[cardI] = level.UIQuads.New(); UIPlacedCards[cardI] = level.UIQuads.New();
@@ -283,9 +338,10 @@ namespace Game
for (int32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI) for (int32_t cardI = 0; cardI < Data.PlacedCardCount; ++cardI)
{ {
Puzzle::PlacedPuzzleCard& card = Data.PlacedCards[cardI]; Generated::PlacedPuzzleCard& card = Data.PlacedCards[cardI];
if (!card.RefCard.IsValid()) continue; if (!Generated::IsValid(card.RefCard)) continue;
const Puzzle::StaticPuzzleCard& cData = Puzzle::StaticPuzzleData::Get().GetCard(card.RefCard); const Generated::StaticPuzzleCard& cData =
Generated::GetCard(Generated::GetStaticPuzzleData(), card.RefCard);
level.PuzzleTiles.Get(TileHandles[cardI]).EData.ModelHandle = cData.ModelHandle; level.PuzzleTiles.Get(TileHandles[cardI]).EData.ModelHandle = cData.ModelHandle;
auto& quad = level.UIQuads.Get(UIPlacedCards[cardI]); auto& quad = level.UIQuads.Get(UIPlacedCards[cardI]);

View File

@@ -128,7 +128,7 @@ namespace Game
struct WorldPuzzle struct WorldPuzzle
{ {
static constexpr Vec2 WorldCardSize{10.0f, 10.0f}; static constexpr Vec2 WorldCardSize{10.0f, 10.0f};
Puzzle::PuzzleData Data; Generated::PuzzleData Data;
Vec3 WorldPosition; Vec3 WorldPosition;
PuzzleTileEntityHandle TileHandles[Puzzle::Config::MaxCardsInPuzzle]; PuzzleTileEntityHandle TileHandles[Puzzle::Config::MaxCardsInPuzzle];
UIQuadEntityHandle UIPlacedCards[Puzzle::Config::MaxCardsInPuzzle]; UIQuadEntityHandle UIPlacedCards[Puzzle::Config::MaxCardsInPuzzle];
@@ -146,7 +146,7 @@ namespace Game
EntityManager<UIQuadEntity, UIQuadEntityHandle, 1024> UIQuads; EntityManager<UIQuadEntity, UIQuadEntityHandle, 1024> UIQuads;
public: public:
Puzzle::StaticPuzzleData PuzzleData; Generated::StaticPuzzleData PuzzleData;
WorldPuzzle Puzzles[1]; WorldPuzzle Puzzles[1];
public: public:

View File

@@ -9,73 +9,79 @@
namespace namespace
{ {
static constexpr Puzzle::PuzPos Dirs[4]{ static constexpr Generated::PuzPos Dirs[4]{
{-1, 0}, {-1, 0},
{0, -1}, {0, -1},
{0, 1}, {0, 1},
{1, 0}, {1, 0},
}; };
Puzzle::StaticPuzzleData* StaticDataInstance = nullptr; Generated::StaticPuzzleData* StaticDataInstance = nullptr;
} // namespace } // namespace
namespace Puzzle namespace Generated
{ {
void StaticPuzzleData::Setup() void Setup(StaticPuzzleData& data)
{ {
StaticDataInstance = this; StaticDataInstance = &data;
LOG("Setting up static puzzle data"); LOG("Setting up static puzzle data");
for (int32_t i = 0; i < BX_COUNTOF(Cards); ++i) for (int32_t i = 0; i < BX_COUNTOF(data.Cards); ++i)
{ {
Cards[i].ModelHandle = Game::GameRendering::Get().GetModelHandleFromPath("models/w straight.glb"); data.Cards[i].ModelHandle = Game::GameRendering::Get().GetModelHandleFromPath("models/w straight.glb");
} }
} }
StaticPuzzleData& StaticPuzzleData::Get() StaticPuzzleData& GetStaticPuzzleData()
{ {
assert(StaticDataInstance != nullptr); assert(StaticDataInstance != nullptr);
return *StaticDataInstance; return *StaticDataInstance;
} }
const StaticPuzzleCard& StaticPuzzleData::GetCard(StaticPuzzleCardHandle H) const const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H)
{ {
assert(H.IsValid()); assert(IsValid(H));
return Cards[H.Idx]; return data.Cards[H.Idx];
} }
bool PuzzleNode::HasElement(PuzzleElementType search) const bool HasElement(const PuzzleNode& node, PuzzleElementType::Enum search)
{ {
for (int32_t i = 0; i < Config::MaxElementsPerTile; ++i) for (int32_t i = 0; i < Puzzle::Config::MaxElementsPerTile; ++i)
{ {
if (PlacedTypes[i] == search) return true; if (node.PlacedTypes[i] == search) return true;
} }
return false; return false;
} }
bool PuzzleNode::IsEmpty() const bool IsEmpty(const PuzzleNode& node)
{ {
for (int32_t i = 0; i < Config::MaxElementsPerTile; ++i) for (int32_t i = 0; i < Puzzle::Config::MaxElementsPerTile; ++i)
{ {
if (PlacedTypes[i] != PuzzleElementType::None) return false; if (node.PlacedTypes[i] != PuzzleElementType::None) return false;
} }
return true; return true;
} }
uint8_t PuzzleCardStack::GetRemainingCount() bool IsValid(StaticPuzzleCardHandle h)
{ {
assert(MaxAvailableCount >= UsedCount); return h.Idx != UINT16_MAX;
return MaxAvailableCount - UsedCount;
} }
const PuzzleNode& PuzzleData::GetNodeAt(PuzPos pos) const uint8_t GetRemainingCount(const PuzzleCardStack& stack)
{ {
assert(pos.X < Config::MaxPuzzleSizeCards && pos.Y < Config::MaxPuzzleSizeCards && pos.X >= 0 && pos.Y >= 0); assert(stack.MaxAvailableCount >= stack.UsedCount);
return PlacedNodes[pos.Y * Config::MaxPuzzleSizeCards + pos.X]; return stack.MaxAvailableCount - stack.UsedCount;
} }
PuzzleElementType PuzzleData::GetElementAt(ElemPos pos) const const PuzzleNode& GetNodeAt(const PuzzleData& puz, PuzPos pos)
{ {
assert(pos.ElemIdx < Config::MaxElementsPerTile); assert(pos.X < Puzzle::Config::MaxPuzzleSizeCards && pos.Y < Puzzle::Config::MaxPuzzleSizeCards && pos.X >= 0 &&
const PuzzleNode& node = GetNodeAt(pos.Position); pos.Y >= 0);
return puz.PlacedNodes[pos.Y * Puzzle::Config::MaxPuzzleSizeCards + pos.X];
}
PuzzleElementType::Enum GetElementAt(const PuzzleData& puz, ElemPos pos)
{
assert(pos.ElemIdx < Puzzle::Config::MaxElementsPerTile);
const PuzzleNode& node = GetNodeAt(puz, pos.Position);
return node.PlacedTypes[pos.ElemIdx]; return node.PlacedTypes[pos.ElemIdx];
} }
@@ -95,26 +101,26 @@ namespace Puzzle
bool PuzzleSolver::IsExitSatisfied(const PuzzleData& puzzle, ElemPos pos) bool PuzzleSolver::IsExitSatisfied(const PuzzleData& puzzle, ElemPos pos)
{ {
const PuzzleNode& goalNode = puzzle.GetNodeAt(pos.Position); const PuzzleNode& goalNode = GetNodeAt(puzzle, pos.Position);
PuzzleElementType goalType = puzzle.GetElementAt(pos); PuzzleElementType::Enum goalType = GetElementAt(puzzle, pos);
uint32_t currentPositionQueueIdx = 0; uint32_t currentPositionQueueIdx = 0;
uint32_t positionQueueCount = 0; uint32_t positionQueueCount = 0;
PuzPos positionQueue[Config::MaxTilesInPuzzle]; PuzPos positionQueue[Puzzle::Config::MaxTilesInPuzzle];
positionQueue[0] = pos.Position; positionQueue[0] = pos.Position;
positionQueueCount++; positionQueueCount++;
while (positionQueueCount > 0) while (positionQueueCount > 0)
{ {
assert(currentPositionQueueIdx < Config::MaxTilesInPuzzle); assert(currentPositionQueueIdx < Puzzle::Config::MaxTilesInPuzzle);
PuzPos currentPos = positionQueue[currentPositionQueueIdx]; PuzPos currentPos = positionQueue[currentPositionQueueIdx];
for (PuzPos dir : Dirs) for (PuzPos dir : Dirs)
{ {
PuzPos nextPos = currentPos + dir; PuzPos nextPos = currentPos + dir;
if (IsValidGoalConnection(puzzle, nextPos, currentPos, goalType)) if (IsValidGoalConnection(puzzle, nextPos, currentPos, goalType))
{ {
const PuzzleNode& node = puzzle.GetNodeAt(nextPos); const PuzzleNode& node = GetNodeAt(puzzle, nextPos);
for (PuzzleElementType e : node.PlacedTypes) for (PuzzleElementType::Enum e : node.PlacedTypes)
{ {
if (IsValidSource(e, goalType)) if (IsValidSource(e, goalType))
{ {
@@ -133,46 +139,50 @@ namespace Puzzle
bool PuzzleSolver::IsValidGoalConnection(const PuzzleData& puzzle, bool PuzzleSolver::IsValidGoalConnection(const PuzzleData& puzzle,
PuzPos flowFrom, PuzPos flowFrom,
PuzPos flowTo, PuzPos flowTo,
PuzzleElementType goalType) PuzzleElementType::Enum goalType)
{ {
const PuzzleNode& from = puzzle.GetNodeAt(flowFrom); const PuzzleNode& from = GetNodeAt(puzzle, flowFrom);
const PuzzleNode& to = puzzle.GetNodeAt(flowTo); const PuzzleNode& to = GetNodeAt(puzzle, flowTo);
if (goalType == PuzzleElementType::WaterGoal) if (goalType == PuzzleElementType::WaterGoal)
{ {
return from.HasElement(PuzzleElementType::WaterIn) || from.HasElement(PuzzleElementType::WaterChannel) || return HasElement(from, PuzzleElementType::WaterIn) || HasElement(from, PuzzleElementType::WaterChannel) ||
from.HasElement(PuzzleElementType::WaterGoal); HasElement(from, PuzzleElementType::WaterGoal);
} }
else if (goalType == PuzzleElementType::ElectricGoal) else if (goalType == PuzzleElementType::ElectricGoal)
{ {
return from.HasElement(PuzzleElementType::ElectricIn) || from.HasElement(PuzzleElementType::ElectricGoal) || return HasElement(from, PuzzleElementType::ElectricIn) ||
from.IsEmpty(); HasElement(from, PuzzleElementType::ElectricGoal) || IsEmpty(from);
} }
assert(false); assert(false);
return false; return false;
} }
bool PuzzleSolver::IsValidSource(PuzzleElementType sourceType, PuzzleElementType goalType) bool PuzzleSolver::IsValidSource(PuzzleElementType::Enum sourceType, PuzzleElementType::Enum goalType)
{ {
return (sourceType == PuzzleElementType::WaterIn && goalType == PuzzleElementType::WaterGoal) || return (sourceType == PuzzleElementType::WaterIn && goalType == PuzzleElementType::WaterGoal) ||
(sourceType == PuzzleElementType::ElectricIn && goalType == PuzzleElementType::ElectricGoal); (sourceType == PuzzleElementType::ElectricIn && goalType == PuzzleElementType::ElectricGoal);
} }
bool PuzzleData::RenderDebugUI() } // namespace Generated
namespace Generated
{
bool RenderDebugUI(PuzzleData& obj)
{ {
bool dataChanged = false; bool dataChanged = false;
bool isVisible = true; bool isVisible = true;
if (ImGui::Begin("Puzzle", &isVisible)) if (ImGui::Begin("Puzzle", &isVisible))
{ {
ImGui::Text("%s", PuzzleName); ImGui::Text("%s", obj.PuzzleName);
int32_t W = S.WidthTiles; int32_t W = obj.WidthTiles;
int32_t H = S.HeightTiles; int32_t H = obj.HeightTiles;
ImGui::PushID("width"); ImGui::PushID("width");
ImGui::SetNextItemWidth(40); ImGui::SetNextItemWidth(40);
if (ImGui::DragInt("", &W, 0.3f, 0, Config::MaxPuzzleSizeTiles)) if (ImGui::DragInt("", &W, 0.3f, 0, Puzzle::Config::MaxPuzzleSizeTiles))
{ {
S.WidthTiles = uint8_t(W); obj.WidthTiles = uint8_t(W);
dataChanged = true; dataChanged = true;
} }
ImGui::PopID(); ImGui::PopID();
@@ -181,9 +191,9 @@ namespace Puzzle
ImGui::SameLine(); ImGui::SameLine();
ImGui::SetNextItemWidth(40); ImGui::SetNextItemWidth(40);
ImGui::PushID("height"); ImGui::PushID("height");
if (ImGui::DragInt("", &H, 0.3f, 0, Config::MaxPuzzleSizeTiles)) if (ImGui::DragInt("", &H, 0.3f, 0, Puzzle::Config::MaxPuzzleSizeTiles))
{ {
S.HeightTiles = uint8_t(H); obj.HeightTiles = uint8_t(H);
dataChanged = true; dataChanged = true;
} }
ImGui::PopID(); ImGui::PopID();
@@ -193,10 +203,43 @@ namespace Puzzle
if (dataChanged) if (dataChanged)
{ {
char path[128]{0}; char path[128]{0};
bx::snprintf(path, sizeof(path), "game/data/%s.pzl", PuzzleName); bx::snprintf(path, sizeof(path), "game/data/puzzles/%s.pzl", obj.PuzzleName);
SerializeStruct(&S, sizeof(S), path); Serializer ser;
ser.Init(path);
if (Save(&obj, 1, ser))
{
LOG("Saved to %s", path);
}
else
{
LOG_ERROR("Failed to save to %s", path);
}
ser.Finish();
} }
return isVisible; return isVisible;
} }
} // namespace Puzzle
PuzPos operator+=(PuzPos lhs, const PuzPos& rhs)
{
lhs.X += rhs.X;
lhs.Y += rhs.Y;
return lhs;
}
PuzPos operator+(PuzPos lhs, const PuzPos& rhs)
{
lhs += rhs;
return lhs;
}
PuzPos operator-=(PuzPos lhs, const PuzPos& rhs)
{
lhs.X -= rhs.X;
lhs.Y -= rhs.Y;
return lhs;
}
PuzPos operator-(PuzPos lhs, const PuzPos& rhs)
{
lhs -= rhs;
return lhs;
}
} // namespace Generated

View File

@@ -19,125 +19,139 @@ namespace Puzzle
static constexpr uint32_t MaxGoalPositions = 16; static constexpr uint32_t MaxGoalPositions = 16;
}; };
struct PuzPos // 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
{ {
int8_t X = 0; PuzPos operator+=(PuzPos lhs, const PuzPos& rhs);
int8_t Y = 0; PuzPos operator+(PuzPos lhs, const PuzPos& rhs);
PuzPos& operator+=(const PuzPos& rhs) void Setup(StaticPuzzleData& data);
{ StaticPuzzleData& GetStaticPuzzleData();
X += rhs.X; const StaticPuzzleCard& GetCard(const StaticPuzzleData& data, StaticPuzzleCardHandle H);
Y += rhs.Y; bool HasElement(const PuzzleNode& node, PuzzleElementType::Enum search);
return *this; bool IsEmpty(const PuzzleNode& node);
} bool IsValid(StaticPuzzleCardHandle h);
uint8_t GetRemainingCount(const PuzzleCardStack& stack);
friend PuzPos operator+(PuzPos lhs, const PuzPos& rhs) const PuzzleNode& GetNodeAt(const PuzzleData& puz, PuzPos pos);
{ PuzzleElementType::Enum GetElementAt(const PuzzleData& puz, ElemPos pos);
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
{
SER_HEADER(1, "PZZL");
Generated::PuzzleData S;
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();
};
struct PuzzleSolver struct PuzzleSolver
{ {
bool IsPuzzleSolved(const PuzzleData& puzzle); bool IsPuzzleSolved(const Generated::PuzzleData& puzzle);
bool IsExitSatisfied(const PuzzleData& puzzle, ElemPos pos); bool IsExitSatisfied(const Generated::PuzzleData& puzzle, ElemPos pos);
// This assumes flowFrom is already verified to be connected. // This assumes flowFrom is already verified to be connected.
bool IsValidGoalConnection(const PuzzleData& puzzle, bool IsValidGoalConnection(const Generated::PuzzleData& puzzle,
PuzPos flowFrom, PuzPos flowFrom,
PuzPos flowTo, PuzPos flowTo,
PuzzleElementType goalType); PuzzleElementType::Enum goalType);
bool IsValidSource(PuzzleElementType sourceType, PuzzleElementType goalType); bool IsValidSource(PuzzleElementType::Enum sourceType, PuzzleElementType::Enum goalType);
}; };
} // namespace Puzzle bool RenderDebugUI(PuzzleData& obj);
} // namespace Generated

Binary file not shown.

BIN
src/game/data/puzzles/test.pzl LFS Normal file

Binary file not shown.

View File

@@ -69,4 +69,5 @@ type PuzzleData
PuzzleNode PlacedNodes Arr(1024) PuzzleNode PlacedNodes Arr(1024)
u32 GoalPositionCount u32 GoalPositionCount
ElemPos GoalPositions Arr(16) ElemPos GoalPositions Arr(16)
str PuzzleName Arr(64)
} }

View File

@@ -511,6 +511,7 @@ namespace Game
if (ImGui::Begin("Puzzles")) if (ImGui::Begin("Puzzles"))
{ {
ImGui::Text("List"); ImGui::Text("List");
ImGui::Separator();
for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i)
{ {
auto& puzzleData = level.Puzzles[i].Data; auto& puzzleData = level.Puzzles[i].Data;
@@ -524,10 +525,10 @@ namespace Game
if (isSelected) if (isSelected)
{ {
ImGui::PushID("edit field"); ImGui::PushID("edit field");
ImGui::InputText("", puzzleData.PuzzleName, sizeof(Puzzle::PuzzleData::PuzzleName)); ImGui::InputText("", puzzleData.PuzzleName, sizeof(Generated::PuzzleData::PuzzleName));
ImGui::PopID(); ImGui::PopID();
if (!puzzleData.RenderDebugUI()) if (!Generated::RenderDebugUI(puzzleData))
{ {
debug.SelectedDebugLevel = UINT16_MAX; debug.SelectedDebugLevel = UINT16_MAX;
} }
@@ -540,13 +541,6 @@ namespace Game
GetInstance().GameLevel.Update(); GetInstance().GameLevel.Update();
GetInstance().GameLevel.Render(MainViewID, Models, Materials); GetInstance().GameLevel.Render(MainViewID, Models, Materials);
// bgfx::dbgTextPrintf(1, 1, 0x0F, "Time: %.1fs", GetInstance().Time.Now);
// for (int32_t i = 0; i < (int32_t)PerfCounterType::COUNT; ++i)
// {
// bgfx::dbgTextPrintf(
// 1, 2 + i, 0x0F, "%s Max: %.3fs", PerfCounterNames[i], shared.Window.PerfCounters[i].GetMax());
// }
// Finish Frame // Finish Frame
imguiEndFrame(); imguiEndFrame();

41
src/gen/Def.cpp Normal file
View File

@@ -0,0 +1,41 @@
#include "Def.h"
#define INST(T) \
template bool Save<T>(const T* obj, uint32_t count, Serializer& serializer); \
template bool Load<T>(T * obj, uint32_t count, Deserializer & serializer);
namespace Generated
{
template <typename T> bool Save(const T* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = serializer.Write(&obj[i], sizeof(obj[i])) && isOk;
}
return isOk;
}
template <typename T> bool Load(T* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = serializer.Read(&obj[i], sizeof(obj[i])) && isOk;
}
return isOk;
}
INST(uint8_t)
INST(uint16_t)
INST(uint32_t)
INST(uint64_t)
INST(int8_t)
INST(int16_t)
INST(int32_t)
INST(int64_t)
INST(float)
INST(double)
INST(bool)
INST(char)
} // namespace Generated

View File

@@ -1,2 +1,59 @@
#pragma once #pragma once
#include <bx/file.h>
#include <cstdint> #include <cstdint>
namespace Generated
{
struct Serializer
{
bx::Error Err;
bx::FilePath Path;
bx::FileWriter Writer;
bool Init(const bx::FilePath& path)
{
Path = path;
Writer.open(path, false, &Err);
return Err.isOk();
}
bool Write(const void* data, uint32_t size)
{
Writer.write(data, size, &Err);
return Err.isOk();
}
void Finish()
{
Writer.close();
}
};
struct Deserializer
{
bx::Error Err;
bx::FilePath Path;
bx::FileReader Reader;
bool Init(const bx::FilePath& path)
{
Path = path;
Reader.open(path, &Err);
return Err.isOk();
}
bool Read(void* data, uint32_t size)
{
Reader.read(data, size, &Err);
return Err.isOk();
}
void Finish()
{
Reader.close();
}
};
template <typename T> bool Save(const T* obj, uint32_t count, Serializer& serializer);
template <typename T> bool Load(T* obj, uint32_t count, Deserializer& serializer);
} // namespace Generated

221
src/gen/Generated.cpp Normal file
View File

@@ -0,0 +1,221 @@
#include "Generated.h"
namespace Generated
{
bool Save(const PuzzleElementType::Enum* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
auto val = (int32_t)obj[i];
isOk = Save(&val, 1, serializer) && isOk;
}
return isOk;
}
bool Load(PuzzleElementType::Enum* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
auto val = (int32_t)obj[i];
isOk = Load(&val, 1, serializer) && isOk;
}
return isOk;
}
bool Save(const PuzPos* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Save(&obj[i].X, 1, serializer) && isOk;
isOk = Save(&obj[i].Y, 1, serializer) && isOk;
}
return isOk;
}
bool Load(PuzPos* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Load(&obj[i].X, 1, serializer) && isOk;
isOk = Load(&obj[i].Y, 1, serializer) && isOk;
}
return isOk;
}
bool Save(const ElemPos* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Save(&obj[i].Position, 1, serializer) && isOk;
isOk = Save(&obj[i].ElemIdx, 1, serializer) && isOk;
}
return isOk;
}
bool Load(ElemPos* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Load(&obj[i].Position, 1, serializer) && isOk;
isOk = Load(&obj[i].ElemIdx, 1, serializer) && isOk;
}
return isOk;
}
bool Save(const PuzzleNode* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Save(obj[i].PlacedTypes, 4, serializer) && isOk;
}
return isOk;
}
bool Load(PuzzleNode* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Load(obj[i].PlacedTypes, 4, serializer) && isOk;
}
return isOk;
}
bool Save(const StaticPuzzleCard* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Save(obj[i].Nodes, 4, serializer) && isOk;
isOk = Save(&obj[i].ModelHandle, 1, serializer) && isOk;
}
return isOk;
}
bool Load(StaticPuzzleCard* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Load(obj[i].Nodes, 4, serializer) && isOk;
isOk = Load(&obj[i].ModelHandle, 1, serializer) && isOk;
}
return isOk;
}
bool Save(const StaticPuzzleCardHandle* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Save(&obj[i].Idx, 1, serializer) && isOk;
}
return isOk;
}
bool Load(StaticPuzzleCardHandle* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Load(&obj[i].Idx, 1, serializer) && isOk;
}
return isOk;
}
bool Save(const StaticPuzzleData* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Save(obj[i].Cards, 64, serializer) && isOk;
}
return isOk;
}
bool Load(StaticPuzzleData* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Load(obj[i].Cards, 64, serializer) && isOk;
}
return isOk;
}
bool Save(const PuzzleCardStack* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Save(&obj[i].RefCard, 1, serializer) && isOk;
isOk = Save(&obj[i].MaxAvailableCount, 1, serializer) && isOk;
isOk = Save(&obj[i].UsedCount, 1, serializer) && isOk;
}
return isOk;
}
bool Load(PuzzleCardStack* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Load(&obj[i].RefCard, 1, serializer) && isOk;
isOk = Load(&obj[i].MaxAvailableCount, 1, serializer) && isOk;
isOk = Load(&obj[i].UsedCount, 1, serializer) && isOk;
}
return isOk;
}
bool Save(const PlacedPuzzleCard* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Save(&obj[i].RefCard, 1, serializer) && isOk;
isOk = Save(&obj[i].Position, 1, serializer) && isOk;
isOk = Save(&obj[i].Rotation, 1, serializer) && isOk;
isOk = Save(&obj[i].IsLocked, 1, serializer) && isOk;
}
return isOk;
}
bool Load(PlacedPuzzleCard* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Load(&obj[i].RefCard, 1, serializer) && isOk;
isOk = Load(&obj[i].Position, 1, serializer) && isOk;
isOk = Load(&obj[i].Rotation, 1, serializer) && isOk;
isOk = Load(&obj[i].IsLocked, 1, serializer) && isOk;
}
return isOk;
}
bool Save(const PuzzleData* obj, uint32_t count, Serializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Save(&obj[i].WidthTiles, 1, serializer) && isOk;
isOk = Save(&obj[i].HeightTiles, 1, serializer) && isOk;
isOk = Save(&obj[i].AvailableCardCount, 1, serializer) && isOk;
isOk = Save(obj[i].AvailableCards, 16, serializer) && isOk;
isOk = Save(&obj[i].PlacedCardCount, 1, serializer) && isOk;
isOk = Save(obj[i].PlacedCards, 256, serializer) && isOk;
isOk = Save(obj[i].PlacedNodes, 1024, serializer) && isOk;
isOk = Save(&obj[i].GoalPositionCount, 1, serializer) && isOk;
isOk = Save(obj[i].GoalPositions, 16, serializer) && isOk;
isOk = Save(obj[i].PuzzleName, 64, serializer) && isOk;
}
return isOk;
}
bool Load(PuzzleData* obj, uint32_t count, Deserializer& serializer)
{
bool isOk = true;
for (uint32_t i = 0; i < count; ++i)
{
isOk = Load(&obj[i].WidthTiles, 1, serializer) && isOk;
isOk = Load(&obj[i].HeightTiles, 1, serializer) && isOk;
isOk = Load(&obj[i].AvailableCardCount, 1, serializer) && isOk;
isOk = Load(obj[i].AvailableCards, 16, serializer) && isOk;
isOk = Load(&obj[i].PlacedCardCount, 1, serializer) && isOk;
isOk = Load(obj[i].PlacedCards, 256, serializer) && isOk;
isOk = Load(obj[i].PlacedNodes, 1024, serializer) && isOk;
isOk = Load(&obj[i].GoalPositionCount, 1, serializer) && isOk;
isOk = Load(obj[i].GoalPositions, 16, serializer) && isOk;
isOk = Load(obj[i].PuzzleName, 64, serializer) && isOk;
}
return isOk;
}
}

View File

@@ -6,7 +6,7 @@ namespace Generated
struct PuzzleElementType struct PuzzleElementType
{ {
static constexpr int32_t EntryCount = 8; static constexpr int32_t EntryCount = 8;
enum class Enum : int32_t enum Enum : int32_t
{ {
None, None,
WaterIn, WaterIn,
@@ -52,7 +52,7 @@ namespace Generated
}; };
struct PuzzleNode struct PuzzleNode
{ {
PuzzleElementType PlacedTypes[4] = {}; PuzzleElementType::Enum PlacedTypes[4] = {};
}; };
struct StaticPuzzleCard struct StaticPuzzleCard
{ {
@@ -91,5 +91,26 @@ namespace Generated
PuzzleNode PlacedNodes[1024] = {}; PuzzleNode PlacedNodes[1024] = {};
uint32_t GoalPositionCount = {}; uint32_t GoalPositionCount = {};
ElemPos GoalPositions[16] = {}; ElemPos GoalPositions[16] = {};
char PuzzleName[64] = {};
}; };
bool Save(const PuzzleElementType::Enum* obj, uint32_t count, Serializer& serializer);
bool Load(PuzzleElementType::Enum* obj, uint32_t count, Deserializer& serializer);
bool Save(const PuzPos* obj, uint32_t count, Serializer& serializer);
bool Load(PuzPos* obj, uint32_t count, Deserializer& serializer);
bool Save(const ElemPos* obj, uint32_t count, Serializer& serializer);
bool Load(ElemPos* obj, uint32_t count, Deserializer& serializer);
bool Save(const PuzzleNode* obj, uint32_t count, Serializer& serializer);
bool Load(PuzzleNode* obj, uint32_t count, Deserializer& serializer);
bool Save(const StaticPuzzleCard* obj, uint32_t count, Serializer& serializer);
bool Load(StaticPuzzleCard* obj, uint32_t count, Deserializer& serializer);
bool Save(const StaticPuzzleCardHandle* obj, uint32_t count, Serializer& serializer);
bool Load(StaticPuzzleCardHandle* obj, uint32_t count, Deserializer& serializer);
bool Save(const StaticPuzzleData* obj, uint32_t count, Serializer& serializer);
bool Load(StaticPuzzleData* obj, uint32_t count, Deserializer& serializer);
bool Save(const PuzzleCardStack* obj, uint32_t count, Serializer& serializer);
bool Load(PuzzleCardStack* obj, uint32_t count, Deserializer& serializer);
bool Save(const PlacedPuzzleCard* obj, uint32_t count, Serializer& serializer);
bool Load(PlacedPuzzleCard* obj, uint32_t count, Deserializer& serializer);
bool Save(const PuzzleData* obj, uint32_t count, Serializer& serializer);
bool Load(PuzzleData* obj, uint32_t count, Deserializer& serializer);
} }