diff --git a/source/WorldServer/Chat/Chat.cpp b/source/WorldServer/Chat/Chat.cpp index 8c41c25..7eea159 100644 --- a/source/WorldServer/Chat/Chat.cpp +++ b/source/WorldServer/Chat/Chat.cpp @@ -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::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){ diff --git a/source/WorldServer/Chat/Chat.h b/source/WorldServer/Chat/Chat.h index fe6c4e2..6033285 100644 --- a/source/WorldServer/Chat/Chat.h +++ b/source/WorldServer/Chat/Chat.h @@ -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*); diff --git a/source/WorldServer/Chat/ChatChannel.cpp b/source/WorldServer/Chat/ChatChannel.cpp index e0fbf9e..59b7ea5 100644 --- a/source/WorldServer/Chat/ChatChannel.cpp +++ b/source/WorldServer/Chat/ChatChannel.cpp @@ -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::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 { diff --git a/source/WorldServer/Chat/ChatChannel.h b/source/WorldServer/Chat/ChatChannel.h index 8dce202..7c31de3 100644 --- a/source/WorldServer/Chat/ChatChannel.h +++ b/source/WorldServer/Chat/ChatChannel.h @@ -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); diff --git a/source/WorldServer/Commands/Commands.cpp b/source/WorldServer/Commands/Commands.cpp index 9613be4..66b275d 100644 --- a/source/WorldServer/Commands/Commands.cpp +++ b/source/WorldServer/Commands/Commands.cpp @@ -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) { diff --git a/source/WorldServer/Web/PeerManager.cpp b/source/WorldServer/Web/PeerManager.cpp index 713094b..62b0d07 100644 --- a/source/WorldServer/Web/PeerManager.cpp +++ b/source/WorldServer/Web/PeerManager.cpp @@ -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); + } } \ No newline at end of file diff --git a/source/WorldServer/Web/PeerManager.h b/source/WorldServer/Web/PeerManager.h index 0bb27ff..3d272f3 100644 --- a/source/WorldServer/Web/PeerManager.h +++ b/source/WorldServer/Web/PeerManager.h @@ -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); }; diff --git a/source/WorldServer/Web/WorldWeb.cpp b/source/WorldServer/Web/WorldWeb.cpp index bc38e52..7dc02cf 100644 --- a/source/WorldServer/Web/WorldWeb.cpp +++ b/source/WorldServer/Web/WorldWeb.cpp @@ -25,6 +25,7 @@ #include "../LuaInterface.h" #include "../Guilds/Guild.h" #include "../Broker/BrokerManager.h" +#include "../Chat/Chat.h" #include #include @@ -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("message")) { msg = message.get(); } + + if (auto in_channel = json_tree.get_optional("channel_name")) { + channelName = in_channel.get(); + } if (auto from_language = json_tree.get_optional("from_language")) { language = from_language.get(); } @@ -769,7 +775,7 @@ void World::Web_worldhandle_sendglobalmessage(const http::requestGetPlayer()->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 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& req, http::response& 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("character_id")) { + charID = character_id.get(); + } + if (auto house_id = json_tree.get_optional("house_id")) { + houseID = house_id.get(); + } + if (auto unique_id = json_tree.get_optional("unique_id")) { + uniqueID = unique_id.get(); + } + if (auto instance_id = json_tree.get_optional("instance_id")) { + instanceID = instance_id.get(); + } + if (auto upkeep_due = json_tree.get_optional("upkeep_due")) { + upkeepDue = upkeep_due.get(); + } + if (auto name = json_tree.get_optional("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& req, http::response& 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("escrow_coins")) { + escrowCoin = escrow_coins.get(); + } + if (auto escrow_status = json_tree.get_optional("escrow_status")) { + escrowStatus = escrow_status.get(); + } + if (auto instance_id = json_tree.get_optional("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& req, http::response& 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("channel_name")) { + channelname = name.get(); + } + if (auto passwd = json_tree.get_optional("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(); +} diff --git a/source/WorldServer/World.cpp b/source/WorldServer/World.cpp index 5c9909a..6057a67 100644 --- a/source/WorldServer/World.cpp +++ b/source/WorldServer/World.cpp @@ -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) diff --git a/source/WorldServer/World.h b/source/WorldServer/World.h index 8c6e2c3..7bbe6fe 100644 --- a/source/WorldServer/World.h +++ b/source/WorldServer/World.h @@ -744,6 +744,9 @@ public: static void Web_worldhandle_removeseller(const http::request& req, http::response& res); static void Web_worldhandle_additemsale(const http::request& req, http::response& res); static void Web_worldhandle_removeitemsale(const http::request& req, http::response& res); + static void Web_worldhandle_addplayerhouse(const http::request& req, http::response& res); + static void Web_worldhandle_updatehousedeposit(const http::request& req, http::response& res); + static void Web_worldhandle_addchatchannel(const http::request& req, http::response& res); static void Web_populate_status(boost::property_tree::ptree& pt); diff --git a/source/WorldServer/client.cpp b/source/WorldServer/client.cpp index e3724f4..1ee4c69 100644 --- a/source/WorldServer/client.cpp +++ b/source/WorldServer/client.cpp @@ -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()); diff --git a/source/WorldServer/net.cpp b/source/WorldServer/net.cpp index a43ce61..afbfdd2 100644 --- a/source/WorldServer/net.cpp +++ b/source/WorldServer/net.cpp @@ -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); } });