Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/game/StarChatProcessor.hpp
blob: 1c42b75fd7ff25b4c91d6abb56391a40e186ba8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#pragma once

#include "StarChatTypes.hpp"
#include "StarSet.hpp"
#include "StarThread.hpp"

namespace Star {

STAR_CLASS(ChatProcessor);

// Handles all chat routing and command parsing for client / server chat.
// Thread safe.
class ChatProcessor {
public:
  static char const* ServerNick;

  // CommandHandler is passed the origin connection, the command portion
  // excluding the '/' character, and the remaining command line in full.
  typedef function<String(ConnectionId, String, String)> CommandHandler;

  String connectClient(ConnectionId clientId, String nick = "");
  // Returns any pending messages.
  List<ChatReceivedMessage> disconnectClient(ConnectionId clientId);

  List<ConnectionId> clients() const;
  bool hasClient(ConnectionId clientId) const;

  // Clears all clients and channels
  void reset();

  // Will return nothing if nick is not found.
  Maybe<ConnectionId> findNick(String const& nick) const;
  String connectionNick(ConnectionId connectionId) const;
  String renick(ConnectionId clientId, String const& nick);

  // join / leave return true in the even that the client channel state was
  // actually changed.
  bool joinChannel(ConnectionId clientId, String const& channelName);
  bool leaveChannel(ConnectionId clientId, String const& channelName);

  StringList clientChannels(ConnectionId clientId) const;
  StringList activeChannels() const;

  void broadcast(ConnectionId sourceConnectionId, String const& text, JsonObject data = {});
  void message(ConnectionId sourceConnectionId, MessageContext::Mode context, String const& channelName, String const& text, JsonObject data = {});
  void whisper(ConnectionId sourceConnectionId, ConnectionId targetClientId, String const& text, JsonObject data = {});

  // Shorthand for passing ServerConnectionId as sourceConnectionId to
  // broadcast / message / whisper
  void adminBroadcast(String const& text);
  void adminMessage(MessageContext::Mode context, String const& channelName, String const& text);
  void adminWhisper(ConnectionId targetClientId, String const& text);

  List<ChatReceivedMessage> pullPendingMessages(ConnectionId clientId);

  void setCommandHandler(CommandHandler commandHandler);
  void clearCommandHandler();

private:
  struct ClientInfo {
    ClientInfo(ConnectionId clientId, String const& nick);

    ConnectionId clientId;
    String nick;
    List<ChatReceivedMessage> pendingMessages;
  };

  String makeNickUnique(String nick);

  // Returns true if message was handled completely and needs no further
  // processing.
  bool handleCommand(ChatReceivedMessage& message);

  mutable RecursiveMutex m_mutex;

  HashMap<ConnectionId, ClientInfo> m_clients;
  StringMap<ConnectionId> m_nicks;
  StringMap<Set<ConnectionId>> m_channels;

  CommandHandler m_commandHandler;
};

}