diff options
Diffstat (limited to 'src/net')
99 files changed, 1053 insertions, 1207 deletions
diff --git a/src/net/specialhandler.h b/src/net/abilityhandler.h index fb8ffdfd..8e61d0c5 100644 --- a/src/net/specialhandler.h +++ b/src/net/abilityhandler.h @@ -19,25 +19,22 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef SPECIALHANDLER_H -#define SPECIALHANDLER_H - -#include <iosfwd> +#pragma once namespace Net { -class SpecialHandler + +class AbilityHandler { public: - virtual ~SpecialHandler () {} + virtual ~AbilityHandler () {} virtual void use(int id) = 0; - virtual void use(int id, int level, int beingId) = 0; + virtual void useOn(int id, int beingId) = 0; - virtual void use(int id, int level, int x, int y) = 0; + virtual void useAt(int id, int x, int y) = 0; - virtual void use(int id, const std::string &map) = 0; + virtual void useInDirection(int id, int direction) = 0; }; -} -#endif // SPECIALHANDLER_H +} // namespace Net diff --git a/src/net/adminhandler.h b/src/net/adminhandler.h index 492918a7..87853317 100644 --- a/src/net/adminhandler.h +++ b/src/net/adminhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef ADMINHANDLER_H -#define ADMINHANDLER_H +#pragma once #include <string> @@ -39,5 +38,3 @@ class AdminHandler }; } // namespace Net - -#endif // ADMINHANDLER_H diff --git a/src/net/charhandler.h b/src/net/charhandler.h index 72e67739..3f0c096f 100644 --- a/src/net/charhandler.h +++ b/src/net/charhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef CHARHANDLER_H -#define CHARHANDLER_H +#pragma once #include "localplayer.h" #include "playerinfo.h" @@ -111,5 +110,3 @@ class CharHandler }; } // namespace Net - -#endif // CHARHANDLER_H diff --git a/src/net/chathandler.h b/src/net/chathandler.h index 382ac39a..5524f458 100644 --- a/src/net/chathandler.h +++ b/src/net/chathandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef CHATHANDLER_H -#define CHATHANDLER_H +#pragma once #include <string> @@ -62,5 +61,3 @@ class ChatHandler virtual void requestOnlineList() = 0; }; } - -#endif // CHATHANDLER_H diff --git a/src/net/download.cpp b/src/net/download.cpp index 8a41ebfa..7aab3b2f 100644 --- a/src/net/download.cpp +++ b/src/net/download.cpp @@ -31,7 +31,7 @@ #include <zlib.h> -const char *DOWNLOAD_ERROR_MESSAGE_THREAD = "Could not create download thread!"; +constexpr char DOWNLOAD_ERROR_MESSAGE_THREAD[] = "Could not create download thread!"; namespace Net { @@ -59,32 +59,26 @@ unsigned long Download::fadler32(FILE *file) return adler; } - -Download::Download(void *ptr, const std::string &url, - DownloadUpdate updateFunction): - mPtr(ptr), - mUrl(url), - mUpdateFunction(updateFunction) +Download::Download(const std::string &url) + : mUrl(url) { - mError = (char*) malloc(CURL_ERROR_SIZE); mError[0] = 0; - - mOptions.cancel = false; } Download::~Download() { - if (mHeaders) - curl_slist_free_all(mHeaders); + mCancel = true; + SDL_WaitThread(mThread, nullptr); - int status; - SDL_WaitThread(mThread, &status); - free(mError); + curl_slist_free_all(mHeaders); + free(mBuffer); } -void Download::addHeader(const std::string &header) +void Download::addHeader(const char *header) { - mHeaders = curl_slist_append(mHeaders, header.c_str()); + assert(!mThread); // Cannot add headers after starting download + + mHeaders = curl_slist_append(mHeaders, header); } void Download::noCache() @@ -96,19 +90,24 @@ void Download::noCache() void Download::setFile(const std::string &filename, std::optional<unsigned long> adler32) { - mOptions.memoryWrite = false; + assert(!mThread); // Cannot set file after starting download + + mMemoryWrite = false; mFileName = filename; mAdler = adler32; } -void Download::setWriteFunction(WriteFunction write) +void Download::setUseBuffer() { - mOptions.memoryWrite = true; - mWriteFunction = write; + assert(!mThread); // Cannot set write function after starting download + + mMemoryWrite = true; } bool Download::start() { + assert(!mThread); // Download already started + logger->log("Starting download: %s", mUrl.c_str()); mThread = SDL_CreateThread(downloadThread, "Download", this); @@ -116,9 +115,8 @@ bool Download::start() if (!mThread) { logger->log("%s", DOWNLOAD_ERROR_MESSAGE_THREAD); - strcpy(mError, DOWNLOAD_ERROR_MESSAGE_THREAD); - mUpdateFunction(mPtr, DOWNLOAD_STATUS_THREAD_ERROR, 0, 0); - + strncpy(mError, DOWNLOAD_ERROR_MESSAGE_THREAD, CURL_ERROR_SIZE - 1); + mState.lock()->status = DownloadStatus::Error; return false; } @@ -128,196 +126,186 @@ bool Download::start() void Download::cancel() { logger->log("Canceling download: %s", mUrl.c_str()); - - mOptions.cancel = true; - if (mThread && SDL_GetThreadID(mThread) != 0) - { - SDL_WaitThread(mThread, nullptr); - mThread = nullptr; - } + mCancel = true; } -const char *Download::getError() const +std::string_view Download::getBuffer() const { - return mError; + assert(mMemoryWrite); // Buffer not used + return std::string_view(mBuffer, mDownloadedBytes); } +/** + * A libcurl callback for reporting progress. + */ int Download::downloadProgress(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { auto *d = reinterpret_cast<Download*>(clientp); - if (d->mOptions.cancel) + auto state = d->mState.lock(); + state->status = DownloadStatus::InProgress; + state->progress = 0.0f; + if (dltotal > 0) + state->progress = static_cast<float>(dlnow) / dltotal; + + return d->mCancel; +} + +/** + * A libcurl callback for writing to memory. + */ +size_t Download::writeBuffer(char *ptr, size_t size, size_t nmemb, void *stream) +{ + auto *d = reinterpret_cast<Download *>(stream); + + const size_t totalMem = size * nmemb; + d->mBuffer = (char *) realloc(d->mBuffer, d->mDownloadedBytes + totalMem); + if (d->mBuffer) { - return d->mUpdateFunction(d->mPtr, DOWNLOAD_STATUS_CANCELLED, - (size_t) dltotal, (size_t) dlnow); - return -5; + memcpy(d->mBuffer + d->mDownloadedBytes, ptr, totalMem); + d->mDownloadedBytes += totalMem; } - return d->mUpdateFunction(d->mPtr, DOWNLOAD_STATUS_IDLE, - (size_t) dltotal, (size_t) dlnow); + return totalMem; } int Download::downloadThread(void *ptr) { - int attempts = 0; - bool complete = false; auto *d = reinterpret_cast<Download*>(ptr); - CURLcode res; + bool complete = false; std::string outFilename; - if (!d) - { - return 0; - } - if (!d->mOptions.memoryWrite) - { + if (!d->mMemoryWrite) outFilename = d->mFileName + ".part"; - } - while (attempts < 3 && !complete && !d->mOptions.cancel) + for (int attempts = 0; attempts < 3 && !complete && !d->mCancel; ++attempts) { - FILE *file = nullptr; + CURL *curl = curl_easy_init(); + if (!curl) + break; - d->mUpdateFunction(d->mPtr, DOWNLOAD_STATUS_STARTING, 0, 0); + logger->log("Downloading: %s", d->mUrl.c_str()); - if (d->mOptions.cancel) - { - d->mThread = nullptr; - return 0; - } + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, d->mHeaders); - d->mCurl = curl_easy_init(); + FILE *file = nullptr; - if (d->mCurl && !d->mOptions.cancel) + if (d->mMemoryWrite) + { + curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &Download::writeBuffer); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, ptr); + } + else { - logger->log("Downloading: %s", d->mUrl.c_str()); + file = fopen(outFilename.c_str(), "w+b"); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); + } - curl_easy_setopt(d->mCurl, CURLOPT_FOLLOWLOCATION, 1); - curl_easy_setopt(d->mCurl, CURLOPT_HTTPHEADER, d->mHeaders); + const std::string appShort = branding.getStringValue("appShort"); + const std::string userAgent = + strprintf(PACKAGE_EXTENDED_VERSION, appShort.c_str()); - if (d->mOptions.memoryWrite) - { - curl_easy_setopt(d->mCurl, CURLOPT_FAILONERROR, 1); - curl_easy_setopt(d->mCurl, CURLOPT_WRITEFUNCTION, d->mWriteFunction); - curl_easy_setopt(d->mCurl, CURLOPT_WRITEDATA, d->mPtr); - } - else - { - file = fopen(outFilename.c_str(), "w+b"); - curl_easy_setopt(d->mCurl, CURLOPT_WRITEDATA, file); - } + curl_easy_setopt(curl, CURLOPT_USERAGENT, userAgent.c_str()); + curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, d->mError); + curl_easy_setopt(curl, CURLOPT_URL, d->mUrl.c_str()); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, &Download::downloadProgress); + curl_easy_setopt(curl, CURLOPT_XFERINFODATA, ptr); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15); - const std::string appShort = branding.getStringValue("appShort"); - const std::string userAgent = - strprintf(PACKAGE_EXTENDED_VERSION, appShort.c_str()); + const CURLcode res = curl_easy_perform(curl); + curl_easy_cleanup(curl); - curl_easy_setopt(d->mCurl, CURLOPT_USERAGENT, userAgent.c_str()); - curl_easy_setopt(d->mCurl, CURLOPT_ERRORBUFFER, d->mError); - curl_easy_setopt(d->mCurl, CURLOPT_URL, d->mUrl.c_str()); - curl_easy_setopt(d->mCurl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(d->mCurl, CURLOPT_XFERINFOFUNCTION, downloadProgress); - curl_easy_setopt(d->mCurl, CURLOPT_XFERINFODATA, ptr); - curl_easy_setopt(d->mCurl, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(d->mCurl, CURLOPT_CONNECTTIMEOUT, 15); + if (res == CURLE_ABORTED_BY_CALLBACK) + { + d->mCancel = true; - if ((res = curl_easy_perform(d->mCurl)) != 0 && !d->mOptions.cancel) + if (file) { - switch (res) - { - case CURLE_ABORTED_BY_CALLBACK: - d->mOptions.cancel = true; - break; - case CURLE_COULDNT_CONNECT: - default: - logger->log("curl error %d: %s host: %s", - res, d->mError, d->mUrl.c_str()); - break; - } + fclose(file); + ::remove(outFilename.c_str()); + } - if (d->mOptions.cancel) - { - break; - } + break; + } - d->mUpdateFunction(d->mPtr, DOWNLOAD_STATUS_ERROR, 0, 0); + if (res != CURLE_OK) + { + logger->log("curl error %d: %s host: %s", + res, d->mError, d->mUrl.c_str()); - if (!d->mOptions.memoryWrite) - { - fclose(file); - ::remove(outFilename.c_str()); - } - attempts++; - continue; + if (file) + { + fclose(file); + ::remove(outFilename.c_str()); } - curl_easy_cleanup(d->mCurl); + break; + } - if (!d->mOptions.memoryWrite) + if (!d->mMemoryWrite) + { + // Check the checksum if available + if (d->mAdler) { - // Don't check resources.xml checksum - if (d->mAdler) - { - unsigned long adler = fadler32(file); + unsigned long adler = fadler32(file); - if (d->mAdler != adler) - { + if (d->mAdler != adler) + { + if (file) fclose(file); - // Remove the corrupted file - ::remove(d->mFileName.c_str()); - logger->log("Checksum for file %s failed: (%lx/%lx)", - d->mFileName.c_str(), - adler, *d->mAdler); - attempts++; - continue; // Bail out here to avoid the renaming - } + // Remove the corrupted file + ::remove(outFilename.c_str()); + logger->log("Checksum for file %s failed: (%lx/%lx)", + d->mFileName.c_str(), + adler, *d->mAdler); + + continue; // Bail out here to avoid the renaming } + } + + if (file) fclose(file); - // Any existing file with this name is deleted first, otherwise - // the rename will fail on Windows. - ::remove(d->mFileName.c_str()); - ::rename(outFilename.c_str(), d->mFileName.c_str()); + // Any existing file with this name is deleted first, otherwise + // the rename will fail on Windows. + ::remove(d->mFileName.c_str()); + ::rename(outFilename.c_str(), d->mFileName.c_str()); - // Check if we can open it and no errors were encountered - // during renaming - file = fopen(d->mFileName.c_str(), "rb"); - if (file) - { - fclose(file); - complete = true; - } - } - else + // Check if we can open it and no errors were encountered + // during renaming + file = fopen(d->mFileName.c_str(), "rb"); + if (file) { - // It's stored in memory, we're done + fclose(file); + file = nullptr; complete = true; } } - if (d->mOptions.cancel) + else { - d->mThread = nullptr; - return 0; + // It's stored in memory, we're done + complete = true; } - attempts++; - } - if (d->mOptions.cancel) - { - // Nothing to do... - } - else if (!complete || attempts >= 3) - { - d->mUpdateFunction(d->mPtr, DOWNLOAD_STATUS_ERROR, 0, 0); + if (file) + fclose(file); } + + auto state = d->mState.lock(); + if (d->mCancel) + state->status = DownloadStatus::Canceled; + else if (complete) + state->status = DownloadStatus::Complete; else - { - d->mUpdateFunction(d->mPtr, DOWNLOAD_STATUS_COMPLETE, 0, 0); - } + state->status = DownloadStatus::Error; - d->mThread = nullptr; return 0; } diff --git a/src/net/download.h b/src/net/download.h index 0ce8cc8a..e9483fa5 100644 --- a/src/net/download.h +++ b/src/net/download.h @@ -18,44 +18,41 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <cstdlib> // pulls in int64_t +#include "utils/mutex.h" + #include <cstdio> -#include <string> #include <optional> +#include <string> #include <curl/curl.h> -#ifndef NET_DOWNLOAD_H -#define NET_DOWNLOAD_H +#pragma once -enum DownloadStatus +enum class DownloadStatus { - DOWNLOAD_STATUS_CANCELLED = -3, - DOWNLOAD_STATUS_THREAD_ERROR = -2, - DOWNLOAD_STATUS_ERROR = -1, - DOWNLOAD_STATUS_STARTING = 0, - DOWNLOAD_STATUS_IDLE, - DOWNLOAD_STATUS_COMPLETE + InProgress, + Canceled, + Error, + Complete }; -using DownloadUpdate = int (*)(void *, DownloadStatus, size_t, size_t); - -// Matches what CURL expects -using WriteFunction = size_t (*)(void *, size_t, size_t, void *); - struct SDL_Thread; -using CURL = void; -struct curl_slist; namespace Net { + class Download { public: - Download(void *ptr, const std::string &url, DownloadUpdate updateFunction); + struct State + { + DownloadStatus status = DownloadStatus::InProgress; + float progress = 0.0f; + }; + Download(const std::string &url); ~Download(); - void addHeader(const std::string &header); + void addHeader(const char *header); /** * Convience method for adding no-cache headers. @@ -65,47 +62,66 @@ class Download void setFile(const std::string &filename, std::optional<unsigned long> adler32 = {}); - void setWriteFunction(WriteFunction write); + void setUseBuffer(); /** * Starts the download thread. - * @returns true if thread was created - * false if the thread could not be made or download wasn't - * properly setup + * @returns whether the thread could be created */ bool start(); /** - * Cancels the download. Returns immediately, the cancelled status will - * be noted in the next avialable update call. + * Cancels the download. Returns immediately, the canceled status will + * be noted in the next available update call. */ void cancel(); + /** + * Returns a view on the downloaded data. + */ + std::string_view getBuffer() const; + + State getState(); + const char *getError() const; static unsigned long fadler32(FILE *file); private: - static int downloadThread(void *ptr); static int downloadProgress(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow); - void *mPtr; + + static size_t writeBuffer(char *ptr, size_t size, size_t nmemb, + void *stream); + + static int downloadThread(void *ptr); + + ThreadSafe<State> mState; std::string mUrl; - struct { - unsigned cancel : 1; - unsigned memoryWrite: 1; - } mOptions; + bool mCancel = false; + bool mMemoryWrite = false; std::string mFileName; - WriteFunction mWriteFunction = nullptr; std::optional<unsigned long> mAdler; - DownloadUpdate mUpdateFunction; SDL_Thread *mThread = nullptr; - CURL *mCurl = nullptr; curl_slist *mHeaders = nullptr; - char *mError; + char mError[CURL_ERROR_SIZE]; + + /** Byte count currently downloaded in mMemoryBuffer. */ + size_t mDownloadedBytes = 0; + + /** Buffer for files downloaded to memory. */ + char *mBuffer = nullptr; }; -} // namespace Net +inline Download::State Download::getState() +{ + return *mState.lock(); +} -#endif // NET_DOWNLOAD_H +inline const char *Download::getError() const +{ + return mError; +} + +} // namespace Net diff --git a/src/net/gamehandler.h b/src/net/gamehandler.h index 3f47aba5..08c6c33f 100644 --- a/src/net/gamehandler.h +++ b/src/net/gamehandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef MAPHANDLER_H -#define MAPHANDLER_H +#pragma once #include <iosfwd> @@ -58,5 +57,3 @@ class GameHandler }; } // namespace Net - -#endif // MAPHANDLER_H diff --git a/src/net/generalhandler.h b/src/net/generalhandler.h index 76cde7ce..93d76421 100644 --- a/src/net/generalhandler.h +++ b/src/net/generalhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef GENERALHANDLER_H -#define GENERALHANDLER_H +#pragma once namespace Net { @@ -36,10 +35,6 @@ class GeneralHandler virtual void unload() = 0; virtual void flushNetwork() = 0; - - virtual void clearHandlers() = 0; }; } // namespace Net - -#endif // GENERALHANDLER_H diff --git a/src/net/guildhandler.h b/src/net/guildhandler.h index 00eae99c..37127599 100644 --- a/src/net/guildhandler.h +++ b/src/net/guildhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef GUILDHANDLER_H -#define GUILDHANDLER_H +#pragma once #include "guild.h" @@ -64,5 +63,3 @@ class GuildHandler }; } - -#endif // GUILDHANDLER_H diff --git a/src/net/inventoryhandler.h b/src/net/inventoryhandler.h index 8a67a7db..995e54d9 100644 --- a/src/net/inventoryhandler.h +++ b/src/net/inventoryhandler.h @@ -19,20 +19,17 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef INVENTORYHANDLER_H -#define INVENTORYHANDLER_H +#pragma once #include "equipment.h" -#include "inventory.h" -#include "item.h" #include "position.h" -#include <iosfwd> +#include <string> namespace Net { // Default positions of the boxes, 2nd dimension is X and Y respectively. -const int fallBackBoxesPosition[][2] = { +constexpr Position fallBackBoxPositions[] = { { 90, 40 }, // EQUIP_TORSO_SLOT { 8, 78 }, // EQUIP_GLOVES_SLOT { 70, 0 }, // EQUIP_HEAD_SLOT @@ -46,29 +43,27 @@ const int fallBackBoxesPosition[][2] = { { 129, 78 } // EQUIP_PROJECTILE_SLOT }; -const std::string fallBackBoxesBackground[] = { - "equip-box-chest.png", - "equip-box-hands.png", - "equip-box-head.png", - "equip-box-legs.png", - "equip-box-feet.png", - "equip-box-ring.png", - "equip-box-ring.png", - "equip-box-neck.png", - "equip-box-weapon.png", - "equip-box-shield.png", - "equip-box-ammo.png" +const std::string fallBackBoxIcons[] = { + "equip-box-chest", + "equip-box-hands", + "equip-box-head", + "equip-box-legs", + "equip-box-feet", + "equip-box-ring", + "equip-box-ring", + "equip-box-neck", + "equip-box-weapon", + "equip-box-shield", + "equip-box-ammo" }; -static const std::string empty = std::string(); +static const std::string empty; class InventoryHandler { public: virtual ~InventoryHandler() {} - virtual bool canSplit(const Item *item) = 0; - // TODO: fix/remove me virtual size_t getSize(int type) const = 0; @@ -83,21 +78,17 @@ class InventoryHandler virtual Position getBoxPosition(unsigned int slotIndex) const { - if (slotIndex < (sizeof(fallBackBoxesPosition) - / sizeof(fallBackBoxesPosition[0][0]))) - return Position(fallBackBoxesPosition[slotIndex][0], - fallBackBoxesPosition[slotIndex][1]); + if (slotIndex < sizeof(fallBackBoxPositions) / sizeof(fallBackBoxPositions[0])) + return fallBackBoxPositions[slotIndex]; return Position(0,0); } - virtual const std::string& getBoxBackground(unsigned int slotIndex) const + virtual const std::string& getBoxIcon(unsigned int slotIndex) const { - if (slotIndex < sizeof(fallBackBoxesBackground)) - return fallBackBoxesBackground[slotIndex]; + if (slotIndex < sizeof(fallBackBoxIcons) / sizeof(fallBackBoxIcons[0])) + return fallBackBoxIcons[slotIndex]; return empty; // The empty string } }; } // namespace Net - -#endif // INVENTORYHANDLER_H diff --git a/src/net/logindata.h b/src/net/logindata.h index 34b259fb..4af402ec 100644 --- a/src/net/logindata.h +++ b/src/net/logindata.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef LOGINDATA_H -#define LOGINDATA_H +#pragma once #include "being.h" @@ -40,7 +39,7 @@ public: std::string email; std::string captchaResponse; - Gender gender = Gender::UNSPECIFIED; + Gender gender = Gender::Unspecified; bool remember; /**< Whether to store the username. */ bool registerLogin; /**< Whether an account is being registered. */ @@ -64,9 +63,7 @@ public: updateHost.clear(); email.clear(); captchaResponse.clear(); - gender = Gender::UNSPECIFIED; + gender = Gender::Unspecified; resetCharacterSlots(); } }; - -#endif // LOGINDATA_H diff --git a/src/net/loginhandler.h b/src/net/loginhandler.h index 43d15b77..992e0709 100644 --- a/src/net/loginhandler.h +++ b/src/net/loginhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef LOGINHANDLER_H -#define LOGINHANDLER_H +#pragma once #include "net/logindata.h" #include "net/serverinfo.h" @@ -98,5 +97,3 @@ class LoginHandler }; } // namespace Net - -#endif // LOGINHANDLER_H diff --git a/src/net/manaserv/specialhandler.cpp b/src/net/manaserv/abilityhandler.cpp index 0a477ff8..a9ce8e37 100644 --- a/src/net/manaserv/specialhandler.cpp +++ b/src/net/manaserv/abilityhandler.cpp @@ -19,57 +19,60 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "net/manaserv/specialhandler.h" +#include "net/manaserv/abilityhandler.h" #include "net/manaserv/connection.h" #include "net/manaserv/messagein.h" #include "net/manaserv/messageout.h" #include "net/manaserv/manaserv_protocol.h" -extern Net::SpecialHandler *specialHandler; +extern Net::AbilityHandler *abilityHandler; namespace ManaServ { extern Connection *gameServerConnection; -SpecialHandler::SpecialHandler() +AbilityHandler::AbilityHandler() { - specialHandler = this; + abilityHandler = this; } -void SpecialHandler::handleMessage(MessageIn &msg) +void AbilityHandler::handleMessage(MessageIn &msg) { // TODO } -void SpecialHandler::use(int id) +void AbilityHandler::use(int id) { - MessageOut msg(PGMSG_USE_SPECIAL_ON_BEING); + MessageOut msg(PGMSG_USE_ABILITY_ON_BEING); msg.writeInt8(id); msg.writeInt16(0); gameServerConnection->send(msg); } -void SpecialHandler::use(int id, int level, int beingId) +void AbilityHandler::useOn(int id, int beingId) { - MessageOut msg(PGMSG_USE_SPECIAL_ON_BEING); + MessageOut msg(PGMSG_USE_ABILITY_ON_BEING); msg.writeInt8(id); msg.writeInt16(beingId); gameServerConnection->send(msg); } -void SpecialHandler::use(int id, int level, int x, int y) +void AbilityHandler::useAt(int id, int x, int y) { - MessageOut msg(PGMSG_USE_SPECIAL_ON_POINT); + MessageOut msg(PGMSG_USE_ABILITY_ON_POINT); msg.writeInt8(id); msg.writeInt16(x); msg.writeInt16(y); gameServerConnection->send(msg); } -void SpecialHandler::use(int id, const std::string &map) +void AbilityHandler::useInDirection(int id, int direction) { - // TODO + MessageOut msg(PGMSG_USE_ABILITY_ON_DIRECTION); + msg.writeInt8(id); + msg.writeInt8(direction); + gameServerConnection->send(msg); } } // namespace ManaServ diff --git a/src/net/manaserv/specialhandler.h b/src/net/manaserv/abilityhandler.h index dbd203d8..e8263989 100644 --- a/src/net/manaserv/specialhandler.h +++ b/src/net/manaserv/abilityhandler.h @@ -19,31 +19,28 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_SKILLHANDLER_H -#define NET_MANASERV_SKILLHANDLER_H +#pragma once -#include "net/specialhandler.h" +#include "net/abilityhandler.h" #include "net/manaserv/messagehandler.h" namespace ManaServ { -class SpecialHandler final : public MessageHandler, public Net::SpecialHandler +class AbilityHandler final : public MessageHandler, public Net::AbilityHandler { public: - SpecialHandler(); + AbilityHandler(); void handleMessage(MessageIn &msg) override; void use(int id) override; - void use(int id, int level, int beingId) override; + void useOn(int id, int beingId) override; - void use(int id, int level, int x, int y) override; + void useAt(int id, int x, int y) override; - void use(int id, const std::string &map) override; + void useInDirection(int id, int direction) override; }; } // namespace ManaServ - -#endif // NET_MANASERV_SKILLHANDLER_H diff --git a/src/net/manaserv/adminhandler.cpp b/src/net/manaserv/adminhandler.cpp index 78e6acb2..ef155a38 100644 --- a/src/net/manaserv/adminhandler.cpp +++ b/src/net/manaserv/adminhandler.cpp @@ -31,17 +31,11 @@ extern Connection *chatServerConnection; AdminHandler::AdminHandler() { - static const uint16_t _messages[] = - { - 0 - }; - handledMessages = _messages; adminHandler = this; } void AdminHandler::handleMessage(MessageIn &msg) { - } void AdminHandler::kick(const std::string &name) diff --git a/src/net/manaserv/adminhandler.h b/src/net/manaserv/adminhandler.h index fd0c7de0..bc92872b 100644 --- a/src/net/manaserv/adminhandler.h +++ b/src/net/manaserv/adminhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_ADMINHANDLER_H -#define NET_MANASERV_ADMINHANDLER_H +#pragma once #include "net/adminhandler.h" @@ -43,5 +42,3 @@ class AdminHandler final : public Net::AdminHandler, public MessageHandler }; } // namespace ManaServ - -#endif diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp index 186239c1..9bb52ac1 100644 --- a/src/net/manaserv/beinghandler.cpp +++ b/src/net/manaserv/beinghandler.cpp @@ -23,6 +23,7 @@ #include "actorspritemanager.h" #include "being.h" +#include "effectmanager.h" #include "localplayer.h" #include "gui/okdialog.h" @@ -34,6 +35,9 @@ #include "net/manaserv/playerhandler.h" #include "net/manaserv/manaserv_protocol.h" +#include "playerrelations.h" +#include "resources/abilitydb.h" +#include "resources/emotedb.h" #include "resources/hairdb.h" #include "utils/gettext.h" @@ -45,10 +49,13 @@ namespace ManaServ { BeingHandler::BeingHandler() { static const Uint16 _messages[] = { - GPMSG_BEING_ATTACK, GPMSG_BEING_ENTER, GPMSG_BEING_LEAVE, + GPMSG_BEING_EMOTE, GPMSG_BEINGS_MOVE, + GPMSG_BEING_ABILITY_POINT, + GPMSG_BEING_ABILITY_BEING, + GPMSG_BEING_ABILITY_DIRECTION, GPMSG_BEINGS_DAMAGE, GPMSG_BEING_ACTION_CHANGE, GPMSG_BEING_LOOKS_CHANGE, @@ -68,11 +75,20 @@ void BeingHandler::handleMessage(MessageIn &msg) case GPMSG_BEING_LEAVE: handleBeingLeaveMessage(msg); break; + case GPMSG_BEING_EMOTE: + handleBeingEmoteMessage(msg); + break; case GPMSG_BEINGS_MOVE: handleBeingsMoveMessage(msg); break; - case GPMSG_BEING_ATTACK: - handleBeingAttackMessage(msg); + case GPMSG_BEING_ABILITY_POINT: + handleBeingAbilityPointMessage(msg); + break; + case GPMSG_BEING_ABILITY_BEING: + handleBeingAbilityBeingMessage(msg); + break; + case GPMSG_BEING_ABILITY_DIRECTION: + handleBeingAbilityDirectionMessage(msg); break; case GPMSG_BEINGS_DAMAGE: handleBeingsDamageMessage(msg); @@ -91,17 +107,40 @@ void BeingHandler::handleMessage(MessageIn &msg) static void handleLooks(Being *being, MessageIn &msg) { - int lookChanges = msg.readInt8(); + const int hairStyle = msg.readInt8(); + const int hairColor = msg.readInt8(); + being->setSprite(SPRITE_LAYER_HAIR, hairStyle * -1, + hairDB.getHairColor(hairColor)); + + std::map<unsigned, int> equippedSlots; + + if (msg.getUnreadLength() > 1) { + int equippedSlotCount = msg.readInt8(); + while (equippedSlotCount-- > 0) { + unsigned slot = msg.readInt8(); + int itemId = msg.readInt16(); + equippedSlots[slot] = itemId; + } + } - if (lookChanges <= 0) - return; + unsigned endSlot = equippedSlots.empty() ? 0 : equippedSlots.rbegin()->first + 1; + if (being->getSpriteCount() > endSlot + FIXED_SPRITE_LAYER_SIZE) + endSlot = being->getSpriteCount() - FIXED_SPRITE_LAYER_SIZE; - while (lookChanges-- > 0) + for (unsigned slot = 0; slot < endSlot; ++slot) { - unsigned int slotTypeId = msg.readInt8(); - being->setSprite(slotTypeId + FIXED_SPRITE_LAYER_SIZE, - msg.readInt16(), "", - Net::getInventoryHandler()->isWeaponSlot(slotTypeId)); + auto it = equippedSlots.find(slot); + if (it == equippedSlots.end()) + { + being->setSprite(slot + FIXED_SPRITE_LAYER_SIZE, 0); + } + else + { + being->setSprite(slot + FIXED_SPRITE_LAYER_SIZE, + it->second, + std::string(), + Net::getInventoryHandler()->isWeaponSlot(slot)); + } } } @@ -113,14 +152,19 @@ void BeingHandler::handleBeingEnterMessage(MessageIn &msg) int px = msg.readInt16(); int py = msg.readInt16(); auto direction = (BeingDirection)msg.readInt8(); - Gender gender; - int genderAsInt = msg.readInt8(); - if (genderAsInt == GENDER_FEMALE) - gender = Gender::FEMALE; - else if (genderAsInt == GENDER_MALE) - gender = Gender::MALE; - else - gender = Gender::UNSPECIFIED; + + Gender gender = Gender::Unspecified; + switch (getGender(msg.readInt8())) { + case GENDER_MALE: + gender = Gender::Male; + break; + case GENDER_FEMALE: + gender = Gender::Female; + break; + case GENDER_UNSPECIFIED: + break; + } + Being *being; switch (type) @@ -139,9 +183,7 @@ void BeingHandler::handleBeingEnterMessage(MessageIn &msg) ActorSprite::PLAYER, 0); being->setName(name); } - int hs = msg.readInt8(), hc = msg.readInt8(); - being->setSprite(SPRITE_LAYER_HAIR, hs * -1, - hairDB.getHairColor(hc)); + handleLooks(being, msg); } break; @@ -152,7 +194,8 @@ void BeingHandler::handleBeingEnterMessage(MessageIn &msg) being = actorSpriteManager->createBeing(id, type == OBJECT_MONSTER ? ActorSprite::MONSTER : ActorSprite::NPC, subtype); std::string name = msg.readString(); - if (name.length() > 0) being->setName(name); + if (!name.empty()) + being->setName(name); } break; default: @@ -175,6 +218,19 @@ void BeingHandler::handleBeingLeaveMessage(MessageIn &msg) actorSpriteManager->destroyActor(being); } +void BeingHandler::handleBeingEmoteMessage(MessageIn &msg) +{ + Being *being = actorSpriteManager->findBeing(msg.readInt16()); + if (!being) + return; + + if (player_relations.hasPermission(being, PlayerPermissions::EMOTE)) + { + const int fx = EmoteDB::get(msg.readInt8() - 1).effectId; + effectManager->trigger(fx, being); + } +} + void BeingHandler::handleBeingsMoveMessage(MessageIn &msg) { while (msg.getUnreadLength()) @@ -235,18 +291,51 @@ void BeingHandler::handleBeingsMoveMessage(MessageIn &msg) } } -void BeingHandler::handleBeingAttackMessage(MessageIn &msg) +void BeingHandler::handleBeingAbilityPointMessage(MessageIn &msg) { Being *being = actorSpriteManager->findBeing(msg.readInt16()); - const auto direction = (BeingDirection) msg.readInt8(); - const int attackId = msg.readInt8(); + if (!being) + return; + + const int abilityId = msg.readInt8(); + const int x = msg.readInt16(); + const int y = msg.readInt16(); + + being->lookAt(Vector(x, y)); + + if (auto ability = AbilityDB::get(abilityId)) + being->setAction(ability->useAction); +} +void BeingHandler::handleBeingAbilityBeingMessage(MessageIn &msg) +{ + Being *being = actorSpriteManager->findBeing(msg.readInt16()); if (!being) return; + const int abilityId = msg.readInt8(); + const int targetId = msg.readInt16(); + + if (Being *target = actorSpriteManager->findBeing(targetId)) + being->lookAt(target->getPosition()); + + if (auto ability = AbilityDB::get(abilityId)) + being->setAction(ability->useAction); +} + +void BeingHandler::handleBeingAbilityDirectionMessage(MessageIn &msg) +{ + Being *being = actorSpriteManager->findBeing(msg.readInt16()); + if (!being) + return; + + const int abilityId = msg.readInt8(); + const int direction = msg.readInt8(); + being->setDirection(direction); - being->setAction(Being::ATTACK, attackId); + if (auto ability = AbilityDB::get(abilityId)) + being->setAction(ability->useAction); } void BeingHandler::handleBeingsDamageMessage(MessageIn &msg) @@ -256,9 +345,7 @@ void BeingHandler::handleBeingsDamageMessage(MessageIn &msg) Being *being = actorSpriteManager->findBeing(msg.readInt16()); int damage = msg.readInt16(); if (being) - { being->takeDamage(nullptr, damage, Being::HIT); - } } } @@ -306,14 +393,8 @@ void BeingHandler::handleBeingLooksChangeMessage(MessageIn &msg) Being *being = actorSpriteManager->findBeing(msg.readInt16()); if (!being || being->getType() != ActorSprite::PLAYER) return; + handleLooks(being, msg); - if (msg.getUnreadLength()) - { - int style = msg.readInt16(); - int color = msg.readInt16(); - being->setSprite(SPRITE_LAYER_HAIR, style * -1, - hairDB.getHairColor(color)); - } } void BeingHandler::handleBeingDirChangeMessage(MessageIn &msg) diff --git a/src/net/manaserv/beinghandler.h b/src/net/manaserv/beinghandler.h index 63424de9..9580c284 100644 --- a/src/net/manaserv/beinghandler.h +++ b/src/net/manaserv/beinghandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_BEINGHANDLER_H -#define NET_MANASERV_BEINGHANDLER_H +#pragma once #include "net/manaserv/messagehandler.h" @@ -44,10 +43,13 @@ class BeingHandler final : public MessageHandler void handleMessage(MessageIn &msg) override; private: - void handleBeingAttackMessage(MessageIn &msg); void handleBeingEnterMessage(MessageIn &msg); void handleBeingLeaveMessage(MessageIn &msg); + void handleBeingEmoteMessage(MessageIn &msg); void handleBeingsMoveMessage(MessageIn &msg); + void handleBeingAbilityPointMessage(MessageIn &msg); + void handleBeingAbilityBeingMessage(MessageIn &msg); + void handleBeingAbilityDirectionMessage(MessageIn &msg); void handleBeingsDamageMessage(MessageIn &msg); void handleBeingActionChangeMessage(MessageIn &msg); void handleBeingLooksChangeMessage(MessageIn &msg); @@ -55,5 +57,3 @@ class BeingHandler final : public MessageHandler }; } // namespace ManaServ - -#endif diff --git a/src/net/manaserv/buysellhandler.h b/src/net/manaserv/buysellhandler.h index 0629bd7b..c19090e1 100644 --- a/src/net/manaserv/buysellhandler.h +++ b/src/net/manaserv/buysellhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_BUYSELLHANDLER_H -#define NET_MANASERV_BUYSELLHANDLER_H +#pragma once #include "net/manaserv/messagehandler.h" @@ -35,5 +34,3 @@ class BuySellHandler final : public MessageHandler }; } // namespace ManaServ - -#endif diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp index 8a922e70..98591669 100644 --- a/src/net/manaserv/charhandler.cpp +++ b/src/net/manaserv/charhandler.cpp @@ -44,6 +44,7 @@ #include "utils/dtor.h" #include "utils/gettext.h" +#include "utils/stringutils.h" extern Net::CharHandler *charHandler; extern ManaServ::GameHandler *gameHandler; @@ -99,28 +100,44 @@ void CharHandler::handleMessage(MessageIn &msg) void CharHandler::handleCharacterInfo(MessageIn &msg) { - CachedCharacterInfo info; - info.slot = msg.readInt8(); - info.name = msg.readString(); - info.gender = msg.readInt8() == ManaServ::GENDER_MALE ? Gender::MALE - : Gender::FEMALE; - info.hairStyle = msg.readInt8(); - info.hairColor = msg.readInt8(); - info.level = msg.readInt16(); - info.characterPoints = msg.readInt16(); - info.correctionPoints = msg.readInt16(); - while (msg.getUnreadLength() > 0) { - int id = msg.readInt32(); - CachedAttrbiute attr; - attr.base = msg.readInt32() / 256.0; - attr.mod = msg.readInt32() / 256.0; + CachedCharacterInfo &info = mCachedCharacterInfos.emplace_back(); - info.attribute[id] = attr; - } + info.slot = msg.readInt8(); + info.name = msg.readString(); + switch (getGender(msg.readInt8())) { + case GENDER_MALE: + info.gender = Gender::Male; + break; + case GENDER_FEMALE: + info.gender = Gender::Female; + break; + case GENDER_UNSPECIFIED: + info.gender = Gender::Unspecified; + break; + } + info.hairStyle = msg.readInt8(); + info.hairColor = msg.readInt8(); + info.characterPoints = msg.readInt16(); + info.correctionPoints = msg.readInt16(); - mCachedCharacterInfos.push_back(info); + int equipmentCount = msg.readInt8(); + while (equipmentCount--) + { + auto &slot = info.equipment.emplace_back(); + slot.id = msg.readInt16(); + slot.itemId = msg.readInt16(); + } + + int attributeCount = msg.readInt8(); + while (attributeCount--) + { + CachedAttribute &attr = info.attributes[msg.readInt32()]; + attr.base = msg.readInt32() / 256.0; + attr.mod = msg.readInt32() / 256.0; + } + } updateCharacters(); } @@ -182,6 +199,8 @@ void CharHandler::handleCharacterCreateResponse(MessageIn &msg) } else { + handleCharacterInfo(msg); + // Close the character create dialog if (mCharCreateDialog) { @@ -380,10 +399,8 @@ void CharHandler::updateCharacters() return; // Create new characters and initialize them from the cached infos - for (unsigned i = 0; i < mCachedCharacterInfos.size(); ++i) + for (const auto &info : mCachedCharacterInfos) { - const CachedCharacterInfo &info = mCachedCharacterInfos.at(i); - auto *character = new Net::Character; character->slot = info.slot; LocalPlayer *player = character->dummy = new LocalPlayer; @@ -391,14 +408,30 @@ void CharHandler::updateCharacters() player->setGender(info.gender); player->setSprite(SPRITE_LAYER_HAIR, info.hairStyle * -1, hairDB.getHairColor(info.hairColor)); - character->data.mAttributes[LEVEL] = info.level; + + for (auto &slot : info.equipment) + { + player->setSprite(slot.id + FIXED_SPRITE_LAYER_SIZE, + slot.itemId, + std::string(), + Net::getInventoryHandler()->isWeaponSlot(slot.id)); + } + character->data.mAttributes[CHAR_POINTS] = info.characterPoints; character->data.mAttributes[CORR_POINTS] = info.correctionPoints; - for (const auto &it : info.attribute) + for (const auto &[id, attr] : info.attributes) { - character->data.mStats[i].base = it.second.base; - character->data.mStats[i].mod = it.second.mod; + int playerInfoId = Attributes::getPlayerInfoIdFromAttrId(id); + if (playerInfoId > -1) + { + character->data.mAttributes[playerInfoId] = attr.mod; + } + else + { + character->data.mStats[id].base = attr.base; + character->data.mStats[id].mod = attr.mod; + } } mCharacters.push_back(character); diff --git a/src/net/manaserv/charhandler.h b/src/net/manaserv/charhandler.h index 9ec5cdbb..e962bdfa 100644 --- a/src/net/manaserv/charhandler.h +++ b/src/net/manaserv/charhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_CHARSERVERHANDLER_H -#define NET_MANASERV_CHARSERVERHANDLER_H +#pragma once #include "gui/charselectdialog.h" @@ -89,12 +88,15 @@ class CharHandler final : public MessageHandler, public Net::CharHandler * we have loaded the dynamic data, so we can't resolve load any * sprites yet. */ - struct CachedAttrbiute { + struct CachedAttribute { double base; double mod; }; - using CachedAttributes = std::map<int, CachedAttrbiute>; + struct EquipmentSlot { + int id; + int itemId; + }; struct CachedCharacterInfo { int slot; @@ -102,10 +104,10 @@ class CharHandler final : public MessageHandler, public Net::CharHandler Gender gender; int hairStyle; int hairColor; - int level; int characterPoints; int correctionPoints; - CachedAttributes attribute; + std::vector<EquipmentSlot> equipment; + std::map<int, CachedAttribute> attributes; }; void handleCharacterInfo(MessageIn &msg); @@ -120,5 +122,3 @@ class CharHandler final : public MessageHandler, public Net::CharHandler }; } // namespace ManaServ - -#endif diff --git a/src/net/manaserv/chathandler.h b/src/net/manaserv/chathandler.h index f17883ae..6099fe93 100644 --- a/src/net/manaserv/chathandler.h +++ b/src/net/manaserv/chathandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_CHATHANDLER_H -#define NET_MANASERV_CHATHANDLER_H +#pragma once #include "net/chathandler.h" @@ -127,5 +126,3 @@ class ChatHandler final : public MessageHandler, public Net::ChatHandler }; } // namespace ManaServ - -#endif diff --git a/src/net/manaserv/connection.cpp b/src/net/manaserv/connection.cpp index 896d86ad..1b6f757a 100644 --- a/src/net/manaserv/connection.cpp +++ b/src/net/manaserv/connection.cpp @@ -45,6 +45,8 @@ Connection::~Connection() bool Connection::connect(const std::string &address, enet_uint16 port) { logger->log("Net::Connection::connect(%s, %i)", address.c_str(), port); + if (mConnection) + disconnect(); if (address.empty()) { @@ -87,8 +89,7 @@ void Connection::disconnect() bool Connection::isConnected() { - return (mConnection) ? - (mConnection->state == ENET_PEER_STATE_CONNECTED) : false; + return mConnection && mConnection->state == ENET_PEER_STATE_CONNECTED; } void Connection::send(const ManaServ::MessageOut &msg) diff --git a/src/net/manaserv/connection.h b/src/net/manaserv/connection.h index dfd45e31..196d034b 100644 --- a/src/net/manaserv/connection.h +++ b/src/net/manaserv/connection.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_CONNECTION_H -#define NET_MANASERV_CONNECTION_H +#pragma once #include <enet/enet.h> #include "net/manaserv/network.h" @@ -76,5 +75,3 @@ namespace ManaServ State mState = OK; }; } - -#endif // NET_MANASERV_CONNECTION_H diff --git a/src/net/manaserv/defines.h b/src/net/manaserv/defines.h index f1d12339..e224c045 100644 --- a/src/net/manaserv/defines.h +++ b/src/net/manaserv/defines.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef MANASERV_DEFINES_H -#define MANASERV_DEFINES_H +#pragma once /** * Attributes used during combat. Available to all the beings. @@ -72,5 +71,3 @@ enum NB_CHARACTER_ATTRIBUTES = CHAR_ATTR_END }; - -#endif // MANASERV_DEFINES_H diff --git a/src/net/manaserv/effecthandler.h b/src/net/manaserv/effecthandler.h index 4ba711d7..9b4e7adf 100644 --- a/src/net/manaserv/effecthandler.h +++ b/src/net/manaserv/effecthandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_EFFECTSHANDLER_H -#define NET_MANASERV_EFFECTSHANDLER_H +#pragma once #include "net/manaserv/messagehandler.h" @@ -41,5 +40,3 @@ class EffectHandler final : public MessageHandler }; } // namespace ManaServ - -#endif // NET_MANASERV_EFFECTSHANDLER_H diff --git a/src/net/manaserv/gamehandler.cpp b/src/net/manaserv/gamehandler.cpp index 1bf4d69f..3dae5640 100644 --- a/src/net/manaserv/gamehandler.cpp +++ b/src/net/manaserv/gamehandler.cpp @@ -44,6 +44,7 @@ extern ServerInfo chatServer; GameHandler::GameHandler() { static const Uint16 _messages[] = { + GPMSG_CONNECT_RESPONSE, GPMSG_DISCONNECT_RESPONSE, 0 }; @@ -55,6 +56,9 @@ void GameHandler::handleMessage(MessageIn &msg) { switch (msg.getId()) { + case GPMSG_CONNECT_RESPONSE: + break; + case GPMSG_DISCONNECT_RESPONSE: { int errMsg = msg.readInt8(); diff --git a/src/net/manaserv/gamehandler.h b/src/net/manaserv/gamehandler.h index 019c2dfa..4db8a9ee 100644 --- a/src/net/manaserv/gamehandler.h +++ b/src/net/manaserv/gamehandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_MAPHANDLER_H -#define NET_MANASERV_MAPHANDLER_H +#pragma once #include "net/gamehandler.h" @@ -62,5 +61,3 @@ class GameHandler final : public MessageHandler, public Net::GameHandler }; } // namespace ManaServ - -#endif // NET_MANASERV_MAPHANDLER_H diff --git a/src/net/manaserv/generalhandler.cpp b/src/net/manaserv/generalhandler.cpp index 0692ee82..32141c29 100644 --- a/src/net/manaserv/generalhandler.cpp +++ b/src/net/manaserv/generalhandler.cpp @@ -23,7 +23,6 @@ #include "client.h" -#include "gui/inventorywindow.h" #include "gui/skilldialog.h" #include "net/manaserv/adminhandler.h" @@ -42,13 +41,11 @@ #include "net/manaserv/npchandler.h" #include "net/manaserv/partyhandler.h" #include "net/manaserv/playerhandler.h" -#include "net/manaserv/specialhandler.h" +#include "net/manaserv/abilityhandler.h" #include "net/manaserv/tradehandler.h" #include "resources/attributes.h" -extern Net::GeneralHandler *generalHandler; - extern ManaServ::LoginHandler *loginHandler; namespace ManaServ { @@ -76,7 +73,7 @@ GeneralHandler::GeneralHandler(): mPartyHandler(new PartyHandler), mPlayerHandler(new PlayerHandler), mTradeHandler(new TradeHandler), - mSpecialHandler(new SpecialHandler) + mAbilityHandler(new AbilityHandler) { initialize(); @@ -84,8 +81,6 @@ GeneralHandler::GeneralHandler(): gameServerConnection = getConnection(); chatServerConnection = getConnection(); - generalHandler = this; - listen(Event::ClientChannel); listen(Event::GameChannel); } @@ -129,18 +124,28 @@ void GeneralHandler::reload() void GeneralHandler::unload() { - clearHandlers(); + clearNetworkHandlers(); if (accountServerConnection) + { accountServerConnection->disconnect(); + delete accountServerConnection; + accountServerConnection = nullptr; + } + if (gameServerConnection) + { gameServerConnection->disconnect(); + delete gameServerConnection; + gameServerConnection = nullptr; + } + if (chatServerConnection) + { chatServerConnection->disconnect(); - - delete accountServerConnection; - delete gameServerConnection; - delete chatServerConnection; + delete chatServerConnection; + chatServerConnection = nullptr; + } finalize(); } @@ -157,11 +162,6 @@ void GeneralHandler::flushNetwork() } } -void GeneralHandler::clearHandlers() -{ - clearNetworkHandlers(); -} - void GeneralHandler::event(Event::Channel channel, const Event &event) { @@ -182,7 +182,6 @@ void GeneralHandler::event(Event::Channel channel, { if (event.getType() == Event::GuiWindowsLoaded) { - inventoryWindow->setSplitAllowed(true); skillDialog->loadSkills(); PlayerInfo::setAttribute(EXP_NEEDED, 100); diff --git a/src/net/manaserv/generalhandler.h b/src/net/manaserv/generalhandler.h index 582c1796..de0e3138 100644 --- a/src/net/manaserv/generalhandler.h +++ b/src/net/manaserv/generalhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_GENERALHANDLER_H -#define NET_MANASERV_GENERALHANDLER_H +#pragma once #include "eventlistener.h" @@ -44,8 +43,6 @@ class GeneralHandler : public Net::GeneralHandler, public EventListener void flushNetwork() override; - void clearHandlers() override; - void event(Event::Channel channel, const Event &event) override; protected: @@ -64,9 +61,7 @@ class GeneralHandler : public Net::GeneralHandler, public EventListener MessageHandlerPtr mPartyHandler; MessageHandlerPtr mPlayerHandler; MessageHandlerPtr mTradeHandler; - MessageHandlerPtr mSpecialHandler; + MessageHandlerPtr mAbilityHandler; }; } // namespace ManaServ - -#endif // NET_MANASERV_GENERALHANDLER_H diff --git a/src/net/manaserv/guildhandler.h b/src/net/manaserv/guildhandler.h index 666ae862..d7eb798c 100644 --- a/src/net/manaserv/guildhandler.h +++ b/src/net/manaserv/guildhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_GUILDHANDLER_H -#define NET_MANASERV_GUILDHANDLER_H +#pragma once #include "net/guildhandler.h" @@ -67,5 +66,3 @@ protected: }; } // namespace ManaServ - -#endif diff --git a/src/net/manaserv/internal.h b/src/net/manaserv/internal.h index 2961f4bb..701c9ee6 100644 --- a/src/net/manaserv/internal.h +++ b/src/net/manaserv/internal.h @@ -19,12 +19,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_INTERNAL_H -#define NET_MANASERV_INTERNAL_H +#pragma once namespace ManaServ { extern int connections; } - -#endif diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp index 9754beb0..58a495af 100644 --- a/src/net/manaserv/inventoryhandler.cpp +++ b/src/net/manaserv/inventoryhandler.cpp @@ -43,16 +43,6 @@ extern Net::InventoryHandler *inventoryHandler; namespace ManaServ { -struct EquipItemInfo -{ - - EquipItemInfo(int itemId, int slotTypeId, int amountUsed): - mItemId(itemId), mSlotTypeId(slotTypeId), mAmountUsed(amountUsed) - {} - - int mItemId, mSlotTypeId, mAmountUsed; -}; - extern Connection *gameServerConnection; EquipBackend::EquipBackend() @@ -61,15 +51,13 @@ EquipBackend::EquipBackend() mVisibleSlots = 0; } -EquipBackend::~EquipBackend() -{ - clear(); -} - Item *EquipBackend::getEquipment(int slotIndex) const { auto it = mSlots.find(slotIndex); - return it == mSlots.end() ? nullptr : it->second.item; + if (it == mSlots.end()) + return nullptr; + + return PlayerInfo::getInventory()->getItem(it->second.inventorySlot); } std::string EquipBackend::getSlotName(int slotIndex) const @@ -80,111 +68,55 @@ std::string EquipBackend::getSlotName(int slotIndex) const void EquipBackend::triggerUnequip(int slotIndex) const { - // First get the itemInstance - auto it = mSlots.find(slotIndex); - - if (it == mSlots.end() || it->second.itemInstance == 0 || !it->second.item) + auto item = getEquipment(slotIndex); + if (!item) return; Event event(Event::DoUnequip); - event.setItem("item", it->second.item); - event.setInt("itemInstance", it->second.itemInstance); + event.setItem("item", item); event.trigger(Event::ItemChannel); } - void EquipBackend::clear() { - for (auto &slot : mSlots) - { - if (slot.second.item) - { - delete slot.second.item; - slot.second.item = nullptr; - } - } - mSlots.clear(); + for (auto &[_, slot] : mSlots) + slot.inventorySlot = -1; } -void EquipBackend::equip(int itemId, int slotTypeId, int amountUsed, - int itemInstance) +void EquipBackend::equip(int inventorySlot, int equipmentSlot) { - if (itemInstance <= 0) - { - logger->log("ManaServ::EquipBackend: Equipment slot %i" - " has an invalid item instance.", slotTypeId); - return; - } - - auto it = mSlots.begin(); - auto it_end = mSlots.end(); - bool slotTypeFound = false; - for (; it != it_end; ++it) - if (it->second.slotTypeId == (unsigned)slotTypeId) - slotTypeFound = true; - - if (!slotTypeFound) + auto slotIt = mSlots.find(equipmentSlot); + if (slotIt == mSlots.end()) { logger->log("ManaServ::EquipBackend: Equipment slot %i" - " is not existing.", slotTypeId); + " is not existing.", + equipmentSlot); return; } - if (!itemDb->exists(itemId)) - { - logger->log("ManaServ::EquipBackend: No item with id %d", - itemId); - return; - } + slotIt->second.inventorySlot = inventorySlot; - // Place the item in the slots with corresponding id until - // the capacity requested has been reached - for (it = mSlots.begin(); it != it_end && amountUsed > 0; ++it) - { - // If we're on the right slot type and that its unit - // isn't already equipped, we can equip there. - // The slots are already sorted by id, and subId anyway. - if (it->second.slotTypeId == (unsigned)slotTypeId - && (!it->second.itemInstance) && (!it->second.item)) - { - it->second.itemInstance = itemInstance; - it->second.item = new Item(itemId, 1, true); - --amountUsed; - } - } + if (auto item = PlayerInfo::getInventory()->getItem(inventorySlot)) + item->setEquipped(true); } -void EquipBackend::unequip(int itemInstance) +void EquipBackend::unequip(int inventorySlot) { - auto it = mSlots.begin(); - auto it_end = mSlots.end(); - bool itemInstanceFound = false; - for (; it != it_end; ++it) - if (it->second.itemInstance == (unsigned)itemInstance) - itemInstanceFound = true; - - if (!itemInstanceFound) + for (auto &[_, slot] : mSlots) { - logger->log("ManaServ::EquipBackend: Equipment item instance %i" - " is not existing. The item couldn't be unequipped!", - itemInstance); - return; - } + if (slot.inventorySlot == inventorySlot) + { + slot.inventorySlot = -1; - for (it = mSlots.begin(); it != it_end; ++it) - { - if (it->second.itemInstance != (unsigned)itemInstance) - continue; + if (auto item = PlayerInfo::getInventory()->getItem(inventorySlot)) + item->setEquipped(false); - // We remove the item - it->second.itemInstance = 0; - // We also delete the item objects - if (it->second.item) - { - delete it->second.item; - it->second.item = nullptr; + return; } } + + logger->log("ManaServ::EquipBackend: No equipped item found at inventory " + "slot %i!", inventorySlot); } void EquipBackend::event(Event::Channel, const Event &event) @@ -195,7 +127,7 @@ void EquipBackend::event(Event::Channel, const Event &event) void EquipBackend::readEquipFile() { - clear(); + mSlots.clear(); XML::Document doc(EQUIP_FILE); XML::Node rootNode = doc.rootNode(); @@ -245,7 +177,7 @@ void EquipBackend::readEquipFile() } slot.subId = i; - mSlots.insert(std::make_pair(slotIndex, slot)); + mSlots.insert(std::make_pair(slotIndex, std::move(slot))); ++slotIndex; } } @@ -262,14 +194,13 @@ void EquipBackend::readBoxNode(XML::Node slotNode) if (boxNode.name() != "box") continue; - int x = boxNode.getProperty("x" , 0); - int y = boxNode.getProperty("y" , 0); + const int x = boxNode.getProperty("x" , 0); + const int y = boxNode.getProperty("y" , 0); - mBoxesPositions.push_back(Position(x, y)); + mBoxPositions.emplace_back(x, y); - std::string backgroundFile = - boxNode.getProperty("background" , std::string()); - mBoxesBackgroundFile.push_back(backgroundFile); + const auto icon = boxNode.getProperty("icon", std::string()); + mBoxIcons.push_back(icon); } } @@ -295,15 +226,15 @@ bool EquipBackend::isAmmoSlot(int slotTypeId) const Position EquipBackend::getBoxPosition(unsigned int slotIndex) const { - if (slotIndex < mBoxesPositions.size()) - return mBoxesPositions.at(slotIndex); + if (slotIndex < mBoxPositions.size()) + return mBoxPositions.at(slotIndex); return Position(0, 0); } -const std::string &EquipBackend::getBoxBackground(unsigned int slotIndex) const +const std::string &EquipBackend::getBoxIcon(unsigned int slotIndex) const { - if (slotIndex < mBoxesBackgroundFile.size()) - return mBoxesBackgroundFile.at(slotIndex); + if (slotIndex < mBoxIcons.size()) + return mBoxIcons.at(slotIndex); return Net::empty; } @@ -313,6 +244,7 @@ InventoryHandler::InventoryHandler() GPMSG_INVENTORY_FULL, GPMSG_INVENTORY, GPMSG_EQUIP, + GPMSG_UNEQUIP, 0 }; handledMessages = _messages; @@ -331,87 +263,43 @@ void InventoryHandler::handleMessage(MessageIn &msg) int count = msg.readInt16(); while (count--) { - int slot = msg.readInt16(); - int id = msg.readInt16(); - int amount = msg.readInt16(); - PlayerInfo::setInventoryItem(slot, id, amount); + const int slot = msg.readInt16(); + const int itemId = msg.readInt16(); + const int amount = msg.readInt16(); + const int equipmentSlot = msg.readInt16(); + PlayerInfo::setInventoryItem(slot, itemId, amount); + + if (equipmentSlot > 0) + mEquipBackend.equip(slot, equipmentSlot); } - // A map of { item instance, {slot type id, item id, amount used}} - std::map<int, EquipItemInfo> equipItemsInfo; - std::map<int, EquipItemInfo>::iterator it; - while (msg.getUnreadLength()) - { - int slotTypeId = msg.readInt16(); - int itemId = msg.readInt16(); - int itemInstance = msg.readInt16(); - - // Turn the data received into a usable format - it = equipItemsInfo.find(itemInstance); - if (it == equipItemsInfo.end()) - { - // Add a new entry - equipItemsInfo.insert(std::make_pair(itemInstance, - EquipItemInfo(itemId, slotTypeId, 1))); - } - else - { - // Add amount to the existing entry - it->second.mAmountUsed++; - } - } - - for (it = equipItemsInfo.begin(); it != equipItemsInfo.end(); - ++it) - { - mEquipBackend.equip(it->second.mItemId, - it->second.mSlotTypeId, - it->second.mAmountUsed, - it->first); - } + inventoryWindow->updateButtons(); } break; case GPMSG_INVENTORY: while (msg.getUnreadLength()) { - unsigned int slot = msg.readInt16(); - int id = msg.readInt16(); - unsigned int amount = id ? msg.readInt16() : 0; + const unsigned int slot = msg.readInt16(); + const int id = msg.readInt16(); + const unsigned int amount = id ? msg.readInt16() : 0; PlayerInfo::setInventoryItem(slot, id, amount); } break; case GPMSG_EQUIP: { - int itemId = msg.readInt16(); - int equipSlotCount = msg.readInt16(); - - if (equipSlotCount <= 0) - break; - - // Otherwise equip the item in the given slots - while (equipSlotCount--) - { - unsigned int parameter = msg.readInt16(); - unsigned int amountUsed = msg.readInt16(); - - if (amountUsed == 0) - { - // No amount means to unequip this item - // Note that in that case, the parameter is - // in fact the itemInstanceId - mEquipBackend.unequip(parameter); - } - else - { - int itemInstance = msg.readInt16(); - // The parameter is in that case the slot type id. - mEquipBackend.equip(itemId, parameter, - amountUsed, itemInstance); - } - } + const int inventorySlot = msg.readInt16(); + const int equipmentSlot = msg.readInt16(); + mEquipBackend.equip(inventorySlot, equipmentSlot); + inventoryWindow->updateButtons(); + } + case GPMSG_UNEQUIP: + { + const int inventorySlot = msg.readInt16(); + mEquipBackend.unequip(inventorySlot); + inventoryWindow->updateButtons(); } break; } @@ -423,9 +311,7 @@ void InventoryHandler::event(Event::Channel channel, if (channel == Event::ItemChannel) { Item *item = event.getItem("item"); - int itemInstance = event.getInt("itemInstance", 0); - - if (!item && itemInstance == 0) + if (!item) return; int index = item->getInvIndex(); @@ -439,7 +325,7 @@ void InventoryHandler::event(Event::Channel channel, else if (event.getType() == Event::DoUnequip) { MessageOut msg(PGMSG_UNEQUIP); - msg.writeInt16(itemInstance); + msg.writeInt16(index); gameServerConnection->send(msg); } else if (event.getType() == Event::DoUse) @@ -457,53 +343,9 @@ void InventoryHandler::event(Event::Channel channel, msg.writeInt16(amount); gameServerConnection->send(msg); } - else if (event.getType() == Event::DoSplit) - { - int amount = event.getInt("amount", 1); - - int newIndex = PlayerInfo::getInventory()->getFreeSlot(); - if (newIndex > Inventory::NO_SLOT_INDEX) - { - MessageOut msg(PGMSG_MOVE_ITEM); - msg.writeInt16(index); - msg.writeInt16(newIndex); - msg.writeInt16(amount); - gameServerConnection->send(msg); - } - } - else if (event.getType() == Event::DoMove) - { - int newIndex = event.getInt("newIndex", -1); - - if (newIndex >= 0) - { - if (index == newIndex) - return; - - MessageOut msg(PGMSG_MOVE_ITEM); - msg.writeInt16(index); - msg.writeInt16(newIndex); - msg.writeInt16(item->getQuantity()); - gameServerConnection->send(msg); - } - else - { - /*int source = event.getInt("source"); - int destination = event.getInt("destination"); - int amount = event.getInt("amount", 1);*/ - - // TODO Support drag'n'drop to the map ground, or with other - // windows. - } - } } } -bool InventoryHandler::canSplit(const Item *item) -{ - return item && item->getQuantity() > 1; -} - size_t InventoryHandler::getSize(int type) const { switch (type) diff --git a/src/net/manaserv/inventoryhandler.h b/src/net/manaserv/inventoryhandler.h index e01bb5d8..b72922b3 100644 --- a/src/net/manaserv/inventoryhandler.h +++ b/src/net/manaserv/inventoryhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_INVENTORYHANDLER_H -#define NET_MANASERV_INVENTORYHANDLER_H +#pragma once #include "eventlistener.h" @@ -28,6 +27,9 @@ #include "net/manaserv/messagehandler.h" +#include "utils/xml.h" + +#include <map> #include <vector> namespace ManaServ { @@ -37,15 +39,12 @@ class EquipBackend final : public Equipment::Backend, public EventListener public: EquipBackend(); - ~EquipBackend() override; - Item *getEquipment(int slotIndex) const override; std::string getSlotName(int slotIndex) const override; void clear() override; - void equip(int itemId, int slotTypeId, int amountUsed = 1, - int itemInstance = 0); - void unequip(int slotTypeId); + void equip(int inventorySlot, int equipmentSlot); + void unequip(int inventorySlot); void event(Event::Channel channel, const Event &event) override; @@ -62,7 +61,7 @@ class EquipBackend final : public Equipment::Backend, public EventListener Position getBoxPosition(unsigned int slotIndex) const; - const std::string &getBoxBackground(unsigned int slotIndex) const; + const std::string &getBoxIcon(unsigned int slotIndex) const; private: void readEquipFile() override; @@ -73,9 +72,7 @@ class EquipBackend final : public Equipment::Backend, public EventListener // Generic info std::string name; - // The Item reference, used for graphical representation - // and info. - Item *item = nullptr; + int inventorySlot = 0; // Manaserv specific info @@ -89,10 +86,6 @@ class EquipBackend final : public Equipment::Backend, public EventListener // This is used to sort the multimap along with the slot id. unsigned int subId = 0; - // This is the (per character) unique item Id, used especially when - // equipping the same item multiple times on the same slot type. - unsigned int itemInstance = 0; - // Tell whether the slot is a weapon slot bool weaponSlot = false; @@ -103,10 +96,9 @@ class EquipBackend final : public Equipment::Backend, public EventListener unsigned int mVisibleSlots; // slot client index, slot info - using Slots = std::map<unsigned int, Slot>; - Slots mSlots; - std::vector<Position> mBoxesPositions; - std::vector<std::string> mBoxesBackgroundFile; + std::map<unsigned int, Slot> mSlots; + std::vector<Position> mBoxPositions; + std::vector<std::string> mBoxIcons; }; class InventoryHandler final : public MessageHandler, Net::InventoryHandler, @@ -119,8 +111,6 @@ class InventoryHandler final : public MessageHandler, Net::InventoryHandler, void event(Event::Channel channel, const Event &event) override; - bool canSplit(const Item *item) override; - size_t getSize(int type) const override; bool isWeaponSlot(unsigned int slotTypeId) const override @@ -138,13 +128,11 @@ class InventoryHandler final : public MessageHandler, Net::InventoryHandler, Position getBoxPosition(unsigned int slotIndex) const override { return mEquipBackend.getBoxPosition(slotIndex); } - const std::string& getBoxBackground(unsigned int slotIndex) const override - { return mEquipBackend.getBoxBackground(slotIndex); } + const std::string& getBoxIcon(unsigned int slotIndex) const override + { return mEquipBackend.getBoxIcon(slotIndex); } private: EquipBackend mEquipBackend; }; } // namespace ManaServ - -#endif // NET_MANASERV_INVENTORYHANDLER_H diff --git a/src/net/manaserv/itemhandler.cpp b/src/net/manaserv/itemhandler.cpp index de5b36fa..870e7a9f 100644 --- a/src/net/manaserv/itemhandler.cpp +++ b/src/net/manaserv/itemhandler.cpp @@ -26,8 +26,6 @@ #include "net/manaserv/manaserv_protocol.h" #include "net/manaserv/messagein.h" -#include "log.h" - namespace ManaServ { ItemHandler::ItemHandler() diff --git a/src/net/manaserv/itemhandler.h b/src/net/manaserv/itemhandler.h index 22adf8fb..c15d4638 100644 --- a/src/net/manaserv/itemhandler.h +++ b/src/net/manaserv/itemhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_ITEMHANDLER_H -#define NET_MANASERV_ITEMHANDLER_H +#pragma once #include "net/manaserv/messagehandler.h" @@ -35,5 +34,3 @@ class ItemHandler final : public MessageHandler }; } // namespace ManaServ - -#endif // NET_MANASERV_ITEMHANDLER_H diff --git a/src/net/manaserv/loginhandler.cpp b/src/net/manaserv/loginhandler.cpp index b9a56834..1c398990 100644 --- a/src/net/manaserv/loginhandler.cpp +++ b/src/net/manaserv/loginhandler.cpp @@ -399,8 +399,6 @@ void LoginHandler::loginAccount(LoginData *loginData) mTmpPassword = loginData->password; MessageOut msg(PAMSG_LOGIN_RNDTRGR); - msg.writeString(mLoginData->username); - accountServerConnection->send(msg); } diff --git a/src/net/manaserv/loginhandler.h b/src/net/manaserv/loginhandler.h index 87fbe9bc..e8d40835 100644 --- a/src/net/manaserv/loginhandler.h +++ b/src/net/manaserv/loginhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_LOGINHANDLER_H -#define NET_MANASERV_LOGINHANDLER_H +#pragma once #include "net/loginhandler.h" @@ -91,5 +90,3 @@ class LoginHandler final : public MessageHandler, public Net::LoginHandler }; } // namespace ManaServ - -#endif // NET_MANASERV_LOGINHANDLER_H diff --git a/src/net/manaserv/manaserv_protocol.h b/src/net/manaserv/manaserv_protocol.h index 760fe655..cb27d6f4 100644 --- a/src/net/manaserv/manaserv_protocol.h +++ b/src/net/manaserv/manaserv_protocol.h @@ -19,14 +19,14 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef MANASERV_PROTOCOL_H -#define MANASERV_PROTOCOL_H +#pragma once namespace ManaServ { enum { - PROTOCOL_VERSION = 3, - SUPPORTED_DB_VERSION = 21 + PROTOCOL_VERSION = 9, + MIN_PROTOCOL_VERSION = 9, + SUPPORTED_DB_VERSION = 27 }; /** @@ -69,19 +69,22 @@ enum { PAMSG_REQUEST_REGISTER_INFO = 0x0005, // APMSG_REGISTER_INFO_RESPONSE = 0x0006, // B byte registration Allowed, byte minNameLength, byte maxNameLength, string captchaURL, string captchaInstructions PAMSG_LOGIN = 0x0010, // D version, S username, S password - APMSG_LOGIN_RESPONSE = 0x0012, // B error, S updatehost, S Client data URL, B Character slots + APMSG_LOGIN_RESPONSE = 0x0012, // B error, S updatehost, S Client data URL, B Character slots, {content of APMSG_CHAR_CREATE_RESPONSE (without error code)}* PAMSG_LOGOUT = 0x0013, // - APMSG_LOGOUT_RESPONSE = 0x0014, // B error - PAMSG_LOGIN_RNDTRGR = 0x0015, // S username + PAMSG_LOGIN_RNDTRGR = 0x0015, // - APMSG_LOGIN_RNDTRGR_RESPONSE = 0x0016, // S random seed + PAMSG_STELLAR_LOGIN = 0x0017, // D version + APMSG_STELLAR_LOGIN_RESPONSE = 0x0018, // B error, S token, S url PAMSG_CHAR_CREATE = 0x0020, // S name, B hair style, B hair color, B gender, B slot, {W stats}* - APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error + APMSG_CHAR_CREATE_RESPONSE = 0x0021, // B error, on success: B slot, S name, B gender, B hair style, B hair color, + // W character points, W correction points, B amount of items equipped, + // { W slot, W itemId }* + // B attributeCount, + // {D attr id, D base value (in 1/256ths) D mod value (in 256ths) }* PAMSG_CHAR_DELETE = 0x0022, // B slot APMSG_CHAR_DELETE_RESPONSE = 0x0023, // B error - // B slot, S name, B gender, B hair style, B hair color, W level, - // W character points, W correction points, - // {D attr id, D base value (in 1/256ths) D mod value (in 256ths) }* - APMSG_CHAR_INFO = 0x0024, // ^ + APMSG_CHAR_INFO = 0x0024, // {content of APMSG_CHAR_CREATE_RESPONSE (without error code)}* PAMSG_CHAR_SELECT = 0x0026, // B slot APMSG_CHAR_SELECT_RESPONSE = 0x0027, // B error, B*32 token, S game address, W game port, S chat address, W chat port PAMSG_EMAIL_CHANGE = 0x0030, // S email @@ -109,26 +112,28 @@ enum { PGMSG_DROP = 0x0111, // W slot, W amount PGMSG_EQUIP = 0x0112, // W inventory slot PGMSG_UNEQUIP = 0x0113, // W item Instance id - PGMSG_MOVE_ITEM = 0x0114, // W slot1, W slot2, W amount GPMSG_INVENTORY = 0x0120, // { W slot, W item id [, W amount] (if item id is nonzero) }* - GPMSG_INVENTORY_FULL = 0x0121, // W inventory slot count { W slot, W itemId, W amount }, { W equip slot, W item Id, W item Instance}* - GPMSG_EQUIP = 0x0122, // W item Id, W equip slot type count //{ W equip slot, W capacity used}*//<- When equipping, //{ W item instance, W 0}*//<- When unequipping + GPMSG_INVENTORY_FULL = 0x0121, // W inventory slot count { W slot, W itemId, W amount, W equipmentSlot } + GPMSG_EQUIP = 0x0122, // W equipped inventory slot, W slot equipmentSlot + GPMSG_EQUIP_RESPONSE = 0x0123, // B error, W slot + GPMSG_UNEQUIP = 0x0124, // W equipped inventory slot + GPMSG_UNEQUIP_RESPONSE = 0x0125, // B error, W slot GPMSG_PLAYER_ATTRIBUTE_CHANGE = 0x0130, // { W attribute, D base value (in 1/256ths), D modified value (in 1/256ths)}* - GPMSG_PLAYER_EXP_CHANGE = 0x0140, // { W skill, D exp got, D exp needed, W skill level }* - GPMSG_LEVELUP = 0x0150, // W new level, W character points, W correction points - GPMSG_LEVEL_PROGRESS = 0x0151, // B percent completed to next levelup + GPMSG_ATTRIBUTE_POINTS_STATUS = 0x0140, // W character points, W correction points PGMSG_RAISE_ATTRIBUTE = 0x0160, // W attribute GPMSG_RAISE_ATTRIBUTE_RESPONSE = 0x0161, // B error, W attribute PGMSG_LOWER_ATTRIBUTE = 0x0170, // W attribute GPMSG_LOWER_ATTRIBUTE_RESPONSE = 0x0171, // B error, W attribute PGMSG_RESPAWN = 0x0180, // - GPMSG_BEING_ENTER = 0x0200, // B type, W being id, B action, W*2 position, B direction, B gender - // character: S name, B hair style, B hair color, B sprite layers changed, { B slot type, W item id }* + // character: S name, B hair style, B hair color [, B sprite layers changed, { B slot type, W item id }*] // monster: W type id // npc: W type id GPMSG_BEING_LEAVE = 0x0201, // W being id GPMSG_ITEM_APPEAR = 0x0202, // W item id, W*2 position - GPMSG_BEING_LOOKS_CHANGE = 0x0210, // B sprite layers changed, { B slot type, W item id }* + GPMSG_BEING_LOOKS_CHANGE = 0x0210, // B hairstyle, B haircolor [, B sprite layers changed, { B slot type, W item id }*] + GPMSG_BEING_EMOTE = 0x0211, // W being id, W emote id + PGMSG_BEING_EMOTE = 0x0212, // W emoticon id PGMSG_WALK = 0x0260, // W*2 destination PGMSG_ACTION_CHANGE = 0x0270, // B Action GPMSG_BEING_ACTION_CHANGE = 0x0271, // W being id, B action @@ -137,45 +142,50 @@ enum { GPMSG_BEING_HEALTH_CHANGE = 0x0274, // W being id, W hp, W max hp GPMSG_BEINGS_MOVE = 0x0280, // { W being id, B flags [, [W*2 position,] W*2 destination, B speed] }* GPMSG_ITEMS = 0x0281, // { W item id, W*2 position }* - PGMSG_ATTACK = 0x0290, // W being id - GPMSG_BEING_ATTACK = 0x0291, // W being id, B direction, B attack Id - PGMSG_USE_SPECIAL_ON_BEING = 0x0292, // B specialID, W being id - GPMSG_SPECIAL_STATUS = 0x0293, // { B specialID, D current, D max, D recharge } - PGMSG_USE_SPECIAL_ON_POINT = 0x0294, // B specialID, W*2 position - PGMSG_SAY = 0x02A0, // S text - GPMSG_SAY = 0x02A1, // W being id, S text - GPMSG_NPC_CHOICE = 0x02B0, // W being id, { S text }* - GPMSG_NPC_MESSAGE = 0x02B1, // W being id, B* text - PGMSG_NPC_TALK = 0x02B2, // W being id - PGMSG_NPC_TALK_NEXT = 0x02B3, // W being id - PGMSG_NPC_SELECT = 0x02B4, // W being id, B choice - GPMSG_NPC_BUY = 0x02B5, // W being id, { W item id, W amount, W cost }* - GPMSG_NPC_SELL = 0x02B6, // W being id, { W item id, W amount, W cost }* - PGMSG_NPC_BUYSELL = 0x02B7, // W item id, W amount - GPMSG_NPC_ERROR = 0x02B8, // B error - GPMSG_NPC_CLOSE = 0x02B9, // W being id + GPMSG_BEING_ABILITY_POINT = 0x0282, // W being id, B abilityId, W*2 point + GPMSG_BEING_ABILITY_BEING = 0x0283, // W being id, B abilityId, W target being id + GPMSG_BEING_ABILITY_DIRECTION = 0x0284, // W being id, B abilityId, B direction + PGMSG_USE_ABILITY_ON_BEING = 0x0290, // B abilityID, W being id + PGMSG_USE_ABILITY_ON_POINT = 0x0291, // B abilityID, W*2 position + PGMSG_USE_ABILITY_ON_DIRECTION = 0x0292, // B abilityID, B direction + GPMSG_ABILITY_STATUS = 0x02A0, // { B abilityID, D remainingTicks } + GPMSG_ABILITY_REMOVED = 0x02A1, // B abilityID + GPMSG_ABILITY_COOLDOWN = 0x02A2, // W ticks to wait + PGMSG_SAY = 0x02B0, // S text + GPMSG_SAY = 0x02B1, // W being id, S text + GPMSG_NPC_CHOICE = 0x02C0, // W being id, { S text }* + GPMSG_NPC_MESSAGE = 0x02C1, // W being id, B* text + PGMSG_NPC_TALK = 0x02C2, // W being id + PGMSG_NPC_TALK_NEXT = 0x02C3, // W being id + PGMSG_NPC_SELECT = 0x02C4, // W being id, B choice + GPMSG_NPC_BUY = 0x02C5, // W being id, { W item id, W amount, W cost }* + GPMSG_NPC_SELL = 0x02C6, // W being id, { W item id, W amount, W cost }* + PGMSG_NPC_BUYSELL = 0x02C7, // W item id, W amount + GPMSG_NPC_ERROR = 0x02C8, // B error + GPMSG_NPC_CLOSE = 0x02C9, // W being id GPMSG_NPC_POST = 0x02D0, // W being id PGMSG_NPC_POST_SEND = 0x02D1, // W being id, { S name, S text, W item id } GPMSG_NPC_POST_GET = 0x02D2, // W being id, { S name, S text, W item id } PGMSG_NPC_NUMBER = 0x02D3, // W being id, D number PGMSG_NPC_STRING = 0x02D4, // W being id, S string - GPMSG_NPC_NUMBER = 0x02D5, // W being id, D max, D min, D default + GPMSG_NPC_NUMBER = 0x02D5, // W being id, D min, D max, D default GPMSG_NPC_STRING = 0x02D6, // W being id - PGMSG_TRADE_REQUEST = 0x02C0, // W being id - GPMSG_TRADE_REQUEST = 0x02C1, // W being id - GPMSG_TRADE_START = 0x02C2, // - - GPMSG_TRADE_COMPLETE = 0x02C3, // - - PGMSG_TRADE_CANCEL = 0x02C4, // - - GPMSG_TRADE_CANCEL = 0x02C5, // - - PGMSG_TRADE_AGREED = 0x02C6, // - - GPMSG_TRADE_AGREED = 0x02C7, // - - PGMSG_TRADE_CONFIRM = 0x02C8, // - - GPMSG_TRADE_CONFIRM = 0x02C9, // - - PGMSG_TRADE_ADD_ITEM = 0x02CA, // B slot, B amount - GPMSG_TRADE_ADD_ITEM = 0x02CB, // W item id, B amount - PGMSG_TRADE_SET_MONEY = 0x02CC, // D amount - GPMSG_TRADE_SET_MONEY = 0x02CD, // D amount - GPMSG_TRADE_BOTH_CONFIRM = 0x02CE, // - + GPMSG_NPC_BUYSELL_RESPONSE = 0x02D7, // B error, W item id, W amount + PGMSG_TRADE_REQUEST = 0x02E0, // W being id + GPMSG_TRADE_REQUEST = 0x02E1, // W being id + GPMSG_TRADE_START = 0x02E2, // - + GPMSG_TRADE_COMPLETE = 0x02E3, // - + PGMSG_TRADE_CANCEL = 0x02E4, // - + GPMSG_TRADE_CANCEL = 0x02E5, // - + PGMSG_TRADE_AGREED = 0x02E6, // - + GPMSG_TRADE_AGREED = 0x02E7, // - + PGMSG_TRADE_CONFIRM = 0x02E8, // - + GPMSG_TRADE_CONFIRM = 0x02E9, // - + PGMSG_TRADE_ADD_ITEM = 0x02EA, // B slot, B amount + GPMSG_TRADE_ADD_ITEM = 0x02EB, // W item id, B amount + PGMSG_TRADE_SET_MONEY = 0x02EC, // D amount + GPMSG_TRADE_SET_MONEY = 0x02ED, // D amount + GPMSG_TRADE_BOTH_CONFIRM = 0x02EE, // - PGMSG_USE_ITEM = 0x0300, // B slot GPMSG_USE_RESPONSE = 0x0301, // B error GPMSG_BEINGS_DAMAGE = 0x0310, // { W being id, W amount }* @@ -243,8 +253,11 @@ enum { PCMSG_USER_MODE = 0x0465, // W channel id, S name, B mode PCMSG_KICK_USER = 0x0466, // W channel id, S name + // -- Questlog + GPMSG_QUESTLOG_STATUS = 0x0470, // {W quest id, B flags, [B status], [S questname], [S questdescription]}* + // Inter-server - GAMSG_REGISTER = 0x0500, // S address, W port, S password, D items db revision, { W map id }* + GAMSG_REGISTER = 0x0500, // S address, W port, S password, D items db revision AGMSG_REGISTER_RESPONSE = 0x0501, // W item version, W password response, { S globalvar_key, S globalvar_value } AGMSG_ACTIVE_MAP = 0x0502, // W map id, W Number of mapvar_key mapvar_value sent, { S mapvar_key, S mapvar_value }, W Number of map items, { D item Id, W amount, W posX, W posY } AGMSG_PLAYER_ENTER = 0x0510, // B*32 token, D id, S name, serialised character data @@ -263,7 +276,6 @@ enum { GAMSG_SET_VAR_WORLD = 0x0547, // S name, S value AGMSG_SET_VAR_WORLD = 0x0548, // S name, S value GAMSG_BAN_PLAYER = 0x0550, // D id, W duration - GAMSG_CHANGE_PLAYER_LEVEL = 0x0555, // D id, W level GAMSG_CHANGE_ACCOUNT_LEVEL = 0x0556, // D id, W level GAMSG_STATISTICS = 0x0560, // { W map id, W entity nb, W monster nb, W player nb, { D character id }* }* CGMSG_CHANGED_PARTY = 0x0590, // D character id, D party id @@ -295,7 +307,8 @@ enum { ERRMSG_TIME_OUT, // data failed to arrive in due time ERRMSG_LIMIT_REACHED, // limit reached ERRMSG_ADMINISTRATIVE_LOGOFF, // kicked by server administrator - ERRMSG_ALREADY_MEMBER // is already member of guild/party + ERRMSG_ALREADY_MEMBER, // is already member of guild/party + ERRMSG_LOGIN_WAS_TAKEN_OVER // a different connection took over }; // used in AGMSG_REGISTER_RESPONSE to show state of item db @@ -314,7 +327,6 @@ enum { enum { SYNC_CHARACTER_POINTS = 0x01, // D charId, D charPoints, D corrPoints SYNC_CHARACTER_ATTRIBUTE = 0x02, // D charId, D attrId, DF base, DF mod - SYNC_CHARACTER_SKILL = 0x03, // D charId, B skillId, D skill value SYNC_ONLINE_STATUS = 0x04 // D charId, B 0 = offline, 1 = online }; @@ -358,21 +370,18 @@ enum AttribmodResponseCode { enum EntityType { // A simple item. - OBJECT_ITEM = 0, - // An item that toggle map/quest actions (doors, switchs, ...) - // and can speak (map panels). - OBJECT_ACTOR, + OBJECT_ITEM = 0, // Non-Playable-Character is an actor capable of movement and maybe actions. - OBJECT_NPC, + OBJECT_NPC = 2, // A monster (moving actor with AI. Should be able to toggle map/quest // actions, too). - OBJECT_MONSTER, + OBJECT_MONSTER = 3, // A normal being. - OBJECT_CHARACTER, + OBJECT_CHARACTER = 4, // A effect to be shown. - OBJECT_EFFECT, + OBJECT_EFFECT = 5, // Server-only object. - OBJECT_OTHER + OBJECT_OTHER = 6 }; // Moving object flags @@ -406,6 +415,13 @@ enum { GUILD_EVENT_OFFLINE_PLAYER }; +enum { + QUESTLOG_UPDATE_STATE = 1, + QUESTLOG_UPDATE_TITLE = 2, + QUESTLOG_UPDATE_DESCRIPTION = 4, + QUESTLOG_SHOW_NOTIFICATION = 8 +}; + /** * Moves enum for beings and actors for others players vision. * WARNING: Has to be in sync with the same enum in the Being class @@ -415,27 +431,12 @@ enum BeingAction { STAND, WALK, - ATTACK, SIT, DEAD, HURT }; /** - * Moves enum for beings and actors for others players attack types. - * WARNING: Has to be in sync with the same enum in the Being class - * of the client! - */ -enum AttackType -{ - HIT = 0x00, - CRITICAL = 0x0a, - MULTI = 0x08, - REFLECT = 0x04, - FLEE = 0x0b -}; - -/** * Beings and actors directions * WARNING: Has to be in sync with the same enum in the Being class * of the client! @@ -458,6 +459,55 @@ enum BeingGender GENDER_UNSPECIFIED }; +// Helper functions for gender + +/** +* Helper function for getting gender by int +*/ +inline ManaServ::BeingGender getGender(int gender) +{ + switch (gender) + { + case 0: + return ManaServ::GENDER_MALE; + case 1: + return ManaServ::GENDER_FEMALE; + default: + return ManaServ::GENDER_UNSPECIFIED; + } +} + +/** + * Quest states + */ +enum QuestStatus +{ + STATUS_OPEN = 0, + STATUS_STARTED, + STATUS_FINISHED, + STATUS_INVALID +}; + +/** + * Helper function for getting quest status by id + * @param status id of the status + * @return the status as enum value + */ +inline ManaServ::QuestStatus getQuestStatus(int status) +{ + switch (status) + { + case 0: + return ManaServ::STATUS_OPEN; + case 1: + return ManaServ::STATUS_STARTED; + case 2: + return ManaServ::STATUS_FINISHED; + default: + return ManaServ::STATUS_INVALID; + } +} + /** The permited range to pick up an item */ const int PICKUP_RANGE = 32 + 16; @@ -465,5 +515,3 @@ const int PICKUP_RANGE = 32 + 16; const int NPC_TALK_RANGE = 32 * 7; } // namespace ManaServ - -#endif // MANASERV_PROTOCOL_H diff --git a/src/net/manaserv/messagehandler.h b/src/net/manaserv/messagehandler.h index f9ee09ab..2c68cde5 100644 --- a/src/net/manaserv/messagehandler.h +++ b/src/net/manaserv/messagehandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_MESSAGEHANDLER_H -#define NET_MANASERV_MESSAGEHANDLER_H +#pragma once #include "net/messagehandler.h" @@ -44,5 +43,3 @@ class MessageHandler : public Net::MessageHandler using MessageHandlerPtr = const std::unique_ptr<MessageHandler>; } // namespace ManaServ - -#endif // NET_MANASERV_MESSAGEHANDLER_H diff --git a/src/net/manaserv/messagein.h b/src/net/manaserv/messagein.h index 1edc4fe7..cd072fe0 100644 --- a/src/net/manaserv/messagein.h +++ b/src/net/manaserv/messagein.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_MESSAGEIN_H -#define NET_MANASERV_MESSAGEIN_H +#pragma once #include "net/manaserv/manaserv_protocol.h" @@ -95,5 +94,3 @@ class MessageIn }; } // namespace ManaServ - -#endif // NET_MANASERV_MESSAGEIN_H diff --git a/src/net/manaserv/messageout.h b/src/net/manaserv/messageout.h index d452f784..d9d2e68a 100644 --- a/src/net/manaserv/messageout.h +++ b/src/net/manaserv/messageout.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_MESSAGEOUT_H -#define NET_MANASERV_MESSAGEOUT_H +#pragma once #include "net/manaserv/manaserv_protocol.h" @@ -91,5 +90,3 @@ class MessageOut }; } // namespace ManaServ - -#endif // NET_MANASERV_MESSAGEOUT_H diff --git a/src/net/manaserv/network.cpp b/src/net/manaserv/network.cpp index b8d3fa93..d69d3397 100644 --- a/src/net/manaserv/network.cpp +++ b/src/net/manaserv/network.cpp @@ -88,17 +88,13 @@ Connection *getConnection() void registerHandler(MessageHandler *handler) { for (const uint16_t *i = handler->handledMessages; *i; i++) - { mMessageHandlers[*i] = handler; - } } void unregisterHandler(MessageHandler *handler) { for (const uint16_t *i = handler->handledMessages; *i; i++) - { mMessageHandlers.erase(*i); - } } void clearNetworkHandlers() diff --git a/src/net/manaserv/network.h b/src/net/manaserv/network.h index f484d54d..a51a8168 100644 --- a/src/net/manaserv/network.h +++ b/src/net/manaserv/network.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_NETWORK_H -#define NET_MANASERV_NETWORK_H +#pragma once #include <iosfwd> @@ -71,5 +70,3 @@ namespace ManaServ */ void flush(); } // namespace ManaServ - -#endif diff --git a/src/net/manaserv/npchandler.cpp b/src/net/manaserv/npchandler.cpp index f19bf134..df139d23 100644 --- a/src/net/manaserv/npchandler.cpp +++ b/src/net/manaserv/npchandler.cpp @@ -47,6 +47,7 @@ NpcHandler::NpcHandler() GPMSG_NPC_CLOSE, GPMSG_NPC_NUMBER, GPMSG_NPC_STRING, + GPMSG_NPC_BUYSELL_RESPONSE, 0 }; handledMessages = _messages; @@ -100,7 +101,7 @@ void NpcHandler::handleMessage(MessageIn &msg) break; case GPMSG_NPC_ERROR: - event = new Event(Event::End); + event = new Event(Event::CloseDialog); event->setInt("id", npcId); event->trigger(Event::NpcChannel); break; @@ -122,6 +123,9 @@ void NpcHandler::handleMessage(MessageIn &msg) event->setInt("id", npcId); event->trigger(Event::NpcChannel); break; + + case GPMSG_NPC_BUYSELL_RESPONSE: + break; } delete event; diff --git a/src/net/manaserv/npchandler.h b/src/net/manaserv/npchandler.h index ee3a9a12..6c485650 100644 --- a/src/net/manaserv/npchandler.h +++ b/src/net/manaserv/npchandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_NPCHANDLER_H -#define NET_MANASERV_NPCHANDLER_H +#pragma once #include "net/npchandler.h" @@ -65,5 +64,3 @@ class NpcHandler final : public MessageHandler, public Net::NpcHandler }; } // namespace ManaServ - -#endif // NET_MANASERV_NPCHANDLER_H diff --git a/src/net/manaserv/partyhandler.h b/src/net/manaserv/partyhandler.h index ac4249a9..ab5aad9a 100644 --- a/src/net/manaserv/partyhandler.h +++ b/src/net/manaserv/partyhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_PARTYHANDLER_H -#define NET_MANASERV_PARTYHANDLER_H +#pragma once #include "net/partyhandler.h" @@ -70,5 +69,3 @@ private: }; } // namespace ManaServ - -#endif // NET_MANASERV_PARTYHANDLER_H diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp index bf5694c6..8ee9ed80 100644 --- a/src/net/manaserv/playerhandler.cpp +++ b/src/net/manaserv/playerhandler.cpp @@ -29,17 +29,18 @@ #include "log.h" #include "particle.h" #include "playerinfo.h" -#include "configuration.h" #include "gui/viewport.h" #include "net/net.h" +#include "net/abilityhandler.h" #include "net/manaserv/connection.h" #include "net/manaserv/messagein.h" #include "net/manaserv/messageout.h" #include "net/manaserv/manaserv_protocol.h" +#include "resources/abilitydb.h" #include "resources/attributes.h" /** @@ -50,6 +51,7 @@ const int MAP_TELEPORT_SCROLL_DISTANCE = 256; extern Net::PlayerHandler *playerHandler; +extern Net::AbilityHandler *abilityHandler; namespace ManaServ { @@ -70,12 +72,11 @@ PlayerHandler::PlayerHandler() GPMSG_PLAYER_MAP_CHANGE, GPMSG_PLAYER_SERVER_CHANGE, GPMSG_PLAYER_ATTRIBUTE_CHANGE, - GPMSG_PLAYER_EXP_CHANGE, - GPMSG_LEVELUP, - GPMSG_LEVEL_PROGRESS, + GPMSG_ATTRIBUTE_POINTS_STATUS, GPMSG_RAISE_ATTRIBUTE_RESPONSE, GPMSG_LOWER_ATTRIBUTE_RESPONSE, - GPMSG_SPECIAL_STATUS, + GPMSG_ABILITY_STATUS, + GPMSG_ABILITY_REMOVED, 0 }; handledMessages = _messages; @@ -129,39 +130,10 @@ void PlayerHandler::handleMessage(MessageIn &msg) } } break; - case GPMSG_PLAYER_EXP_CHANGE: - { - logger->log("EXP Update"); - while (msg.getUnreadLength()) - { - int skill = msg.readInt16(); - int current = msg.readInt32(); - int next = msg.readInt32(); - int level = msg.readInt16(); - - PlayerInfo::setStatExperience(skill, current, next); - PlayerInfo::setStatBase(skill, level); - } - } break; - - case GPMSG_LEVELUP: - { - PlayerInfo::setAttribute(LEVEL, msg.readInt16()); + case GPMSG_ATTRIBUTE_POINTS_STATUS: PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16()); PlayerInfo::setAttribute(CORR_POINTS, msg.readInt16()); - Particle* effect = particleEngine->addEffect( - paths.getStringValue("particles") - + paths.getStringValue("levelUpEffectFile") - ,0, 0); - local_player->controlParticle(effect); - } break; - - - case GPMSG_LEVEL_PROGRESS: - { - PlayerInfo::setAttribute(EXP, msg.readInt8()); - } break; - + break; case GPMSG_RAISE_ATTRIBUTE_RESPONSE: { @@ -243,19 +215,24 @@ void PlayerHandler::handleMessage(MessageIn &msg) } break; - case GPMSG_SPECIAL_STATUS : + case GPMSG_ABILITY_STATUS: { - PlayerInfo::clearSpecialStatus(); while (msg.getUnreadLength()) { - // { B specialID, L current, L max, L recharge } int id = msg.readInt8(); int current = msg.readInt32(); int max = msg.readInt32(); int recharge = msg.readInt32(); - PlayerInfo::setSpecialStatus(id, current, max, recharge); + PlayerInfo::setAbilityStatus(id, current, max, recharge); } } break; + + case GPMSG_ABILITY_REMOVED: + { + int id = msg.readInt8(); + PlayerInfo::clearAbilityStatus(id); + } break; + /* case SMSG_PLAYER_ARROW_MESSAGE: { @@ -315,14 +292,31 @@ void PlayerHandler::handleMapChangeMessage(MessageIn &msg) void PlayerHandler::attack(int id) { - MessageOut msg(PGMSG_ATTACK); - msg.writeInt16(id); - gameServerConnection->send(msg); + auto ability = AbilityDB::find("Strike"); + if (!ability) + { + logger->log("PlayerHandler::attack: 'Strike' ability not found."); + return; + } + + switch (ability->targetMode) { + case AbilityInfo::TARGET_BEING: + abilityHandler->useOn(ability->id, id); + break; + case AbilityInfo::TARGET_POINT: + logger->log("PlayerHandler::attack: Unsupported target mode 'point' for 'Strike' ability."); + break; + case AbilityInfo::TARGET_DIRECTION: + abilityHandler->useInDirection(ability->id, local_player->getDirection()); + break; + } } void PlayerHandler::emote(int emoteId) { - // TODO + MessageOut msg(PGMSG_BEING_EMOTE); + msg.writeInt8(emoteId); + gameServerConnection->send(msg); } void PlayerHandler::increaseAttribute(int attr) diff --git a/src/net/manaserv/playerhandler.h b/src/net/manaserv/playerhandler.h index a6839112..134b449c 100644 --- a/src/net/manaserv/playerhandler.h +++ b/src/net/manaserv/playerhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_PLAYERHANDLER_H -#define NET_MANASERV_PLAYERHANDLER_H +#pragma once #include "net/playerhandler.h" @@ -77,5 +76,3 @@ class PlayerHandler final : public MessageHandler, public Net::PlayerHandler }; } // namespace ManaServ - -#endif // NET_MANASERV_PLAYERHANDLER_H diff --git a/src/net/manaserv/tradehandler.h b/src/net/manaserv/tradehandler.h index 928a62d9..374dde16 100644 --- a/src/net/manaserv/tradehandler.h +++ b/src/net/manaserv/tradehandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MANASERV_TRADEHANDLER_H -#define NET_MANASERV_TRADEHANDLER_H +#pragma once #include "net/tradehandler.h" @@ -72,5 +71,3 @@ class TradeHandler final : public MessageHandler, public Net::TradeHandler }; } // namespace ManaServ - -#endif // NET_MANASERV_TRADEHANDLER_H diff --git a/src/net/messagehandler.h b/src/net/messagehandler.h index 3bf6c419..21973fa9 100644 --- a/src/net/messagehandler.h +++ b/src/net/messagehandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_MESSAGEHANDLER_H -#define NET_MESSAGEHANDLER_H +#pragma once #include <cstdint> @@ -32,11 +31,12 @@ namespace Net { class MessageHandler { public: - const uint16_t *handledMessages; + const uint16_t *handledMessages = _no_messages; virtual ~MessageHandler() {} + + private: + static constexpr uint16_t _no_messages[] = { 0 }; }; } // namespace Net - -#endif // NET_MESSAGEHANDLER_H diff --git a/src/net/net.cpp b/src/net/net.cpp index 3a389db2..1d157b3d 100644 --- a/src/net/net.cpp +++ b/src/net/net.cpp @@ -34,7 +34,7 @@ #include "net/npchandler.h" #include "net/partyhandler.h" #include "net/playerhandler.h" -#include "net/specialhandler.h" +#include "net/abilityhandler.h" #include "net/tradehandler.h" #include "net/tmwa/generalhandler.h" @@ -54,7 +54,7 @@ Net::GuildHandler *guildHandler = nullptr; Net::NpcHandler *npcHandler = nullptr; Net::PartyHandler *partyHandler = nullptr; Net::PlayerHandler *playerHandler = nullptr; -Net::SpecialHandler *specialHandler = nullptr; +Net::AbilityHandler *abilityHandler = nullptr; Net::TradeHandler *tradeHandler = nullptr; Net::AdminHandler *Net::getAdminHandler() @@ -112,9 +112,9 @@ Net::PlayerHandler *Net::getPlayerHandler() return playerHandler; } -Net::SpecialHandler *Net::getSpecialHandler() +Net::AbilityHandler *Net::getAbilityHandler() { - return specialHandler; + return abilityHandler; } Net::TradeHandler *Net::getTradeHandler() @@ -124,18 +124,19 @@ Net::TradeHandler *Net::getTradeHandler() namespace Net { -ServerType networkType = ServerType::UNKNOWN; + +static ServerType networkType = ServerType::Unknown; void connectToServer(ServerInfo &server) { - if (server.type == ServerType::UNKNOWN) + if (server.type == ServerType::Unknown) { // TODO: Query the server about itself and choose the netcode based on // that if (server.port == 6901) - server.type = ServerType::TMWATHENA; + server.type = ServerType::TmwAthena; else if (server.port == 9601) - server.type = ServerType::MANASERV; + server.type = ServerType::ManaServ; else logger->error(_("Unknown Server Type! Exiting.")); } @@ -146,20 +147,17 @@ void connectToServer(ServerInfo &server) } else { - if (networkType != ServerType::UNKNOWN && getGeneralHandler() != nullptr) - { - getGeneralHandler()->unload(); - } + unload(); switch (server.type) { #ifdef MANASERV_SUPPORT - case ServerType::MANASERV: - new ManaServ::GeneralHandler; + case ServerType::ManaServ: + generalHandler = new ManaServ::GeneralHandler; break; #endif - case ServerType::TMWATHENA: - new TmwAthena::GeneralHandler; + case ServerType::TmwAthena: + generalHandler = new TmwAthena::GeneralHandler; break; default: logger->error(_("Server protocol unsupported")); @@ -178,10 +176,25 @@ void connectToServer(ServerInfo &server) void unload() { - if (GeneralHandler *handler = getGeneralHandler()) - { - handler->unload(); - } + if (!generalHandler) + return; + + generalHandler->unload(); + delete generalHandler; + + adminHandler = nullptr; + charHandler = nullptr; + chatHandler = nullptr; + generalHandler = nullptr; + inventoryHandler = nullptr; + loginHandler = nullptr; + gameHandler = nullptr; + guildHandler = nullptr; + npcHandler = nullptr; + partyHandler = nullptr; + playerHandler = nullptr; + abilityHandler = nullptr; + tradeHandler = nullptr; } ServerType getNetworkType() diff --git a/src/net/net.h b/src/net/net.h index 135f2cb7..ced0f7ba 100644 --- a/src/net/net.h +++ b/src/net/net.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_H -#define NET_H +#pragma once /** * \namespace Net @@ -45,7 +44,7 @@ class LoginHandler; class NpcHandler; class PartyHandler; class PlayerHandler; -class SpecialHandler; +class AbilityHandler; class TradeHandler; AdminHandler *getAdminHandler(); @@ -59,7 +58,7 @@ LoginHandler *getLoginHandler(); NpcHandler *getNpcHandler(); PartyHandler *getPartyHandler(); PlayerHandler *getPlayerHandler(); -SpecialHandler *getSpecialHandler(); +AbilityHandler *getAbilityHandler(); TradeHandler *getTradeHandler(); ServerType getNetworkType(); @@ -72,5 +71,3 @@ void connectToServer(ServerInfo &server); void unload(); } // namespace Net - -#endif // NET_H diff --git a/src/net/npchandler.h b/src/net/npchandler.h index ac575605..7eeb54f1 100644 --- a/src/net/npchandler.h +++ b/src/net/npchandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NPCHANDLER_H -#define NPCHANDLER_H +#pragma once #include <iosfwd> @@ -61,5 +60,3 @@ class NpcHandler }; } // namespace Net - -#endif // NPCHANDLER_H diff --git a/src/net/partyhandler.h b/src/net/partyhandler.h index 4e14ddbd..58871358 100644 --- a/src/net/partyhandler.h +++ b/src/net/partyhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef PARTYHANDLER_H -#define PARTYHANDLER_H +#pragma once #include <string> @@ -74,5 +73,3 @@ class PartyHandler }; } // namespace Net - -#endif // PARTYHANDLER_H diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h index 6187da2a..b9cf1abf 100644 --- a/src/net/playerhandler.h +++ b/src/net/playerhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef PLAYERHANDLER_H -#define PLAYERHANDLER_H +#pragma once #include "being.h" #include "flooritem.h" @@ -84,5 +83,3 @@ class PlayerHandler }; } // namespace Net - -#endif // PLAYERHANDLER_H diff --git a/src/net/serverinfo.h b/src/net/serverinfo.h index fd66c676..ad862427 100644 --- a/src/net/serverinfo.h +++ b/src/net/serverinfo.h @@ -19,10 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef SERVERINFO_H -#define SERVERINFO_H - -#include "utils/stringutils.h" +#pragma once #include <cstdint> #include <deque> @@ -30,9 +27,9 @@ enum class ServerType { - UNKNOWN, - MANASERV, - TMWATHENA + Unknown, + ManaServ, + TmwAthena }; class ServerInfo @@ -40,7 +37,7 @@ class ServerInfo public: using VersionString = std::pair<int, std::string>; - ServerType type = ServerType::UNKNOWN; + ServerType type = ServerType::Unknown; std::string name; std::string hostname; uint16_t port = 0; @@ -53,7 +50,7 @@ public: bool isValid() const { - return !hostname.empty() && port != 0 && type != ServerType::UNKNOWN; + return !hostname.empty() && port != 0 && type != ServerType::Unknown; } void clear() @@ -75,14 +72,14 @@ public: static ServerType parseType(const std::string &type) { - if (compareStrI(type, "tmwathena") == 0) - return ServerType::TMWATHENA; + if (type == "tmwathena") + return ServerType::TmwAthena; // Used for backward compatibility - if (compareStrI(type, "eathena") == 0) - return ServerType::TMWATHENA; - if (compareStrI(type, "manaserv") == 0) - return ServerType::MANASERV; - return ServerType::UNKNOWN; + if (type == "eathena") + return ServerType::TmwAthena; + if (type == "manaserv") + return ServerType::ManaServ; + return ServerType::Unknown; } static uint16_t defaultPortForServerType(ServerType type) @@ -90,11 +87,11 @@ public: switch (type) { default: - case ServerType::UNKNOWN: + case ServerType::Unknown: return 0; - case ServerType::TMWATHENA: + case ServerType::TmwAthena: return 6901; - case ServerType::MANASERV: + case ServerType::ManaServ: return 9601; } } @@ -102,13 +99,11 @@ public: static ServerType defaultServerTypeForPort(uint16_t port) { if (port == 6901) - return ServerType::TMWATHENA; + return ServerType::TmwAthena; if (port == 9601) - return ServerType::MANASERV; - return ServerType::UNKNOWN; + return ServerType::ManaServ; + return ServerType::Unknown; } }; using ServerInfos = std::deque<ServerInfo>; - -#endif // SERVERINFO_H diff --git a/src/net/tmwa/specialhandler.cpp b/src/net/tmwa/abilityhandler.cpp index 2e22b00a..ab891b40 100644 --- a/src/net/tmwa/specialhandler.cpp +++ b/src/net/tmwa/abilityhandler.cpp @@ -19,7 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "net/tmwa/specialhandler.h" +#include "net/tmwa/abilityhandler.h" #include "event.h" #include "log.h" @@ -64,11 +64,11 @@ /** should always be zero if failed */ #define SKILL_FAILED 0x00 -extern Net::SpecialHandler *specialHandler; +extern Net::AbilityHandler *abilityHandler; namespace TmwAthena { -SpecialHandler::SpecialHandler() +AbilityHandler::AbilityHandler() { static const Uint16 _messages[] = { SMSG_PLAYER_SKILLS, @@ -77,23 +77,20 @@ SpecialHandler::SpecialHandler() 0 }; handledMessages = _messages; - specialHandler = this; + abilityHandler = this; } -void SpecialHandler::handleMessage(MessageIn &msg) +void AbilityHandler::handleMessage(MessageIn &msg) { - int skillCount; - int skillId; - switch (msg.getId()) { - case SMSG_PLAYER_SKILLS: + case SMSG_PLAYER_SKILLS: { msg.readInt16(); // length - skillCount = (msg.getLength() - 4) / 37; + const int skillCount = (msg.getLength() - 4) / 37; for (int k = 0; k < skillCount; k++) { - skillId = msg.readInt16(); + int skillId = msg.readInt16(); msg.readInt16(); // target type msg.skip(2); // unused int level = msg.readInt16(); @@ -107,10 +104,11 @@ void SpecialHandler::handleMessage(MessageIn &msg) skillDialog->setModifiable(skillId, up); } break; + } case SMSG_PLAYER_SKILL_UP: { - skillId = msg.readInt16(); + int skillId = msg.readInt16(); int level = msg.readInt16(); msg.readInt16(); // sp msg.readInt16(); // range @@ -124,20 +122,20 @@ void SpecialHandler::handleMessage(MessageIn &msg) case SMSG_SKILL_FAILED: // Action failed (ex. sit because you have not reached the // right level) - skillId = msg.readInt16(); - short bskill = msg.readInt16(); - msg.readInt16(); // unknown - char success = msg.readInt8(); - char reason = msg.readInt8(); - if (success != SKILL_FAILED && bskill == BSKILL_EMOTE) + int skillId = msg.readInt16(); + auto btype = msg.readInt16(); + msg.readInt16(); // zero1 + msg.readInt8(); // zero2 + auto type = msg.readInt8(); + if (btype == BSKILL_EMOTE) { - logger->log("Action: %d/%d", bskill, success); + logger->log("Action: %d", btype); } std::string msg; - if (success == SKILL_FAILED && skillId == SKILL_BASIC) + if (skillId == SKILL_BASIC) { - switch (bskill) + switch (btype) { case BSKILL_TRADE: msg = _("Trade failed!"); @@ -161,7 +159,7 @@ void SpecialHandler::handleMessage(MessageIn &msg) msg += " "; - switch (reason) + switch (type) { case RFAIL_SKILLDEP: msg += _("You have not yet reached a high enough lvl!"); @@ -219,19 +217,19 @@ void SpecialHandler::handleMessage(MessageIn &msg) } } -void SpecialHandler::use(int id) +void AbilityHandler::use(int id) { } -void SpecialHandler::use(int id, int level, int beingId) +void AbilityHandler::useOn(int id, int beingId) { } -void SpecialHandler::use(int id, int level, int x, int y) +void AbilityHandler::useAt(int id, int x, int y) { } -void SpecialHandler::use(int id, const std::string &map) +void AbilityHandler::useInDirection(int id, int direction) { } diff --git a/src/net/tmwa/specialhandler.h b/src/net/tmwa/abilityhandler.h index 09b6ce8d..171f7d41 100644 --- a/src/net/tmwa/specialhandler.h +++ b/src/net/tmwa/abilityhandler.h @@ -19,32 +19,29 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_SKILLHANDLER_H -#define NET_TA_SKILLHANDLER_H +#pragma once #include "net/net.h" -#include "net/specialhandler.h" +#include "net/abilityhandler.h" #include "net/tmwa/messagehandler.h" namespace TmwAthena { -class SpecialHandler final : public MessageHandler, public Net::SpecialHandler +class AbilityHandler final : public MessageHandler, public Net::AbilityHandler { public: - SpecialHandler(); + AbilityHandler(); void handleMessage(MessageIn &msg) override; void use(int id) override; - void use(int id, int level, int beingId) override; + void useOn(int id, int beingId) override; - void use(int id, int level, int x, int y) override; + void useAt(int id, int x, int y) override; - void use(int id, const std::string &map) override; + void useInDirection(int id, int direction) override; }; } // namespace TmwAthena - -#endif // NET_TA_SKILLHANDLER_H diff --git a/src/net/tmwa/adminhandler.cpp b/src/net/tmwa/adminhandler.cpp index c60050bd..4c4ecdad 100644 --- a/src/net/tmwa/adminhandler.cpp +++ b/src/net/tmwa/adminhandler.cpp @@ -68,10 +68,7 @@ void AdminHandler::handleMessage(MessageIn &msg) id = msg.readInt32(); int ip = msg.readInt32(); if (Being *player = actorSpriteManager->findBeing(id)) - { player->setIp(ip); - player->updateName(); - } break; } } diff --git a/src/net/tmwa/adminhandler.h b/src/net/tmwa/adminhandler.h index 17d547a8..6a233823 100644 --- a/src/net/tmwa/adminhandler.h +++ b/src/net/tmwa/adminhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_ADMINHANDLER_H -#define NET_TA_ADMINHANDLER_H +#pragma once #include "net/adminhandler.h" #include "net/net.h" @@ -44,5 +43,3 @@ class AdminHandler final : public MessageHandler, public Net::AdminHandler }; } // namespace TmwAthena - -#endif // NET_TA_ADMINHANDLER_H diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index e2c4f158..c5979e9f 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -40,6 +40,7 @@ #include "resources/emotedb.h" #include "resources/hairdb.h" +#include "resources/statuseffectdb.h" #include <cmath> @@ -78,29 +79,51 @@ BeingHandler::BeingHandler(bool enableSync): handledMessages = _messages; } -static Being *createBeing(int id, short job) +static ActorSprite::Type typeFromJob(short job) { - ActorSprite::Type type = ActorSprite::UNKNOWN; if (job <= 25 || (job >= 4001 && job <= 4049)) - type = ActorSprite::PLAYER; - else if (job >= 46 && job <= 1000) - type = ActorSprite::NPC; - else if (job > 1000 && job <= 2000) - type = ActorSprite::MONSTER; - else if (job == 45) + return ActorSprite::PLAYER; + if (job >= 46 && job <= 1000) + return ActorSprite::NPC; + if (job > 1000 && job <= 2000) + return ActorSprite::MONSTER; + if (job == 45) + return ActorSprite::PORTAL; + + return ActorSprite::UNKNOWN; +} + +static Being *createBeing(int id, short job) +{ + const auto type = typeFromJob(job); + if (type == ActorSprite::PORTAL) return nullptr; // Skip portals Being *being = actorSpriteManager->createBeing(id, type, job); if (type == ActorSprite::PLAYER || type == ActorSprite::NPC) { - MessageOut outMsg(0x0094); - outMsg.writeInt32(id);//readLong(2)); + MessageOut outMsg(CMSG_NAME_REQUEST); + outMsg.writeInt32(id); } return being; } +static void updateBeingType(Being *being, short job) +{ + const auto type = typeFromJob(job); + const bool typeChanged = being->getType() != type; + + being->setType(type, job); + + if (typeChanged && type == ActorSprite::PLAYER) + { + MessageOut outMsg(CMSG_NAME_REQUEST); + outMsg.writeInt32(being->getId()); + } +} + static void handleMoveMessage(Map *map, Being *dstBeing, Uint16 srcX, Uint16 srcY, Uint16 dstX, Uint16 dstY) @@ -146,6 +169,42 @@ static void handlePosMessage(Map *map, Being *dstBeing, Uint16 x, Uint16 y, } } +static void applyStatusEffectsByOption1(Being *being, + const StatusEffectDB::OptionsMap &map, + uint16_t option) +{ + for (auto &[opt, id] : map) + being->setStatusEffect(id, option == opt); +} + +static void applyStatusEffectsByOption(Being *being, + const StatusEffectDB::OptionsMap &map, + uint16_t option) +{ + for (auto &[opt, id] : map) + { + const bool enabled = (option & opt) != 0; + being->setStatusEffect(id, enabled); + } +} + +/** + * Maps flags or indexes to their corresponding status effect index and + * updates the state of the given being. This is tmwAthena-specific. + */ +static void applyStatusEffects(Being *being, + uint16_t opt0, + uint16_t opt1, + uint16_t opt2, + std::optional<uint16_t> opt3 = {}) +{ + applyStatusEffectsByOption(being, StatusEffectDB::opt0ToIdMap(), opt0); + applyStatusEffectsByOption1(being, StatusEffectDB::opt1ToIdMap(), opt1); + applyStatusEffectsByOption(being, StatusEffectDB::opt2ToIdMap(), opt2); + if (opt3) + applyStatusEffectsByOption(being, StatusEffectDB::opt3ToIdMap(), *opt3); +} + void BeingHandler::handleMessage(MessageIn &msg) { if (!actorSpriteManager) @@ -159,8 +218,10 @@ void BeingHandler::handleMessage(MessageIn &msg) Uint16 weapon, shield; Uint16 gmstatus; int param1; - int stunMode; - Uint32 statusEffects; + uint16_t opt0; + uint16_t opt1; + uint16_t opt2; + uint16_t opt3; int type, guild; Uint16 status; Being *srcBeing, *dstBeing; @@ -176,9 +237,9 @@ void BeingHandler::handleMessage(MessageIn &msg) // Information about a being in range id = msg.readInt32(); speed = (float)msg.readInt16(); - stunMode = msg.readInt16(); // opt1 - statusEffects = msg.readInt16(); // opt2 - statusEffects |= ((Uint32)msg.readInt16()) << 16; // option + opt1 = msg.readInt16(); + opt2 = msg.readInt16(); + opt0 = msg.readInt16(); job = msg.readInt16(); // class dstBeing = actorSpriteManager->findBeing(id); @@ -209,7 +270,7 @@ void BeingHandler::handleMessage(MessageIn &msg) speed = 150.0f; // In ticks per tile * 10 dstBeing->setMoveSpeed(Vector(speed / 10, speed / 10)); - dstBeing->setSubtype(job); + updateBeingType(dstBeing, job); hairStyle = msg.readInt16(); weapon = msg.readInt16(); headBottom = msg.readInt16(); @@ -236,14 +297,14 @@ void BeingHandler::handleMessage(MessageIn &msg) } msg.readInt16(); // guild emblem msg.readInt16(); // manner - dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3 + opt3 = msg.readInt16(); msg.readInt8(); // karma gender = msg.readInt8(); if (dstBeing->getType() == ActorSprite::PLAYER) { - dstBeing->setGender(gender == 0 ? Gender::FEMALE - : Gender::MALE); + dstBeing->setGender(gender == 0 ? Gender::Female + : Gender::Male); // Set these after the gender, as the sprites may be gender-specific dstBeing->setSprite(SPRITE_HAIR, hairStyle * -1, hairDB.getHairColor(hairColor)); @@ -274,9 +335,7 @@ void BeingHandler::handleMessage(MessageIn &msg) msg.readInt8(); // unknown msg.readInt8(); // unknown / sit - dstBeing->setStunMode(stunMode); - dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff); - dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff); + applyStatusEffects(dstBeing, opt0, opt1, opt2, opt3); break; case SMSG_BEING_SPAWN: @@ -417,6 +476,9 @@ void BeingHandler::handleMessage(MessageIn &msg) switch (type) { + case LOOK::BASE: + updateBeingType(dstBeing, id); + break; case LOOK::HAIR: { // const int look = id / 256; @@ -505,10 +567,9 @@ void BeingHandler::handleMessage(MessageIn &msg) // An update about a player, potentially including movement. id = msg.readInt32(); speed = msg.readInt16(); - stunMode = msg.readInt16(); // opt1; Aethyra use this as cape - statusEffects = msg.readInt16(); // opt2; Aethyra use this as misc1 - statusEffects |= ((Uint32) msg.readInt16()) - << 16; // status.options; Aethyra uses this as misc2 + opt1 = msg.readInt16(); + opt2 = msg.readInt16(); + opt0 = msg.readInt16(); job = msg.readInt16(); dstBeing = actorSpriteManager->findBeing(id); @@ -531,7 +592,7 @@ void BeingHandler::handleMessage(MessageIn &msg) else dstBeing->setMoveSpeed(Net::getPlayerHandler()->getDefaultMoveSpeed()); - dstBeing->setSubtype(job); + updateBeingType(dstBeing, job); hairStyle = msg.readInt16(); weapon = msg.readInt16(); shield = msg.readInt16(); @@ -545,15 +606,16 @@ void BeingHandler::handleMessage(MessageIn &msg) headTop = msg.readInt16(); headMid = msg.readInt16(); hairColor = msg.readInt16(); - shoes = msg.readInt16(); - gloves = msg.readInt16(); + msg.readInt16(); // clothes_color + msg.readInt8(); // head_dir + msg.readInt8(); // unused2 msg.readInt32(); // guild msg.readInt16(); // emblem msg.readInt16(); // manner - dstBeing->setStatusEffectBlock(32, msg.readInt16()); // opt3 + opt3 = msg.readInt16(); msg.readInt8(); // karma - dstBeing->setGender(msg.readInt8() == 0 ? Gender::FEMALE - : Gender::MALE); + dstBeing->setGender(msg.readInt8() == 0 ? Gender::Female + : Gender::Male); // Set these after the gender, as the sprites may be gender-specific dstBeing->setSprite(SPRITE_WEAPON, weapon, "", true); dstBeing->setSprite(SPRITE_SHIELD, shield); @@ -601,15 +663,13 @@ void BeingHandler::handleMessage(MessageIn &msg) } else if (msg.getId() == SMSG_PLAYER_MOVE) { - msg.readInt8(); // unknown + msg.readInt8(); // five } msg.readInt8(); // Lv - msg.readInt8(); // unknown + msg.readInt8(); // unused - dstBeing->setStunMode(stunMode); - dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff); - dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff); + applyStatusEffects(dstBeing, opt0, opt1, opt2, opt3); break; case SMSG_PLAYER_STOP: @@ -654,14 +714,12 @@ void BeingHandler::handleMessage(MessageIn &msg) if (!dstBeing) break; - stunMode = msg.readInt16(); - statusEffects = msg.readInt16(); - statusEffects |= ((Uint32) msg.readInt16()) << 16; - msg.readInt8(); // Unused? + opt1 = msg.readInt16(); + opt2 = msg.readInt16(); + opt0 = msg.readInt16(); + msg.readInt8(); // zero - dstBeing->setStunMode(stunMode); - dstBeing->setStatusEffectBlock(0, (statusEffects >> 16) & 0xffff); - dstBeing->setStatusEffectBlock(16, statusEffects & 0xffff); + applyStatusEffects(dstBeing, opt0, opt1, opt2); break; case SMSG_BEING_STATUS_CHANGE: diff --git a/src/net/tmwa/beinghandler.h b/src/net/tmwa/beinghandler.h index f1c8887f..fd8f08f5 100644 --- a/src/net/tmwa/beinghandler.h +++ b/src/net/tmwa/beinghandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_BEINGHANDLER_H -#define NET_TA_BEINGHANDLER_H +#pragma once #include "net/tmwa/messagehandler.h" @@ -39,5 +38,3 @@ class BeingHandler final : public MessageHandler }; } // namespace TmwAthena - -#endif // NET_TA_BEINGHANDLER_H diff --git a/src/net/tmwa/buysellhandler.cpp b/src/net/tmwa/buysellhandler.cpp index 1fdf1ffe..d7acd674 100644 --- a/src/net/tmwa/buysellhandler.cpp +++ b/src/net/tmwa/buysellhandler.cpp @@ -99,7 +99,7 @@ void BuySellHandler::handleMessage(MessageIn &msg) Item *item = PlayerInfo::getInventory()->getItem(index); - if (item && !(item->isEquipped())) + if (item && !item->isEquipped()) dialog->addItem(item, value); } } diff --git a/src/net/tmwa/buysellhandler.h b/src/net/tmwa/buysellhandler.h index 8f7a324f..cad9f943 100644 --- a/src/net/tmwa/buysellhandler.h +++ b/src/net/tmwa/buysellhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_BUYSELLHANDLER_H -#define NET_TA_BUYSELLHANDLER_H +#pragma once #include "net/tmwa/messagehandler.h" @@ -41,5 +40,3 @@ class BuySellHandler final : public MessageHandler }; } // namespace TmwAthena - -#endif // NET_TA_BUYSELLHANDLER_H diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index 636b58ce..0ecbb135 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -28,7 +28,6 @@ #include "gui/charcreatedialog.h" #include "gui/okdialog.h" -#include "net/logindata.h" #include "net/net.h" #include "net/tmwa/gamehandler.h" @@ -210,21 +209,20 @@ void CharServerHandler::readPlayerData(MessageIn &msg, Net::Character *character const Token &token = static_cast<LoginHandler*>(Net::getLoginHandler())->getToken(); - auto *tempPlayer = new LocalPlayer(msg.readInt32(), 0); - tempPlayer->setGender(token.sex); + const int id = msg.readInt32(); character->data.mAttributes[EXP] = msg.readInt32(); character->data.mAttributes[MONEY] = msg.readInt32(); character->data.mStats[JOB].exp = msg.readInt32(); - int temp = msg.readInt32(); + const int temp = msg.readInt32(); character->data.mStats[JOB].base = temp; character->data.mStats[JOB].mod = temp; - tempPlayer->setSprite(SPRITE_SHOE, msg.readInt16()); - tempPlayer->setSprite(SPRITE_GLOVES, msg.readInt16()); - tempPlayer->setSprite(SPRITE_CAPE, msg.readInt16()); - tempPlayer->setSprite(SPRITE_MISC1, msg.readInt16()); + const int shoe = msg.readInt16(); + const int gloves = msg.readInt16(); + const int cape = msg.readInt16(); + const int misc1 = msg.readInt16(); msg.readInt32(); // option msg.readInt32(); // karma @@ -240,8 +238,15 @@ void CharServerHandler::readPlayerData(MessageIn &msg, Net::Character *character const uint16_t race = msg.readInt16(); // class (used for race) int hairStyle = msg.readInt8(); msg.readInt8(); // look - tempPlayer->setSubtype(race); - Uint16 weapon = msg.readInt16(); + const uint16_t weapon = msg.readInt16(); + + auto *tempPlayer = new LocalPlayer(id, race); + tempPlayer->setGender(token.sex); + + tempPlayer->setSprite(SPRITE_SHOE, shoe); + tempPlayer->setSprite(SPRITE_GLOVES, gloves); + tempPlayer->setSprite(SPRITE_CAPE, cape); + tempPlayer->setSprite(SPRITE_MISC1, misc1); tempPlayer->setSprite(SPRITE_WEAPON, weapon, "", true); character->data.mAttributes[LEVEL] = msg.readInt16(); @@ -263,7 +268,7 @@ void CharServerHandler::readPlayerData(MessageIn &msg, Net::Character *character character->slot = msg.readInt8(); // character slot const uint8_t sex = msg.readInt8(); - tempPlayer->setGender(sex ? Gender::MALE : Gender::FEMALE); + tempPlayer->setGender(sex ? Gender::Male : Gender::Female); } void CharServerHandler::setCharSelectDialog(CharSelectDialog *window) @@ -395,7 +400,7 @@ void CharServerHandler::connect() // [Fate] The next word is unused by the old char server, so we squeeze in // mana client version information outMsg.writeInt16(CLIENT_PROTOCOL_VERSION); - outMsg.writeInt8(token.sex == Gender::MALE ? 1 : 0); + outMsg.writeInt8(token.sex == Gender::Male ? 1 : 0); // We get 4 useless bytes before the real answer comes in (what are these?) mNetwork->skip(4); diff --git a/src/net/tmwa/charserverhandler.h b/src/net/tmwa/charserverhandler.h index 9633c8d9..b0d3e970 100644 --- a/src/net/tmwa/charserverhandler.h +++ b/src/net/tmwa/charserverhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_CHARSERVERHANDLER_H -#define NET_TA_CHARSERVERHANDLER_H +#pragma once #include "net/charhandler.h" @@ -75,9 +74,7 @@ class CharServerHandler final : public MessageHandler, public Net::CharHandler void connect(); private: - void readPlayerData(MessageIn &msg, Net::Character *character); + static void readPlayerData(MessageIn &msg, Net::Character *character); }; } // namespace TmwAthena - -#endif // NET_TA_CHARSERVERHANDLER_H diff --git a/src/net/tmwa/chathandler.cpp b/src/net/tmwa/chathandler.cpp index 4f998922..cce5a41d 100644 --- a/src/net/tmwa/chathandler.cpp +++ b/src/net/tmwa/chathandler.cpp @@ -193,7 +193,10 @@ void ChatHandler::handleMessage(MessageIn &msg) trim(chatMsg); std::string reducedMessage = chatMsg; - chatMsg = removeColors(sender_name) + " : " + reducedMessage; + chatMsg = sender_name; + removeColors(chatMsg); + chatMsg += " : "; + chatMsg += reducedMessage; Event event(Event::Being); event.setString("message", chatMsg); @@ -271,7 +274,7 @@ void ChatHandler::handleMessage(MessageIn &msg) msg.readInt8(); // gm level msg.readInt8(); // gender - Avatar *avatar = new Avatar(nick); + auto *avatar = new Avatar(nick); avatar->setOnline(true); players.push_back(avatar); } diff --git a/src/net/tmwa/chathandler.h b/src/net/tmwa/chathandler.h index d545b221..b16b3dc4 100644 --- a/src/net/tmwa/chathandler.h +++ b/src/net/tmwa/chathandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_CHATHANDLER_H -#define NET_TA_CHATHANDLER_H +#pragma once #include "net/chathandler.h" #include "net/net.h" @@ -73,5 +72,3 @@ class ChatHandler final : public MessageHandler, public Net::ChatHandler }; } // namespace TmwAthena - -#endif // NET_TA_CHATHANDLER_H diff --git a/src/net/tmwa/gamehandler.cpp b/src/net/tmwa/gamehandler.cpp index abc9c73c..0a3bb9d9 100644 --- a/src/net/tmwa/gamehandler.cpp +++ b/src/net/tmwa/gamehandler.cpp @@ -140,7 +140,7 @@ void GameHandler::connect() outMsg.writeInt32(mCharID); outMsg.writeInt32(token.session_ID1); outMsg.writeInt32(token.session_ID2); - outMsg.writeInt8(token.sex == Gender::MALE ? 1 : 0); + outMsg.writeInt8(token.sex == Gender::Male ? 1 : 0); // We get 4 useless bytes before the real answer comes in (what are these?) mNetwork->skip(4); diff --git a/src/net/tmwa/gamehandler.h b/src/net/tmwa/gamehandler.h index ecd8df2d..2f876b82 100644 --- a/src/net/tmwa/gamehandler.h +++ b/src/net/tmwa/gamehandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_MAPHANDLER_H -#define NET_TA_MAPHANDLER_H +#pragma once #include "eventlistener.h" @@ -74,5 +73,3 @@ class GameHandler final : public MessageHandler, public Net::GameHandler, }; } // namespace TmwAthena - -#endif // NET_TA_MAPHANDLER_H diff --git a/src/net/tmwa/generalhandler.cpp b/src/net/tmwa/generalhandler.cpp index e1b1a9ea..d6eb3b34 100644 --- a/src/net/tmwa/generalhandler.cpp +++ b/src/net/tmwa/generalhandler.cpp @@ -25,7 +25,6 @@ #include "configuration.h" #include "log.h" -#include "gui/inventorywindow.h" #include "gui/skilldialog.h" #include "gui/socialwindow.h" #include "gui/statuswindow.h" @@ -49,7 +48,7 @@ #include "net/tmwa/playerhandler.h" #include "net/tmwa/protocol.h" #include "net/tmwa/tradehandler.h" -#include "net/tmwa/specialhandler.h" +#include "net/tmwa/abilityhandler.h" #include "net/tmwa/gui/guildtab.h" #include "net/tmwa/gui/partytab.h" @@ -60,8 +59,6 @@ #include <list> -extern Net::GeneralHandler *generalHandler; - namespace TmwAthena { ServerInfo charServer; @@ -84,7 +81,7 @@ GeneralHandler::GeneralHandler(): mNpcHandler(new NpcHandler), mPartyHandler(new PartyHandler), mPlayerHandler(new PlayerHandler), - mSpecialHandler(new SpecialHandler), + mAbilityHandler(new AbilityHandler), mTradeHandler(new TradeHandler) { static const Uint16 _messages[] = { @@ -92,7 +89,6 @@ GeneralHandler::GeneralHandler(): 0 }; handledMessages = _messages; - generalHandler = this; std::list<ItemStat> stats; stats.emplace_back("str", _("Strength %+d")); @@ -155,6 +151,7 @@ void GeneralHandler::handleMessage(MessageIn &msg) void GeneralHandler::load() { + // This sets mNetwork to the created Network instance (new Network)->registerHandler(this); mNetwork->registerHandler(mAdminHandler.get()); @@ -169,7 +166,7 @@ void GeneralHandler::load() mNetwork->registerHandler(mLoginHandler.get()); mNetwork->registerHandler(mNpcHandler.get()); mNetwork->registerHandler(mPlayerHandler.get()); - mNetwork->registerHandler(mSpecialHandler.get()); + mNetwork->registerHandler(mAbilityHandler.get()); mNetwork->registerHandler(mTradeHandler.get()); mNetwork->registerHandler(mPartyHandler.get()); } @@ -209,11 +206,6 @@ void GeneralHandler::flushNetwork() } } -void GeneralHandler::clearHandlers() -{ - mNetwork->clearHandlers(); -} - void GeneralHandler::event(Event::Channel channel, const Event &event) { @@ -221,7 +213,6 @@ void GeneralHandler::event(Event::Channel channel, { if (event.getType() == Event::GuiWindowsLoaded) { - inventoryWindow->setSplitAllowed(false); skillDialog->loadSkills(); statusWindow->addAttribute(STRENGTH, _("Strength"), true, ""); diff --git a/src/net/tmwa/generalhandler.h b/src/net/tmwa/generalhandler.h index f105da96..1da81ba8 100644 --- a/src/net/tmwa/generalhandler.h +++ b/src/net/tmwa/generalhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TMWA_GENERALHANDLER_H -#define NET_TMWA_GENERALHANDLER_H +#pragma once #include "eventlistener.h" @@ -49,8 +48,6 @@ class GeneralHandler final : public MessageHandler, public Net::GeneralHandler, void flushNetwork() override; - void clearHandlers() override; - void event(Event::Channel channel, const Event &event) override; protected: @@ -67,10 +64,8 @@ class GeneralHandler final : public MessageHandler, public Net::GeneralHandler, MessageHandlerPtr mNpcHandler; MessageHandlerPtr mPartyHandler; MessageHandlerPtr mPlayerHandler; - MessageHandlerPtr mSpecialHandler; + MessageHandlerPtr mAbilityHandler; MessageHandlerPtr mTradeHandler; }; } // namespace TmwAthena - -#endif // NET_TMWA_GENERALHANDLER_H diff --git a/src/net/tmwa/gui/guildtab.h b/src/net/tmwa/gui/guildtab.h index 3f864748..c51e63d0 100644 --- a/src/net/tmwa/gui/guildtab.h +++ b/src/net/tmwa/gui/guildtab.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef TA_GUILDTAB_H -#define TA_GUILDTAB_H +#pragma once #include "gui/widgets/chattab.h" @@ -49,5 +48,3 @@ class GuildTab : public ChatTab extern GuildTab *guildTab; } // namespace TmwAthena - -#endif // TA_GUILDTAB_H diff --git a/src/net/tmwa/gui/partytab.cpp b/src/net/tmwa/gui/partytab.cpp index 418e0843..ee29757a 100644 --- a/src/net/tmwa/gui/partytab.cpp +++ b/src/net/tmwa/gui/partytab.cpp @@ -32,14 +32,13 @@ #include "resources/theme.h" #include "utils/gettext.h" -#include "utils/stringutils.h" namespace TmwAthena { PartyTab::PartyTab() : ChatTab(_("Party")) { - setTabColor(&Theme::getThemeColor(Theme::PARTY_CHAT_TAB)); + setTabColor(&Theme::getThemeColor(Theme::PARTY_TAB)); } void PartyTab::handleInput(const std::string &msg) diff --git a/src/net/tmwa/gui/partytab.h b/src/net/tmwa/gui/partytab.h index a6c52f58..39a1f978 100644 --- a/src/net/tmwa/gui/partytab.h +++ b/src/net/tmwa/gui/partytab.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef TA_PARTYTAB_H -#define TA_PARTYTAB_H +#pragma once #include "gui/widgets/chattab.h" @@ -49,5 +48,3 @@ class PartyTab : public ChatTab extern PartyTab *partyTab; } // namespace TmwAthena - -#endif // TA_PARTYTAB_H diff --git a/src/net/tmwa/guildhandler.cpp b/src/net/tmwa/guildhandler.cpp index 1877f0f1..e8ee4848 100644 --- a/src/net/tmwa/guildhandler.cpp +++ b/src/net/tmwa/guildhandler.cpp @@ -40,11 +40,6 @@ Guild *taGuild; GuildHandler::GuildHandler() { - static const Uint16 _messages[] = { - 0 - }; - handledMessages = _messages; - guildHandler = this; } diff --git a/src/net/tmwa/guildhandler.h b/src/net/tmwa/guildhandler.h index 9bbe9b4a..6faca0cc 100644 --- a/src/net/tmwa/guildhandler.h +++ b/src/net/tmwa/guildhandler.h @@ -18,8 +18,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_GUILDHANDLER_H -#define NET_TA_GUILDHANDLER_H +#pragma once #include "net/guildhandler.h" @@ -67,5 +66,3 @@ class GuildHandler final : public Net::GuildHandler, public MessageHandler }; } - -#endif // NET_TA_GUILDHANDLER_H diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp index 496ce621..0d8e3005 100644 --- a/src/net/tmwa/inventoryhandler.cpp +++ b/src/net/tmwa/inventoryhandler.cpp @@ -521,11 +521,6 @@ void InventoryHandler::event(Event::Channel channel, } } -bool InventoryHandler::canSplit(const Item *item) -{ - return false; -} - size_t InventoryHandler::getSize(int type) const { switch (type) diff --git a/src/net/tmwa/inventoryhandler.h b/src/net/tmwa/inventoryhandler.h index 51a0fe51..f5ef4492 100644 --- a/src/net/tmwa/inventoryhandler.h +++ b/src/net/tmwa/inventoryhandler.h @@ -19,11 +19,11 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_INVENTORYHANDLER_H -#define NET_TA_INVENTORYHANDLER_H +#pragma once #include "eventlistener.h" #include "inventory.h" +#include "item.h" #include "log.h" #include "playerinfo.h" @@ -38,7 +38,7 @@ #include "utils/gettext.h" -#include <list> +#include <vector> namespace TmwAthena { @@ -166,8 +166,6 @@ class InventoryHandler final : public MessageHandler, public Net::InventoryHandl void event(Event::Channel channel, const Event &event) override; - bool canSplit(const Item *item) override; - size_t getSize(int type) const override; // Note the slot type id is equal to the slot Index for tA. @@ -195,5 +193,3 @@ class InventoryHandler final : public MessageHandler, public Net::InventoryHandl }; } // namespace TmwAthena - -#endif // NET_TA_INVENTORYHANDLER_H diff --git a/src/net/tmwa/itemhandler.h b/src/net/tmwa/itemhandler.h index 0c6175d8..5e42e0d8 100644 --- a/src/net/tmwa/itemhandler.h +++ b/src/net/tmwa/itemhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_ITEMHANDLER_H -#define NET_TA_ITEMHANDLER_H +#pragma once #include "net/tmwa/messagehandler.h" @@ -35,5 +34,3 @@ class ItemHandler final : public MessageHandler }; } // namespace TmwAthena - -#endif // NET_TA_ITEMHANDLER_H diff --git a/src/net/tmwa/loginhandler.cpp b/src/net/tmwa/loginhandler.cpp index 24bc9ab2..a7162ee6 100644 --- a/src/net/tmwa/loginhandler.cpp +++ b/src/net/tmwa/loginhandler.cpp @@ -103,17 +103,15 @@ void LoginHandler::handleMessage(MessageIn &msg) } break; - case SMSG_UPDATE_HOST: - int len; - - len = msg.readInt16() - 4; + case SMSG_UPDATE_HOST: { + int len = msg.readInt16() - 4; mUpdateHost = msg.readString(len); loginData.updateHost = mUpdateHost; logger->log("Received update host \"%s\" from login server.", mUpdateHost.c_str()); break; - + } case SMSG_LOGIN_DATA: // Skip the length word msg.skip(2); @@ -126,7 +124,7 @@ void LoginHandler::handleMessage(MessageIn &msg) mToken.account_ID = msg.readInt32(); mToken.session_ID2 = msg.readInt32(); msg.skip(30); // unused - mToken.sex = msg.readInt8() ? Gender::MALE : Gender::FEMALE; + mToken.sex = msg.readInt8() ? Gender::Male : Gender::Female; for (int i = 0; i < worldCount; i++) { @@ -306,7 +304,7 @@ void LoginHandler::chooseServer(unsigned int server) void LoginHandler::registerAccount(LoginData *loginData) { std::string username = loginData->username; - username.append(loginData->gender == Gender::FEMALE ? "_F" : "_M"); + username.append(loginData->gender == Gender::Female ? "_F" : "_M"); sendLoginRegister(username, loginData->password); } diff --git a/src/net/tmwa/loginhandler.h b/src/net/tmwa/loginhandler.h index 25dd414d..f6b8a530 100644 --- a/src/net/tmwa/loginhandler.h +++ b/src/net/tmwa/loginhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TMWA_LOGINHANDLER_H -#define NET_TMWA_LOGINHANDLER_H +#pragma once #include "net/loginhandler.h" @@ -94,5 +93,3 @@ class LoginHandler final : public MessageHandler, public Net::LoginHandler }; } // namespace TmwAthena - -#endif // NET_TA_LOGINHANDLER_H diff --git a/src/net/tmwa/messagehandler.h b/src/net/tmwa/messagehandler.h index 0d278c15..8e3c6a19 100644 --- a/src/net/tmwa/messagehandler.h +++ b/src/net/tmwa/messagehandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_MESSAGEHANDLER_H -#define NET_TA_MESSAGEHANDLER_H +#pragma once #include "net/messagehandler.h" @@ -52,5 +51,3 @@ class MessageHandler : public Net::MessageHandler using MessageHandlerPtr = const std::unique_ptr<MessageHandler>; } - -#endif // NET_TA_MESSAGEHANDLER_H diff --git a/src/net/tmwa/messagein.cpp b/src/net/tmwa/messagein.cpp index 7c142619..c0db0fca 100644 --- a/src/net/tmwa/messagein.cpp +++ b/src/net/tmwa/messagein.cpp @@ -21,6 +21,9 @@ #include "net/tmwa/messagein.h" +#include "being.h" +#include "net/tmwa/protocol.h" + #include <SDL_endian.h> #define MAKEWORD(low,high) \ @@ -88,38 +91,20 @@ void MessageIn::readCoordinates(uint16_t &x, uint16_t &y, uint8_t &direction) direction = data[2] & 0x000f; // Translate from tmwAthena format - switch (direction) + switch (static_cast<DIR>(direction)) { - case 0: - direction = 1; - break; - case 1: - direction = 3; - break; - case 2: - direction = 2; - break; - case 3: - direction = 6; - break; - case 4: - direction = 4; - break; - case 5: - direction = 12; - break; - case 6: - direction = 8; - break; - case 7: - direction = 9; - break; - case 8: - direction = 8; - break; + case DIR::S: direction = Being::DOWN; break; + case DIR::SW: direction = Being::DOWN | Being::LEFT; break; + case DIR::W: direction = Being::LEFT; break; + case DIR::NW: direction = Being::UP | Being::LEFT; break; + case DIR::N: direction = Being::UP; break; + case DIR::NE: direction = Being::UP | Being::RIGHT; break; + case DIR::E: direction = Being::RIGHT; break; + case DIR::SE: direction = Being::DOWN | Being::RIGHT; break; default: // OOPSIE! Impossible or unknown direction = 0; + break; } } mPos += 3; @@ -162,7 +147,7 @@ std::string MessageIn::readString(int length) if (length < 0 || mPos + length > mLength) { mPos = mLength + 1; - return ""; + return std::string(); } // Read the string diff --git a/src/net/tmwa/messagein.h b/src/net/tmwa/messagein.h index 2f66ca28..b2fb6716 100644 --- a/src/net/tmwa/messagein.h +++ b/src/net/tmwa/messagein.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_MESSAGEIN_H -#define NET_TA_MESSAGEIN_H +#pragma once #include <cstdint> #include <string> @@ -109,5 +108,3 @@ class MessageIn }; } // TmwAthena - -#endif // NET_TA_MESSAGEIN_H diff --git a/src/net/tmwa/messageout.cpp b/src/net/tmwa/messageout.cpp index 12c9419a..a886fb4d 100644 --- a/src/net/tmwa/messageout.cpp +++ b/src/net/tmwa/messageout.cpp @@ -31,6 +31,9 @@ namespace TmwAthena { MessageOut::MessageOut(uint16_t id) { +#ifdef DEBUG + logger->log("Sending %s (0x%x)", Network::mInstance->messageName(id), id); +#endif writeInt16(id); } diff --git a/src/net/tmwa/messageout.h b/src/net/tmwa/messageout.h index b60644de..ba2d3c75 100644 --- a/src/net/tmwa/messageout.h +++ b/src/net/tmwa/messageout.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_MESSAGEOUT_H -#define NET_TA_MESSAGEOUT_H +#pragma once #include <cstdint> #include <string> @@ -73,5 +72,3 @@ class MessageOut }; } // namespace TmwAthena - -#endif // NET_TA_MESSAGEOUT_H diff --git a/src/net/tmwa/network.cpp b/src/net/tmwa/network.cpp index 5a2dd0d0..b448dc4f 100644 --- a/src/net/tmwa/network.cpp +++ b/src/net/tmwa/network.cpp @@ -45,9 +45,9 @@ struct PacketInfo }; // indicator for a variable-length packet -const uint16_t VAR = 1; +constexpr uint16_t VAR = 1; -static const PacketInfo packet_infos[] = { +static constexpr PacketInfo packet_infos[] = { // login server messages { SMSG_UPDATE_HOST, VAR, "SMSG_UPDATE_HOST" }, { CMSG_LOGIN_REGISTER, 55, "CMSG_LOGIN_REGISTER" }, @@ -331,20 +331,16 @@ void Network::disconnect() void Network::registerHandler(MessageHandler *handler) { - for (const Uint16 *i = handler->handledMessages; *i; ++i) - { + for (const uint16_t *i = handler->handledMessages; *i; ++i) mMessageHandlers[*i] = handler; - } handler->setNetwork(this); } void Network::unregisterHandler(MessageHandler *handler) { - for (const Uint16 *i = handler->handledMessages; *i; ++i) - { + for (const uint16_t *i = handler->handledMessages; *i; ++i) mMessageHandlers.erase(*i); - } handler->setNetwork(nullptr); } @@ -352,12 +348,20 @@ void Network::unregisterHandler(MessageHandler *handler) void Network::clearHandlers() { for (auto& [_, messageHandler] : mMessageHandlers) - { messageHandler->setNetwork(nullptr); - } + mMessageHandlers.clear(); } +const char *Network::messageName(uint16_t id) const +{ + auto packetInfoIt = mPacketInfo.find(id); + if (packetInfoIt != mPacketInfo.end()) + return packetInfoIt->second->name; + + return "Unknown"; +} + void Network::dispatchMessages() { MutexLocker lock(&mMutex); diff --git a/src/net/tmwa/network.h b/src/net/tmwa/network.h index fa0237dd..b27d1eda 100644 --- a/src/net/tmwa/network.h +++ b/src/net/tmwa/network.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_NETWORK_H -#define NET_TA_NETWORK_H +#pragma once #include "utils/mutex.h" @@ -67,6 +66,8 @@ class Network void clearHandlers(); + const char *messageName(uint16_t id) const; + int getState() const { return mState; } const std::string &getError() const { return mError; } @@ -125,5 +126,3 @@ class Network }; } // namespace TmwAthena - -#endif // NET_TA_NETWORK_H diff --git a/src/net/tmwa/npchandler.h b/src/net/tmwa/npchandler.h index b55a8155..df23531f 100644 --- a/src/net/tmwa/npchandler.h +++ b/src/net/tmwa/npchandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_NPCHANDLER_H -#define NET_TA_NPCHANDLER_H +#pragma once #include "net/npchandler.h" @@ -65,5 +64,3 @@ class NpcHandler final : public MessageHandler, public Net::NpcHandler }; } // namespace TmwAthena - -#endif // NET_TA_NPCHANDLER_H diff --git a/src/net/tmwa/partyhandler.h b/src/net/tmwa/partyhandler.h index 14c6d9f3..3f99de20 100644 --- a/src/net/tmwa/partyhandler.h +++ b/src/net/tmwa/partyhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_PARTYHANDLER_H -#define NET_TA_PARTYHANDLER_H +#pragma once #include "net/net.h" #include "net/partyhandler.h" @@ -71,5 +70,3 @@ class PartyHandler final : public MessageHandler, public Net::PartyHandler }; } // namespace TmwAthena - -#endif // NET_TA_PARTYHANDLER_H diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h index 1a90532e..f1a67e94 100644 --- a/src/net/tmwa/playerhandler.h +++ b/src/net/tmwa/playerhandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_PLAYERHANDLER_H -#define NET_TA_PLAYERHANDLER_H +#pragma once #include "net/net.h" #include "net/playerhandler.h" @@ -67,5 +66,3 @@ class PlayerHandler final : public MessageHandler, public Net::PlayerHandler }; } // namespace TmwAthena - -#endif // NET_TA_PLAYERHANDLER_H diff --git a/src/net/tmwa/protocol.h b/src/net/tmwa/protocol.h index 609b18a5..532ac90e 100644 --- a/src/net/tmwa/protocol.h +++ b/src/net/tmwa/protocol.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef TA_PROTOCOL_H -#define TA_PROTOCOL_H +#pragma once #include <cstdint> @@ -80,6 +79,20 @@ enum class LOOK : uint8_t MISC2 = 13, }; +enum class DIR : uint8_t +{ + S = 0, + SW = 1, + W = 2, + NW = 3, + N = 4, + NE = 5, + E = 6, + SE = 7, + + COUNT, +}; + enum NpcCommand { NPC_REQUEST_LANG = 0, @@ -283,5 +296,3 @@ enum { }; } - -#endif diff --git a/src/net/tmwa/token.h b/src/net/tmwa/token.h index c0a2b3c8..b563bf65 100644 --- a/src/net/tmwa/token.h +++ b/src/net/tmwa/token.h @@ -21,8 +21,7 @@ #include "being.h" -#ifndef NET_TA_TOKEN_H -#define NET_TA_TOKEN_H +#pragma once struct Token { @@ -36,8 +35,6 @@ struct Token account_ID = 0; session_ID1 = 0; session_ID2 = 0; - sex = Gender::UNSPECIFIED; + sex = Gender::Unspecified; } }; - -#endif // NET_TA_TOKEN_H diff --git a/src/net/tmwa/tradehandler.cpp b/src/net/tmwa/tradehandler.cpp index 60732eef..c129cfd4 100644 --- a/src/net/tmwa/tradehandler.cpp +++ b/src/net/tmwa/tradehandler.cpp @@ -131,7 +131,7 @@ void TradeHandler::handleMessage(MessageIn &msg) "doesn't exist.")); break; case 2: // Invite request check failed... - serverNotice(_("Trade cancelled due to an unknown " + serverNotice(_("Trade canceled due to an unknown " "reason.")); break; case 3: // Trade accepted @@ -140,11 +140,11 @@ void TradeHandler::handleMessage(MessageIn &msg) tradePartnerName.c_str())); tradeWindow->setVisible(true); break; - case 4: // Trade cancelled + case 4: // Trade canceled if (player_relations.hasPermission(tradePartnerName, PlayerPermissions::SPEECH_LOG)) { - serverNotice(strprintf(_("Trade with %s cancelled."), + serverNotice(strprintf(_("Trade with %s canceled."), tradePartnerName.c_str())); } // otherwise ignore silently diff --git a/src/net/tmwa/tradehandler.h b/src/net/tmwa/tradehandler.h index fa7ec034..1a2cfcef 100644 --- a/src/net/tmwa/tradehandler.h +++ b/src/net/tmwa/tradehandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef NET_TA_TRADEHANDLER_H -#define NET_TA_TRADEHANDLER_H +#pragma once #include "net/net.h" #include "net/tradehandler.h" @@ -57,5 +56,3 @@ class TradeHandler final : public MessageHandler, public Net::TradeHandler }; } // namespace TmwAthena - -#endif // NET_TA_TRADEHANDLER_H diff --git a/src/net/tradehandler.h b/src/net/tradehandler.h index 609f8087..605d122b 100644 --- a/src/net/tradehandler.h +++ b/src/net/tradehandler.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef TRADEHANDLER_H -#define TRADEHANDLER_H +#pragma once #include "being.h" @@ -49,5 +48,3 @@ class TradeHandler virtual void cancel() {} }; } - -#endif // TRADEHANDLER_H diff --git a/src/net/worldinfo.h b/src/net/worldinfo.h index d9596239..acc8a376 100644 --- a/src/net/worldinfo.h +++ b/src/net/worldinfo.h @@ -19,8 +19,7 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef WORLD_INFO_H -#define WORLD_INFO_H +#pragma once #include <string> #include <vector> @@ -34,5 +33,3 @@ struct WorldInfo { }; using Worlds = std::vector<WorldInfo *>; - -#endif // WORLD_INFO_H |