inital commit (message v3)
This commit is contained in:
commit
b08d2bf366
31
CMakeLists.txt
Normal file
31
CMakeLists.txt
Normal file
@ -0,0 +1,31 @@
|
||||
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
|
||||
|
||||
project(solanaceae)
|
||||
|
||||
add_library(solanaceae_message3
|
||||
./solanaceae/message3/file.hpp
|
||||
./solanaceae/message3/file_r_mem.hpp
|
||||
./solanaceae/message3/file_r_file.hpp
|
||||
./solanaceae/message3/file_w_file.hpp
|
||||
./solanaceae/message3/file_rw_file.hpp
|
||||
|
||||
./solanaceae/message3/components.hpp
|
||||
./solanaceae/message3/components_id.inl
|
||||
|
||||
./solanaceae/message3/message_model3.hpp
|
||||
|
||||
./solanaceae/message3/registry_message_model.hpp
|
||||
./solanaceae/message3/registry_message_model.cpp
|
||||
|
||||
./solanaceae/message3/message_time_sort.hpp
|
||||
./solanaceae/message3/message_time_sort.cpp
|
||||
)
|
||||
|
||||
target_include_directories(solanaceae_message3 PUBLIC .)
|
||||
target_compile_features(solanaceae_message3 PUBLIC cxx_std_17)
|
||||
target_link_libraries(solanaceae_message3 PUBLIC
|
||||
solanaceae_util
|
||||
solanaceae_contact
|
||||
EnTT::EnTT
|
||||
)
|
||||
|
24
LICENSE
Normal file
24
LICENSE
Normal file
@ -0,0 +1,24 @@
|
||||
The Code is under the following License, if not stated otherwise:
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Erik Scholz
|
||||
|
||||
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.
|
||||
|
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
||||
`plant !`
|
||||
|
||||
provides `message` functionallity for solanaceae code.
|
||||
|
||||
relies on [EnTT](https://github.com/skypjack/entt)
|
||||
|
120
solanaceae/message3/components.hpp
Normal file
120
solanaceae/message3/components.hpp
Normal file
@ -0,0 +1,120 @@
|
||||
#pragma once
|
||||
|
||||
#include <solanaceae/contact/contact_model3.hpp>
|
||||
|
||||
//fwd
|
||||
struct FileI;
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace Message::Components {
|
||||
|
||||
struct ContactFrom {
|
||||
Contact3 c;
|
||||
};
|
||||
|
||||
struct ContactTo {
|
||||
Contact3 c;
|
||||
};
|
||||
|
||||
struct Timestamp {
|
||||
uint64_t ts {0};
|
||||
};
|
||||
|
||||
struct TimestampProcessed {
|
||||
uint64_t ts {0};
|
||||
};
|
||||
|
||||
struct TimestampWritten {
|
||||
uint64_t ts {0};
|
||||
};
|
||||
|
||||
struct MessageText {
|
||||
std::string text;
|
||||
MessageText(const std::string_view& view) : text(view) {}
|
||||
};
|
||||
|
||||
struct TagMessageIsAction {};
|
||||
|
||||
namespace Transfer {
|
||||
|
||||
//struct TransferState {
|
||||
//enum State {
|
||||
//running,
|
||||
//paused,
|
||||
//finished,
|
||||
//failed,
|
||||
//} state = paused;
|
||||
//};
|
||||
struct TagHaveAll {};
|
||||
|
||||
struct BytesSent {
|
||||
uint64_t total {0u};
|
||||
};
|
||||
|
||||
struct BytesReceived {
|
||||
uint64_t total {0u};
|
||||
};
|
||||
|
||||
// TODO: rename to stream?
|
||||
using File = std::unique_ptr<FileI>;
|
||||
|
||||
struct TagReceiving {};
|
||||
struct TagSending {};
|
||||
// TODO: add both?
|
||||
|
||||
// convert to enum?
|
||||
// TODO: local/remote
|
||||
// TODO: invert?
|
||||
struct TagPaused {};
|
||||
|
||||
struct StateCanceled {
|
||||
enum Reason {
|
||||
disconnected,
|
||||
remote_canceld,
|
||||
local_canceld,
|
||||
} reason = disconnected;
|
||||
};
|
||||
|
||||
#if 0
|
||||
struct FileID {
|
||||
// persistent ID
|
||||
// sometimes called file_id or hash
|
||||
ToxKey id;
|
||||
// TODO: variable length
|
||||
};
|
||||
|
||||
struct FileKind {
|
||||
// TODO: use tox file kind
|
||||
uint64_t kind {0};
|
||||
};
|
||||
#endif
|
||||
|
||||
struct FileInfo {
|
||||
struct FileDirEntry {
|
||||
std::string file_name; // full path relative to base
|
||||
uint64_t file_size {0};
|
||||
};
|
||||
std::vector<FileDirEntry> file_list;
|
||||
uint64_t total_size {0};
|
||||
};
|
||||
|
||||
// describes the files locally
|
||||
// filename might be different to non local FileInfo
|
||||
// order is the same
|
||||
struct FileInfoLocal {
|
||||
std::vector<std::string> file_list;
|
||||
};
|
||||
|
||||
// TODO: rename to start? or set or ...
|
||||
struct ActionAccept {
|
||||
std::string save_to_path;
|
||||
};
|
||||
|
||||
} // Transfer
|
||||
|
||||
} // Message::Components
|
||||
|
||||
#include "./components_id.inl"
|
||||
|
36
solanaceae/message3/components_id.inl
Normal file
36
solanaceae/message3/components_id.inl
Normal file
@ -0,0 +1,36 @@
|
||||
#include "./components.hpp"
|
||||
|
||||
#include <entt/core/type_info.hpp>
|
||||
|
||||
// TODO: move more central
|
||||
#define DEFINE_COMP_ID(x) \
|
||||
template<> \
|
||||
constexpr entt::id_type entt::type_hash<x>::value() noexcept { \
|
||||
using namespace entt::literals; \
|
||||
return #x##_hs; \
|
||||
}
|
||||
|
||||
// cross compile(r) stable ids
|
||||
|
||||
DEFINE_COMP_ID(Message::Components::ContactFrom)
|
||||
DEFINE_COMP_ID(Message::Components::ContactTo)
|
||||
DEFINE_COMP_ID(Message::Components::Timestamp)
|
||||
DEFINE_COMP_ID(Message::Components::TimestampProcessed)
|
||||
DEFINE_COMP_ID(Message::Components::TimestampWritten)
|
||||
DEFINE_COMP_ID(Message::Components::MessageText)
|
||||
DEFINE_COMP_ID(Message::Components::TagMessageIsAction)
|
||||
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::TagHaveAll)
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::BytesSent)
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::BytesReceived)
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::File)
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::TagReceiving)
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::TagSending)
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::TagPaused)
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::StateCanceled)
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::FileInfo)
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::FileInfoLocal)
|
||||
DEFINE_COMP_ID(Message::Components::Transfer::ActionAccept)
|
||||
|
||||
#undef DEFINE_COMP_ID
|
||||
|
20
solanaceae/message3/file.hpp
Normal file
20
solanaceae/message3/file.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
struct FileI {
|
||||
uint64_t _file_size {0};
|
||||
// TODO: remove?
|
||||
uint64_t _bytes_read {0};
|
||||
uint64_t _bytes_written {0};
|
||||
|
||||
virtual ~FileI(void) {}
|
||||
|
||||
virtual bool isGood(void) = 0;
|
||||
|
||||
// TODO: move to owning/nonowning pointers
|
||||
virtual std::vector<uint8_t> read(uint64_t pos, uint32_t size) = 0;
|
||||
virtual bool write(uint64_t pos, const std::vector<uint8_t>& data) = 0;
|
||||
};
|
||||
|
53
solanaceae/message3/file_r_file.hpp
Normal file
53
solanaceae/message3/file_r_file.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
#pragma once
|
||||
|
||||
#include "./file.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
struct FileRFile : public FileI {
|
||||
std::ifstream _file;
|
||||
|
||||
FileRFile(std::string_view file_path) : _file(static_cast<std::string>(file_path), std::ios::binary) {
|
||||
if (!_file.is_open()) {
|
||||
return; // TODO: error
|
||||
}
|
||||
|
||||
// figure out size
|
||||
_file.seekg(0, _file.end);
|
||||
_file_size = _file.tellg();
|
||||
_file.seekg(0, _file.beg);
|
||||
}
|
||||
|
||||
//FileRFile(std::ifstream&& other_file) : _file(std::move(other_file)) {}
|
||||
//FileRFile(std::ifstream&& other_file, size_t file_size) : _file(std::move(other_file)), _file_size(file_size) {}
|
||||
|
||||
virtual ~FileRFile(void) {}
|
||||
|
||||
bool isGood(void) override {
|
||||
return _file.is_open() && _file.good();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> read(uint64_t pos, uint32_t size) override {
|
||||
if (_file_size > 0 && pos >= _file_size) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// TODO: error check
|
||||
_file.seekg(pos);
|
||||
|
||||
// TODO: optimize
|
||||
std::vector<uint8_t> chunk;
|
||||
int read_char;
|
||||
for (size_t i = 0; i < size && (_file_size == 0 || i+pos < _file_size) && (read_char = _file.get()) != std::ifstream::traits_type::eof(); i++) {
|
||||
chunk.push_back(read_char);
|
||||
}
|
||||
|
||||
_bytes_read += chunk.size();
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
// read only
|
||||
bool write(uint64_t, const std::vector<uint8_t>&) override { return false; }
|
||||
};
|
||||
|
38
solanaceae/message3/file_r_mem.hpp
Normal file
38
solanaceae/message3/file_r_mem.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "./file.hpp"
|
||||
|
||||
struct FileRMem : public FileI {
|
||||
std::vector<uint8_t> _data;
|
||||
|
||||
FileRMem(void) = delete;
|
||||
FileRMem(const std::vector<uint8_t>& data) : _data(data) {
|
||||
_file_size = _data.size();
|
||||
}
|
||||
virtual ~FileRMem(void) {}
|
||||
|
||||
bool isGood(void) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> read(uint64_t pos, uint32_t size) override {
|
||||
if (_file_size > 0 && pos >= _data.size()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// TODO: optimize
|
||||
std::vector<uint8_t> chunk;
|
||||
for (size_t i = 0; i < size && i+pos < _data.size(); i++) {
|
||||
chunk.push_back(_data[pos+i]);
|
||||
}
|
||||
//chunk.insert(chunk.begin(), _data.cbegin()+pos, _data.cbegin()+pos+size);
|
||||
|
||||
_bytes_read += chunk.size();
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
// read only
|
||||
bool write(uint64_t, const std::vector<uint8_t>&) override { return false; }
|
||||
};
|
||||
|
60
solanaceae/message3/file_rw_file.hpp
Normal file
60
solanaceae/message3/file_rw_file.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include "./file.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
struct FileRWFile : public FileI {
|
||||
std::fstream _file;
|
||||
|
||||
//FileWFile(std::string_view file_path, uint64_t file_size) : _file(static_cast<std::string>(file_path), std::ios::binary) {
|
||||
//_file_size = file_size;
|
||||
|
||||
//if (!_file.is_open()) {
|
||||
//return; // TODO: error
|
||||
//}
|
||||
//}
|
||||
|
||||
virtual ~FileRWFile(void) {}
|
||||
|
||||
bool isGood(void) override {
|
||||
return _file.is_open() && _file.good();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> read(uint64_t pos, uint32_t size) override {
|
||||
if (pos >= _file_size) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// TODO: error check
|
||||
_file.seekg(pos);
|
||||
|
||||
// TODO: optimize
|
||||
std::vector<uint8_t> chunk;
|
||||
int read_char;
|
||||
for (size_t i = 0; i < size && (_file_size == 0 || i+pos < _file_size) && (read_char = _file.get()) != std::ifstream::traits_type::eof(); i++) {
|
||||
chunk.push_back(read_char);
|
||||
}
|
||||
|
||||
_bytes_read += chunk.size();
|
||||
|
||||
return chunk;
|
||||
}
|
||||
|
||||
bool write(uint64_t pos, const std::vector<uint8_t>& data) override {
|
||||
if (pos >= _file_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if out-of-order, seek
|
||||
if (_file.tellp() != int64_t(pos)) {
|
||||
// TODO: error check
|
||||
_file.seekp(pos);
|
||||
}
|
||||
|
||||
_file.write(reinterpret_cast<const char*>(data.data()), data.size());
|
||||
|
||||
return _file.good();
|
||||
}
|
||||
};
|
||||
|
46
solanaceae/message3/file_w_file.hpp
Normal file
46
solanaceae/message3/file_w_file.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include "./file.hpp"
|
||||
|
||||
#include <string_view>
|
||||
#include <fstream>
|
||||
|
||||
struct FileWFile : public FileI {
|
||||
std::ofstream _file;
|
||||
|
||||
FileWFile(std::string_view file_path, uint64_t file_size) : _file(static_cast<std::string>(file_path), std::ios::binary) {
|
||||
_file_size = file_size;
|
||||
|
||||
if (!_file.is_open()) {
|
||||
return; // TODO: error
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~FileWFile(void) {}
|
||||
|
||||
bool isGood(void) override {
|
||||
return _file.is_open() && _file.good();
|
||||
}
|
||||
|
||||
// write only
|
||||
std::vector<uint8_t> read(uint64_t, uint32_t) override { return {}; }
|
||||
|
||||
bool write(uint64_t pos, const std::vector<uint8_t>& data) override {
|
||||
if (_file_size > 0 && pos >= _file_size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if out-of-order, seek
|
||||
if (_file.tellp() != int64_t(pos)) {
|
||||
// TODO: error check
|
||||
_file.seekp(pos);
|
||||
}
|
||||
|
||||
_file.write(reinterpret_cast<const char*>(data.data()), data.size());
|
||||
|
||||
_bytes_written += data.size();
|
||||
|
||||
return _file.good();
|
||||
}
|
||||
};
|
||||
|
27
solanaceae/message3/message_model3.hpp
Normal file
27
solanaceae/message3/message_model3.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include <solanaceae/contact/contact_model3.hpp>
|
||||
|
||||
//#include "./file.hpp"
|
||||
|
||||
// TODO: move, rename, do something?, change in favor of tox?
|
||||
//enum class FileKind : uint32_t {
|
||||
//file = 0u,
|
||||
//avatar = 1u,
|
||||
//};
|
||||
|
||||
// interface to send messages
|
||||
struct MessageModel3I {
|
||||
virtual ~MessageModel3I(void) {}
|
||||
|
||||
// return true if a handler was found for the contact
|
||||
|
||||
virtual bool sendText(const Contact3 c, std::string_view message, bool action = false) { (void)c,(void)message,(void)action; return false; }
|
||||
|
||||
//virtual bool sendFile(const Contact& c, std::string_view file_name, std::unique_ptr<FileI> file) { (void)c,(void)message,(void)action; return false; }
|
||||
virtual bool sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) { (void)c,(void)file_name,(void)file_path; return false; }
|
||||
|
||||
|
||||
//virtual bool sendFileMem(const Contact& c, std::string_view file_name, const std::vector<uint8_t>& file) = 0;
|
||||
};
|
||||
|
29
solanaceae/message3/message_time_sort.cpp
Normal file
29
solanaceae/message3/message_time_sort.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "./message_time_sort.hpp"
|
||||
|
||||
#include <solanaceae/registry_message_model/components.hpp>
|
||||
|
||||
MessageTimeSort::MessageTimeSort(RegistryMessageModel& rmm) : _rmm(rmm) {
|
||||
_rmm.subscribe(this, RegistryMessageModel_Event::message_construct);
|
||||
_rmm.subscribe(this, RegistryMessageModel_Event::message_updated);
|
||||
}
|
||||
|
||||
void MessageTimeSort::iterate(void) {
|
||||
// TODO: maybe only every x for updated
|
||||
for (auto* reg : _to_sort) {
|
||||
reg->sort<Message::Components::Timestamp>([](const auto& lhs, const auto& rhs) -> bool {
|
||||
return lhs.ts < rhs.ts;
|
||||
}, entt::insertion_sort{});
|
||||
}
|
||||
_to_sort.clear();
|
||||
}
|
||||
|
||||
bool MessageTimeSort::onEvent(const Message::Events::MessageConstruct& e) {
|
||||
_to_sort.emplace(e.e.registry());
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MessageTimeSort::onEvent(const Message::Events::MessageUpdated& e) {
|
||||
_to_sort.emplace(e.e.registry());
|
||||
return false;
|
||||
}
|
||||
|
23
solanaceae/message3/message_time_sort.hpp
Normal file
23
solanaceae/message3/message_time_sort.hpp
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "./registry_message_model.hpp"
|
||||
|
||||
#include <entt/container/dense_set.hpp>
|
||||
|
||||
class MessageTimeSort : public RegistryMessageModelEventI {
|
||||
RegistryMessageModel& _rmm;
|
||||
|
||||
// TODO: use contact instead
|
||||
entt::dense_set<Message3Registry*> _to_sort;
|
||||
|
||||
public:
|
||||
MessageTimeSort(RegistryMessageModel& rmm);
|
||||
|
||||
// do the sorting
|
||||
void iterate(void);
|
||||
|
||||
protected: // mm
|
||||
bool onEvent(const Message::Events::MessageConstruct& e) override;
|
||||
bool onEvent(const Message::Events::MessageUpdated& e) override;
|
||||
};
|
||||
|
131
solanaceae/message3/registry_message_model.cpp
Normal file
131
solanaceae/message3/registry_message_model.cpp
Normal file
@ -0,0 +1,131 @@
|
||||
#include "./registry_message_model.hpp"
|
||||
|
||||
#include <solanaceae/contact/components.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
Message3Registry* RegistryMessageModel::get(Contact3 c) {
|
||||
if (_cr.valid(c) && !_cr.all_of<Contact::Components::TagBig>(c)) {
|
||||
// TODO: loop upwards
|
||||
if (!_cr.all_of<Contact::Components::Parent>(c)) {
|
||||
return nullptr;
|
||||
}
|
||||
c = _cr.get<Contact::Components::Parent>(c).parent;
|
||||
}
|
||||
|
||||
if (!_cr.valid(c)) {
|
||||
// TODO: throw error
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto it = _contact_messages.find(c);
|
||||
if (it != _contact_messages.end()) {
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
auto& reg_sh = _contact_messages[c] = std::make_unique<Message3Registry>();
|
||||
return reg_sh.get();
|
||||
}
|
||||
|
||||
Message3Registry* RegistryMessageModel::get(Contact3 c) const {
|
||||
if (_cr.valid(c) && !_cr.all_of<Contact::Components::TagBig>(c)) {
|
||||
// TODO: loop upwards
|
||||
if (!_cr.all_of<Contact::Components::Parent>(c)) {
|
||||
return nullptr;
|
||||
}
|
||||
c = _cr.get<Contact::Components::Parent>(c).parent;
|
||||
}
|
||||
|
||||
if (!_cr.valid(c)) {
|
||||
// TODO: throw error
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto it = _contact_messages.find(c);
|
||||
if (it != _contact_messages.cend()) {
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RegistryMessageModel::throwEventConstruct(Message3Registry& reg, Message3 e) {
|
||||
std::cout << "RMM debug: event construct " << entt::to_integral(e) << "\n";
|
||||
dispatch(
|
||||
RegistryMessageModel_Event::message_construct,
|
||||
Message::Events::MessageConstruct{
|
||||
Message3Handle{reg, e}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void RegistryMessageModel::throwEventUpdate(Message3Registry& reg, Message3 e) {
|
||||
// the update while update lock is hacky
|
||||
_update_queue.push_back({reg, e});
|
||||
if (!_update_in_progess) {
|
||||
_update_in_progess = true;
|
||||
for (size_t i = 0; i < _update_queue.size(); i++) {
|
||||
std::cout << "RMM debug: event update " << entt::to_integral(e) << "\n";
|
||||
dispatch(
|
||||
RegistryMessageModel_Event::message_updated,
|
||||
Message::Events::MessageUpdated{
|
||||
_update_queue.at(i)
|
||||
}
|
||||
);
|
||||
}
|
||||
_update_queue.clear();
|
||||
_update_in_progess = false;
|
||||
}
|
||||
}
|
||||
|
||||
void RegistryMessageModel::throwEventDestroy(Message3Registry& reg, Message3 e) {
|
||||
std::cout << "RMM debug: event destroy " << entt::to_integral(e) << "\n";
|
||||
dispatch(
|
||||
RegistryMessageModel_Event::message_destroy,
|
||||
Message::Events::MessageDestory{
|
||||
Message3Handle{reg, e}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void RegistryMessageModel::throwEventConstruct(const Contact3 c, Message3 e) {
|
||||
if (auto* reg_ptr = get(c); reg_ptr) {
|
||||
throwEventConstruct(*reg_ptr, e);
|
||||
}
|
||||
}
|
||||
|
||||
void RegistryMessageModel::throwEventUpdate(const Contact3 c, Message3 e) {
|
||||
if (auto* reg_ptr = get(c); reg_ptr) {
|
||||
throwEventUpdate(*reg_ptr, e);
|
||||
}
|
||||
}
|
||||
|
||||
void RegistryMessageModel::throwEventDestroy(const Contact3 c, Message3 e) {
|
||||
if (auto* reg_ptr = get(c); reg_ptr) {
|
||||
throwEventDestroy(*reg_ptr, e);
|
||||
}
|
||||
}
|
||||
|
||||
bool RegistryMessageModel::sendText(const Contact3 c, std::string_view message, bool action) {
|
||||
std::cout << "RMM debug: event send text\n";
|
||||
|
||||
// manual, bc its not an "event"
|
||||
for (auto* zei : _subscribers.at(size_t(RegistryMessageModel_Event::send_text))) {
|
||||
if (zei->sendText(c, message, action)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool RegistryMessageModel::sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) {
|
||||
std::cout << "RMM debug: event send file path\n";
|
||||
|
||||
// manual, bc its not an "event"
|
||||
for (auto* zei : _subscribers.at(size_t(RegistryMessageModel_Event::send_file_path))) {
|
||||
if (zei->sendFilePath(c, file_name, file_path)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
100
solanaceae/message3/registry_message_model.hpp
Normal file
100
solanaceae/message3/registry_message_model.hpp
Normal file
@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
|
||||
#include <solanaceae/util/event_provider.hpp>
|
||||
|
||||
#include "./message_model3.hpp"
|
||||
|
||||
#include <entt/entity/registry.hpp>
|
||||
#include <entt/entity/handle.hpp>
|
||||
#include <entt/container/dense_map.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
// strong typing
|
||||
enum class Message3 : uint32_t {};
|
||||
using Message3Registry = entt::basic_registry<Message3>;
|
||||
using Message3Handle = entt::basic_handle<Message3Registry>;
|
||||
|
||||
namespace Message::Events {
|
||||
|
||||
struct MessageConstruct {
|
||||
const Message3Handle e;
|
||||
};
|
||||
|
||||
struct MessageUpdated {
|
||||
const Message3Handle e;
|
||||
// hint?
|
||||
// like component list?
|
||||
};
|
||||
|
||||
struct MessageDestory {
|
||||
const Message3Handle e;
|
||||
};
|
||||
|
||||
} // Events
|
||||
|
||||
enum class RegistryMessageModel_Event : uint32_t {
|
||||
message_construct,
|
||||
message_updated,
|
||||
message_destroy,
|
||||
|
||||
send_text,
|
||||
send_file_path,
|
||||
|
||||
MAX
|
||||
};
|
||||
|
||||
// 2 in 1
|
||||
struct RegistryMessageModelEventI : public MessageModel3I {
|
||||
using enumType = RegistryMessageModel_Event;
|
||||
|
||||
virtual ~RegistryMessageModelEventI(void) {}
|
||||
|
||||
virtual bool onEvent(const Message::Events::MessageConstruct&) { return false; }
|
||||
virtual bool onEvent(const Message::Events::MessageUpdated&) { return false; }
|
||||
virtual bool onEvent(const Message::Events::MessageDestory&) { return false; }
|
||||
|
||||
// mm3
|
||||
// send text
|
||||
// send file path
|
||||
};
|
||||
using RegistryMessageModelEventProviderI = EventProviderI<RegistryMessageModelEventI>;
|
||||
|
||||
class RegistryMessageModel : public RegistryMessageModelEventProviderI, public MessageModel3I {
|
||||
protected:
|
||||
Contact3Registry& _cr;
|
||||
|
||||
entt::dense_map<Contact3, std::unique_ptr<Message3Registry>> _contact_messages;
|
||||
|
||||
bool _update_in_progess {false};
|
||||
std::vector<Message3Handle> _update_queue {};
|
||||
|
||||
public:
|
||||
RegistryMessageModel(Contact3Registry& cr) : _cr(cr) {}
|
||||
virtual ~RegistryMessageModel(void) {}
|
||||
|
||||
// TODO: iterate?
|
||||
|
||||
public:
|
||||
Message3Registry* get(Contact3 c);
|
||||
Message3Registry* get(Contact3 c) const;
|
||||
|
||||
public: // dispatcher
|
||||
// !!! remember to manually throw these externally
|
||||
void throwEventConstruct(Message3Registry& reg, Message3 e);
|
||||
void throwEventUpdate(Message3Registry& reg, Message3 e);
|
||||
void throwEventDestroy(Message3Registry& reg, Message3 e);
|
||||
|
||||
void throwEventConstruct(Message3Handle h) { throwEventConstruct(*h.registry(), h.entity()); }
|
||||
void throwEventUpdate(Message3Handle h) { throwEventUpdate(*h.registry(), h.entity()); }
|
||||
void throwEventDestroy(Message3Handle h) { throwEventDestroy(*h.registry(), h.entity()); }
|
||||
|
||||
void throwEventConstruct(const Contact3 c, Message3 e);
|
||||
void throwEventUpdate(const Contact3 c, Message3 e);
|
||||
void throwEventDestroy(const Contact3 c, Message3 e);
|
||||
|
||||
public: // mm3
|
||||
bool sendText(const Contact3 c, std::string_view message, bool action = false) override;
|
||||
bool sendFilePath(const Contact3 c, std::string_view file_name, std::string_view file_path) override;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user