2020-08-14 13:18:00 +00:00
|
|
|
#ifndef CREATURELIB_HISTORYHOLDER_HPP
|
|
|
|
#define CREATURELIB_HISTORYHOLDER_HPP
|
|
|
|
|
|
|
|
#include "../../Library/Exceptions/CreatureException.hpp"
|
|
|
|
#include "HistoryElements/HistoryElement.hpp"
|
|
|
|
|
2021-04-11 13:20:50 +00:00
|
|
|
template <class T>
|
|
|
|
concept HistoryElementType = std::is_base_of<CreatureLib::Battling::HistoryElement, T>::value;
|
2020-08-14 13:18:00 +00:00
|
|
|
|
|
|
|
namespace CreatureLib::Battling {
|
|
|
|
class HistoryHolder {
|
|
|
|
size_t _offset;
|
|
|
|
size_t _capacity;
|
2021-04-11 13:20:50 +00:00
|
|
|
u8* _memory = nullptr;
|
2020-08-14 13:18:00 +00:00
|
|
|
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) {
|
2020-08-17 10:18:01 +00:00
|
|
|
THROW("Out of memory.");
|
2020-08-14 13:18:00 +00:00
|
|
|
}
|
2021-04-11 13:20:50 +00:00
|
|
|
_memory = static_cast<u8*>(ptr);
|
2020-08-14 13:18:00 +00:00
|
|
|
}
|
|
|
|
HistoryHolder(const HistoryHolder&) = delete;
|
|
|
|
HistoryHolder& operator=(const HistoryHolder&) = delete;
|
|
|
|
|
|
|
|
~HistoryHolder() {
|
|
|
|
if (_top != nullptr)
|
|
|
|
_top->Clear();
|
|
|
|
free(_memory);
|
|
|
|
}
|
|
|
|
|
2021-04-11 13:20:50 +00:00
|
|
|
void Resize() {
|
|
|
|
_capacity += stepSize;
|
|
|
|
auto newPtr = realloc(_memory, _capacity);
|
|
|
|
if (newPtr == nullptr) {
|
|
|
|
THROW("Out of memory.");
|
|
|
|
}
|
|
|
|
_memory = static_cast<u8*>(newPtr);
|
|
|
|
}
|
|
|
|
|
2020-08-14 13:18:00 +00:00
|
|
|
template <HistoryElementType T, class... parameters> void Register(parameters... args) {
|
|
|
|
if (_offset + sizeof(T) >= _capacity) {
|
2021-04-11 13:20:50 +00:00
|
|
|
Resize();
|
2020-08-14 13:18:00 +00:00
|
|
|
}
|
2021-04-11 13:20:50 +00:00
|
|
|
u8* ptr = _memory + _offset;
|
2020-08-14 13:18:00 +00:00
|
|
|
T* element = new (ptr) T(args...);
|
|
|
|
_offset += sizeof(T);
|
2021-04-11 13:20:50 +00:00
|
|
|
if (_top != nullptr) {
|
|
|
|
element->_previousOffset = (u8*)sizeof(T);
|
|
|
|
}
|
2020-08-14 13:18:00 +00:00
|
|
|
_top = element;
|
|
|
|
}
|
|
|
|
|
|
|
|
ArbUt::BorrowedPtr<const HistoryElement> GetTopElement() const noexcept { return _top; }
|
|
|
|
|
2020-12-12 11:22:48 +00:00
|
|
|
std::optional<ArbUt::BorrowedPtr<const HistoryElement>> GetLastUsedAttack() const noexcept {
|
2020-08-14 13:18:00 +00:00
|
|
|
const auto* c = _top;
|
|
|
|
while (c != nullptr) {
|
|
|
|
if (c->GetKind() == HistoryElementKind::AttackUse)
|
|
|
|
return c;
|
2021-04-11 13:20:50 +00:00
|
|
|
c = c->GetPrevious();
|
2020-08-14 13:18:00 +00:00
|
|
|
}
|
2020-12-12 11:22:48 +00:00
|
|
|
return {};
|
2020-08-14 13:18:00 +00:00
|
|
|
}
|
2021-04-11 13:20:50 +00:00
|
|
|
|
|
|
|
void CloneOnto(HistoryHolder& other) {
|
|
|
|
if (other._top != nullptr) {
|
|
|
|
other._top->Clear();
|
|
|
|
}
|
|
|
|
free(other._memory);
|
|
|
|
other._offset = _offset;
|
|
|
|
other._capacity = _capacity;
|
|
|
|
other._memory = static_cast<uint8_t*>(malloc(_capacity));
|
|
|
|
if (_top != nullptr) {
|
|
|
|
other._top = reinterpret_cast<HistoryElement*>(other._memory + ((u8*)_top - _memory));
|
|
|
|
}
|
|
|
|
}
|
2020-08-14 13:18:00 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // CREATURELIB_HISTORYHOLDER_HPP
|