#include "Chat.h" #include #include #include "Game.h" #include "Player.h" const Framework::Text Chat::CHANNEL_INFO = "system:INFO"; const Framework::Text Chat::CHANNEL_WARNING = "system:WARNING"; const Framework::Text Chat::CHANNEL_ERROR = "system:ERROR"; Chat::Chat() : ReferenceCounter(), commandExecutor(new ChatCommandExecutor()) { Framework::Datei messageData; messageData.setDatei( Game::INSTANCE->getWorldDirectory() + "/chat/history.chat"); if (messageData.existiert() && messageData.open(Framework::Datei::Style::lesen)) { Framework::Logging::info() << "loading chat history from " << messageData.zPfad()->getText() << "\nDelete that file to reset the chat history or use the " "'/resetChat [channel] [timestamp]' command."; // TODO: implement // /resetChat // command while (!messageData.istEnde()) { ChatMessage* message = new ChatMessage(&messageData); history.add(message); } messageData.close(); } } Chat::~Chat() { commandExecutor->release(); } void Chat::addMessage(ChatMessage* message) { cs.lock(); history.add(message); NetworkMessage* nMsg = new NetworkMessage(); nMsg->sendChatMessage(message); nMsg->setUseBackground(); for (auto it = observer.begin(); it;) { if (!it->isValid()) { it.remove(); continue; } if (it->isSubscribedTo(message->getChannel()) && (!message->getTargetPlayerName().getLength() || it->getPlayerName().istGleich( message->getTargetPlayerName()))) { Entity* zEtity = Game::INSTANCE->zEntity(it->getEntityId()); if (zEtity) { Game::INSTANCE->sendMessage( dynamic_cast(nMsg->getThis()), zEtity); } } it++; } nMsg->release(); cs.unlock(); } void Chat::addObserver(int entityId) { cs.lock(); ChatObserver* obs = new ChatObserver(entityId); this->observer.add(obs); Framework::Text name = obs->getPlayerName(); for (ChatMessage* msg : history) { if (obs->isSubscribedTo(msg->getChannel()) && (!msg->getTargetPlayerName().getLength() || name.istGleich(msg->getTargetPlayerName()))) { NetworkMessage* nMsg = new NetworkMessage(); nMsg->sendChatMessage(msg); nMsg->setUseBackground(); Game::INSTANCE->sendMessage( nMsg, Game::INSTANCE->zEntity(entityId)); } } Entity* zPlayer = Game::INSTANCE->zEntity(entityId); if (zPlayer) { NetworkMessage* options = new NetworkMessage(); options->sendChatOptions(obs); Game::INSTANCE->sendMessage(options, zPlayer); } cs.unlock(); } void Chat::removeObserver(int entityId) { cs.lock(); for (auto it = this->observer.begin(); it; it++) { if (it->getEntityId() == entityId) { it->save(); it.remove(); break; } } cs.unlock(); } void Chat::chatApi(Framework::StreamReader* zRequest, Entity* zSource, NetworkMessage* zResponse) { char id; zRequest->lese(&id, 1); switch (id) { case 0: // send message { short len; zRequest->lese((char*)&len, 2); char* buffer = new char[len + 1]; zRequest->lese(buffer, len); buffer[len] = 0; if (buffer[0] == '/') { if (!commandExecutor->execute(buffer, zSource)) { sendMessageTo("Unknown kommand. Use /help to get " "information about all known commands.", zSource, CHANNEL_ERROR); } } else { Player* p = dynamic_cast(zSource); if (p) { broadcastMessage( buffer, getPlayerChannelName(p->getName())); } else { // TODO: implement entity channels } } delete[] buffer; break; } case 1: // add channel { char len; zRequest->lese(&len, 1); char* buffer = new char[len + 1]; zRequest->lese(buffer, len); buffer[(int)len] = 0; for (ChatObserver* observer : this->observer) { if (observer->getEntityId() == zSource->getId()) { observer->addChannel(buffer); break; } } delete[] buffer; break; } case 2: // remove channel { char len; zRequest->lese(&len, 1); char* buffer = new char[len + 1]; zRequest->lese(buffer, len); buffer[(int)len] = 0; for (ChatObserver* observer : this->observer) { if (observer->getEntityId() == zSource->getId()) { observer->removeChannel(buffer); } } delete[] buffer; break; } case 3: // add ignored player { char len; zRequest->lese(&len, 1); char* buffer = new char[len + 1]; zRequest->lese(buffer, len); buffer[(int)len] = 0; for (ChatObserver* observer : this->observer) { if (observer->getEntityId() == zSource->getId()) { observer->addIgnoredPlayer(buffer); } } delete[] buffer; break; } case 4: // remove ignored player { char len; zRequest->lese(&len, 1); char* buffer = new char[len + 1]; zRequest->lese(buffer, len); buffer[(int)len] = 0; for (ChatObserver* observer : this->observer) { if (observer->getEntityId() == zSource->getId()) { observer->removeIgnoredPlayer(buffer); } } delete[] buffer; break; } } } void Chat::broadcastMessage(Framework::Text message, Framework::Text channel) { addMessage(new ChatMessage(message, channel, "")); Framework::Logging::info() << "Chat [" << channel << "] " << message; } void Chat::sendMessageTo( Framework::Text message, Entity* zTarget, Framework::Text channel) { if (!zTarget) { Framework::Logging::info() << message; return; } Player* p = dynamic_cast(zTarget); if (p) { addMessage(new ChatMessage(message, channel, p->getName())); } } void Chat::save() { cs.lock(); for (ChatObserver* obs : observer) { obs->save(); } Framework::Datei messageData; messageData.setDatei( Game::INSTANCE->getWorldDirectory() + "/chat/history.chat"); if (!messageData.existiert()) messageData.erstellen(); messageData.open(Framework::Datei::Style::schreiben); for (ChatMessage* msg : history) { msg->writeTo(&messageData); } messageData.close(); cs.unlock(); } ChatCommandExecutor* Chat::zCommandExecutor() const { return commandExecutor; } Framework::Text Chat::getPlayerChannelName(Framework::Text playerName) { return Framework::Text("player:") + playerName; }