From 5de975b03c7200cc66188a4b1a76e1213524975d Mon Sep 17 00:00:00 2001 From: jbzdarkid Date: Thu, 1 Nov 2018 20:56:56 -0700 Subject: pain and suffering, but I can read/write decorations & dots. --- Source/Main.cpp | 25 + Source/Memory.h | 25 + Source/Panel.cpp | 134 + Source/Panel.h | 85 + Source/Randomizer.cpp | 74 +- Source/RandomizerCore.cpp | 16 +- Source/RandomizerCore.h | 15 +- Source/Source.vcxproj | 2 + Source/Source.vcxproj.filters | 6 + Source/json.hpp | 20274 ++++++++++++++++++++++++++++++++++++++++ 10 files changed, 20597 insertions(+), 59 deletions(-) create mode 100644 Source/Panel.cpp create mode 100644 Source/Panel.h create mode 100644 Source/json.hpp (limited to 'Source') diff --git a/Source/Main.cpp b/Source/Main.cpp index 8336c77..8c4bf8c 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp @@ -6,13 +6,19 @@ #include "Randomizer.h" #include "Version.h" #include "Random.h" +#include "Panel.h" #define IDC_RANDOMIZE 0x401 #define IDC_TOGGLESPEED 0x402 #define IDC_SPEEDRUNNER 0x403 #define IDC_HARDMODE 0x404 +#define IDC_READ 0x405 +#define IDC_RANDOM 0x406 +#define IDC_WRITE 0x407 HWND hwndSeed, hwndRandomize; +int panel = 0x12C9; +std::shared_ptr _panel; LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { @@ -57,6 +63,15 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) SetWindowText(hwndRandomize, L"Randomized!"); break; } + case IDC_READ: + _panel = std::make_shared(panel); + break; + case IDC_RANDOM: + _panel->Random(); + break; + case IDC_WRITE: + _panel->Write(panel); + break; } } return DefWindowProc(hwnd, message, wParam, lParam); @@ -99,6 +114,16 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmd WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 160, 10, 100, 26, hwnd, (HMENU)IDC_RANDOMIZE, hInstance, NULL); + CreateWindow(L"BUTTON", L"READ", + WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 160, 100, 100, 26, hwnd, (HMENU)IDC_READ, hInstance, NULL); + CreateWindow(L"BUTTON", L"RANDOM", + WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 160, 130, 100, 26, hwnd, (HMENU)IDC_RANDOM, hInstance, NULL); + CreateWindow(L"BUTTON", L"WRITE", + WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, + 160, 160, 100, 26, hwnd, (HMENU)IDC_WRITE, hInstance, NULL); + CreateWindow(L"BUTTON", L"", WS_VISIBLE | WS_CHILD | BS_CHECKBOX, 10, 52, 12, 12, hwnd, (HMENU)IDC_TOGGLESPEED, hInstance, NULL); diff --git a/Source/Memory.h b/Source/Memory.h index 53fa1e0..310c971 100644 --- a/Source/Memory.h +++ b/Source/Memory.h @@ -3,6 +3,9 @@ #include #include +#define GLOBALS 0x5B28C0 +//#define GLOBALS 0x62A080 + // https://github.com/erayarslan/WriteProcessMemory-Example // http://stackoverflow.com/q/32798185 // http://stackoverflow.com/q/36018838 @@ -16,6 +19,27 @@ public: Memory(const Memory& memory) = delete; Memory& operator=(const Memory& other) = delete; + + template + std::vector ReadArray(int panel, int offset, int size) { + return ReadData({GLOBALS, 0x18, panel*8, offset, 0}, size); + } + + template + void WriteArray(int panel, int offset, const std::vector& data) { + WriteData({GLOBALS, 0x18, panel*8, offset, 0}, data); + } + + template + std::vector ReadPanelData(int panel, int offset, size_t size) { + return ReadData({GLOBALS, 0x18, panel*8, offset}, size); + } + + template + void WritePanelData(int panel, int offset, const std::vector& data) { + WriteData({GLOBALS, 0x18, panel*8, offset}, data); + } + template std::vector ReadData(const std::vector& offsets, size_t numItems) { std::vector data; @@ -41,6 +65,7 @@ public: } private: + void ThrowError(); void* ComputeOffset(std::vector offsets); diff --git a/Source/Panel.cpp b/Source/Panel.cpp new file mode 100644 index 0000000..0f62664 --- /dev/null +++ b/Source/Panel.cpp @@ -0,0 +1,134 @@ +#include "Panel.h" +#include "Random.h" + +Decoration::Decoration(int shape) { + _shape = shape; +} + +int Decoration::GetValue() { + return _shape; +} + +Intersection::Intersection(float x, float y, int flags) { + _x = x; + _y = y; + _flags = flags; +} + +int Intersection::GetValue() { + return _flags; +} + +Panel::Panel(int id) { + _width = _memory.ReadPanelData(id, GRID_SIZE_X, 1)[0]; + _height = _memory.ReadPanelData(id, GRID_SIZE_Y, 1)[0]; + + ReadIntersections(id); + ReadDecorations(id); +} + +void Panel::Write(int id) { + WriteIntersections(id); + WriteDecorations(id); + + _memory.WritePanelData(id, GRID_SIZE_X, {_width}); + _memory.WritePanelData(id, GRID_SIZE_Y, {_height}); +} + +void Panel::Random() { + for (auto& row : _decorations) { + for (auto& cell : row) { + cell._shape &= 0xFFFFFFF0; + cell._shape |= Random::RandInt(1, 10); + } + } +} + +void Panel::ReadDecorations(int id) { + int numDecorations = _memory.ReadPanelData(id, NUM_DECORATIONS, 1)[0]; + std::vector decorations = _memory.ReadArray(id, DECORATIONS, numDecorations); + _decorations.resize(_width - 1); + for (int x=0; x<_width-1; x++) { + _decorations[x].resize(_height - 1); + for (int y=0; y<_height-1; y++) { + int i = x * (_height - 1) + y; + _decorations[x][y] = Decoration(decorations[i]); + } + } +} + +void Panel::WriteDecorations(int id) { + std::vector flattenedDecorations; + for (std::vector row : _decorations) { + for (Decoration decoration : row) { + flattenedDecorations.push_back(decoration.GetValue()); + } + } + + _memory.WritePanelData(id, NUM_DECORATIONS, {static_cast(flattenedDecorations.size())}); + _memory.WriteArray(id, DECORATIONS, flattenedDecorations); +} + +void Panel::ReadIntersections(int id) { + int numIntersections = _memory.ReadPanelData(id, NUM_DOTS, 1)[0]; + std::vector intersections = _memory.ReadArray(id, DOT_POSITIONS, numIntersections*2); + std::vector intersectionFlags = _memory.ReadArray(id, DOT_FLAGS, numIntersections); + _intersections.resize(_width); + int i=0; + for (int y=0; y<_height; y++) { + for (int x=0; x<_width; x++) { + _intersections[x].resize(_height); + _intersections[x][y] = Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i]); + i++; + } + } + + // Iterate the remaining intersections (either endpoints or gaps) + for (; i < numIntersections; i++) { + if (intersectionFlags[i] & Intersection::Flags::IS_ENDPOINT) { + _endpoints.push_back(Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i])); + } + if (intersectionFlags[i] & Intersection::Flags::IS_GAP) { + _gaps.push_back(Intersection(intersections[2*i], intersections[2*i+1], intersectionFlags[i])); + } + } +} + +void Panel::WriteIntersections(int id) { + std::vector intersections; + std::vector intersectionFlags; + std::pair, std::vector> connections; + + for (int y=0; y<_height; y++) { + for (int x=0; x<_width; x++) { + Intersection intersection = _intersections[x][y]; + intersections.push_back(intersection._x); + intersections.push_back(intersection._y); + intersectionFlags.push_back(intersection._flags); + if (y > 0) { + connections.first.push_back(y * _width + x); + connections.second.push_back((y - 1) * _width + x); + } + if (x > 0) { + connections.first.push_back(y * _width + x); + connections.second.push_back(y * _width + (x - 1)); + } + } + } + + // Endpoints go here :( + + int a = _memory.ReadPanelData(id, NUM_DOTS, 1)[0]; + std::vector b = _memory.ReadArray(id, DOT_POSITIONS, a*2); + std::vector c = _memory.ReadArray(id, DOT_FLAGS, a); + std::pair, std::vector> d; + d.first = _memory.ReadArray(id, DOT_CONNECTION_A, a); + d.second = _memory.ReadArray(id, DOT_CONNECTION_B, a); + + _memory.WritePanelData(id, NUM_DOTS, {_width * _height}); + _memory.WriteArray(id, DOT_POSITIONS, intersections); + _memory.WriteArray(id, DOT_FLAGS, intersectionFlags); + _memory.WriteArray(id, DOT_CONNECTION_A, connections.first); + _memory.WriteArray(id, DOT_CONNECTION_B, connections.second); +} + diff --git a/Source/Panel.h b/Source/Panel.h new file mode 100644 index 0000000..fa3f750 --- /dev/null +++ b/Source/Panel.h @@ -0,0 +1,85 @@ +#pragma once +#include "json.hpp" +#include "RandomizerCore.h" + +class Decoration +{ +public: + enum Shape { + Stone = 100, + Star = 200, + Poly = 400, + Eraser = 500, + Triangle = 600, + }; + + Decoration() = default; + explicit Decoration(int shape); + + int GetValue(); + +//private: + int _shape; +}; + +class Intersection +{ +public: + enum Flags { + IS_ENDPOINT = 0x1, + IS_STARTPOINT = 0x2, + IS_GAP = 0x10000, + HAS_DOT = 0x8, + DOT_IS_BLUE = 0x100, + DOT_IS_ORANGE = 0x200, + DOT_IS_INVISIBLE = 0x1000, + }; + + Intersection() = default; + explicit Intersection(float x, float y, int flags); + + int GetValue(); + +// private: + float _x, _y; + int _flags; +}; + +class Panel +{ +public: + explicit Panel(int id); + void Write(int id); + + void Random(); + + enum Style { + SYMMETRICAL = 0x2, + IS_2COLOR = 0x10, + HAS_DOTS = 0x4, + HAS_STARS = 0x40, + HAS_STONES = 0x100, + HAS_ERASERS = 0x1000, + HAS_SHAPERS = 0x2000, + }; + +private: + void ReadIntersections(int id); + void WriteIntersections(int id); + void ReadDecorations(int id); + void WriteDecorations(int id); + + // TODO: Reflection data + // TODO: Decoration colors + + + Memory _memory = Memory("witness64_d3d11.exe"); + + int _width, _height; + + std::vector> _decorations; + std::vector> _intersections; + std::vector _endpoints; + std::vector _gaps; + int _style; +}; \ No newline at end of file diff --git a/Source/Randomizer.cpp b/Source/Randomizer.cpp index 9622601..8833078 100644 --- a/Source/Randomizer.cpp +++ b/Source/Randomizer.cpp @@ -66,19 +66,19 @@ short Randomizer::Randomize(int seed) void Randomizer::AdjustSpeed() { // Desert Surface Final Control - _core.WritePanelData(0x09F95, OPEN_RATE, {0.04f}); // 4x + _core._memory.WritePanelData(0x09F95, OPEN_RATE, {0.04f}); // 4x // Swamp Sliding Bridge - _core.WritePanelData(0x0061A, OPEN_RATE, {0.1f}); // 4x + _core._memory.WritePanelData(0x0061A, OPEN_RATE, {0.1f}); // 4x // Mountain 2 Elevator - _core.WritePanelData(0x09EEC, OPEN_RATE, {0.075f}); // 3x + _core._memory.WritePanelData(0x09EEC, OPEN_RATE, {0.075f}); // 3x } void Randomizer::RandomizeTutorial() { // Disable tutorial cursor speed modifications (not working?) - _core.WritePanelData(0x00295, CURSOR_SPEED_SCALE, {1.0}); - _core.WritePanelData(0x0C373, CURSOR_SPEED_SCALE, {1.0}); - _core.WritePanelData(0x00293, CURSOR_SPEED_SCALE, {1.0}); - _core.WritePanelData(0x002C2, CURSOR_SPEED_SCALE, {1.0}); + _core._memory.WritePanelData(0x00295, CURSOR_SPEED_SCALE, {1.0}); + _core._memory.WritePanelData(0x0C373, CURSOR_SPEED_SCALE, {1.0}); + _core._memory.WritePanelData(0x00293, CURSOR_SPEED_SCALE, {1.0}); + _core._memory.WritePanelData(0x002C2, CURSOR_SPEED_SCALE, {1.0}); } void Randomizer::RandomizeSymmetry() { @@ -88,11 +88,11 @@ void Randomizer::RandomizeDesert() { _core.Randomize(desertPanels, SWAP_LINES); // Turn off desert surface 8 - _core.WritePanelData(0x09F94, POWER, {0.0, 0.0}); + _core._memory.WritePanelData(0x09F94, POWER, {0.0, 0.0}); // Turn off desert flood final - _core.WritePanelData(0x18076, POWER, {0.0, 0.0}); + _core._memory.WritePanelData(0x18076, POWER, {0.0, 0.0}); // Change desert floating target to desert flood final - _core.WritePanelData(0x17ECA, TARGET, {0x18077}); + _core._memory.WritePanelData(0x17ECA, TARGET, {0x18077}); } void Randomizer::RandomizeQuarry() { @@ -100,14 +100,14 @@ void Randomizer::RandomizeQuarry() { void Randomizer::RandomizeTreehouse() { // Ensure that whatever pivot panels we have are flagged as "pivotable" - int panelFlags = _core.ReadPanelData(0x17DD1, STYLE_FLAGS, 1)[0]; - _core.WritePanelData(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); - panelFlags = _core.ReadPanelData(0x17CE3, STYLE_FLAGS, 1)[0]; - _core.WritePanelData(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000}); - panelFlags = _core.ReadPanelData(0x17DB7, STYLE_FLAGS, 1)[0]; - _core.WritePanelData(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000}); - panelFlags = _core.ReadPanelData(0x17E52, STYLE_FLAGS, 1)[0]; - _core.WritePanelData(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000}); + int panelFlags = _core._memory.ReadPanelData(0x17DD1, STYLE_FLAGS, 1)[0]; + _core._memory.WritePanelData(0x17DD1, STYLE_FLAGS, {panelFlags | 0x8000}); + panelFlags = _core._memory.ReadPanelData(0x17CE3, STYLE_FLAGS, 1)[0]; + _core._memory.WritePanelData(0x17CE3, STYLE_FLAGS, {panelFlags | 0x8000}); + panelFlags = _core._memory.ReadPanelData(0x17DB7, STYLE_FLAGS, 1)[0]; + _core._memory.WritePanelData(0x17DB7, STYLE_FLAGS, {panelFlags | 0x8000}); + panelFlags = _core._memory.ReadPanelData(0x17E52, STYLE_FLAGS, 1)[0]; + _core._memory.WritePanelData(0x17E52, STYLE_FLAGS, {panelFlags | 0x8000}); } void Randomizer::RandomizeKeep() { @@ -115,11 +115,11 @@ void Randomizer::RandomizeKeep() { void Randomizer::RandomizeShadows() { // Distance-gate shadows laser to prevent sniping through the bars - _core.WritePanelData(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); + _core._memory.WritePanelData(0x19650, MAX_BROADCAST_DISTANCE, {2.5}); // Change the shadows tutorial cable to only activate avoid - _core.WritePanelData(0x319A8, CABLE_TARGET_2, {0}); + _core._memory.WritePanelData(0x319A8, CABLE_TARGET_2, {0}); // Change shadows avoid 8 to power shadows follow - _core.WritePanelData(0x1972F, TARGET, {0x1C34C}); + _core._memory.WritePanelData(0x1972F, TARGET, {0x1C34C}); std::vector randomOrder(shadowsPanels.size(), 0); std::iota(randomOrder.begin(), randomOrder.end(), 0); @@ -128,9 +128,9 @@ void Randomizer::RandomizeShadows() { _core.RandomizeRange(randomOrder, SWAP_NONE, 16, 21); // Follow _core.ReassignTargets(shadowsPanels, randomOrder); // Turn off original starting panel - _core.WritePanelData(shadowsPanels[0], POWER, {0.0f, 0.0f}); + _core._memory.WritePanelData(shadowsPanels[0], POWER, {0.0f, 0.0f}); // Turn on new starting panel - _core.WritePanelData(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); + _core._memory.WritePanelData(shadowsPanels[randomOrder[0]], POWER, {1.0f, 1.0f}); } void Randomizer::RandomizeTown() { @@ -167,7 +167,7 @@ void Randomizer::RandomizeJungle() { void Randomizer::RandomizeSwamp() { // Distance-gate swamp snipe 1 to prevent RNG swamp snipe - _core.WritePanelData(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); + _core._memory.WritePanelData(0x17C05, MAX_BROADCAST_DISTANCE, {15.0}); } void Randomizer::RandomizeMountain() { @@ -178,7 +178,7 @@ void Randomizer::RandomizeMountain() { // Randomize final pillars order std::vector targets = {pillars[0] + 1}; for (const int pillar : pillars) { - int target = _core.ReadPanelData(pillar, TARGET, 1)[0]; + int target = _core._memory.ReadPanelData(pillar, TARGET, 1)[0]; targets.push_back(target); } targets[5] = pillars[5] + 1; @@ -189,27 +189,27 @@ void Randomizer::RandomizeMountain() { _core.RandomizeRange(randomOrder, SWAP_NONE, 5, 9); // Right Pillars 1-4 _core.ReassignTargets(pillars, randomOrder, targets); // Turn off original starting panels - _core.WritePanelData(pillars[0], POWER, {0.0f, 0.0f}); - _core.WritePanelData(pillars[5], POWER, {0.0f, 0.0f}); + _core._memory.WritePanelData(pillars[0], POWER, {0.0f, 0.0f}); + _core._memory.WritePanelData(pillars[5], POWER, {0.0f, 0.0f}); // Turn on new starting panels - _core.WritePanelData(pillars[randomOrder[0]], POWER, {1.0f, 1.0f}); - _core.WritePanelData(pillars[randomOrder[5]], POWER, {1.0f, 1.0f}); + _core._memory.WritePanelData(pillars[randomOrder[0]], POWER, {1.0f, 1.0f}); + _core._memory.WritePanelData(pillars[randomOrder[5]], POWER, {1.0f, 1.0f}); // Read the target of keep front laser, and write it to keep back laser. - std::vector keepFrontLaserTarget = _core.ReadPanelData(0x0360E, TARGET, 1); - _core.WritePanelData(0x03317, TARGET, keepFrontLaserTarget); + std::vector keepFrontLaserTarget = _core._memory.ReadPanelData(0x0360E, TARGET, 1); + _core._memory.WritePanelData(0x03317, TARGET, keepFrontLaserTarget); } void Randomizer::RandomizeChallenge() { std::vector randomOrder(challengePanels.size(), 0); std::iota(randomOrder.begin(), randomOrder.end(), 0); _core.RandomizeRange(randomOrder, SWAP_NONE, 1, 9); // Easy maze - Triple 2 - std::vector triple1Target = _core.ReadPanelData(0x00C80, TARGET, 1); - _core.WritePanelData(0x00CA1, TARGET, triple1Target); - _core.WritePanelData(0x00CB9, TARGET, triple1Target); - std::vector triple2Target = _core.ReadPanelData(0x00C22, TARGET, 1); - _core.WritePanelData(0x00C59, TARGET, triple2Target); - _core.WritePanelData(0x00C68, TARGET, triple2Target); + std::vector triple1Target = _core._memory.ReadPanelData(0x00C80, TARGET, 1); + _core._memory.WritePanelData(0x00CA1, TARGET, triple1Target); + _core._memory.WritePanelData(0x00CB9, TARGET, triple1Target); + std::vector triple2Target = _core._memory.ReadPanelData(0x00C22, TARGET, 1); + _core._memory.WritePanelData(0x00C59, TARGET, triple2Target); + _core._memory.WritePanelData(0x00C68, TARGET, triple2Target); _core.ReassignTargets(challengePanels, randomOrder); } diff --git a/Source/RandomizerCore.cpp b/Source/RandomizerCore.cpp index f14a76f..d4aadef 100644 --- a/Source/RandomizerCore.cpp +++ b/Source/RandomizerCore.cpp @@ -101,10 +101,10 @@ void RandomizerCore::SwapPanels(int panel1, int panel2, int flags) { } for (auto const& [offset, size] : offsets) { - std::vector panel1data = ReadPanelData(panel1, offset, size); - std::vector panel2data = ReadPanelData(panel2, offset, size); - WritePanelData(panel2, offset, panel1data); - WritePanelData(panel1, offset, panel2data); + std::vector panel1data = _memory.ReadPanelData(panel1, offset, size); + std::vector panel2data = _memory.ReadPanelData(panel2, offset, size); + _memory.WritePanelData(panel2, offset, panel1data); + _memory.WritePanelData(panel1, offset, panel2data); } } @@ -114,7 +114,7 @@ void RandomizerCore::ReassignTargets(const std::vector& panels, const std:: // The first panel may not have a wire to power it, so we use the panel ID itself. targets = {panels[0] + 1}; for (const int panel : panels) { - int target = ReadPanelData(panel, TARGET, 1)[0]; + int target = _memory.ReadPanelData(panel, TARGET, 1)[0]; targets.push_back(target); } } @@ -122,18 +122,18 @@ void RandomizerCore::ReassignTargets(const std::vector& panels, const std:: for (size_t i=0; i(panels[order[i]], TARGET, {panelTarget}); + _memory.WritePanelData(panels[order[i]], TARGET, {panelTarget}); } } void RandomizerCore::ReassignNames(const std::vector& panels, const std::vector& order) { std::vector names; for (const int panel : panels) { - names.push_back(ReadPanelData(panel, AUDIO_LOG_NAME, 1)[0]); + names.push_back(_memory.ReadPanelData(panel, AUDIO_LOG_NAME, 1)[0]); } for (int i=0; i(panels[i], AUDIO_LOG_NAME, {names[order[i]]}); + _memory.WritePanelData(panels[i], AUDIO_LOG_NAME, {names[order[i]]}); } } diff --git a/Source/RandomizerCore.h b/Source/RandomizerCore.h index 7ec8e33..27e5724 100644 --- a/Source/RandomizerCore.h +++ b/Source/RandomizerCore.h @@ -1,9 +1,6 @@ #pragma once #include "Memory.h" -// #define GLOBALS 0x5B28C0 -#define GLOBALS 0x62A080 - __declspec(selectany) int SWAP_NONE = 0x0; __declspec(selectany) int SWAP_TARGETS = 0x1; __declspec(selectany) int SWAP_LINES = 0x2; @@ -20,20 +17,10 @@ public: void ReassignTargets(const std::vector& panels, const std::vector& order, std::vector targets = {}); void ReassignNames(const std::vector& panels, const std::vector& order); - template - std::vector ReadPanelData(int panel, int offset, size_t size) { - return _memory.ReadData({GLOBALS, 0x18, panel*8, offset}, size); - } - - template - void WritePanelData(int panel, int offset, const std::vector& data) { - _memory.WriteData({GLOBALS, 0x18, panel*8, offset}, data); - } - short ReadMetadata(); void WriteMetadata(short metadata); -private: +// private: Memory _memory = Memory("witness64_d3d11.exe"); }; diff --git a/Source/Source.vcxproj b/Source/Source.vcxproj index 38914a6..020f69b 100644 --- a/Source/Source.vcxproj +++ b/Source/Source.vcxproj @@ -163,6 +163,7 @@ + @@ -172,6 +173,7 @@ + diff --git a/Source/Source.vcxproj.filters b/Source/Source.vcxproj.filters index 2f8f60b..8f94061 100644 --- a/Source/Source.vcxproj.filters +++ b/Source/Source.vcxproj.filters @@ -33,6 +33,9 @@ Header Files + + Header Files + @@ -47,6 +50,9 @@ Source Files + + Source Files + diff --git a/Source/json.hpp b/Source/json.hpp new file mode 100644 index 0000000..1e7cf51 --- /dev/null +++ b/Source/json.hpp @@ -0,0 +1,20274 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.4.0 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2018 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef NLOHMANN_JSON_HPP +#define NLOHMANN_JSON_HPP + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 4 +#define NLOHMANN_JSON_VERSION_PATCH 0 + +#include // all_of, find, for_each +#include // assert +#include // and, not, or +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#include // istream, ostream +#include // iterator_traits, random_access_iterator_tag +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap + +// #include +#ifndef NLOHMANN_JSON_FWD_HPP +#define NLOHMANN_JSON_FWD_HPP + +#include // int64_t, uint64_t +#include // map +#include // allocator +#include // string +#include // vector + +/*! +@brief namespace for Niels Lohmann +@see https://github.com/nlohmann +@since version 1.0.0 +*/ +namespace nlohmann +{ +/*! +@brief default JSONSerializer template argument + +This serializer ignores the template arguments and uses ADL +([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) +for serialization. +*/ +template +struct adl_serializer; + +template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer> +class basic_json; + +/*! +@brief JSON Pointer + +A JSON pointer defines a string syntax for identifying a specific value +within a JSON document. It can be used with functions `at` and +`operator[]`. Furthermore, JSON pointers are the base for JSON patches. + +@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) + +@since version 2.0.0 +*/ +template +class json_pointer; + +/*! +@brief default JSON class + +This type is the default specialization of the @ref basic_json class which +uses the standard template types. + +@since version 1.0.0 +*/ +using json = basic_json<>; +} // namespace nlohmann + +#endif + +// #include + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// disable float-equal warnings on GCC/clang +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdocumentation" +#endif + +// allow for portable deprecation warnings +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) + #define JSON_DEPRECATED __declspec(deprecated) +#else + #define JSON_DEPRECATED +#endif + +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// manual branch prediction +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) + #define JSON_LIKELY(x) __builtin_expect(!!(x), 1) + #define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else + #define JSON_LIKELY(x) x + #define JSON_UNLIKELY(x) x +#endif + +// C++ language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// #include + + +#include // not +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type + +namespace nlohmann +{ +namespace detail +{ +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +template +using uncvref_t = typename std::remove_cv::type>::type; + +// implementation of C++14 index_sequence and affiliates +// source: https://stackoverflow.com/a/32223343 +template +struct index_sequence +{ + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +template +struct merge_and_renumber; + +template +struct merge_and_renumber, index_sequence> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + +template +struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; + +template<> struct make_index_sequence<0> : index_sequence<> {}; +template<> struct make_index_sequence<1> : index_sequence<0> {}; + +template +using index_sequence_for = make_index_sequence; + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static constexpr T value{}; +}; + +template +constexpr T static_const::value; +} // namespace detail +} // namespace nlohmann + +// #include + + +#include // not +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval + +// #include + +// #include + +// #include + + +#include + +// #include + + +namespace nlohmann +{ +namespace detail +{ +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; +} // namespace detail +} // namespace nlohmann + + +// http://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ +namespace detail +{ +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + void operator=(nonesuch const&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template