Adds support for History data, allowing us to store specific interesting occurrences in the data flow, and recall them later.
All checks were successful
continuous-integration/drone/push Build is passing

Signed-off-by: Deukhoofd <Deukhoofd@gmail.com>
This commit is contained in:
2020-08-14 15:18:00 +02:00
parent 939fee3f50
commit cb4765e0cc
12 changed files with 150 additions and 19 deletions

View File

@@ -0,0 +1,6 @@
#ifndef CREATURELIB_HISTORYELEMENTKIND_HPP
#define CREATURELIB_HISTORYELEMENTKIND_HPP
#include <Arbutils/Enum.hpp>
ENUM(HistoryElementKind, uint8_t, AttackUse)
#endif // CREATURELIB_HISTORYELEMENTKIND_HPP

View File

@@ -0,0 +1,24 @@
#ifndef CREATURELIB_ATTACKUSEHISTORY_HPP
#define CREATURELIB_ATTACKUSEHISTORY_HPP
#include "../../Models/ExecutingAttack.hpp"
#include "HistoryElement.hpp"
namespace CreatureLib::Battling {
class AttackUseHistory : public HistoryElement {
std::unique_ptr<const ExecutingAttack> _attack;
protected:
void Clear() override {
_attack.reset();
HistoryElement::Clear();
}
public:
AttackUseHistory(const ExecutingAttack* attack) : _attack(attack) {}
HistoryElementKind GetKind() const noexcept override { return HistoryElementKind::AttackUse; }
ArbUt::BorrowedPtr<const ExecutingAttack> GetAttack() { return _attack; }
};
}
#endif // CREATURELIB_ATTACKUSEHISTORY_HPP

View File

@@ -0,0 +1,25 @@
#ifndef CREATURELIB_HISTORYELEMENT_HPP
#define CREATURELIB_HISTORYELEMENT_HPP
#include <Arbutils/Memory/BorrowedPtr.hpp>
#include "../HistoryElementKind.hpp"
namespace CreatureLib::Battling {
class HistoryElement {
friend class HistoryHolder;
HistoryElement* _previous;
protected:
virtual void Clear() {
if (_previous != nullptr) {
_previous->Clear();
}
}
public:
virtual HistoryElementKind GetKind() const noexcept = 0;
ArbUt::BorrowedPtr<const HistoryElement> GetPrevious() const noexcept { return _previous; }
};
}
#endif // CREATURELIB_HISTORYELEMENT_HPP

View File

@@ -0,0 +1,68 @@
#ifndef CREATURELIB_HISTORYHOLDER_HPP
#define CREATURELIB_HISTORYHOLDER_HPP
#include <cstddef>
#include <cstdint>
#include "../../Library/Exceptions/CreatureException.hpp"
#include "HistoryElements/HistoryElement.hpp"
template <class T> concept HistoryElementType = std::is_base_of<CreatureLib::Battling::HistoryElement, T>::value;
namespace CreatureLib::Battling {
class HistoryHolder {
size_t _offset;
size_t _capacity;
uint8_t* _memory = nullptr;
HistoryElement* _top = nullptr;
static constexpr size_t initialSize = 2048;
static constexpr size_t stepSize = 1024;
public:
HistoryHolder() : _offset(0), _capacity(2048) {
auto ptr = malloc(_capacity);
if (ptr == nullptr) {
THROW_CREATURE("Out of memory.");
}
_memory = static_cast<uint8_t*>(ptr);
}
HistoryHolder(const HistoryHolder&) = delete;
HistoryHolder& operator=(const HistoryHolder&) = delete;
~HistoryHolder() {
if (_top != nullptr)
_top->Clear();
free(_memory);
}
template <HistoryElementType T, class... parameters> void Register(parameters... args) {
if (_offset + sizeof(T) >= _capacity) {
_capacity += stepSize;
auto newPtr = realloc(_memory, _capacity);
if (newPtr == nullptr) {
THROW_CREATURE("Out of memory.");
}
_memory = static_cast<uint8_t*>(newPtr);
}
uint8_t* ptr = _memory + _offset;
T* element = new (ptr) T(args...);
_offset += sizeof(T);
element->_previous = _top;
_top = element;
}
ArbUt::BorrowedPtr<const HistoryElement> GetTopElement() const noexcept { return _top; }
ArbUt::BorrowedPtr<const HistoryElement> GetLastUsedAttack() const noexcept {
const auto* c = _top;
while (c != nullptr) {
if (c->GetKind() == HistoryElementKind::AttackUse)
return c;
c = c->_previous;
}
return nullptr;
}
};
}
#endif // CREATURELIB_HISTORYHOLDER_HPP