Partially document AOClient

This commit is contained in:
Cerapter 2021-03-17 22:44:56 +01:00
parent e375abaaf8
commit ba249af580
No known key found for this signature in database
GPG Key ID: 954F7E448DA2B40B
3 changed files with 333 additions and 84 deletions

View File

@ -261,7 +261,7 @@ TAB_SIZE = 4
# commands \{ and \} for these it is advised to use the version @{ and @} or use
# a double escape (\\{ and \\})
ALIASES =
ALIASES = "iscommand=@param argc The amount of arguments arriving to the function through a command call, equivalent to `argv.size()`.^^See @ref commandArgc \"CommandInfo's `action`'s first parameter\".^^@param argv The list of arguments passed to the function through a command call.^^See @ref commandArgv \"CommandInfo's `action`'s second parameter\""
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"

Binary file not shown.

View File

@ -18,6 +18,53 @@
#ifndef AOCLIENT_H
#define AOCLIENT_H
/**
* @defgroup commandHelperFunctions Command helper functions
*
* @brief A collection of functions of shared behaviour between command functions,
* allowing the abstraction of technical details in the command function definition,
* or the avoidance of repetition over multiple definitions.
*/
/**
* @defgroup commands Commands
*
* @brief These functions all represent actions that would happen if a client called it specifically
* with a `/command` (with `command` being the command's name) in the out-of-character chat.
*
* @details Since all of these functions *are* just command calls, their format is going to be the same.
* They will have the following parameters:
*
* @param argc The amount of arguments arriving to the function through a command call,
* equivalent to `argv.size()`.
* See @ref commandArgc "CommandInfo's `action`'s first parameter".
* @param argv The list of arguments passed to the function through a command call.
* See @ref commandArgv "CommandInfo's `action`'s second parameter".
*
* If documenting a command, you can use the `\@iscommand` alias to quickly add the arguments described
* above to the function's documentation.
*
* @see AOClient::CommandInfo
*/
/**
* @defgroup commandsMessaging Messaging- and client-related commands
*
* @brief All functions that detail the actions of commands,
* that are also related to messages or the client's self-management in some way.
*
* @ingroup commands
*/
/**
* @defgroup commandsRP Roleplay- and casing-related commands
*
* @brief All functions that detail the actions of commands,
* that are also related to various kinds of roleplay actions in some way.
*
* @ingroup commands
*/
#include "include/aopacket.h"
#include "include/server.h"
#include "include/area_data.h"
@ -68,15 +115,14 @@ class AOClient : public QObject {
ClientVersion version;
QMap<QString, unsigned long long> ACLFlags {
{"NONE", 0ULL},
{"KICK", 1ULL << 0},
{"BAN", 1ULL << 1},
{"BGLOCK", 1ULL << 2},
{"MODIFY_USERS", 1ULL << 3},
{"CM", 1ULL << 4},
{"GLOBAL_TIMER", 1ULL << 5},
{"CHANGE_EVI_MOD", 1ULL << 6},
{"SUPER", ~0ULL}
{"KICK", 1ULL << 0},
{"BAN", 1ULL << 1},
{"BGLOCK", 1ULL << 2},
{"MODIFY_USERS", 1ULL << 3},
{"CM", 1ULL << 4},
{"GLOBAL_TIMER", 1ULL << 5},
{"CHANGE_EVI_MOD", 1ULL << 6},
{"SUPER", ~0ULL },
};
public slots:
@ -159,25 +205,25 @@ class AOClient : public QObject {
};
const QMap<QString, PacketInfo> packets {
{"HI", {ACLFlags.value("NONE"), 1, &AOClient::pktHardwareId}},
{"ID", {ACLFlags.value("NONE"), 2, &AOClient::pktSoftwareId}},
{"askchaa", {ACLFlags.value("NONE"), 0, &AOClient::pktBeginLoad}},
{"RC", {ACLFlags.value("NONE"), 0, &AOClient::pktRequestChars}},
{"RM", {ACLFlags.value("NONE"), 0, &AOClient::pktRequestMusic}},
{"RD", {ACLFlags.value("NONE"), 0, &AOClient::pktLoadingDone}},
{"PW", {ACLFlags.value("NONE"), 1, &AOClient::pktCharPassword}},
{"CC", {ACLFlags.value("NONE"), 3, &AOClient::pktSelectChar}},
{"MS", {ACLFlags.value("NONE"), 15, &AOClient::pktIcChat}},
{"CT", {ACLFlags.value("NONE"), 2, &AOClient::pktOocChat}},
{"CH", {ACLFlags.value("NONE"), 1, &AOClient::pktPing}},
{"MC", {ACLFlags.value("NONE"), 2, &AOClient::pktChangeMusic}},
{"RT", {ACLFlags.value("NONE"), 1, &AOClient::pktWtCe}},
{"HP", {ACLFlags.value("NONE"), 2, &AOClient::pktHpBar}},
{"WSIP", {ACLFlags.value("NONE"), 1, &AOClient::pktWebSocketIp}},
{"ZZ", {ACLFlags.value("NONE"), 0, &AOClient::pktModCall}},
{"PE", {ACLFlags.value("NONE"), 3, &AOClient::pktAddEvidence}},
{"DE", {ACLFlags.value("NONE"), 1, &AOClient::pktRemoveEvidence}},
{"EE", {ACLFlags.value("NONE"), 4, &AOClient::pktEditEvidence}}
{"HI", {ACLFlags.value("NONE"), 1, &AOClient::pktHardwareId }},
{"ID", {ACLFlags.value("NONE"), 2, &AOClient::pktSoftwareId }},
{"askchaa", {ACLFlags.value("NONE"), 0, &AOClient::pktBeginLoad }},
{"RC", {ACLFlags.value("NONE"), 0, &AOClient::pktRequestChars }},
{"RM", {ACLFlags.value("NONE"), 0, &AOClient::pktRequestMusic }},
{"RD", {ACLFlags.value("NONE"), 0, &AOClient::pktLoadingDone }},
{"PW", {ACLFlags.value("NONE"), 1, &AOClient::pktCharPassword }},
{"CC", {ACLFlags.value("NONE"), 3, &AOClient::pktSelectChar }},
{"MS", {ACLFlags.value("NONE"), 15, &AOClient::pktIcChat }},
{"CT", {ACLFlags.value("NONE"), 2, &AOClient::pktOocChat }},
{"CH", {ACLFlags.value("NONE"), 1, &AOClient::pktPing }},
{"MC", {ACLFlags.value("NONE"), 2, &AOClient::pktChangeMusic }},
{"RT", {ACLFlags.value("NONE"), 1, &AOClient::pktWtCe }},
{"HP", {ACLFlags.value("NONE"), 2, &AOClient::pktHpBar }},
{"WSIP", {ACLFlags.value("NONE"), 1, &AOClient::pktWebSocketIp }},
{"ZZ", {ACLFlags.value("NONE"), 0, &AOClient::pktModCall }},
{"PE", {ACLFlags.value("NONE"), 3, &AOClient::pktAddEvidence }},
{"DE", {ACLFlags.value("NONE"), 1, &AOClient::pktRemoveEvidence }},
{"EE", {ACLFlags.value("NONE"), 4, &AOClient::pktEditEvidence }},
};
//// Commands
@ -223,90 +269,293 @@ class AOClient : public QObject {
void cmdDoc(int argc, QStringList argv);
void cmdClearDoc(int argc, QStringList argv);
void cmdTimer(int argc, QStringList argv);
/**
* @brief Changes the evidence mod in the area.
*
* @details The only argument is the **evidence mod** to change to.
*
* @iscommand
*
* @see AreaData::EvidenceMod
* @ingroup commandsRP
*/
void cmdEvidenceMod(int argc, QStringList argv);
// Messaging/Client
/**
* @brief Changes the client's position.
*
* @details The only argument is the **target position** to move the client to.
*
* @iscommand
* @ingroup commandsMessaging
*/
void cmdPos(int argc, QStringList argv);
/**
* @brief Forces a client, or all clients in the area, to a specific position.
*
* @details The first argument is the **client's ID**, or `\*` if the client wants to force all
* clients in their area into the position.
* If a specific client ID is given, this command can reach across areas, i.e., the caller and target
* clients don't have to share areas.
*
* The second argument is the **position** to force the clients to.
* This is not checked for nonsense values.
*
* @iscommand
* @ingroup commandsMessaging
*/
void cmdForcePos(int argc, QStringList argv);
/**
* @brief Switches to a different character based on character ID.
*
* @details The only argument is the **character's ID** that the client wants to switch to.
*
* @iscommand
* @ingroup commandsMessaging
*/
void cmdSwitch(int argc, QStringList argv);
/**
* @brief Picks a new random character for the client.
*
* @details No arguments.
*
* Can silently "fail" if the character picked is already being used by another client.
*
* @iscommand
* @ingroup commandsMessaging
*/
void cmdRandomChar(int argc, QStringList argv);
/**
* @brief Sends a global message (i.e., all clients in the server will be able to see it).
*
* @details The arguments are **the message** that the client wants to send.
*
* @iscommand
* @ingroup commandsMessaging
*/
void cmdG(int argc, QStringList argv);
/**
* @brief Toggles whether the client will ignore @ref cmdG "global" messages or not.
*
* @details No arguments.
*
* @iscommand
* @ingroup commandsMessaging
*/
void cmdToggleGlobal(int argc, QStringList argv);
/**
* @brief Sends a direct message to another client on the server based on ID.
*
* @details Has two arguments, the first is **the target's ID** whom the client wants to send the message to,
* while the second is **the message** the client wants to send.
*
* The "second" part is technically everything that isn't the first argument.
*
* @iscommand
* @ingroup commandsMessaging
*/
void cmdPM(int argc, QStringList argv);
// Command helper functions
/**
* @brief Returns a textual representation of the time left in an area's Timer.
*
* @param area_idx The ID of the area whose timer to grab.
* @param timer The pointer to the area's timer.
*
* @return A textual representation of the time left over on the Timer,
* or `"Timer is inactive"` if the timer wasn't started.
*
* @ingroup commandHelperFunctions
*/
QString getAreaTimer(int area_idx, QTimer* timer);
/**
* @brief Generates a tsuserver3-style area list to be displayed to the user in the out-of-character chat.
*
* @details This list shows general details about the area the caller is currently in,
* like who is the owner, what players are in there, the status of the area, etc.
*
* @param area_idx The index of the area whose details should be generated.
*
* @return A QStringList of details about the given area, with every entry in the string list amounting to
* roughly a separate line.
*
* @ingroup commandHelperFunctions
*/
QStringList buildAreaList(int area_idx);
/**
* @brief Convenience function to generate a random integer number between the given minimum and maximum values.
*
* @param min The minimum possible value for the random integer, inclusive.
* @param max The maximum possible value for the random integer, exclusive.
*
* @warning `max` must be greater than `min`.
*
* @return A randomly generated integer within the bounds given.
*
* @ingroup commandHelperFunctions
*/
int genRand(int min, int max);
/**
* @brief A convenience function unifying the various dice-rolling methods.
*
* @internal
* Babby's first code. <3
* @endinternal
*
* @param argc The amount of arguments arriving to the function through a command call,
* equivalent to `argv.size()`.
* See @ref commandArgc "CommandInfo's `action`'s first parameter".
* @param argv The list of arguments passed to the function through a command call.
* See @ref commandArgv "CommandInfo's `action`'s second parameter".
* @param Type The type of the dice-rolling being done.
*
* @ingroup commandHelperFunctions
*/
void diceThrower(int argc, QStringList argv, RollType Type);
// Command function global variables
/**
* @brief A helper variable that is used to direct the called of the `/changeAuth` command through the process
* of changing the authorisation method from simple to advanced.
*
* @see cmdChangeAuth and cmdSetRootPass
*/
bool change_auth_started = false;
/**
* @brief Describes a command's details.
*/
struct CommandInfo {
unsigned long long acl_mask;
int minArgs;
unsigned long long acl_mask; //!< The privileges necessary to be able to run the command. @see ACLFlags.
int minArgs; //!< The minimum mandatory arguments needed for the command to function.
void (AOClient::*action)(int, QStringList);
};
/**
* @property CommandInfo::action
*
* @brief A function reference that contains what the command actually does.
*
* @param int When called, this parameter will be filled with the argument count. @anchor commandArgc
* @param QStringList When called, this parameter will be filled the list of arguments. @anchor commandArgv
*/
/**
* @brief The list of commands available on the server.
*
* @details Generally called with the format of `/command parameters` in the out-of-character chat.
* @showinitializer
*
* @tparam QString The name of the command, without the leading slash.
* @tparam CommandInfo The details of the command.
* See @ref CommandInfo "the type's documentation" for more details.
*/
const QMap<QString, CommandInfo> commands {
{"login", {ACLFlags.value("NONE"), 1, &AOClient::cmdLogin}},
{"getareas", {ACLFlags.value("NONE"), 0 , &AOClient::cmdGetAreas}},
{"getarea", {ACLFlags.value("NONE"), 0, &AOClient::cmdGetArea}},
{"ban", {ACLFlags.value("BAN"), 2, &AOClient::cmdBan}},
{"kick", {ACLFlags.value("KICK"), 2, &AOClient::cmdKick}},
{"changeauth", {ACLFlags.value("SUPER"), 0, &AOClient::cmdChangeAuth}},
{"rootpass", {ACLFlags.value("SUPER"), 1, &AOClient::cmdSetRootPass}},
{"background", {ACLFlags.value("NONE"), 1, &AOClient::cmdSetBackground}},
{"bg", {ACLFlags.value("NONE"), 1, &AOClient::cmdSetBackground}},
{"bglock", {ACLFlags.value("BGLOCK"), 0, &AOClient::cmdBgLock}},
{"bgunlock", {ACLFlags.value("BGLOCK"), 0, &AOClient::cmdBgUnlock}},
{"adduser", {ACLFlags.value("MODIFY_USERS"), 2, &AOClient::cmdAddUser}},
{"listperms", {ACLFlags.value("NONE"), 0, &AOClient::cmdListPerms}},
{"addperm", {ACLFlags.value("MODIFY_USERS"), 2, &AOClient::cmdAddPerms}},
{"removeperm", {ACLFlags.value("MODIFY_USERS"), 2, &AOClient::cmdRemovePerms}},
{"listusers", {ACLFlags.value("MODIFY_USERS"), 0, &AOClient::cmdListUsers}},
{"logout", {ACLFlags.value("NONE"), 0, &AOClient::cmdLogout}},
{"pos", {ACLFlags.value("NONE"), 1, &AOClient::cmdPos}},
{"g", {ACLFlags.value("NONE"), 1, &AOClient::cmdG}},
{"need", {ACLFlags.value("NONE"), 1, &AOClient::cmdNeed}},
{"coinflip", {ACLFlags.value("NONE"), 0, &AOClient::cmdFlip}},
{"roll", {ACLFlags.value("NONE"), 0, &AOClient::cmdRoll}},
{"rollp", {ACLFlags.value("NONE"), 0, &AOClient::cmdRollP}},
{"doc", {ACLFlags.value("NONE"), 0, &AOClient::cmdDoc}},
{"cleardoc", {ACLFlags.value("NONE"), 0, &AOClient::cmdClearDoc}},
{"cm", {ACLFlags.value("NONE"), 0, &AOClient::cmdCM}},
{"uncm", {ACLFlags.value("CM"), 0, &AOClient::cmdUnCM}},
{"invite", {ACLFlags.value("CM"), 1, &AOClient::cmdInvite}},
{"uninvite", {ACLFlags.value("CM"), 1, &AOClient::cmdUnInvite}},
{"lock", {ACLFlags.value("CM"), 0, &AOClient::cmdLock}},
{"area_lock", {ACLFlags.value("CM"), 0, &AOClient::cmdLock}},
{"spectatable", {ACLFlags.value("CM"), 0, &AOClient::cmdSpectatable}},
{"area_spectate", {ACLFlags.value("CM"), 0, &AOClient::cmdSpectatable}},
{"unlock", {ACLFlags.value("CM"), 0, &AOClient::cmdUnLock}},
{"area_unlock", {ACLFlags.value("CM"), 0, &AOClient::cmdUnLock}},
{"timer", {ACLFlags.value("CM"), 0, &AOClient::cmdTimer}},
{"area", {ACLFlags.value("NONE"), 1, &AOClient::cmdArea}},
{"play", {ACLFlags.value("CM"), 1, &AOClient::cmdPlay}},
{"areakick", {ACLFlags.value("CM"), 1, &AOClient::cmdAreaKick}},
{"area_kick", {ACLFlags.value("CM"), 1, &AOClient::cmdAreaKick}},
{"randomchar", {ACLFlags.value("NONE"), 0, &AOClient::cmdRandomChar}},
{"switch", {ACLFlags.value("NONE"), 1, &AOClient::cmdSwitch}},
{"toggleglobal", {ACLFlags.value("NONE"), 0, &AOClient::cmdToggleGlobal}},
{"mods", {ACLFlags.value("NONE"), 0, &AOClient::cmdMods}},
{"help", {ACLFlags.value("NONE"), 0, &AOClient::cmdHelp}},
{"status", {ACLFlags.value("NONE"), 1, &AOClient::cmdStatus}},
{"forcepos", {ACLFlags.value("CM"), 2, &AOClient::cmdForcePos}},
{"currentmusic", {ACLFlags.value("NONE"), 0, &AOClient::cmdCurrentMusic}},
{"pm", {ACLFlags.value("NONE"), 2, &AOClient::cmdPM}},
{"evidence_mod", {ACLFlags.value("CHANGE_EVI_MOD"), 1, &AOClient::cmdEvidenceMod}}
{"login", {ACLFlags.value("NONE"), 1, &AOClient::cmdLogin }},
{"getareas", {ACLFlags.value("NONE"), 0, &AOClient::cmdGetAreas }},
{"getarea", {ACLFlags.value("NONE"), 0, &AOClient::cmdGetArea }},
{"ban", {ACLFlags.value("BAN"), 2, &AOClient::cmdBan }},
{"kick", {ACLFlags.value("KICK"), 2, &AOClient::cmdKick }},
{"changeauth", {ACLFlags.value("SUPER"), 0, &AOClient::cmdChangeAuth }},
{"rootpass", {ACLFlags.value("SUPER"), 1, &AOClient::cmdSetRootPass }},
{"background", {ACLFlags.value("NONE"), 1, &AOClient::cmdSetBackground }},
{"bg", {ACLFlags.value("NONE"), 1, &AOClient::cmdSetBackground }},
{"bglock", {ACLFlags.value("BGLOCK"), 0, &AOClient::cmdBgLock }},
{"bgunlock", {ACLFlags.value("BGLOCK"), 0, &AOClient::cmdBgUnlock }},
{"adduser", {ACLFlags.value("MODIFY_USERS"), 2, &AOClient::cmdAddUser }},
{"listperms", {ACLFlags.value("NONE"), 0, &AOClient::cmdListPerms }},
{"addperm", {ACLFlags.value("MODIFY_USERS"), 2, &AOClient::cmdAddPerms }},
{"removeperm", {ACLFlags.value("MODIFY_USERS"), 2, &AOClient::cmdRemovePerms }},
{"listusers", {ACLFlags.value("MODIFY_USERS"), 0, &AOClient::cmdListUsers }},
{"logout", {ACLFlags.value("NONE"), 0, &AOClient::cmdLogout }},
{"pos", {ACLFlags.value("NONE"), 1, &AOClient::cmdPos }},
{"g", {ACLFlags.value("NONE"), 1, &AOClient::cmdG }},
{"need", {ACLFlags.value("NONE"), 1, &AOClient::cmdNeed }},
{"coinflip", {ACLFlags.value("NONE"), 0, &AOClient::cmdFlip }},
{"roll", {ACLFlags.value("NONE"), 0, &AOClient::cmdRoll }},
{"rollp", {ACLFlags.value("NONE"), 0, &AOClient::cmdRollP }},
{"doc", {ACLFlags.value("NONE"), 0, &AOClient::cmdDoc }},
{"cleardoc", {ACLFlags.value("NONE"), 0, &AOClient::cmdClearDoc }},
{"cm", {ACLFlags.value("NONE"), 0, &AOClient::cmdCM }},
{"uncm", {ACLFlags.value("CM"), 0, &AOClient::cmdUnCM }},
{"invite", {ACLFlags.value("CM"), 1, &AOClient::cmdInvite }},
{"uninvite", {ACLFlags.value("CM"), 1, &AOClient::cmdUnInvite }},
{"lock", {ACLFlags.value("CM"), 0, &AOClient::cmdLock }},
{"area_lock", {ACLFlags.value("CM"), 0, &AOClient::cmdLock }},
{"spectatable", {ACLFlags.value("CM"), 0, &AOClient::cmdSpectatable }},
{"area_spectate", {ACLFlags.value("CM"), 0, &AOClient::cmdSpectatable }},
{"unlock", {ACLFlags.value("CM"), 0, &AOClient::cmdUnLock }},
{"area_unlock", {ACLFlags.value("CM"), 0, &AOClient::cmdUnLock }},
{"timer", {ACLFlags.value("CM"), 0, &AOClient::cmdTimer }},
{"area", {ACLFlags.value("NONE"), 1, &AOClient::cmdArea }},
{"play", {ACLFlags.value("CM"), 1, &AOClient::cmdPlay }},
{"areakick", {ACLFlags.value("CM"), 1, &AOClient::cmdAreaKick }},
{"area_kick", {ACLFlags.value("CM"), 1, &AOClient::cmdAreaKick }},
{"randomchar", {ACLFlags.value("NONE"), 0, &AOClient::cmdRandomChar }},
{"switch", {ACLFlags.value("NONE"), 1, &AOClient::cmdSwitch }},
{"toggleglobal", {ACLFlags.value("NONE"), 0, &AOClient::cmdToggleGlobal }},
{"mods", {ACLFlags.value("NONE"), 0, &AOClient::cmdMods }},
{"help", {ACLFlags.value("NONE"), 0, &AOClient::cmdHelp }},
{"status", {ACLFlags.value("NONE"), 1, &AOClient::cmdStatus }},
{"forcepos", {ACLFlags.value("CM"), 2, &AOClient::cmdForcePos }},
{"currentmusic", {ACLFlags.value("NONE"), 0, &AOClient::cmdCurrentMusic }},
{"pm", {ACLFlags.value("NONE"), 2, &AOClient::cmdPM }},
{"evidence_mod", {ACLFlags.value("CHANGE_EVI_MOD"), 1, &AOClient::cmdEvidenceMod }},
};
/**
* @brief Filled with part of a packet if said packet could not be read fully from the client's socket.
*
* @details Per AO2's network protocol, a packet is finished with the character `%`.
*
* @see #is_partial
*/
QString partial_packet;
/**
* @brief True when the previous `readAll()` call from the client's socket returned an unfinished packet.
*
* @see #partial_packet
*/
bool is_partial;
/**
* @brief The hardware ID of the client.
*
* @details Generated based on the client's own supplied hardware ID.
* The client supplied hardware ID is generally a machine unique ID.
*/
QString hwid;
/**
* @brief The IPID of the client.
*
* @details Generated based on the client's IP, but cannot be reversed to identify the client's IP.
*/
QString ipid;
/**
* @brief The time in seconds since the client last sent a Witness Testimony / Cross Examination
* popup packet.
*
* @details Used to filter out potential spam.
*/
long last_wtce_time;
/**
* @brief The text of the last in-character message that was sent by the client.
*
* @details Used to determine if the incoming message is a duplicate.
*/
QString last_message;
};