v1.4.4
This commit is contained in:
commit
9c94d113d3
10260 changed files with 1237388 additions and 0 deletions
257
source/game/StarChatProcessor.cpp
Normal file
257
source/game/StarChatProcessor.cpp
Normal file
|
@ -0,0 +1,257 @@
|
|||
#include "StarChatProcessor.hpp"
|
||||
|
||||
namespace Star {
|
||||
|
||||
char const* ChatProcessor::ServerNick = "server";
|
||||
|
||||
String ChatProcessor::connectClient(ConnectionId clientId, String nick) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
if (nick.empty())
|
||||
nick = strf("Player_%s", clientId);
|
||||
|
||||
nick = makeNickUnique(nick);
|
||||
|
||||
for (auto& pair : m_clients) {
|
||||
pair.second.pendingMessages.append({
|
||||
{MessageContext::Broadcast},
|
||||
ServerConnectionId,
|
||||
ServerNick,
|
||||
strf("Player '%s' connected", nick)
|
||||
});
|
||||
}
|
||||
|
||||
m_clients.add(clientId, ClientInfo(clientId, nick));
|
||||
m_nicks[nick] = clientId;
|
||||
return nick;
|
||||
}
|
||||
|
||||
List<ChatReceivedMessage> ChatProcessor::disconnectClient(ConnectionId clientId) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
for (auto channel : clientChannels(clientId))
|
||||
leaveChannel(clientId, channel);
|
||||
|
||||
auto clientInfo = m_clients.take(clientId);
|
||||
|
||||
m_nicks.remove(clientInfo.nick);
|
||||
|
||||
for (auto& pair : m_clients) {
|
||||
pair.second.pendingMessages.append({
|
||||
{MessageContext::Broadcast},
|
||||
ServerConnectionId,
|
||||
ServerNick,
|
||||
strf("Player '%s' disconnected", clientInfo.nick)
|
||||
});
|
||||
}
|
||||
|
||||
return clientInfo.pendingMessages;
|
||||
}
|
||||
|
||||
List<ConnectionId> ChatProcessor::clients() const {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
return m_clients.keys();
|
||||
}
|
||||
|
||||
bool ChatProcessor::hasClient(ConnectionId clientId) const {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
return m_clients.contains(clientId);
|
||||
}
|
||||
|
||||
Maybe<ConnectionId> ChatProcessor::findNick(String const& nick) const {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
if (auto m = m_nicks.maybe(nick))
|
||||
return m;
|
||||
if (nick == ServerNick)
|
||||
return ServerConnectionId;
|
||||
return {};
|
||||
}
|
||||
|
||||
String ChatProcessor::connectionNick(ConnectionId clientId) const {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
if (clientId == ServerConnectionId)
|
||||
return ServerNick;
|
||||
else
|
||||
return m_clients.get(clientId).nick;
|
||||
}
|
||||
|
||||
String ChatProcessor::renick(ConnectionId clientId, String const& nick) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
auto& clientInfo = m_clients.get(clientId);
|
||||
m_nicks.remove(clientInfo.nick);
|
||||
|
||||
clientInfo.nick = makeNickUnique(nick);
|
||||
m_clients.get(clientId).nick = nick;
|
||||
m_nicks[nick] = clientId;
|
||||
return nick;
|
||||
}
|
||||
|
||||
bool ChatProcessor::joinChannel(ConnectionId clientId, String const& channelName) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
// Right now channels are simply created on join if they don't exist.
|
||||
return m_channels[channelName].add(clientId);
|
||||
}
|
||||
|
||||
bool ChatProcessor::leaveChannel(ConnectionId clientId, String const& channelName) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
return m_channels[channelName].remove(clientId);
|
||||
}
|
||||
|
||||
StringList ChatProcessor::clientChannels(ConnectionId clientId) const {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
StringList channels;
|
||||
for (auto const& pair : m_channels) {
|
||||
if (pair.second.contains(clientId))
|
||||
channels.append(pair.first);
|
||||
}
|
||||
return channels;
|
||||
}
|
||||
|
||||
StringList ChatProcessor::activeChannels() const {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
StringList channels;
|
||||
for (auto const& pair : m_channels) {
|
||||
if (!pair.second.empty())
|
||||
channels.append(pair.first);
|
||||
}
|
||||
return channels;
|
||||
}
|
||||
|
||||
void ChatProcessor::broadcast(ConnectionId sourceConnectionId, String const& text) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
ChatReceivedMessage message = {
|
||||
{MessageContext::Broadcast},
|
||||
sourceConnectionId,
|
||||
connectionNick(sourceConnectionId),
|
||||
text
|
||||
};
|
||||
|
||||
if (handleCommand(message))
|
||||
return;
|
||||
|
||||
for (auto& pair : m_clients)
|
||||
pair.second.pendingMessages.append(message);
|
||||
}
|
||||
|
||||
void ChatProcessor::message(ConnectionId sourceConnectionId, MessageContext::Mode mode, String const& channelName, String const& text) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
ChatReceivedMessage message = {
|
||||
{mode, channelName},
|
||||
sourceConnectionId,
|
||||
connectionNick(sourceConnectionId),
|
||||
text
|
||||
};
|
||||
|
||||
if (handleCommand(message))
|
||||
return;
|
||||
|
||||
for (auto clientId : m_channels[channelName]) {
|
||||
auto& clientInfo = m_clients.get(clientId);
|
||||
clientInfo.pendingMessages.append(message);
|
||||
}
|
||||
}
|
||||
|
||||
void ChatProcessor::whisper(ConnectionId sourceConnectionId, ConnectionId targetClientId, String const& text) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
|
||||
ChatReceivedMessage message = {
|
||||
{MessageContext::Whisper}, sourceConnectionId, connectionNick(sourceConnectionId), text};
|
||||
|
||||
if (handleCommand(message))
|
||||
return;
|
||||
|
||||
if (sourceConnectionId != ServerConnectionId)
|
||||
m_clients.get(sourceConnectionId).pendingMessages.append(message);
|
||||
|
||||
m_clients.get(targetClientId).pendingMessages.append(message);
|
||||
}
|
||||
|
||||
void ChatProcessor::adminBroadcast(String const& text) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
broadcast(ServerConnectionId, text);
|
||||
}
|
||||
|
||||
void ChatProcessor::adminMessage(MessageContext::Mode context, String const& channelName, String const& text) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
ChatProcessor::message(ServerConnectionId, context, channelName, text);
|
||||
}
|
||||
|
||||
void ChatProcessor::adminWhisper(ConnectionId targetClientId, String const& text) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
whisper(ServerConnectionId, targetClientId, text);
|
||||
}
|
||||
|
||||
List<ChatReceivedMessage> ChatProcessor::pullPendingMessages(ConnectionId clientId) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
if (m_clients.contains(clientId))
|
||||
return take(m_clients.get(clientId).pendingMessages);
|
||||
return {};
|
||||
}
|
||||
|
||||
void ChatProcessor::setCommandHandler(CommandHandler commandHandler) {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
m_commandHandler = commandHandler;
|
||||
}
|
||||
|
||||
void ChatProcessor::clearCommandHandler() {
|
||||
RecursiveMutexLocker locker(m_mutex);
|
||||
m_commandHandler = {};
|
||||
}
|
||||
|
||||
ChatProcessor::ClientInfo::ClientInfo(ConnectionId clientId, String const& nick) : clientId(clientId), nick(nick) {}
|
||||
|
||||
String ChatProcessor::makeNickUnique(String nick) {
|
||||
while (m_nicks.contains(nick) || nick == ServerNick)
|
||||
nick.append("_");
|
||||
|
||||
return nick;
|
||||
}
|
||||
|
||||
bool ChatProcessor::handleCommand(ChatReceivedMessage& message) {
|
||||
if (!message.text.beginsWith("/")) {
|
||||
return false;
|
||||
} else if (message.text.beginsWith("//")) {
|
||||
message.text = message.text.substr(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
String commandLine = message.text.substr(1);
|
||||
String command = commandLine.extract();
|
||||
|
||||
String response;
|
||||
|
||||
if (command == "nick") {
|
||||
auto newNick = renick(message.fromConnection, commandLine.trim());
|
||||
response = strf("Nick changed to %s", newNick);
|
||||
} else if (command == "w") {
|
||||
String target = commandLine.extract();
|
||||
if (m_nicks.contains(target))
|
||||
whisper(message.fromConnection, m_nicks.get(target), commandLine.trim());
|
||||
else
|
||||
response = strf("No such nick %s", target);
|
||||
} else if (m_commandHandler) {
|
||||
response = m_commandHandler(message.fromConnection, command, commandLine);
|
||||
} else {
|
||||
response = strf("No such command %s", command);
|
||||
}
|
||||
|
||||
if (!response.empty()) {
|
||||
m_clients.get(message.fromConnection).pendingMessages.append({
|
||||
MessageContext(MessageContext::CommandResult),
|
||||
ServerConnectionId,
|
||||
connectionNick(ServerConnectionId),
|
||||
response
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue