|
@@ -0,0 +1,255 @@
|
|
|
+#include "Chat.h"
|
|
|
+
|
|
|
+#include <Datei.h>
|
|
|
+
|
|
|
+#include "Game.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(Datei::Style::lesen))
|
|
|
+ {
|
|
|
+ std::cout << "loading chat history from "
|
|
|
+ << messageData.zPfad()->getText() << std::endl
|
|
|
+ << "Delete that file to reset the chat history or use the "
|
|
|
+ "'/resetChat [channel] [timestamp]' command."
|
|
|
+ << std::endl; // 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<NetworkMessage*>(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));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 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::charApi(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] == '/')
|
|
|
+ {
|
|
|
+ commandExecutor->execute(buffer, zSource);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ Player* p = dynamic_cast<Player*>(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;
|
|
|
+ }
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void Chat::broadcastMessage(Framework::Text message, Framework::Text channel)
|
|
|
+{
|
|
|
+ addMessage(new ChatMessage(message, channel, ""));
|
|
|
+ std::cout << "Chat [" << channel << "] " << message << "\n";
|
|
|
+}
|
|
|
+
|
|
|
+void Chat::sendMessageTo(
|
|
|
+ Framework::Text message, Entity* zTarget, Framework::Text channel)
|
|
|
+{
|
|
|
+ Player* p = dynamic_cast<Player*>(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(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;
|
|
|
+}
|