port to contact4

This commit is contained in:
Green Sky 2025-03-10 16:45:16 +01:00
parent 998ba002e4
commit f321cea6eb
No known key found for this signature in database
GPG Key ID: DBE05085D874AB4A
7 changed files with 114 additions and 98 deletions

View File

@ -36,13 +36,13 @@ SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api)
try {
auto* completion = PLUG_RESOLVE_INSTANCE(TextCompletionI);
auto* conf = PLUG_RESOLVE_INSTANCE(ConfigModelI);
auto* cr = PLUG_RESOLVE_INSTANCE_VERSIONED(Contact3Registry, "1");
auto* cs = PLUG_RESOLVE_INSTANCE(ContactStore4I);
auto* rmm = PLUG_RESOLVE_INSTANCE(RegistryMessageModelI);
auto* mcd = PLUG_RESOLVE_INSTANCE(MessageCommandDispatcher);
// static store, could be anywhere tho
// construct with fetched dependencies
g_rpbot = std::make_unique<RPBot>(*completion, *conf, *cr, *rmm, mcd);
g_rpbot = std::make_unique<RPBot>(*completion, *conf, *cs, *rmm, mcd);
// register types
PLUG_PROVIDE_INSTANCE(RPBot, plugin_name, g_rpbot.get());

View File

@ -2,30 +2,32 @@
#include "./rpbot.hpp"
#include <solanaceae/contact/contact_store_i.hpp>
#include <solanaceae/contact/components.hpp>
#include <solanaceae/message3/components.hpp>
bool MessagePromptBuilder::buildNameLookup(void) {
if (_cr.all_of<Contact::Components::ParentOf>(_c)) { // group rpbot
const auto& subs = _cr.get<Contact::Components::ParentOf>(_c).subs;
const auto& cr = _cs.registry();
if (cr.all_of<Contact::Components::ParentOf>(_c)) { // group rpbot
const auto& subs = cr.get<Contact::Components::ParentOf>(_c).subs;
// should include self
for (const auto sub_c : subs) {
if (_cr.all_of<Contact::Components::Name>(sub_c)) {
names[sub_c] = _cr.get<Contact::Components::Name>(sub_c).name;
if (cr.all_of<Contact::Components::Name>(sub_c)) {
names[sub_c] = cr.get<Contact::Components::Name>(sub_c).name;
}
}
} else { // pm rpbot
if (_cr.all_of<Contact::Components::Name>(_c)) {
names[_c] = _cr.get<Contact::Components::Name>(_c).name;
if (cr.all_of<Contact::Components::Name>(_c)) {
names[_c] = cr.get<Contact::Components::Name>(_c).name;
} else {
std::cerr << "RPBot error: other missing name\n";
return false;
}
if (_cr.all_of<Contact::Components::Self>(_c)) {
const auto self = _cr.get<Contact::Components::Self>(_c).self;
if (_cr.all_of<Contact::Components::Name>(self)) {
names[self] = _cr.get<Contact::Components::Name>(self).name;
if (cr.all_of<Contact::Components::Self>(_c)) {
const auto self = cr.get<Contact::Components::Self>(_c).self;
if (cr.all_of<Contact::Components::Name>(self)) {
names[self] = cr.get<Contact::Components::Name>(self).name;
} else {
std::cerr << "RPBot error: self missing name\n";
return false;
@ -87,7 +89,7 @@ std::string MessagePromptBuilder::buildPromptMessage(const Message3Handle m) {
}
std::string MessagePromptBuilder::promptMessagePrefixSimple(const Message3Handle m) {
const Contact3 from = m.get<Message::Components::ContactFrom>().c;
const Contact4 from = m.get<Message::Components::ContactFrom>().c;
if (names.count(from)) {
return std::string{names[from]};
} else {
@ -98,8 +100,8 @@ std::string MessagePromptBuilder::promptMessagePrefixSimple(const Message3Handle
std::string MessagePromptBuilder::promptMessagePrefixDirected(const Message3Handle m) {
// with both contacts (eg: "Name1 to Name2"; or "Name1 to Everyone"
const Contact3 from = m.get<Message::Components::ContactFrom>().c;
const Contact3 to = m.get<Message::Components::ContactTo>().c;
const Contact4 from = m.get<Message::Components::ContactFrom>().c;
const Contact4 to = m.get<Message::Components::ContactTo>().c;
std::string res;

View File

@ -1,19 +1,19 @@
#pragma once
#include <solanaceae/util/config_model.hpp>
#include <solanaceae/contact/contact_model3.hpp>
#include <solanaceae/contact/fwd.hpp>
#include <solanaceae/message3/registry_message_model.hpp>
#include <entt/container/dense_map.hpp>
// TODO: improve caching
struct MessagePromptBuilder {
Contact3Registry& _cr;
const Contact3 _c;
ContactStore4I& _cs;
const Contact4 _c;
RegistryMessageModelI& _rmm;
// lookup table, string_view since no name-components are changed
entt::dense_map<Contact3, std::string_view> names;
entt::dense_map<Contact4, std::string_view> names;
bool buildNameLookup(void);

View File

@ -18,22 +18,24 @@
#include <cstdint>
template<>
void RPBot::stateTransition(const Contact3 c, const StateIdle& from, StateNextActor& to) {
void RPBot::stateTransition(const Contact4 c, const StateIdle& from, StateNextActor& to) {
// collect promp
MessagePromptBuilder mpb{_cr, c, _rmm, {}};
MessagePromptBuilder mpb{_cs, c, _rmm, {}};
mpb.buildNameLookup();
const auto& cr = _cs.registry();
int64_t self {-1};
{ // get set of possible usernames (even if forced, just to make sure)
// copy mpb.names (contains string views, needs copies)
for (const auto& [name_c, name] : mpb.names) {
if (_cr.all_of<Contact::Components::TagSelfStrong>(name_c)) {
if (cr.all_of<Contact::Components::TagSelfStrong>(name_c)) {
self = to.possible_contacts.size();
to.possible_names.push_back(std::string{name});
to.possible_contacts.push_back(name_c);
} else if (_cr.all_of<Contact::Components::ConnectionState>(name_c)) {
if (_cr.get<Contact::Components::ConnectionState>(name_c).state != Contact::Components::ConnectionState::disconnected) {
} else if (cr.all_of<Contact::Components::ConnectionState>(name_c)) {
if (cr.get<Contact::Components::ConnectionState>(name_c).state != Contact::Components::ConnectionState::disconnected) {
// online
to.possible_names.push_back(std::string{name});
to.possible_contacts.push_back(name_c);
@ -55,7 +57,7 @@ void RPBot::stateTransition(const Contact3 c, const StateIdle& from, StateNextAc
}
{ // - system promp (needs self name etc)
if (const auto* id_comp = _cr.try_get<Contact::Components::ID>(c); id_comp != nullptr) {
if (const auto* id_comp = cr.try_get<Contact::Components::ID>(c); id_comp != nullptr) {
const auto id_hex = bin2hex(id_comp->data);
to.prompt = _conf.get_string("RPBot", "system_prompt", id_hex).value();
} else {
@ -109,17 +111,18 @@ void RPBot::stateTransition(const Contact3 c, const StateIdle& from, StateNextAc
}
template<>
void RPBot::stateTransition(const Contact3, const StateNextActor&, StateIdle& to) {
void RPBot::stateTransition(const Contact4, const StateNextActor&, StateIdle& to) {
to.timeout = std::uniform_real_distribution<>{30.f, 5.f*60.f}(_rng);
}
template<>
void RPBot::stateTransition(const Contact3 c, const StateNextActor& from, StateGenerateMsg& to) {
void RPBot::stateTransition(const Contact4 c, const StateNextActor& from, StateGenerateMsg& to) {
const auto& cr = _cs.registry();
to.prompt = from.prompt; // TODO: move from?
assert(_cr.all_of<Contact::Components::Self>(c));
const Contact3 self = _cr.get<Contact::Components::Self>(c).self;
assert(cr.all_of<Contact::Components::Self>(c));
const Contact4 self = cr.get<Contact::Components::Self>(c).self;
to.prompt += _cr.get<Contact::Components::Name>(self).name + ":"; // TODO: remove space
to.prompt += cr.get<Contact::Components::Name>(self).name + ":"; // TODO: remove space
{ // launch async
to.future = std::async(std::launch::async, [&to, this]() -> std::string {
@ -129,7 +132,7 @@ void RPBot::stateTransition(const Contact3 c, const StateNextActor& from, StateG
}
template<>
void RPBot::stateTransition(const Contact3, const StateGenerateMsg&, StateIdle& to) {
void RPBot::stateTransition(const Contact4, const StateGenerateMsg&, StateIdle& to) {
// relativly slow delay for multi line messages
to.timeout = std::uniform_real_distribution<>{2.f, 15.f}(_rng);
}
@ -137,10 +140,10 @@ void RPBot::stateTransition(const Contact3, const StateGenerateMsg&, StateIdle&
RPBot::RPBot(
TextCompletionI& completion,
ConfigModelI& conf,
Contact3Registry& cr,
ContactStore4I& cs,
RegistryMessageModelI& rmm,
MessageCommandDispatcher* mcd
) : _completion(completion), _conf(conf), _cr(cr), _rmm(rmm), _rmm_sr(_rmm.newSubRef(this)), _mcd(mcd) {
) : _completion(completion), _conf(conf), _cs(cs), _rmm(rmm), _rmm_sr(_rmm.newSubRef(this)), _mcd(mcd) {
//system_prompt = R"sys(Transcript of a group chat, where Bob talks to online strangers.
//)sys";
@ -172,15 +175,16 @@ float RPBot::tick(float time_delta) {
}
float RPBot::doAllIdle(float time_delta) {
auto& cr = _cs.registry();
float min_tick_interval = std::numeric_limits<float>::max();
std::vector<Contact3> to_remove_stateidle;
auto view = _cr.view<StateIdle>();
std::vector<Contact4> to_remove_stateidle;
auto view = cr.view<StateIdle>();
view.each([this, time_delta, &to_remove_stateidle, &min_tick_interval](const Contact3 c, StateIdle& state) {
if (_cr.all_of<TagStopRPBot>(c)) {
view.each([this, &cr, time_delta, &to_remove_stateidle, &min_tick_interval](const Contact4 c, StateIdle& state) {
if (cr.all_of<TagStopRPBot>(c)) {
// marked for deletion, in idle (here) we remove them without adding next state
to_remove_stateidle.push_back(c);
_cr.remove<TagStopRPBot>(c);
cr.remove<TagStopRPBot>(c);
return;
}
@ -204,7 +208,7 @@ float RPBot::doAllIdle(float time_delta) {
auto view_it = tmp_view.begin(), view_last = tmp_view.end();
for (size_t i = 0; i < max_cont_messages && view_it != view_last; view_it++, i++) {
// TODO: also test for weak self?
if (!_cr.any_of<Contact::Components::TagSelfStrong>(tmp_view.get<Message::Components::ContactFrom>(*view_it).c)) {
if (!cr.any_of<Contact::Components::TagSelfStrong>(tmp_view.get<Message::Components::ContactFrom>(*view_it).c)) {
other_sender = true;
break;
}
@ -215,7 +219,7 @@ float RPBot::doAllIdle(float time_delta) {
min_tick_interval = 0.1f;
// transition to Next
emplaceStateTransition<StateNextActor>(_cr, c, state);
emplaceStateTransition<StateNextActor>(_cs, c, state);
return;
}
}
@ -232,16 +236,17 @@ float RPBot::doAllIdle(float time_delta) {
}
});
_cr.remove<StateIdle>(to_remove_stateidle.cbegin(), to_remove_stateidle.cend());
cr.remove<StateIdle>(to_remove_stateidle.cbegin(), to_remove_stateidle.cend());
return min_tick_interval;
}
float RPBot::doAllNext(float) {
auto& cr = _cs.registry();
float min_tick_interval = std::numeric_limits<float>::max();
std::vector<Contact3> to_remove;
auto view = _cr.view<StateNextActor>();
std::vector<Contact4> to_remove;
auto view = cr.view<StateNextActor>();
view.each([this, &to_remove, &min_tick_interval](const Contact3 c, StateNextActor& state) {
view.each([this, &cr, &to_remove, &min_tick_interval](const Contact4 c, StateNextActor& state) {
// TODO: how to timeout?
if (state.future.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) {
to_remove.push_back(c);
@ -251,9 +256,9 @@ float RPBot::doAllNext(float) {
const auto selected = state.future.get();
if (selected >= 0 && size_t(selected) < state.possible_names.size()) {
std::cout << "next is " << state.possible_names.at(selected) << "(" << selected << ")\n";
if (_cr.all_of<Contact::Components::TagSelfStrong>(state.possible_contacts.at(selected))) {
if (cr.all_of<Contact::Components::TagSelfStrong>(state.possible_contacts.at(selected))) {
// we predicted ourselfs
emplaceStateTransition<StateGenerateMsg>(_cr, c, state);
emplaceStateTransition<StateGenerateMsg>(_cs, c, state);
return;
}
} else {
@ -261,21 +266,22 @@ float RPBot::doAllNext(float) {
}
// transition to Idle
emplaceStateTransition<StateIdle>(_cr, c, state);
emplaceStateTransition<StateIdle>(_cs, c, state);
}
});
_cr.remove<StateNextActor>(to_remove.cbegin(), to_remove.cend());
cr.remove<StateNextActor>(to_remove.cbegin(), to_remove.cend());
return min_tick_interval;
}
float RPBot::doAllGenerateMsg(float) {
auto& cr = _cs.registry();
float min_tick_interval = std::numeric_limits<float>::max();
std::vector<Contact3> to_remove;
auto view = _cr.view<StateGenerateMsg>();
std::vector<Contact4> to_remove;
auto view = cr.view<StateGenerateMsg>();
_cr.remove<StateGenerateMsg>(to_remove.cbegin(), to_remove.cend());
view.each([this, &to_remove, &min_tick_interval](const Contact3 c, StateGenerateMsg& state) {
cr.remove<StateGenerateMsg>(to_remove.cbegin(), to_remove.cend());
view.each([this, &to_remove, &min_tick_interval](const Contact4 c, StateGenerateMsg& state) {
// TODO: how to timeout?
if (state.future.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) {
to_remove.push_back(c);
@ -293,11 +299,11 @@ float RPBot::doAllGenerateMsg(float) {
// TODO: timing check?
// transition to Idle
emplaceStateTransition<StateIdle>(_cr, c, state);
emplaceStateTransition<StateIdle>(_cs, c, state);
}
});
_cr.remove<StateGenerateMsg>(to_remove.cbegin(), to_remove.cend());
cr.remove<StateGenerateMsg>(to_remove.cbegin(), to_remove.cend());
return min_tick_interval;
}
@ -311,39 +317,41 @@ bool RPBot::onEvent(const Message::Events::MessageConstruct& e) {
return false;
}
auto& cr = _cs.registry();
const auto contact_to = e.e.get<Message::Components::ContactTo>().c;
const auto contact_from = e.e.get<Message::Components::ContactFrom>().c;
if (!_cr.valid(contact_to) || !_cr.valid(contact_from)) {
if (!cr.valid(contact_to) || !cr.valid(contact_from)) {
std::cerr << "RPBot error: invalid contact in message\n";
return false;
}
if (_cr.any_of<Contact::Components::TagSelfStrong>(contact_from)) {
if (cr.any_of<Contact::Components::TagSelfStrong>(contact_from)) {
return false; // ignore own messages
}
Contact3 rpbot_contact = entt::null;
Contact4 rpbot_contact = entt::null;
// check ContactTo (public)
// check ContactTo parent (group private)
// check ContactFrom (private)
if (_cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(contact_to)) {
if (cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(contact_to)) {
rpbot_contact = contact_to;
} else if (_cr.all_of<Contact::Components::Parent>(contact_to)) {
rpbot_contact = _cr.get<Contact::Components::Parent>(contact_to).parent;
} else if (_cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(contact_from)) {
} else if (cr.all_of<Contact::Components::Parent>(contact_to)) {
rpbot_contact = cr.get<Contact::Components::Parent>(contact_to).parent;
} else if (cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(contact_from)) {
rpbot_contact = contact_from;
} else {
return false; // not a rpbot related message
}
if (!_cr.all_of<StateIdle>(rpbot_contact)) {
if (!cr.all_of<StateIdle>(rpbot_contact)) {
return false; // not idle
}
auto& timeout = _cr.get<StateIdle>(rpbot_contact).timeout;
auto& timeout = cr.get<StateIdle>(rpbot_contact).timeout;
// TODO: config with id
timeout = std::clamp<float>(
timeout,

View File

@ -2,7 +2,7 @@
#include <solanaceae/util/config_model.hpp>
#include <solanaceae/llama-cpp-web/text_completion_interface.hpp>
#include <solanaceae/contact/contact_model3.hpp>
#include <solanaceae/contact/contact_store_i.hpp>
#include <solanaceae/message3/registry_message_model.hpp>
#include <solanaceae/message3/message_command_dispatcher.hpp>
@ -19,7 +19,7 @@ struct StateTimingCheck;
struct RPBot : public RegistryMessageModelEventI {
TextCompletionI& _completion;
ConfigModelI& _conf;
Contact3Registry& _cr;
ContactStore4I& _cs;
RegistryMessageModelI& _rmm;
RegistryMessageModelI::SubscriptionReference _rmm_sr;
MessageCommandDispatcher* _mcd;
@ -30,7 +30,7 @@ struct RPBot : public RegistryMessageModelEventI {
RPBot(
TextCompletionI& completion,
ConfigModelI& conf,
Contact3Registry& cr,
ContactStore4I& cs,
RegistryMessageModelI& rmm,
MessageCommandDispatcher* mcd
);
@ -42,13 +42,13 @@ struct RPBot : public RegistryMessageModelEventI {
protected: // state transitions
// all transitions need to be explicitly declared
template<typename To, typename From>
void stateTransition(const Contact3 c, const From& from, To& to) = delete;
void stateTransition(const Contact4 c, const From& from, To& to) = delete;
// reg helper
template<typename To, typename From>
To& emplaceStateTransition(Contact3Registry& cr, Contact3 c, const From& state) {
To& emplaceStateTransition(ContactStore4I& cs, Contact4 c, const From& state) {
std::cout << "RPBot: transition from " << From::name << " to " << To::name << "\n";
To& to = cr.emplace_or_replace<To>(c);
To& to = cs.registry().emplace_or_replace<To>(c);
stateTransition<To>(c, state, to);
return to;
}

View File

@ -18,16 +18,18 @@ void RPBot::registerCommands(void) {
const auto contact_from = m.get<Message::Components::ContactFrom>().c;
const auto contact_to = m.get<Message::Components::ContactTo>().c;
auto& cr = _cs.registry();
if (params.empty()) {
// contact_to should be the contact this is for
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
_rmm.sendText(
contact_from,
"error: already running"
);
return true;
}
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
_rmm.sendText(
contact_from,
"error: already running"
@ -35,13 +37,13 @@ void RPBot::registerCommands(void) {
return true;
}
if (_cr.all_of<Contact::Components::ParentOf>(contact_to)) {
if (cr.all_of<Contact::Components::ParentOf>(contact_to)) {
// group
auto& new_state = _cr.emplace<StateIdle>(contact_to);
auto& new_state = cr.emplace<StateIdle>(contact_to);
new_state.timeout = 10.f;
} else {
// pm
auto& new_state = _cr.emplace<StateIdle>(contact_from);
auto& new_state = cr.emplace<StateIdle>(contact_from);
new_state.timeout = 10.f;
}
@ -62,10 +64,10 @@ void RPBot::registerCommands(void) {
auto id_bin = hex2bin(params);
auto view = _cr.view<Contact::Components::ID>();
auto view = cr.view<Contact::Components::ID>();
for (auto it = view.begin(), it_end = view.end(); it != it_end; it++) {
if (view.get<Contact::Components::ID>(*it).data == id_bin) {
if (_cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(*it)) {
if (cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(*it)) {
_rmm.sendText(
contact_from,
"RPBot already running"
@ -73,7 +75,7 @@ void RPBot::registerCommands(void) {
return true;
}
auto& new_state = _cr.emplace<StateIdle>(*it);
auto& new_state = cr.emplace<StateIdle>(*it);
new_state.timeout = 10.f;
_rmm.sendText(
@ -102,18 +104,20 @@ void RPBot::registerCommands(void) {
const auto contact_from = m.get<Message::Components::ContactFrom>().c;
const auto contact_to = m.get<Message::Components::ContactTo>().c;
auto& cr = _cs.registry();
if (params.empty()) {
// contact_to should be the contact this is for
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
_cr.emplace_or_replace<TagStopRPBot>(contact_to);
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
cr.emplace_or_replace<TagStopRPBot>(contact_to);
_rmm.sendText(
contact_from,
"stopped"
);
return true;
}
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
_cr.emplace_or_replace<TagStopRPBot>(contact_from);
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
cr.emplace_or_replace<TagStopRPBot>(contact_from);
_rmm.sendText(
contact_from,
"stopped"
@ -138,11 +142,11 @@ void RPBot::registerCommands(void) {
auto id_bin = hex2bin(params);
auto view = _cr.view<Contact::Components::ID>();
auto view = cr.view<Contact::Components::ID>();
for (auto it = view.begin(), it_end = view.end(); it != it_end; it++) {
if (view.get<Contact::Components::ID>(*it).data == id_bin) {
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(*it)) {
_cr.emplace_or_replace<TagStopRPBot>(*it);
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(*it)) {
cr.emplace_or_replace<TagStopRPBot>(*it);
_rmm.sendText(
contact_from,
"stopped"
@ -176,12 +180,14 @@ void RPBot::registerCommands(void) {
const auto contact_from = m.get<Message::Components::ContactFrom>().c;
const auto contact_to = m.get<Message::Components::ContactTo>().c;
auto& cr = _cs.registry();
if (params.empty()) {
// contact_to should be the contact this is for
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
if (_cr.all_of<StateIdle>(contact_to)) {
_cr.get<StateIdle>(contact_to).force = true;
_cr.get<StateIdle>(contact_to).timeout = 2.f;
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
if (cr.all_of<StateIdle>(contact_to)) {
cr.get<StateIdle>(contact_to).force = true;
cr.get<StateIdle>(contact_to).timeout = 2.f;
_rmm.sendText(
contact_from,
"forced its hand"
@ -189,10 +195,10 @@ void RPBot::registerCommands(void) {
}
return true;
}
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
if (_cr.all_of<StateIdle>(contact_from)) {
_cr.get<StateIdle>(contact_from).force = true;
_cr.get<StateIdle>(contact_from).timeout = 2.f;
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
if (cr.all_of<StateIdle>(contact_from)) {
cr.get<StateIdle>(contact_from).force = true;
cr.get<StateIdle>(contact_from).timeout = 2.f;
_rmm.sendText(
contact_from,
"forced its hand"
@ -218,13 +224,13 @@ void RPBot::registerCommands(void) {
auto id_bin = hex2bin(params);
auto view = _cr.view<Contact::Components::ID>();
auto view = cr.view<Contact::Components::ID>();
for (auto it = view.begin(), it_end = view.end(); it != it_end; it++) {
if (view.get<Contact::Components::ID>(*it).data == id_bin) {
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(*it)) {
if (_cr.all_of<StateIdle>(*it)) {
_cr.get<StateIdle>(*it).force = true;
_cr.get<StateIdle>(*it).timeout = 2.f;
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(*it)) {
if (cr.all_of<StateIdle>(*it)) {
cr.get<StateIdle>(*it).force = true;
cr.get<StateIdle>(*it).timeout = 2.f;
_rmm.sendText(
contact_from,
"forced its hand"

View File

@ -22,7 +22,7 @@ struct StateNextActor {
std::string prompt;
std::vector<std::string> possible_names;
std::vector<Contact3> possible_contacts;
std::vector<Contact4> possible_contacts;
std::future<int64_t> future;
};