Chat channels (join channel, send messages) and house peering capabilities

This commit is contained in:
Emagi 2025-08-30 09:29:46 -04:00
parent 00698d3eb0
commit 6401247809
12 changed files with 252 additions and 22 deletions

View File

@ -35,8 +35,10 @@
#endif
#endif
#include "../Web/PeerManager.h"
extern ConfigReader configReader;
extern PeerManager peer_manager;
@ -164,19 +166,23 @@ bool Chat::PasswordMatches(const char *channel_name, const char *password) {
return ret;
}
bool Chat::CreateChannel(const char *channel_name) {
return CreateChannel(channel_name, NULL);
bool Chat::CreateChannel(const char *channel_name, bool fromPeer) {
return CreateChannel(channel_name, NULL, fromPeer);
}
bool Chat::CreateChannel(const char *channel_name, const char *password) {
bool Chat::CreateChannel(const char *channel_name, const char *password, bool fromPeer) {
LogWrite(CHAT__DEBUG, 0, "Chat", "Channel %s being created", channel_name);
ChatChannel *channel = new ChatChannel();
channel->SetName(channel_name);
channel->SetType(CHAT_CHANNEL_TYPE_CUSTOM);
if (password != NULL)
if (password != NULL && strlen(password) > 0)
channel->SetPassword(password);
if(!fromPeer) {
peer_manager.sendPeersAddChatChannel(std::string(channel_name), password != nullptr ? std::string(password) : std::string(""));
}
m_channels.writelock(__FUNCTION__, __LINE__);
channels.push_back(channel);
m_channels.releasewritelock(__FUNCTION__, __LINE__);
@ -274,7 +280,7 @@ bool Chat::LeaveAllChannels(Client *client) {
return true;
}
bool Chat::TellChannel(Client *client, const char *channel_name, const char *message, const char* name) {
bool Chat::TellChannel(Client *client, std::string charName, int8 charLanguage, const char *channel_name, const char *message, const char* name) {
vector<ChatChannel *>::iterator itr;
bool ret = false;
bool enablediscord = rule_manager.GetGlobalRule(R_Discord, DiscordEnabled)->GetBool();
@ -286,7 +292,7 @@ bool Chat::TellChannel(Client *client, const char *channel_name, const char *mes
if (client && name)
ret = (*itr)->TellChannelClient(client, message, name);
else
ret = (*itr)->TellChannel(client, message, name);
ret = (*itr)->TellChannel(charName, charLanguage, message, name);
if(enablediscord == true && client){

View File

@ -99,13 +99,13 @@ public:
bool ChannelExists(const char *channel_name);
bool HasPassword(const char *channel_name);
bool PasswordMatches(const char *channel_name, const char *password);
bool CreateChannel(const char *channel_name);
bool CreateChannel(const char *channel_name, const char *password);
bool CreateChannel(const char *channel_name, bool fromPeer = false);
bool CreateChannel(const char *channel_name, const char *password, bool fromPeer = false);
bool IsInChannel(Client *client, const char *channel_name);
bool JoinChannel(Client *client, const char *channel_name);
bool LeaveChannel(Client *client, const char *channel_name);
bool LeaveAllChannels(Client *client);
bool TellChannel(Client *client, const char *channel_name, const char *message, const char* name = 0);
bool TellChannel(Client *client, std::string charName, int8 charLanguage, const char *channel_name, const char *message, const char* name = 0);
bool SendChannelUserList(Client *client, const char *channel_name);
//devn00b
int PushDiscordMsg(const char*, const char*);

View File

@ -120,7 +120,7 @@ bool ChatChannel::LeaveChannel(Client *client) {
return ret;
}
bool ChatChannel::TellChannel(Client *client, const char *message, const char* name2) {
bool ChatChannel::TellChannel(std::string charName, int8 charLanguage, const char *message, const char* name2) {
vector<int32>::iterator itr;
PacketStruct *packet_struct;
Client *to_client;
@ -135,8 +135,8 @@ bool ChatChannel::TellChannel(Client *client, const char *message, const char* n
packet_struct->setDataByName("from_spawn_id", 0xFFFFFFFF);
packet_struct->setDataByName("to_spawn_id", 0xFFFFFFFF);
if (client != NULL){
packet_struct->setDataByName("from", client->GetPlayer()->GetName());
if (charName.length() > 0){
packet_struct->setDataByName("from", charName.c_str());
} else {
char name3[128];
sprintf(name3,"[%s] from discord",name2);
@ -146,8 +146,8 @@ bool ChatChannel::TellChannel(Client *client, const char *message, const char* n
packet_struct->setDataByName("to", to_client->GetPlayer()->GetName());
packet_struct->setDataByName("channel", to_client->GetMessageChannelColor(CHANNEL_CUSTOM_CHANNEL));
if(client != NULL){
packet_struct->setDataByName("language", client->GetPlayer()->GetCurrentLanguage());
if(charName.length() > 0){
packet_struct->setDataByName("language", charLanguage);
}else{
packet_struct->setDataByName("language", 0);
}
@ -155,8 +155,8 @@ bool ChatChannel::TellChannel(Client *client, const char *message, const char* n
packet_struct->setDataByName("channel_name", name);
packet_struct->setDataByName("show_bubble", 1);
if(client != NULL){
if (client->GetPlayer()->GetCurrentLanguage() == 0 || to_client->GetPlayer()->HasLanguage(client->GetPlayer()->GetCurrentLanguage())) {
if(charName.length() > 0){
if (charLanguage == 0 || to_client->GetPlayer()->HasLanguage(charLanguage)) {
packet_struct->setDataByName("understood", 1);
}
} else {

View File

@ -61,8 +61,9 @@ public:
bool IsInChannel(int32 character_id);
bool JoinChannel(Client *client);
bool LeaveChannel(Client *client);
bool TellChannel(Client *client, const char *message, const char* name2 = 0);
bool TellChannel(std::string charName, int8 charLanguage, const char *message, const char* name2 = 0);
bool TellChannelClient(Client* to_client, const char* message, const char* name2 = 0);
bool SendChannelUserList(Client *client);

View File

@ -3989,8 +3989,10 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
ph->escrow_coins += outValCoin;
ph->escrow_status += outValStatus;
database.UpdateHouseEscrow(ph->house_id, ph->instance_id, ph->escrow_coins, ph->escrow_status);
peer_manager.sendPeersUpdateHouseDeposit(ph->instance_id, ph->escrow_coins, ph->escrow_status);
database.LoadDeposits(ph);
client->PlaySound("coin_cha_ching");
HouseZone* hz = world.GetHouseZone(ph->house_id);
ClientPacketFunctions::SendBaseHouseWindow(client, hz, ph, client->GetVersion() <= 561 ? spawn_id : client->GetPlayer()->GetID());
@ -10237,7 +10239,9 @@ void Commands::Command_TellChannel(Client *client, Seperator *sep) {
return;
}
chat.TellChannel(client, sep->arg[0], sep->argplus[1]);
chat.TellChannel(client, std::string(client->GetPlayer()->GetName()), client->GetPlayer()->GetCurrentLanguage(), sep->arg[0], sep->argplus[1]);
peer_manager.SendPeersChatChannelMessage(std::string(sep->arg[0]), std::string(client->GetPlayer()->GetName()), std::string(sep->argplus[1]),
client->GetPlayer()->GetCurrentLanguage(), "");
}
void Commands::Command_Test(Client* client, EQ2_16BitString* command_parms) {

View File

@ -935,4 +935,60 @@ void PeerManager::sendPeersRemoveItemSale(int32 character_id, int64 uniqueID) {
continue;
peer_https_pool.sendPostRequestToPeerAsync(peer->id, peer->webAddr, std::to_string(peer->webPort), "/removeitemsale", jsonPayload);
}
}
void PeerManager::sendPeersAddPlayerHouse(int32 charID, int64 uniqueID, int32 houseID, int32 instanceID, int32 upkeepDue, std::string charName) {
boost::property_tree::ptree root;
root.put("character_id", charID);
root.put("unique_id", uniqueID);
root.put("instance_id", instanceID);
root.put("upkeep_due", upkeepDue);
root.put("character_name", charName);
std::ostringstream jsonStream;
boost::property_tree::write_json(jsonStream, root);
std::string jsonPayload = jsonStream.str();
LogWrite(PEERING__DEBUG, 0, "Peering", "%s: Add Player House, CharID: %u, UniqueID: %u, instanceID: %u", __FUNCTION__, charID, uniqueID, instanceID);
for (const auto& [id, peer] : peers) {
if (peer->healthCheck.status != HealthStatus::OK)
continue;
peer_https_pool.sendPostRequestToPeerAsync(peer->id, peer->webAddr, std::to_string(peer->webPort), "/addplayerhouse", jsonPayload);
}
}
void PeerManager::sendPeersUpdateHouseDeposit(int32 instanceID, int64 escrowDeposit, int32 escrowStatus) {
boost::property_tree::ptree root;
root.put("instance_id", instanceID);
root.put("escrow_deposit", escrowDeposit);
root.put("escrow_status", escrowStatus);
std::ostringstream jsonStream;
boost::property_tree::write_json(jsonStream, root);
std::string jsonPayload = jsonStream.str();
LogWrite(PEERING__DEBUG, 0, "Peering", "%s: Update House Deposit, instanceID: %u, coin total: %llu, status total: %u", __FUNCTION__, instanceID, escrowDeposit, escrowStatus);
for (const auto& [id, peer] : peers) {
if (peer->healthCheck.status != HealthStatus::OK)
continue;
peer_https_pool.sendPostRequestToPeerAsync(peer->id, peer->webAddr, std::to_string(peer->webPort), "/updatehousedeposit", jsonPayload);
}
}
void PeerManager::sendPeersAddChatChannel(std::string channelName, std::string channelPassword) {
boost::property_tree::ptree root;
root.put("channel_name", channelName);
root.put("channel_password", channelPassword);
std::ostringstream jsonStream;
boost::property_tree::write_json(jsonStream, root);
std::string jsonPayload = jsonStream.str();
LogWrite(PEERING__DEBUG, 0, "Peering", "%s: Add Chat Channel, channel name: %s", __FUNCTION__, channelName.c_str());
for (const auto& [id, peer] : peers) {
if (peer->healthCheck.status != HealthStatus::OK)
continue;
peer_https_pool.sendPostRequestToPeerAsync(peer->id, peer->webAddr, std::to_string(peer->webPort), "/addchatchannel", jsonPayload);
}
}

View File

@ -179,6 +179,7 @@ public:
bool IsClientConnectedPeer(int32 account_id, int32 char_id);
std::string GetCharacterPeerId(std::string charName);
void SendPeersChannelMessage(int32 group_id, std::string fromName, std::string message, int16 channel, int32 language_id = 0, int8 custom_type = 0);
void SendPeersChatChannelMessage(std::string channelName, std::string fromName, std::string message, int32 language_id, std::string toName);
void SendPeersGuildChannelMessage(int32 guild_id, std::string fromName, std::string message, int16 channel, int32 language_id = 0, int8 custom_type = 0);
void sendZonePeerList(Client* client);
std::string getZonePeerId(const std::string& inc_zone_name, int32 inc_zone_id, int32 inc_instance_id, ZoneChangeDetails* opt_details = nullptr, bool only_always_loaded = false, int32 matchDuplicatedId = 0);
@ -231,6 +232,10 @@ public:
void sendPeersRemoveSeller(int32 character_id);
void sendPeersAddItemSale(int32 character_id, int32 house_id, int32 itemID, int64 uniqueID, int64 price, sint32 invSlotID, int16 slotID, int16 count, bool inInventory, bool forSale, std::string itemCreator);
void sendPeersRemoveItemSale(int32 character_id, int64 uniqueID);
void sendPeersAddPlayerHouse(int32 charID, int64 uniqueID, int32 houseID, int32 instanceID, int32 upkeepDue, std::string charName);
void sendPeersUpdateHouseDeposit(int32 instanceID, int64 escrowDeposit, int32 escrowStatus);
void sendPeersAddChatChannel(std::string channelName, std::string channelPassword);
};

View File

@ -25,6 +25,7 @@
#include "../LuaInterface.h"
#include "../Guilds/Guild.h"
#include "../Broker/BrokerManager.h"
#include "../Chat/Chat.h"
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
@ -46,6 +47,7 @@ extern MasterFactionList master_faction_list;
extern ClientList client_list;
extern GuildList guild_list;
extern BrokerManager broker;
extern Chat chat;
PeerManager peer_manager;
HTTPSClientPool peer_https_pool;
@ -739,7 +741,7 @@ void World::Web_worldhandle_sendglobalmessage(const http::request<http::string_b
int32 success = 0;
int8 language = 0;
int16 in_channel = 0;
std::string toName(""), fromName(""), msg("");
std::string toName(""), fromName(""), msg(""), channelName("");
int32 group_id = 0;
int32 guild_id = 0;
int8 custom_type = 0;
@ -752,6 +754,10 @@ void World::Web_worldhandle_sendglobalmessage(const http::request<http::string_b
if (auto message = json_tree.get_optional<std::string>("message")) {
msg = message.get();
}
if (auto in_channel = json_tree.get_optional<std::string>("channel_name")) {
channelName = in_channel.get();
}
if (auto from_language = json_tree.get_optional<int8>("from_language")) {
language = from_language.get();
}
@ -769,7 +775,7 @@ void World::Web_worldhandle_sendglobalmessage(const http::request<http::string_b
}
Client* find_client = zone_list.GetClientByCharName(toName.c_str());
if (find_client && find_client->GetPlayer()->IsIgnored(fromName.c_str()))
if (in_channel == CHANNEL_PRIVATE_TELL && find_client && find_client->GetPlayer()->IsIgnored(fromName.c_str()))
success = 0;
else {
switch (in_channel) {
@ -854,6 +860,13 @@ void World::Web_worldhandle_sendglobalmessage(const http::request<http::string_b
}
break;
}
case CHANNEL_CHAT_CHANNEL_TEXT: {
if(fromName.length() > 0)
chat.TellChannel(nullptr, fromName, language, channelName.c_str(), msg.c_str());
else
chat.TellChannel(nullptr, "", 0, channelName.c_str(), msg.c_str(), toName.c_str()); // toName used as an override for chat channels via discord bot
break;
}
}
}
@ -1582,4 +1595,122 @@ void World::Web_worldhandle_removeitemsale(const http::request<http::string_body
std::string json = oss.str();
res.body() = json;
res.prepare_payload();
}
}
void World::Web_worldhandle_addplayerhouse(const http::request<http::string_body>& req, http::response<http::string_body>& res) {
res.set(http::field::content_type, "application/json; charset=utf-8");
boost::property_tree::ptree pt, json_tree;
std::istringstream json_stream(req.body());
boost::property_tree::read_json(json_stream, json_tree);
int32 charID = 0;
int64 uniqueID = 0;
int32 houseID = 0;
int32 instanceID = 0;
bool success = false;
int32 upkeepDue = 0;
std::string charname("");
if (auto character_id = json_tree.get_optional<int32>("character_id")) {
charID = character_id.get();
}
if (auto house_id = json_tree.get_optional<int32>("house_id")) {
houseID = house_id.get();
}
if (auto unique_id = json_tree.get_optional<int64>("unique_id")) {
uniqueID = unique_id.get();
}
if (auto instance_id = json_tree.get_optional<int32>("instance_id")) {
instanceID = instance_id.get();
}
if (auto upkeep_due = json_tree.get_optional<int32>("upkeep_due")) {
upkeepDue = upkeep_due.get();
}
if (auto name = json_tree.get_optional<std::string>("character_name")) {
charname = name.get();
}
if(charID && houseID && uniqueID && charname.length() > 0) {
world.AddPlayerHouse(charID, houseID, uniqueID, instanceID, upkeepDue, 0, 0, charname);
success = true;
}
pt.put("success", success);
pt.put("character_id", charID);
std::ostringstream oss;
boost::property_tree::write_json(oss, pt);
std::string json = oss.str();
res.body() = json;
res.prepare_payload();
}
void World::Web_worldhandle_updatehousedeposit(const http::request<http::string_body>& req, http::response<http::string_body>& res) {
res.set(http::field::content_type, "application/json; charset=utf-8");
boost::property_tree::ptree pt, json_tree;
std::istringstream json_stream(req.body());
boost::property_tree::read_json(json_stream, json_tree);
int64 escrowCoin = 0;
int64 escrowStatus = 0;
int32 instanceID = 0;
bool success = false;
if (auto escrow_coins = json_tree.get_optional<int64>("escrow_coins")) {
escrowCoin = escrow_coins.get();
}
if (auto escrow_status = json_tree.get_optional<int64>("escrow_status")) {
escrowStatus = escrow_status.get();
}
if (auto instance_id = json_tree.get_optional<int32>("instance_id")) {
instanceID = instance_id.get();
}
if(instanceID) {
PlayerHouse* ph = world.GetPlayerHouseByInstanceID(instanceID);
if(ph) {
ph->escrow_coins = escrowCoin;
ph->escrow_status = escrowStatus;
database.LoadDeposits(ph);
success = true;
}
}
pt.put("success", success);
pt.put("instance_id", instanceID);
std::ostringstream oss;
boost::property_tree::write_json(oss, pt);
std::string json = oss.str();
res.body() = json;
res.prepare_payload();
}
void World::Web_worldhandle_addchatchannel(const http::request<http::string_body>& req, http::response<http::string_body>& res) {
res.set(http::field::content_type, "application/json; charset=utf-8");
boost::property_tree::ptree pt, json_tree;
std::istringstream json_stream(req.body());
boost::property_tree::read_json(json_stream, json_tree);
bool success = false;
std::string channelname("");
std::string channelpasswd("");
if (auto name = json_tree.get_optional<std::string>("channel_name")) {
channelname = name.get();
}
if (auto passwd = json_tree.get_optional<std::string>("channel_password")) {
channelpasswd = passwd.get();
}
if(channelname.length() > 0) {
if (chat.ChannelExists(channelname.c_str()) || chat.CreateChannel(channelname.c_str(), channelpasswd.c_str(), true)) {
success = true;
}
}
pt.put("success", success);
pt.put("channel_name", channelname);
std::ostringstream oss;
boost::property_tree::write_json(oss, pt);
std::string json = oss.str();
res.body() = json;
res.prepare_payload();
}

View File

@ -288,6 +288,9 @@ void World::init(std::string web_ipaddr, int16 web_port, std::string cert_file,
world_webserver->register_route("/removeseller", World::Web_worldhandle_removeseller);
world_webserver->register_route("/additemsale", World::Web_worldhandle_additemsale);
world_webserver->register_route("/removeitemsale", World::Web_worldhandle_removeitemsale);
world_webserver->register_route("/addplayerhouse", World::Web_worldhandle_addplayerhouse);
world_webserver->register_route("/updatehousedeposit", World::Web_worldhandle_updatehousedeposit);
world_webserver->run();
LogWrite(INIT__INFO, 0, "Init", "World Web Server is listening on %s:%u..", web_ipaddr.c_str(), web_port);
web_success = true;
@ -1036,6 +1039,24 @@ void PeerManager::SendPeersGuildChannelMessage(int32 guild_id, std::string fromN
}
}
void PeerManager::SendPeersChatChannelMessage(std::string channelName, std::string fromName, std::string message, int32 language_id, std::string toName) {
boost::property_tree::ptree root;
root.put("message", message);
root.put("channel", CHANNEL_CHAT_CHANNEL_TEXT);
root.put("channel_name", channelName);
root.put("from_language", language_id);
root.put("from_name", fromName);
root.put("to_name", toName);
std::ostringstream jsonStream;
boost::property_tree::write_json(jsonStream, root);
std::string jsonPayload = jsonStream.str();
for (auto& [peerId, peer] : peers) {
if(peer->healthCheck.status != HealthStatus::OK)
continue;
peer_https_pool.sendPostRequestToPeerAsync(peer->id, peer->webAddr, std::to_string(peer->webPort), "/sendglobalmessage", jsonPayload);
}
}
void PeerManager::sendZonePeerList(Client* client) {
for (auto& [peerId, peer] : peers) {
if(peer->healthCheck.status != HealthStatus::OK)

View File

@ -744,6 +744,9 @@ public:
static void Web_worldhandle_removeseller(const http::request<http::string_body>& req, http::response<http::string_body>& res);
static void Web_worldhandle_additemsale(const http::request<http::string_body>& req, http::response<http::string_body>& res);
static void Web_worldhandle_removeitemsale(const http::request<http::string_body>& req, http::response<http::string_body>& res);
static void Web_worldhandle_addplayerhouse(const http::request<http::string_body>& req, http::response<http::string_body>& res);
static void Web_worldhandle_updatehousedeposit(const http::request<http::string_body>& req, http::response<http::string_body>& res);
static void Web_worldhandle_addchatchannel(const http::request<http::string_body>& req, http::response<http::string_body>& res);
static void Web_populate_status(boost::property_tree::ptree& pt);

View File

@ -2435,6 +2435,8 @@ bool Client::HandlePacket(EQApplicationPacket* app) {
GetPlayer()->GetCharacterInstances()->AddInstance(db_id, zone_details.instanceId, 0, 0, zone_details.defaultLockoutTime, zone_details.defaultReenterTime, zoneID, zone_details.instanceType, zone_details.zoneName);
world.AddPlayerHouse(GetPlayer()->GetCharacterID(), hz->id, unique_id, zone_details.instanceId, upkeep_due, 0, 0, GetPlayer()->GetName());
peer_manager.sendPeersAddPlayerHouse(GetPlayer()->GetCharacterID(), unique_id, hz->id, zone_details.instanceId, upkeep_due, GetPlayer()->GetName());
//ClientPacketFunctions::SendHousingList(this);
PlayerHouse* ph = world.GetPlayerHouseByUniqueID(unique_id);
ClientPacketFunctions::SendBaseHouseWindow(this, hz, ph, GetVersion() <= 561 ? house_id : this->GetPlayer()->GetID());

View File

@ -1061,7 +1061,8 @@ ThreadReturnType StartDiscord(void* tmp)
if(chanid.compare(listenchan) != 0 || !chanid.size() || !listenchan.size()) {
return;
}
chat.TellChannel(NULL, listenchan.c_str(), event.msg.content.c_str(), event.msg.author.username.c_str());
chat.TellChannel(nullptr, "", 0, listenchan.c_str(), event.msg.content.c_str(), event.msg.author.username.c_str());
peer_manager.SendPeersChatChannelMessage(listenchan, "", event.msg.content, 0, event.msg.author.username);
}
});