diff --git a/.gitignore b/.gitignore index 8e9237c..9e87793 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,11 @@ -.vscode +.vscode/ bin/* notes.txt config.ini *.o tags *~ +CMakeFiles/ +CMakeCache.txt +build/ +.vs/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..dada585 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.13) +project(OpenFusion) + +set(CMAKE_CXX_STANDARD 17) + +# OpenFusion supports multiple packet/struct versions +# 0104 is the default version to build which can be changed +# For example: cmake -B build -DPACKET_VERSION=0728 +OPTION(PACKET_VERSION "The packet version to build" "0104") + +ADD_DEFINITIONS(-DCNPROTO_OVERRIDE -DCNPROTO_VERSION_${PACKET_VERSION}) + +# Disallow in-source builds +if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) + message(FATAL_ERROR "In-source builds not allowed. Please refer to the wiki for more information. Please remove the CMakeFiles folder and the CMakeCache.txt file.") +endif() + +# Output binaries to the bin folder in the source directory +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) + +# Put CMake targets (ALL_BUILD/ZERO_CHECK) into a folder +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +# Set the OpenFusion project as the default startup project for VS +set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT openfusion) + +if (WIN32) + # Set the output binary name to winfusion to match the regular Makefile + set(BIN_NAME winfusion) +else() + set(BIN_NAME fusion) +endif() + +include_directories(src) + +file(GLOB_RECURSE SOURCES src/**.cpp src/**.hpp) + +add_executable(openfusion ${SOURCES}) + +set_target_properties(openfusion PROPERTIES OUTPUT_NAME ${BIN_NAME}) + +# Use pthreads if not generating a VS solution or MinGW makefile (because MinGW will prefer Win32 threads) +# Checking if the compiler ID is MSVC will allow us to open the project as a CMake project in VS. +# It's not something you should do, but it's there if you need it... +if (NOT CMAKE_GENERATOR MATCHES "Visual Studio" AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND NOT CMAKE_GENERATOR MATCHES "MinGW Makefiles") + find_package(Threads REQUIRED) + target_link_libraries(openfusion pthread) +endif() diff --git a/LICENSE.md b/LICENSE.md index db54105..541618c 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,9 +1,21 @@ -The OpenFusion MIT except Malorn License +MIT License -Copyright 2020 Seth Stubbs +Copyright (c) 2020 Seth Stubbs -Excluding the individual known as "MalornWS" and their associates, permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile index ee6e209..8f455c9 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ SRC=\ src/CNStructs.cpp\ src/main.cpp\ src/NanoManager.cpp\ + src/ItemManager.cpp\ src/NPCManager.cpp\ src/Player.cpp\ src/PlayerManager.cpp\ @@ -36,6 +37,7 @@ HDR=\ src/CNStructs.hpp\ src/INIReader.hpp\ src/NanoManager.hpp\ + src/ItemManager.hpp\ src/NPCManager.hpp\ src/Player.hpp\ src/PlayerManager.hpp\ diff --git a/README.md b/README.md index c6dca65..a242792 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ ![](res/radiorave_logo.png) +[![AppVeyor](https://ci.appveyor.com/api/projects/status/github/OpenFusionProject/OpenFusion?svg=true)](https://ci.appveyor.com/project/Raymonf/openfusion) +[![Discord](https://img.shields.io/badge/chat-on%20discord-7289da.svg?logo=discord)](https://discord.gg/DYavckB) + OpenFusion is a landwalker server for FusionFall. It currently supports versions `beta-20100104` and `beta-20100728` of the original game. Further documentation pending. @@ -21,6 +24,8 @@ Currently the client by default connects to a public server hosted by Cake. Chan You have two randomized characters available to you on the Character Selection screen, one boy, one girl. You can also make your own character and play through the tutorial. The tutorial can be skipped by pressing the ~ key. +If you want, [compiled binaries (artifacts) for each new commit can be found on AppVeyor.](https://ci.appveyor.com/project/Raymonf/openfusion) + For a more detailed overview of the game's architecture and how to configure it, read the following sections. ## Architecture @@ -72,7 +77,15 @@ Some modern IDEs/text editors do this automatically. If all else fails, use Note ## Compiling -OpenFusion can be compiled from source using the included makefile. A detailed compilation guide is available for Windows users [in the wiki](https://github.com/OpenFusionProject/OpenFusion/wiki/Compilation-on-Windows). Otherwise, to compile it for the current platform you're on, just run `make` with the correct build tools installed (currently make and clang). +You have two choices for compiling OpenFusion: the included Makefile and the included CMakeLists file. + +### Makefile + +A detailed compilation guide is available for Windows users in the wiki [using MinGW-w64 and MSYS2](https://github.com/OpenFusionProject/OpenFusion/wiki/Compilation-on-Windows). Otherwise, to compile it for the current platform you're on, just run `make` with the correct build tools installed (currently make and clang). + +### CMake + +A detailed guide is available [in the wiki](https://github.com/OpenFusionProject/OpenFusion/wiki/Compilation-with-CMake-or-Visual-Studio) for people using regular old CMake or the version of CMake that comes with Visual Studio. tl;dr: `cmake -B build` ## "Gameplay" diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..acad59a --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,65 @@ +version: 'openfusion-{branch}-{build}' + +image: + - Visual Studio 2019 + - Ubuntu2004 + +platform: + - x64 + +configuration: + - Release + +for: +- + matrix: + only: + - image: Ubuntu2004 + before_build: + - mkdir -p bin + build_script: + - make + artifacts: + - path: bin + name: ubuntu20_04-bin-x64 + type: zip +- + matrix: + only: + - image: Visual Studio 2019 + build_script: + - ps: | + $versions = "0104", "0728" + $configurations = "Release", "Debug" + + # AppVeyor uses VS2019 Community + $vsPath = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community" + + Import-Module "$vsPath\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" + Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation + + foreach ($version in $versions) { + if (Test-Path -LiteralPath "build") { + Remove-Item "build" -Recurse + Write-Output "Deleted existing build folder" + } + Invoke-Expression "cmake -B build -DPACKET_VERSION=$version" + if ($LASTEXITCODE -ne "0") { + Write-Error "cmake generation failed for version $version" -ErrorAction Stop + } + Write-Output "Generated build files for version $version" + + foreach ($configuration in $configurations) { + Write-Output "Building version $version $configuration" + Invoke-Expression "msbuild build\OpenFusion.sln /p:Configuration=$configuration" + if ($LASTEXITCODE -ne "0") { + Write-Error "msbuild build failed for version $version" -ErrorAction Stop + } + Rename-Item -Path "bin/$configuration" -newName "$version-$configuration" + Write-Output "Built version $version $configuration" + } + } + artifacts: + - path: bin + name: windows-vs2019-bin-x64 + type: zip diff --git a/config.ini b/config.ini index bd72bbc..b6e412c 100644 --- a/config.ini +++ b/config.ini @@ -4,7 +4,7 @@ port=8001 # enables two randomly generated characters in the # character selection menu for convenience -randomcharacters=false +randomcharacters=true # Shard Server configuration [shard] diff --git a/src/CNLoginServer.cpp b/src/CNLoginServer.cpp index 6017a0f..cc3cc4c 100644 --- a/src/CNLoginServer.cpp +++ b/src/CNLoginServer.cpp @@ -93,13 +93,20 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) { loginSessions[sock].characters[UID].PCStyle2 = charInfo->sPC_Style2; for (int i = 0; i < AEQUIP_COUNT; i++) { - // setup item + // setup equips charInfo->aEquip[i].iID = 0; charInfo->aEquip[i].iType = i; charInfo->aEquip[i].iOpt = 0; loginSessions[sock].characters[UID].Equip[i] = charInfo->aEquip[i]; } + for (int i = 0; i < AINVEN_COUNT; i++) { + // setup inventories + loginSessions[sock].characters[UID].Inven[i].iID = 0; + loginSessions[sock].characters[UID].Inven[i].iType = 0; + loginSessions[sock].characters[UID].Inven[i].iOpt = 0; + } + // set default to the first character if (i == 0) loginSessions[sock].selectedChar = UID; diff --git a/src/CNShardServer.hpp b/src/CNShardServer.hpp index fb3b65a..751c03d 100644 --- a/src/CNShardServer.hpp +++ b/src/CNShardServer.hpp @@ -6,71 +6,67 @@ #include enum SHARDPACKETID { + // client 2 shard + P_CL2FE_REQ_PC_ENTER = 318767105, + P_CL2FE_REQ_PC_LOADING_COMPLETE = 318767245, + P_CL2FE_REP_LIVE_CHECK = 318767221, + P_CL2FE_REQ_NANO_ACTIVE = 318767119, + P_CL2FE_REQ_PC_MOVE = 318767107, + P_CL2FE_REQ_PC_STOP = 318767108, + P_CL2FE_REQ_PC_JUMP = 318767109, + P_CL2FE_REQ_PC_JUMPPAD = 318767165, + P_CL2FE_REQ_PC_LAUNCHER = 318767166, + P_CL2FE_REQ_PC_ZIPLINE = 318767167, + P_CL2FE_REQ_PC_MOVEPLATFORM = 318767168, + P_CL2FE_REQ_PC_SLOPE = 318767169, + P_CL2FE_REQ_PC_GOTO = 318767124, + P_CL2FE_GM_REQ_PC_SET_VALUE = 318767211, + P_CL2FE_REQ_SEND_FREECHAT_MESSAGE = 318767111, + P_CL2FE_REQ_PC_AVATAR_EMOTES_CHAT = 318767184, + P_CL2FE_REQ_ITEM_MOVE = 318767114, + P_CL2FE_REQ_PC_EXIT = 318767106, - // client 2 shard - P_CL2FE_REQ_PC_ENTER = 318767105, - P_CL2FE_REQ_PC_LOADING_COMPLETE = 318767245, - P_CL2FE_REP_LIVE_CHECK = 318767221, - P_CL2FE_REQ_NANO_ACTIVE = 318767119, - P_CL2FE_REQ_NANO_EQUIP = 318767117, - P_CL2FE_REQ_NANO_SKILL_USE = 318767121, - P_CL2FE_REQ_NANO_TUNE = 318767120, - P_CL2FE_REQ_PC_MOVE = 318767107, - P_CL2FE_REQ_PC_STOP = 318767108, - P_CL2FE_REQ_PC_JUMP = 318767109, - P_CL2FE_REQ_PC_JUMPPAD = 318767165, - P_CL2FE_REQ_PC_LAUNCHER = 318767166, - P_CL2FE_REQ_PC_ZIPLINE = 318767167, - P_CL2FE_REQ_PC_MOVEPLATFORM = 318767168, - P_CL2FE_REQ_PC_SLOPE = 318767169, - P_CL2FE_REQ_PC_GOTO = 318767124, - P_CL2FE_GM_REQ_PC_SET_VALUE = 318767211, - P_CL2FE_REQ_SEND_FREECHAT_MESSAGE = 318767111, - P_CL2FE_REQ_PC_AVATAR_EMOTES_CHAT = 318767184, - P_CL2FE_REQ_PC_EXIT = 318767106, - P_CL2FE_REQ_PC_FIRST_USE_FLAG_SET = 318767238, - - // shard 2 client - P_FE2CL_REP_NANO_ACTIVE_SUCC = 822083624, - P_FE2CL_REP_PC_NANO_CREATE_SUCC = 822083667, - P_FE2CL_REP_NANO_EQUIP_SUCC = 822083622, - P_FE2CL_NANO_SKILL_USE_SUCC = 822083627, - P_FE2CL_NANO_SKILL_USE = 822083628, - P_FE2CL_REP_NANO_TUNE_SUCC = 822083625, - P_FE2CL_REP_PC_ENTER_SUCC = 822083586, - P_FE2CL_REP_PC_LOADING_COMPLETE_SUCC = 822083833, - P_FE2CL_REQ_LIVE_CHECK = 822083792, - P_FE2CL_PC_NEW = 822083587, - P_FE2CL_PC_MOVE = 822083592, - P_FE2CL_PC_STOP = 822083593, - P_FE2CL_PC_JUMP = 822083594, - P_FE2CL_PC_EXIT = 822083590, - P_FE2CL_PC_JUMPPAD = 822083701, - P_FE2CL_PC_LAUNCHER = 822083702, - P_FE2CL_PC_ZIPLINE = 822083703, - P_FE2CL_PC_MOVEPLATFORM = 822083704, - P_FE2CL_PC_SLOPE = 822083705, - P_FE2CL_REP_PC_GOTO_SUCC = 822083633, - P_FE2CL_GM_REP_PC_SET_VALUE = 822083781, - P_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC = 822083602, - P_FE2CL_REP_PC_AVATAR_EMOTES_CHAT = 822083730, - P_FE2CL_REP_PC_EXIT_SUCC = 822083589, - P_FE2CL_PC_MOTD_LOGIN = 822083793 + // shard 2 client + P_FE2CL_REP_NANO_ACTIVE_SUCC = 822083624, + P_FE2CL_REP_PC_ENTER_SUCC = 822083586, + P_FE2CL_REP_PC_LOADING_COMPLETE_SUCC = 822083833, + P_FE2CL_REP_PC_GOTO_SUCC = 822083633, + P_FE2CL_REQ_LIVE_CHECK = 822083792, + P_FE2CL_PC_NEW = 822083587, + P_FE2CL_PC_MOVE = 822083592, + P_FE2CL_PC_STOP = 822083593, + P_FE2CL_PC_JUMP = 822083594, + P_FE2CL_PC_EXIT = 822083590, + P_FE2CL_PC_JUMPPAD = 822083701, + P_FE2CL_PC_LAUNCHER = 822083702, + P_FE2CL_PC_ZIPLINE = 822083703, + P_FE2CL_PC_MOVEPLATFORM = 822083704, + P_FE2CL_PC_SLOPE = 822083705, + P_FE2CL_NPC_ENTER = 822083595, + P_FE2CL_NPC_EXIT = 822083596, + P_FE2CL_ANNOUNCE_MSG = 822083778, + P_FE2CL_GM_REP_PC_SET_VALUE = 822083781, + P_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC = 822083602, + P_FE2CL_REP_PC_AVATAR_EMOTES_CHAT = 822083730, + P_FE2CL_PC_ITEM_MOVE_SUCC = 822083610, + P_FE2CL_PC_EQUIP_CHANGE = 822083611, + P_FE2CL_REP_PC_EXIT_SUCC = 822083589, + P_FE2CL_PC_MOTD_LOGIN = 822083793 }; #define REGISTER_SHARD_PACKET(pactype, handlr) CNShardServer::ShardPackets[pactype] = handlr; class CNShardServer : public CNServer { private: - static void handlePacket(CNSocket* sock, CNPacketData* data); + static void handlePacket(CNSocket* sock, CNPacketData* data); public: - static std::map ShardPackets; + static std::map ShardPackets; - CNShardServer(uint16_t p); + CNShardServer(uint16_t p); - void killConnection(CNSocket* cns); - void onTimer(); + void killConnection(CNSocket* cns); + void onTimer(); }; #endif diff --git a/src/CNStructs.hpp b/src/CNStructs.hpp index 3c6bfdd..9df5f31 100644 --- a/src/CNStructs.hpp +++ b/src/CNStructs.hpp @@ -5,14 +5,20 @@ #ifndef _CNS_HPP #define _CNS_HPP +#ifdef _MSC_VER + // codecvt_* is deprecated in C++17 and MSVC will throw an annoying warning because of that. + // Defining this before anything else to silence it. + #define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING +#endif + #include #include #include -// Can't use this in MSVC. #ifndef _MSC_VER - #include + #include #else - #include +// Can't use this in MSVC. + #include #endif #include #include @@ -25,13 +31,18 @@ std::string U16toU8(char16_t* src); int U8toU16(std::string src, char16_t* des); // returns number of char16_t that was written at des uint64_t getTime(); -//#define CNPROTO_VERSION_0728 -#define CNPROTO_VERSION_0104 +// The CNPROTO_OVERRIDE definition is defined by cmake if you use it. +// If you don't use cmake, feel free to comment this out and change it around. +// Otherwise, use the PACKET_VERSION option (e.g. -DPACKET_VERSION=0104 in the cmake command) to change it. +#if !defined(CNPROTO_OVERRIDE) + //#define CNPROTO_VERSION_0728 + #define CNPROTO_VERSION_0104 +#endif #if defined(CNPROTO_VERSION_0104) - #include "structs/0104.hpp" + #include "structs/0104.hpp" #elif defined(CNPROTO_VERSION_0728) - #include "structs/0728.hpp" + #include "structs/0728.hpp" #endif #endif diff --git a/src/ChatManager.cpp b/src/ChatManager.cpp index 451bd15..efbc77f 100644 --- a/src/ChatManager.cpp +++ b/src/ChatManager.cpp @@ -9,6 +9,9 @@ void ChatManager::init() { } void ChatManager::chatHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_SEND_FREECHAT_MESSAGE)) + return; // malformed packet + sP_CL2FE_REQ_SEND_FREECHAT_MESSAGE* chat = (sP_CL2FE_REQ_SEND_FREECHAT_MESSAGE*)data->buf; PlayerView plr = PlayerManager::players[sock]; diff --git a/src/ItemManager.cpp b/src/ItemManager.cpp new file mode 100644 index 0000000..b635a7e --- /dev/null +++ b/src/ItemManager.cpp @@ -0,0 +1,76 @@ +#include "CNShardServer.hpp" +#include "CNStructs.hpp" +#include "ItemManager.hpp" +#include "PlayerManager.hpp" +#include "Player.hpp" + +void ItemManager::init() { + REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler); + REGISTER_SHARD_PACKET(P_FE2CL_PC_EQUIP_CHANGE, itemMoveHandler); +} + +void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) { + if (data->size != sizeof(sP_CL2FE_REQ_ITEM_MOVE)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_ITEM_MOVE* itemmove = (sP_CL2FE_REQ_ITEM_MOVE*)data->buf; + sP_FE2CL_PC_ITEM_MOVE_SUCC* resp = (sP_FE2CL_PC_ITEM_MOVE_SUCC*)xmalloc(sizeof(sP_FE2CL_PC_ITEM_MOVE_SUCC)); + + PlayerView plr = PlayerManager::players[sock]; + sItemBase fromItem; + sItemBase toItem; + + // eFrom 0 means from equip + if (itemmove->eFrom == 0) { + // unequiping an item + std::cout << "unequipting item" << std::endl; + fromItem = plr.plr.Equip[itemmove->iFromSlotNum]; + } else { + fromItem = plr.plr.Inven[itemmove->iFromSlotNum]; + } + + // eTo 0 means to equip + if (itemmove->eTo == 0) { + std::cout << "equipting item" << std::endl; + // equiping an item + toItem = plr.plr.Equip[itemmove->iToSlotNum]; + plr.plr.Equip[itemmove->iToSlotNum] = fromItem; + } else { + toItem = plr.plr.Inven[itemmove->iToSlotNum]; + plr.plr.Inven[itemmove->iToSlotNum] = fromItem; + } + + if (itemmove->eFrom == 0) { + plr.plr.Equip[itemmove->iFromSlotNum] = toItem; + } else { + plr.plr.Inven[itemmove->iFromSlotNum] = toItem; + } + + if (itemmove->eFrom == 0 || itemmove->eTo == 0) { + for (CNSocket* otherSock : plr.viewable) { + sP_FE2CL_PC_EQUIP_CHANGE* resp2 = (sP_FE2CL_PC_EQUIP_CHANGE*)xmalloc(sizeof(sP_FE2CL_PC_EQUIP_CHANGE)); + + resp2->iPC_ID = plr.plr.iID; + if (itemmove->eFrom == 0) { + resp2->iEquipSlotNum = itemmove->iFromSlotNum; + resp2->EquipSlotItem = toItem; + } + else { + resp2->iEquipSlotNum = itemmove->iToSlotNum; + resp2->EquipSlotItem = fromItem; + } + otherSock->sendPacket(new CNPacketData((void*)resp2, P_FE2CL_PC_EQUIP_CHANGE, sizeof(sP_FE2CL_PC_EQUIP_CHANGE), otherSock->getFEKey())); + } + } + + PlayerManager::players[sock] = plr; + + resp->eTo = itemmove->eFrom; + resp->iToSlotNum = itemmove->iFromSlotNum; + resp->ToSlotItem = toItem; + resp->eFrom = itemmove->eTo; + resp->iFromSlotNum = itemmove->iToSlotNum; + resp->FromSlotItem = fromItem; + + sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_PC_ITEM_MOVE_SUCC, sizeof(sP_FE2CL_PC_ITEM_MOVE_SUCC), sock->getFEKey())); +} \ No newline at end of file diff --git a/src/ItemManager.hpp b/src/ItemManager.hpp new file mode 100644 index 0000000..0036907 --- /dev/null +++ b/src/ItemManager.hpp @@ -0,0 +1,11 @@ +#ifndef _IM_HPP +#define _IM_HPP + +#include "CNShardServer.hpp" + +namespace ItemManager { + void init(); + void itemMoveHandler(CNSocket* sock, CNPacketData* data); +} + +#endif \ No newline at end of file diff --git a/src/NPC.hpp b/src/NPC.hpp new file mode 100644 index 0000000..f467040 --- /dev/null +++ b/src/NPC.hpp @@ -0,0 +1,26 @@ +#ifndef _NPCCLASS_HPP +#define _NPCCLASS_HPP + +#include "CNStructs.hpp" + +class BaseNPC { +public: + sNPCAppearanceData appearanceData; + + BaseNPC() {}; + BaseNPC(int x, int y, int z, int type) { + appearanceData.iX = x; + appearanceData.iY = y; + appearanceData.iZ = z; + appearanceData.iNPCType = type; + appearanceData.iHP = 400; + appearanceData.iAngle = 0; + appearanceData.iConditionBitFlag = 0; + appearanceData.iBarkerType = 0; + + // hopefully no collisions happen :eyes: + appearanceData.iNPC_ID = (int32_t)getTime(); + }; +}; + +#endif \ No newline at end of file diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index 1b08f75..b8d6c15 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -1,5 +1,64 @@ #include "NPCManager.hpp" +#include "settings.hpp" + +#include +#include +#include + +std::map NPCManager::NPCs; void NPCManager::init() { - + /* BaseNPC test(settings::SPAWN_X, settings::SPAWN_Y, settings::SPAWN_Z, 727); + NPCs[test.appearanceData.iNPC_ID] = test; */ +} + +void NPCManager::updatePlayerNPCS(CNSocket* sock, PlayerView& view) { + std::list yesView; + std::list noView; + + for (auto pair : NPCs) { + int diffX = abs(view.plr.x - pair.second.appearanceData.iX); + int diffY = abs(view.plr.y - pair.second.appearanceData.iY); + + if (diffX < settings::VIEWDISTANCE && diffY < settings::VIEWDISTANCE) { + yesView.push_back(pair.first); + } else { + noView.push_back(pair.first); + } + } + + std::list::iterator i = view.viewableNPCs.begin(); + while (i != view.viewableNPCs.end()) { + int32_t id = *i; + + if (std::find(noView.begin(), noView.end(), id) != noView.end()) { + // it shouldn't be visible, send NPC_EXIT + sP_FE2CL_NPC_EXIT* exitData = (sP_FE2CL_NPC_EXIT*)xmalloc(sizeof(sP_FE2CL_NPC_EXIT)); + + exitData->iNPC_ID = id; + + sock->sendPacket(new CNPacketData((void*)exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT), sock->getFEKey())); + + // remove from view + view.viewableNPCs.erase(i++); + } + + ++i; + } + + for (int32_t id : yesView) { + if (std::find(view.viewableNPCs.begin(), view.viewableNPCs.end(), id) == view.viewableNPCs.end()) { + + // needs to be added to viewableNPCs! send NPC_ENTER + sP_FE2CL_NPC_ENTER* enterData = (sP_FE2CL_NPC_ENTER*)xmalloc(sizeof(sP_FE2CL_NPC_ENTER)); + + enterData->NPCAppearanceData = NPCs[id].appearanceData; + + sock->sendPacket(new CNPacketData((void*)enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER), sock->getFEKey())); + + view.viewableNPCs.push_back(id); + } + } + + PlayerManager::players[sock].viewableNPCs = view.viewableNPCs; } \ No newline at end of file diff --git a/src/NPCManager.hpp b/src/NPCManager.hpp index 659a666..03b7dde 100644 --- a/src/NPCManager.hpp +++ b/src/NPCManager.hpp @@ -2,13 +2,16 @@ #define _NPCMANAGER_HPP #include "CNProtocol.hpp" +#include "PlayerManager.hpp" +#include "NPC.hpp" #include namespace NPCManager { + extern std::map NPCs; void init(); - + void updatePlayerNPCS(CNSocket* sock, PlayerView& plr); } #endif \ No newline at end of file diff --git a/src/NanoManager.cpp b/src/NanoManager.cpp index 6ed526a..4e773d0 100644 --- a/src/NanoManager.cpp +++ b/src/NanoManager.cpp @@ -4,100 +4,20 @@ #include "PlayerManager.hpp" void NanoManager::init() { - REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_ACTIVE, nanoSummonHandler); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_EQUIP, nanoEquipHandler); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_TUNE, nanoSkillSetHandler); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_SKILL_USE, nanoSkillUseHandler); -} - -void NanoManager::nanoEquipHandler(CNSocket* sock, CNPacketData* data) { - sP_CL2FE_REQ_NANO_EQUIP* nano = (sP_CL2FE_REQ_NANO_EQUIP*)data->buf; - sP_FE2CL_REP_NANO_EQUIP_SUCC* resp = (sP_FE2CL_REP_NANO_EQUIP_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_NANO_EQUIP_SUCC)); - resp->iNanoID = nano->iNanoID; - resp->iNanoSlotNum = nano->iNanoSlotNum; - - sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_NANO_EQUIP_SUCC, sizeof(sP_FE2CL_REP_NANO_EQUIP_SUCC), sock->getFEKey())); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_ACTIVE, nanoSummonHandler); } void NanoManager::nanoSummonHandler(CNSocket* sock, CNPacketData* data) { - sP_CL2FE_REQ_NANO_ACTIVE* nano = (sP_CL2FE_REQ_NANO_ACTIVE*)data->buf; - PlayerView plr = PlayerManager::players[sock]; + if (data->size != sizeof(sP_CL2FE_REQ_NANO_ACTIVE)) + return; // malformed packet - // Send to client - sP_FE2CL_REP_NANO_ACTIVE_SUCC* resp = (sP_FE2CL_REP_NANO_ACTIVE_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_NANO_ACTIVE_SUCC)); - resp->iActiveNanoSlotNum = nano->iNanoSlotNum; - sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_NANO_ACTIVE_SUCC, sizeof(sP_FE2CL_REP_NANO_ACTIVE_SUCC), sock->getFEKey())); + sP_CL2FE_REQ_NANO_ACTIVE* nano = (sP_CL2FE_REQ_NANO_ACTIVE*)data->buf; + PlayerView plr = PlayerManager::players[sock]; - std::cout << U16toU8(plr.plr.PCStyle.szFirstName) << U16toU8(plr.plr.PCStyle.szLastName) << " requested to summon nano slot: " << nano->iNanoSlotNum << std::endl; + // Send to client + sP_FE2CL_REP_NANO_ACTIVE_SUCC* resp = (sP_FE2CL_REP_NANO_ACTIVE_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_NANO_ACTIVE_SUCC)); + resp->iActiveNanoSlotNum = nano->iNanoSlotNum; + sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_NANO_ACTIVE_SUCC, sizeof(sP_FE2CL_REP_NANO_ACTIVE_SUCC), sock->getFEKey())); + + std::cout << U16toU8(plr.plr.PCStyle.szFirstName) << U16toU8(plr.plr.PCStyle.szLastName) << " requested to summon nano slot: " << nano->iNanoSlotNum << std::endl; } - -void NanoManager::nanoSkillUseHandler(CNSocket* sock, CNPacketData* data) { - sP_CL2FE_REQ_NANO_SKILL_USE* skill = (sP_CL2FE_REQ_NANO_SKILL_USE*)data->buf; - PlayerView plr = PlayerManager::players[sock]; - - // Send to client - sP_FE2CL_NANO_SKILL_USE_SUCC* resp = (sP_FE2CL_NANO_SKILL_USE_SUCC*)xmalloc(sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC)); - resp->iArg1 = skill->iArg1; - resp->iArg2 = skill->iArg2; - resp->iArg3 = skill->iArg3; - resp->iBulletID = skill->iBulletID; - resp->iTargetCnt = skill->iTargetCnt; - resp->iPC_ID = plr.plr.iID; - resp->iNanoStamina = 150; // Hardcoded for now - - sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_NANO_SKILL_USE_SUCC, sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC), sock->getFEKey())); - - std::cout << U16toU8(plr.plr.PCStyle.szFirstName) << U16toU8(plr.plr.PCStyle.szLastName) << " requested to summon nano skill " << std::endl; -} - -void NanoManager::nanoSkillSetHandler(CNSocket* sock, CNPacketData* data) { - sP_CL2FE_REQ_NANO_TUNE* skill = (sP_CL2FE_REQ_NANO_TUNE*)data->buf; - setNanoSkill(sock, skill->iNanoID, skill->iTuneID); -} - -void NanoManager::addNano(CNSocket* sock, int16_t nanoId, int16_t slot) { - Player plr = PlayerManager::getPlayer(sock); - - // Send to client - sP_FE2CL_REP_PC_NANO_CREATE_SUCC* resp = new sP_FE2CL_REP_PC_NANO_CREATE_SUCC(); - resp->Nano.iID = nanoId; - resp->Nano.iStamina = 150; - resp->iQuestItemSlotNum = slot; - - sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_PC_NANO_CREATE_SUCC, sizeof(sP_FE2CL_REP_PC_NANO_CREATE_SUCC), sock->getFEKey())); - - // Update player - plr.Nanos[nanoId] = resp->Nano; - PlayerManager::updatePlayer(sock, plr); -} - -void NanoManager::setNanoSkill(CNSocket* sock, int16_t nanoId, int16_t skillId) { - Player plr = PlayerManager::getPlayer(sock); - sNano nano = plr.Nanos[nanoId]; - - nano.iSkillID = skillId; - plr.Nanos[nanoId] = nano; - - // Send to client - sP_FE2CL_REP_NANO_TUNE_SUCC* resp = (sP_FE2CL_REP_NANO_TUNE_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_NANO_TUNE_SUCC)); - resp->iNanoID = nanoId; - resp->iSkillID = skillId; - - sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_NANO_TUNE_SUCC, sizeof(sP_FE2CL_REP_NANO_TUNE_SUCC), sock->getFEKey())); - - std::cout << U16toU8(plr.PCStyle.szFirstName) << U16toU8(plr.PCStyle.szLastName) << " set skill id " << skillId << " for nano: " << nanoId << std::endl; - - // Update the player - PlayerManager::updatePlayer(sock, plr); -} - -void NanoManager::resetNanoSkill(CNSocket* sock, int16_t nanoId) { - Player plr = PlayerManager::getPlayer(sock); - sNano nano = plr.Nanos[nanoId]; - - nano.iSkillID = 0; - plr.Nanos[nanoId] = nano; - - // Update the player - PlayerManager::updatePlayer(sock, plr); -} \ No newline at end of file diff --git a/src/Player.hpp b/src/Player.hpp index acc3e4a..98a2f7f 100644 --- a/src/Player.hpp +++ b/src/Player.hpp @@ -21,6 +21,7 @@ struct Player { int x, y, z, angle; sItemBase Equip[AEQUIP_COUNT]; + sItemBase Inven[AINVEN_COUNT]; }; #endif \ No newline at end of file diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index 86a01c3..2d8f694 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -1,6 +1,6 @@ #include "CNProtocol.hpp" -#include "NanoManager.hpp" #include "PlayerManager.hpp" +#include "NPCManager.hpp" #include "CNShardServer.hpp" #include "CNShared.hpp" @@ -13,543 +13,531 @@ std::map PlayerManager::players; void PlayerManager::init() { - // register packet types - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ENTER, PlayerManager::enterPlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_LOADING_COMPLETE, PlayerManager::loadPlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVE, PlayerManager::movePlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_STOP, PlayerManager::stopPlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_JUMP, PlayerManager::jumpPlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_JUMPPAD, PlayerManager::jumppadPlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_LAUNCHER, PlayerManager::launchPlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ZIPLINE, PlayerManager::ziplinePlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVEPLATFORM, PlayerManager::movePlatformPlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SLOPE, PlayerManager::moveSlopePlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GOTO, PlayerManager::gotoPlayer); - REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SET_VALUE, PlayerManager::setSpecialPlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REP_LIVE_CHECK, PlayerManager::heartbeatPlayer); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_EXIT, PlayerManager::exitGame); - REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_FIRST_USE_FLAG_SET, PlayerManager::onPlayerSpawn); + // register packet types + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ENTER, PlayerManager::enterPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_LOADING_COMPLETE, PlayerManager::loadPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVE, PlayerManager::movePlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_STOP, PlayerManager::stopPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_JUMP, PlayerManager::jumpPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_JUMPPAD, PlayerManager::jumppadPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_LAUNCHER, PlayerManager::launchPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ZIPLINE, PlayerManager::ziplinePlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVEPLATFORM, PlayerManager::movePlatformPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SLOPE, PlayerManager::moveSlopePlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GOTO, PlayerManager::gotoPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SET_VALUE, PlayerManager::setSpecialPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REP_LIVE_CHECK, PlayerManager::heartbeatPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_EXIT, PlayerManager::exitGame); } void PlayerManager::addPlayer(CNSocket* key, Player plr) { - players[key] = PlayerView(); - players[key].viewable = std::list(); - players[key].plr = plr; - players[key].lastHeartbeat = 0; + players[key] = PlayerView(); + players[key].viewable = std::list(); + players[key].plr = plr; + players[key].lastHeartbeat = 0; - std::cout << U16toU8(plr.PCStyle.szFirstName) << U16toU8(plr.PCStyle.szLastName) << " has joined!" << std::endl; - std::cout << players.size() << " players" << std::endl; + std::cout << U16toU8(plr.PCStyle.szFirstName) << U16toU8(plr.PCStyle.szLastName) << " has joined!" << std::endl; + std::cout << players.size() << " players" << std::endl; } void PlayerManager::removePlayer(CNSocket* key) { - PlayerView cachedView = players[key]; + PlayerView cachedView = players[key]; - // if players have them in their viewable lists, remove it - for (CNSocket* otherSock : players[key].viewable) { - players[otherSock].viewable.remove(key); // gone + // if players have them in their viewable lists, remove it + for (CNSocket* otherSock : players[key].viewable) { + players[otherSock].viewable.remove(key); // gone - // now sent PC_EXIT packet - sP_FE2CL_PC_EXIT* exitPacket = (sP_FE2CL_PC_EXIT*)xmalloc(sizeof(sP_FE2CL_PC_EXIT)); - exitPacket->iID = players[key].plr.iID; + // now sent PC_EXIT packet + sP_FE2CL_PC_EXIT* exitPacket = (sP_FE2CL_PC_EXIT*)xmalloc(sizeof(sP_FE2CL_PC_EXIT)); + exitPacket->iID = players[key].plr.iID; - otherSock->sendPacket(new CNPacketData((void*)exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT), otherSock->getFEKey())); - } + otherSock->sendPacket(new CNPacketData((void*)exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT), otherSock->getFEKey())); + } - players.erase(key); + players.erase(key); - std::cout << U16toU8(cachedView.plr.PCStyle.szFirstName) << U16toU8(cachedView.plr.PCStyle.szLastName) << " has left!" << std::endl; - std::cout << players.size() << " players" << std::endl; + std::cout << U16toU8(cachedView.plr.PCStyle.szFirstName) << U16toU8(cachedView.plr.PCStyle.szLastName) << " has left!" << std::endl; + std::cout << players.size() << " players" << std::endl; } Player PlayerManager::getPlayer(CNSocket* key) { - return players[key].plr; + return players[key].plr; } void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) { - players[sock].plr.x = X; - players[sock].plr.y = Y; - players[sock].plr.z = Z; + players[sock].plr.x = X; + players[sock].plr.y = Y; + players[sock].plr.z = Z; - std::vector noView; - std::vector yesView; + std::vector noView; + std::vector yesView; - // TODO: oh god this is sooooo perfomance heavy the more players you have - for (auto pair : players) { - if (pair.first == sock) - continue; // ignore our own connection + // TODO: oh god this is sooooo perfomance heavy the more players you have + for (auto pair : players) { + if (pair.first == sock) + continue; // ignore our own connection - int diffX = abs(pair.second.plr.x - X); // the map is like a grid, X and Y are your position on the map, Z is the height. very different from other games... - int diffY = abs(pair.second.plr.y - Y); + int diffX = abs(pair.second.plr.x - X); // the map is like a grid, X and Y are your position on the map, Z is the height. very different from other games... + int diffY = abs(pair.second.plr.y - Y); - if (diffX < settings::VIEWDISTANCE && diffY < settings::VIEWDISTANCE) { - yesView.push_back(pair.first); - } - else { - noView.push_back(pair.first); - } - } + if (diffX < settings::VIEWDISTANCE && diffY < settings::VIEWDISTANCE) { + yesView.push_back(pair.first); + } else { + noView.push_back(pair.first); + } + } - std::list cachedview(players[sock].viewable); // copies the viewable + std::list::iterator i = players[sock].viewable.begin(); + while (i != players[sock].viewable.end()) { + CNSocket* otherSock = *i; + if (std::find(noView.begin(), noView.end(), otherSock) != noView.end()) { + // sock shouldn't be visible, send PC_EXIT packet & remove them - for (CNSocket* otherSock : cachedview) { - if (std::find(noView.begin(), noView.end(), otherSock) != noView.end()) { - // sock shouldn't be visible, send PC_EXIT packet & remove them + sP_FE2CL_PC_EXIT* exitPacket = (sP_FE2CL_PC_EXIT*)xmalloc(sizeof(sP_FE2CL_PC_EXIT)); + sP_FE2CL_PC_EXIT* exitPacketOther = (sP_FE2CL_PC_EXIT*)xmalloc(sizeof(sP_FE2CL_PC_EXIT)); + + exitPacket->iID = players[sock].plr.iID; + exitPacketOther->iID = players[otherSock].plr.iID; - sP_FE2CL_PC_EXIT* exitPacket = (sP_FE2CL_PC_EXIT*)xmalloc(sizeof(sP_FE2CL_PC_EXIT)); - sP_FE2CL_PC_EXIT* exitPacketOther = (sP_FE2CL_PC_EXIT*)xmalloc(sizeof(sP_FE2CL_PC_EXIT)); + otherSock->sendPacket(new CNPacketData((void*)exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT), otherSock->getFEKey())); + sock->sendPacket(new CNPacketData((void*)exitPacketOther, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT), sock->getFEKey())); - exitPacket->iID = players[sock].plr.iID; - exitPacketOther->iID = players[otherSock].plr.iID; + players[sock].viewable.erase(i++); + players[otherSock].viewable.remove(sock); + continue; + } - otherSock->sendPacket(new CNPacketData((void*)exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT), otherSock->getFEKey())); - sock->sendPacket(new CNPacketData((void*)exitPacketOther, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT), sock->getFEKey())); + ++i; + } - players[sock].viewable.remove(otherSock); - players[otherSock].viewable.remove(sock); - } - } + for (CNSocket* otherSock : yesView) { + if (std::find(players[sock].viewable.begin(), players[sock].viewable.end(), otherSock) == players[sock].viewable.end()) { + // this needs to be added to the viewable players, send PC_ENTER - cachedview = players[sock].viewable; + sP_FE2CL_PC_NEW* newPlayer = (sP_FE2CL_PC_NEW*)xmalloc(sizeof(sP_FE2CL_PC_NEW)); // current connection to other player + sP_FE2CL_PC_NEW* newOtherPlayer = (sP_FE2CL_PC_NEW*)xmalloc(sizeof(sP_FE2CL_PC_NEW)); // other player to current connection - for (CNSocket* otherSock : yesView) { - if (std::find(cachedview.begin(), cachedview.end(), otherSock) == cachedview.end()) { - // this needs to be added to the viewable players, send PC_ENTER + Player otherPlr = players[otherSock].plr; + Player plr = players[sock].plr; - sP_FE2CL_PC_NEW* newPlayer = (sP_FE2CL_PC_NEW*)xmalloc(sizeof(sP_FE2CL_PC_NEW)); // current connection to other player - sP_FE2CL_PC_NEW* newOtherPlayer = (sP_FE2CL_PC_NEW*)xmalloc(sizeof(sP_FE2CL_PC_NEW)); // other player to current connection + newPlayer->PCAppearanceData.iID = plr.iID; + newPlayer->PCAppearanceData.iHP = plr.HP; + newPlayer->PCAppearanceData.iLv = plr.level; + newPlayer->PCAppearanceData.iX = plr.x; + newPlayer->PCAppearanceData.iY = plr.y; + newPlayer->PCAppearanceData.iZ = plr.z; + newPlayer->PCAppearanceData.iAngle = plr.angle; + newPlayer->PCAppearanceData.PCStyle = plr.PCStyle; + memcpy(newPlayer->PCAppearanceData.ItemEquip, plr.Equip, sizeof(sItemBase) * AEQUIP_COUNT); - Player otherPlr = players[otherSock].plr; - Player plr = players[sock].plr; + newOtherPlayer->PCAppearanceData.iID = otherPlr.iID; + newOtherPlayer->PCAppearanceData.iHP = otherPlr.HP; + newOtherPlayer->PCAppearanceData.iLv = otherPlr.level; + newOtherPlayer->PCAppearanceData.iX = otherPlr.x; + newOtherPlayer->PCAppearanceData.iY = otherPlr.y; + newOtherPlayer->PCAppearanceData.iZ = otherPlr.z; + newOtherPlayer->PCAppearanceData.iAngle = otherPlr.angle; + newOtherPlayer->PCAppearanceData.PCStyle = otherPlr.PCStyle; + memcpy(newOtherPlayer->PCAppearanceData.ItemEquip, otherPlr.Equip, sizeof(sItemBase) * AEQUIP_COUNT); - newPlayer->PCAppearanceData.iID = plr.iID; - newPlayer->PCAppearanceData.iHP = plr.HP; - newPlayer->PCAppearanceData.iLv = plr.level; - newPlayer->PCAppearanceData.iX = plr.x; - newPlayer->PCAppearanceData.iY = plr.y; - newPlayer->PCAppearanceData.iZ = plr.z; - newPlayer->PCAppearanceData.iAngle = plr.angle; - newPlayer->PCAppearanceData.PCStyle = plr.PCStyle; - memcpy(newPlayer->PCAppearanceData.ItemEquip, plr.Equip, sizeof(sItemBase) * AEQUIP_COUNT); + sock->sendPacket(new CNPacketData((void*)newOtherPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW), sock->getFEKey())); + otherSock->sendPacket(new CNPacketData((void*)newPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW), otherSock->getFEKey())); - newOtherPlayer->PCAppearanceData.iID = otherPlr.iID; - newOtherPlayer->PCAppearanceData.iHP = otherPlr.HP; - newOtherPlayer->PCAppearanceData.iLv = otherPlr.level; - newOtherPlayer->PCAppearanceData.iX = otherPlr.x; - newOtherPlayer->PCAppearanceData.iY = otherPlr.y; - newOtherPlayer->PCAppearanceData.iZ = otherPlr.z; - newOtherPlayer->PCAppearanceData.iAngle = otherPlr.angle; - newOtherPlayer->PCAppearanceData.PCStyle = otherPlr.PCStyle; - memcpy(newOtherPlayer->PCAppearanceData.ItemEquip, otherPlr.Equip, sizeof(sItemBase) * AEQUIP_COUNT); + players[sock].viewable.push_back(otherSock); + players[otherSock].viewable.push_back(sock); + } + } - sock->sendPacket(new CNPacketData((void*)newOtherPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW), sock->getFEKey())); - otherSock->sendPacket(new CNPacketData((void*)newPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW), otherSock->getFEKey())); - - players[sock].viewable.push_back(otherSock); - players[otherSock].viewable.push_back(sock); - } - } + NPCManager::updatePlayerNPCS(sock, players[sock]); } void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_ENTER)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_ENTER)) + return; // ignore the malformed packet - sP_CL2FE_REQ_PC_ENTER* enter = (sP_CL2FE_REQ_PC_ENTER*)data->buf; - sP_FE2CL_REP_PC_ENTER_SUCC* response = (sP_FE2CL_REP_PC_ENTER_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_ENTER_SUCC)); + sP_CL2FE_REQ_PC_ENTER* enter = (sP_CL2FE_REQ_PC_ENTER*)data->buf; + sP_FE2CL_REP_PC_ENTER_SUCC* response = (sP_FE2CL_REP_PC_ENTER_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_ENTER_SUCC)); - // TODO: check if serialkey exists, if it doesn't send sP_FE2CL_REP_PC_ENTER_FAIL - Player plr = CNSharedData::getPlayer(enter->iEnterSerialKey); + // TODO: check if serialkey exists, if it doesn't send sP_FE2CL_REP_PC_ENTER_FAIL + Player plr = CNSharedData::getPlayer(enter->iEnterSerialKey); - DEBUGLOG( - std::cout << "P_CL2FE_REQ_PC_ENTER:" << std::endl; - std::cout << "\tID: " << U16toU8(enter->szID) << std::endl; - std::cout << "\tSerial: " << enter->iEnterSerialKey << std::endl; - std::cout << "\tTemp: " << enter->iTempValue << std::endl; - std::cout << "\tPC_UID: " << plr.PCStyle.iPC_UID << std::endl; - ) + DEBUGLOG( + std::cout << "P_CL2FE_REQ_PC_ENTER:" << std::endl; + std::cout << "\tID: " << U16toU8(enter->szID) << std::endl; + std::cout << "\tSerial: " << enter->iEnterSerialKey << std::endl; + std::cout << "\tTemp: " << enter->iTempValue << std::endl; + std::cout << "\tPC_UID: " << plr.PCStyle.iPC_UID << std::endl; + ) - response->iID = rand(); - response->uiSvrTime = getTime(); - response->PCLoadData2CL.iUserLevel = 1; - response->PCLoadData2CL.iHP = 1000 * plr.level; - response->PCLoadData2CL.iLevel = plr.level; - response->PCLoadData2CL.iMentor = 1; - response->PCLoadData2CL.iMentorCount = 4; - response->PCLoadData2CL.iMapNum = 0; - response->PCLoadData2CL.iX = plr.x; - response->PCLoadData2CL.iY = plr.y; - response->PCLoadData2CL.iZ = plr.z; - response->PCLoadData2CL.iActiveNanoSlotNum = -1; - response->PCLoadData2CL.iFatigue = 50; - response->PCLoadData2CL.PCStyle = plr.PCStyle; - response->PCLoadData2CL.PCStyle2 = plr.PCStyle2; + response->iID = rand(); + response->uiSvrTime = getTime(); + response->PCLoadData2CL.iUserLevel = 1; + response->PCLoadData2CL.iHP = 1000 * plr.level; + response->PCLoadData2CL.iLevel = plr.level; + response->PCLoadData2CL.iMentor = 1; + response->PCLoadData2CL.iMentorCount = 4; + response->PCLoadData2CL.iMapNum = 0; + response->PCLoadData2CL.iX = plr.x; + response->PCLoadData2CL.iY = plr.y; + response->PCLoadData2CL.iZ = plr.z; + response->PCLoadData2CL.iActiveNanoSlotNum = -1; + response->PCLoadData2CL.iFatigue = 50; + response->PCLoadData2CL.PCStyle = plr.PCStyle; + response->PCLoadData2CL.PCStyle2 = plr.PCStyle2; - for (int i = 0; i < AEQUIP_COUNT; i++) - response->PCLoadData2CL.aEquip[i] = plr.Equip[i]; + for (int i = 0; i < AEQUIP_COUNT; i++) + response->PCLoadData2CL.aEquip[i] = plr.Equip[i]; - //assign 37 nanos with something.hardcoded for now... - for (int i = 1; i < 37; i++) { - response->PCLoadData2CL.aNanoBank[i].iID = i; - response->PCLoadData2CL.aNanoBank[i].iSkillID = 2; - response->PCLoadData2CL.aNanoBank[i].iStamina = 150; - } + // don't ask.. + for (int i = 1; i < 37; i++) { + response->PCLoadData2CL.aNanoBank[i].iID = i; + response->PCLoadData2CL.aNanoBank[i].iSkillID = 1; + response->PCLoadData2CL.aNanoBank[i].iStamina = 150; + } - response->PCLoadData2CL.aNanoBank[1].iSkillID = 0; - response->PCLoadData2CL.aNanoBank[2].iSkillID = 0; - response->PCLoadData2CL.aNanoBank[3].iSkillID = 0; - response->PCLoadData2CL.aNanoSlots[0] = 1; - response->PCLoadData2CL.aNanoSlots[1] = 2; - response->PCLoadData2CL.aNanoSlots[2] = 3; + response->PCLoadData2CL.aNanoSlots[0] = 1; + response->PCLoadData2CL.aNanoSlots[1] = 2; + response->PCLoadData2CL.aNanoSlots[2] = 3; - response->PCLoadData2CL.aQuestFlag[0] = -1; + response->PCLoadData2CL.aQuestFlag[0] = -1; - plr.iID = response->iID; - plr.SerialKey = enter->iEnterSerialKey; - plr.HP = response->PCLoadData2CL.iHP; + plr.iID = response->iID; + plr.SerialKey = enter->iEnterSerialKey; + plr.HP = response->PCLoadData2CL.iHP; - sock->setEKey(CNSocketEncryption::createNewKey(response->uiSvrTime, response->iID + 1, response->PCLoadData2CL.iFusionMatter + 1)); - sock->setFEKey(plr.FEKey); + sock->setEKey(CNSocketEncryption::createNewKey(response->uiSvrTime, response->iID + 1, response->PCLoadData2CL.iFusionMatter + 1)); + sock->setFEKey(plr.FEKey); - sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_REP_PC_ENTER_SUCC, sizeof(sP_FE2CL_REP_PC_ENTER_SUCC), sock->getFEKey())); + sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_REP_PC_ENTER_SUCC, sizeof(sP_FE2CL_REP_PC_ENTER_SUCC), sock->getFEKey())); - addPlayer(sock, plr); + addPlayer(sock, plr); } void PlayerManager::loadPlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_LOADING_COMPLETE)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_LOADING_COMPLETE)) + return; // ignore the malformed packet - sP_CL2FE_REQ_PC_LOADING_COMPLETE* complete = (sP_CL2FE_REQ_PC_LOADING_COMPLETE*)data->buf; - sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC* response = (sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC)); - sP_FE2CL_PC_MOTD_LOGIN* motd = (sP_FE2CL_PC_MOTD_LOGIN*)xmalloc(sizeof(sP_FE2CL_PC_MOTD_LOGIN)); + sP_CL2FE_REQ_PC_LOADING_COMPLETE* complete = (sP_CL2FE_REQ_PC_LOADING_COMPLETE*)data->buf; + sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC* response = (sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC)); + sP_FE2CL_PC_MOTD_LOGIN* motd = (sP_FE2CL_PC_MOTD_LOGIN*)xmalloc(sizeof(sP_FE2CL_PC_MOTD_LOGIN)); - DEBUGLOG( - std::cout << "P_CL2FE_REQ_PC_LOADING_COMPLETE:" << std::endl; - std::cout << "\tPC_ID: " << complete->iPC_ID << std::endl; - ) + DEBUGLOG( + std::cout << "P_CL2FE_REQ_PC_LOADING_COMPLETE:" << std::endl; + std::cout << "\tPC_ID: " << complete->iPC_ID << std::endl; + ) - response->iPC_ID = complete->iPC_ID; + response->iPC_ID = complete->iPC_ID; - motd->iType = 1; - U8toU16(settings::MOTDSTRING, (char16_t*)motd->szSystemMsg); + motd->iType = 1; + U8toU16(settings::MOTDSTRING, (char16_t*)motd->szSystemMsg); - sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_REP_PC_LOADING_COMPLETE_SUCC, sizeof(sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC), sock->getFEKey())); - sock->sendPacket(new CNPacketData((void*)motd, P_FE2CL_PC_MOTD_LOGIN, sizeof(sP_FE2CL_PC_MOTD_LOGIN), sock->getFEKey())); + sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_REP_PC_LOADING_COMPLETE_SUCC, sizeof(sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC), sock->getFEKey())); + sock->sendPacket(new CNPacketData((void*)motd, P_FE2CL_PC_MOTD_LOGIN, sizeof(sP_FE2CL_PC_MOTD_LOGIN), sock->getFEKey())); } void PlayerManager::movePlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_MOVE)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_MOVE)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_MOVE* moveData = (sP_CL2FE_REQ_PC_MOVE*)data->buf; + updatePlayerPosition(sock, moveData->iX, moveData->iY, moveData->iZ); - sP_CL2FE_REQ_PC_MOVE* moveData = (sP_CL2FE_REQ_PC_MOVE*)data->buf; - updatePlayerPosition(sock, moveData->iX, moveData->iY, moveData->iZ); + players[sock].plr.angle = moveData->iAngle; + uint64_t tm = getTime(); - players[sock].plr.angle = moveData->iAngle; - uint64_t tm = getTime(); + for (CNSocket* otherSock : players[sock].viewable) { + sP_FE2CL_PC_MOVE* moveResponse = (sP_FE2CL_PC_MOVE*)xmalloc(sizeof(sP_FE2CL_PC_MOVE)); - for (CNSocket* otherSock : players[sock].viewable) { - sP_FE2CL_PC_MOVE* moveResponse = (sP_FE2CL_PC_MOVE*)xmalloc(sizeof(sP_FE2CL_PC_MOVE)); + moveResponse->iID = players[sock].plr.iID; + moveResponse->cKeyValue = moveData->cKeyValue; - moveResponse->iID = players[sock].plr.iID; - moveResponse->cKeyValue = moveData->cKeyValue; + moveResponse->iX = moveData->iX; + moveResponse->iY = moveData->iY; + moveResponse->iZ = moveData->iZ; + moveResponse->iAngle = moveData->iAngle; + moveResponse->fVX = moveData->fVX; + moveResponse->fVY = moveData->fVY; + moveResponse->fVZ = moveData->fVZ; + + moveResponse->iSpeed = moveData->iSpeed; + moveResponse->iCliTime = moveData->iCliTime; // maybe don't send this??? seems unneeded... + moveResponse->iSvrTime = tm; - moveResponse->iX = moveData->iX; - moveResponse->iY = moveData->iY; - moveResponse->iZ = moveData->iZ; - moveResponse->iAngle = moveData->iAngle; - moveResponse->fVX = moveData->fVX; - moveResponse->fVY = moveData->fVY; - moveResponse->fVZ = moveData->fVZ; - - moveResponse->iSpeed = moveData->iSpeed; - moveResponse->iCliTime = moveData->iCliTime; // maybe don't send this??? seems unneeded... - moveResponse->iSvrTime = tm; - - otherSock->sendPacket(new CNPacketData((void*)moveResponse, P_FE2CL_PC_MOVE, sizeof(sP_FE2CL_PC_MOVE), otherSock->getFEKey())); - } + otherSock->sendPacket(new CNPacketData((void*)moveResponse, P_FE2CL_PC_MOVE, sizeof(sP_FE2CL_PC_MOVE), otherSock->getFEKey())); + } } void PlayerManager::stopPlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_STOP)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_STOP)) + return; // ignore the malformed packet - sP_CL2FE_REQ_PC_STOP* stopData = (sP_CL2FE_REQ_PC_STOP*)data->buf; - updatePlayerPosition(sock, stopData->iX, stopData->iY, stopData->iZ); + sP_CL2FE_REQ_PC_STOP* stopData = (sP_CL2FE_REQ_PC_STOP*)data->buf; + updatePlayerPosition(sock, stopData->iX, stopData->iY, stopData->iZ); - uint64_t tm = getTime(); + uint64_t tm = getTime(); - for (CNSocket* otherSock : players[sock].viewable) { - sP_FE2CL_PC_STOP* stopResponse = (sP_FE2CL_PC_STOP*)xmalloc(sizeof(sP_FE2CL_PC_STOP)); + for (CNSocket* otherSock : players[sock].viewable) { + sP_FE2CL_PC_STOP* stopResponse = (sP_FE2CL_PC_STOP*)xmalloc(sizeof(sP_FE2CL_PC_STOP)); - stopResponse->iID = players[sock].plr.iID; + stopResponse->iID = players[sock].plr.iID; - stopResponse->iX = stopData->iX; - stopResponse->iY = stopData->iY; - stopResponse->iZ = stopData->iZ; + stopResponse->iX = stopData->iX; + stopResponse->iY = stopData->iY; + stopResponse->iZ = stopData->iZ; - stopResponse->iCliTime = stopData->iCliTime; // maybe don't send this??? seems unneeded... - stopResponse->iSvrTime = tm; + stopResponse->iCliTime = stopData->iCliTime; // maybe don't send this??? seems unneeded... + stopResponse->iSvrTime = tm; - otherSock->sendPacket(new CNPacketData((void*)stopResponse, P_FE2CL_PC_STOP, sizeof(sP_FE2CL_PC_STOP), otherSock->getFEKey())); - } + otherSock->sendPacket(new CNPacketData((void*)stopResponse, P_FE2CL_PC_STOP, sizeof(sP_FE2CL_PC_STOP), otherSock->getFEKey())); + } } void PlayerManager::jumpPlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_JUMP)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_JUMP)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_JUMP* jumpData = (sP_CL2FE_REQ_PC_JUMP*)data->buf; + updatePlayerPosition(sock, jumpData->iX, jumpData->iY, jumpData->iZ); - sP_CL2FE_REQ_PC_JUMP* jumpData = (sP_CL2FE_REQ_PC_JUMP*)data->buf; - updatePlayerPosition(sock, jumpData->iX, jumpData->iY, jumpData->iZ); + uint64_t tm = getTime(); - uint64_t tm = getTime(); + for (CNSocket* otherSock : players[sock].viewable) { + sP_FE2CL_PC_JUMP* jumpResponse = (sP_FE2CL_PC_JUMP*)xmalloc(sizeof(sP_FE2CL_PC_JUMP)); - for (CNSocket* otherSock : players[sock].viewable) { - sP_FE2CL_PC_JUMP* jumpResponse = (sP_FE2CL_PC_JUMP*)xmalloc(sizeof(sP_FE2CL_PC_JUMP)); + jumpResponse->iID = players[sock].plr.iID; + jumpResponse->cKeyValue = jumpData->cKeyValue; - jumpResponse->iID = players[sock].plr.iID; - jumpResponse->cKeyValue = jumpData->cKeyValue; + jumpResponse->iX = jumpData->iX; + jumpResponse->iY = jumpData->iY; + jumpResponse->iZ = jumpData->iZ; + jumpResponse->iAngle = jumpData->iAngle; + jumpResponse->iVX = jumpData->iVX; + jumpResponse->iVY = jumpData->iVY; + jumpResponse->iVZ = jumpData->iVZ; + + jumpResponse->iSpeed = jumpData->iSpeed; + jumpResponse->iCliTime = jumpData->iCliTime; // maybe don't send this??? seems unneeded... + jumpResponse->iSvrTime = tm; - jumpResponse->iX = jumpData->iX; - jumpResponse->iY = jumpData->iY; - jumpResponse->iZ = jumpData->iZ; - jumpResponse->iAngle = jumpData->iAngle; - jumpResponse->iVX = jumpData->iVX; - jumpResponse->iVY = jumpData->iVY; - jumpResponse->iVZ = jumpData->iVZ; - - jumpResponse->iSpeed = jumpData->iSpeed; - jumpResponse->iCliTime = jumpData->iCliTime; // maybe don't send this??? seems unneeded... - jumpResponse->iSvrTime = tm; - - otherSock->sendPacket(new CNPacketData((void*)jumpResponse, P_FE2CL_PC_JUMP, sizeof(sP_FE2CL_PC_JUMP), otherSock->getFEKey())); - } + otherSock->sendPacket(new CNPacketData((void*)jumpResponse, P_FE2CL_PC_JUMP, sizeof(sP_FE2CL_PC_JUMP), otherSock->getFEKey())); + } } void PlayerManager::jumppadPlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_JUMPPAD)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_JUMPPAD)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_JUMPPAD* jumppadData = (sP_CL2FE_REQ_PC_JUMPPAD*)data->buf; + updatePlayerPosition(sock, jumppadData->iX, jumppadData->iY, jumppadData->iZ); - sP_CL2FE_REQ_PC_JUMPPAD* jumppadData = (sP_CL2FE_REQ_PC_JUMPPAD*)data->buf; - updatePlayerPosition(sock, jumppadData->iX, jumppadData->iY, jumppadData->iZ); + uint64_t tm = getTime(); - uint64_t tm = getTime(); + for (CNSocket* otherSock : players[sock].viewable) { + sP_FE2CL_PC_JUMPPAD* jumppadResponse = (sP_FE2CL_PC_JUMPPAD*)xmalloc(sizeof(sP_FE2CL_PC_JUMPPAD)); - for (CNSocket* otherSock : players[sock].viewable) { - sP_FE2CL_PC_JUMPPAD* jumppadResponse = (sP_FE2CL_PC_JUMPPAD*)xmalloc(sizeof(sP_FE2CL_PC_JUMPPAD)); + jumppadResponse->iPC_ID = players[sock].plr.iID; + jumppadResponse->cKeyValue = jumppadData->cKeyValue; - jumppadResponse->iPC_ID = players[sock].plr.iID; - jumppadResponse->cKeyValue = jumppadData->cKeyValue; + jumppadResponse->iX = jumppadData->iX; + jumppadResponse->iY = jumppadData->iY; + jumppadResponse->iZ = jumppadData->iZ; + jumppadResponse->iVX = jumppadData->iVX; + jumppadResponse->iVY = jumppadData->iVY; + jumppadResponse->iVZ = jumppadData->iVZ; + + jumppadResponse->iCliTime = jumppadData->iCliTime; + jumppadResponse->iSvrTime = tm; - jumppadResponse->iX = jumppadData->iX; - jumppadResponse->iY = jumppadData->iY; - jumppadResponse->iZ = jumppadData->iZ; - jumppadResponse->iVX = jumppadData->iVX; - jumppadResponse->iVY = jumppadData->iVY; - jumppadResponse->iVZ = jumppadData->iVZ; - - jumppadResponse->iCliTime = jumppadData->iCliTime; - jumppadResponse->iSvrTime = tm; - - otherSock->sendPacket(new CNPacketData((void*)jumppadResponse, P_FE2CL_PC_JUMPPAD, sizeof(sP_FE2CL_PC_JUMPPAD), otherSock->getFEKey())); - } + otherSock->sendPacket(new CNPacketData((void*)jumppadResponse, P_FE2CL_PC_JUMPPAD, sizeof(sP_FE2CL_PC_JUMPPAD), otherSock->getFEKey())); + } } void PlayerManager::launchPlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_LAUNCHER)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_LAUNCHER)) + return; // ignore the malformed packet + + sP_CL2FE_REQ_PC_LAUNCHER* launchData = (sP_CL2FE_REQ_PC_LAUNCHER*)data->buf; + updatePlayerPosition(sock, launchData->iX, launchData->iY, launchData->iZ); - sP_CL2FE_REQ_PC_LAUNCHER* launchData = (sP_CL2FE_REQ_PC_LAUNCHER*)data->buf; - updatePlayerPosition(sock, launchData->iX, launchData->iY, launchData->iZ); + uint64_t tm = getTime(); - uint64_t tm = getTime(); + for (CNSocket* otherSock : players[sock].viewable) { + sP_FE2CL_PC_LAUNCHER* launchResponse = (sP_FE2CL_PC_LAUNCHER*)xmalloc(sizeof(sP_FE2CL_PC_LAUNCHER)); - for (CNSocket* otherSock : players[sock].viewable) { - sP_FE2CL_PC_LAUNCHER* launchResponse = (sP_FE2CL_PC_LAUNCHER*)xmalloc(sizeof(sP_FE2CL_PC_LAUNCHER)); + launchResponse->iPC_ID = players[sock].plr.iID; - launchResponse->iPC_ID = players[sock].plr.iID; + launchResponse->iX = launchData->iX; + launchResponse->iY = launchData->iY; + launchResponse->iZ = launchData->iZ; + launchResponse->iVX = launchData->iVX; + launchResponse->iVY = launchData->iVY; + launchResponse->iVZ = launchData->iVZ; + launchResponse->iSpeed = launchData->iSpeed; + launchResponse->iAngle = launchData->iAngle; + + launchResponse->iCliTime = launchData->iCliTime; + launchResponse->iSvrTime = tm; - launchResponse->iX = launchData->iX; - launchResponse->iY = launchData->iY; - launchResponse->iZ = launchData->iZ; - launchResponse->iVX = launchData->iVX; - launchResponse->iVY = launchData->iVY; - launchResponse->iVZ = launchData->iVZ; - launchResponse->iSpeed = launchData->iSpeed; - launchResponse->iAngle = launchData->iAngle; - - launchResponse->iCliTime = launchData->iCliTime; - launchResponse->iSvrTime = tm; - - otherSock->sendPacket(new CNPacketData((void*)launchResponse, P_FE2CL_PC_LAUNCHER, sizeof(sP_FE2CL_PC_LAUNCHER), otherSock->getFEKey())); - } + otherSock->sendPacket(new CNPacketData((void*)launchResponse, P_FE2CL_PC_LAUNCHER, sizeof(sP_FE2CL_PC_LAUNCHER), otherSock->getFEKey())); + } } void PlayerManager::ziplinePlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_ZIPLINE)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_ZIPLINE)) + return; // ignore the malformed packet - sP_CL2FE_REQ_PC_ZIPLINE* ziplineData = (sP_CL2FE_REQ_PC_ZIPLINE*)data->buf; - updatePlayerPosition(sock, ziplineData->iX, ziplineData->iY, ziplineData->iZ); + sP_CL2FE_REQ_PC_ZIPLINE* ziplineData = (sP_CL2FE_REQ_PC_ZIPLINE*)data->buf; + updatePlayerPosition(sock, ziplineData->iX, ziplineData->iY, ziplineData->iZ); - uint64_t tm = getTime(); + uint64_t tm = getTime(); - for (CNSocket* otherSock : players[sock].viewable) { + for (CNSocket* otherSock : players[sock].viewable) { - sP_FE2CL_PC_ZIPLINE* ziplineResponse = (sP_FE2CL_PC_ZIPLINE*)xmalloc(sizeof(sP_FE2CL_PC_ZIPLINE)); + sP_FE2CL_PC_ZIPLINE* ziplineResponse = (sP_FE2CL_PC_ZIPLINE*)xmalloc(sizeof(sP_FE2CL_PC_ZIPLINE)); - ziplineResponse->iPC_ID = players[sock].plr.iID; - ziplineResponse->iCliTime = ziplineData->iCliTime; - ziplineResponse->iSvrTime = tm; - ziplineResponse->iX = ziplineData->iX; - ziplineResponse->iY = ziplineData->iY; - ziplineResponse->iZ = ziplineData->iZ; - ziplineResponse->fVX = ziplineData->fVX; - ziplineResponse->fVY = ziplineData->fVY; - ziplineResponse->fVZ = ziplineData->fVZ; - ziplineResponse->fMovDistance = ziplineData->fMovDistance; - ziplineResponse->fMaxDistance = ziplineData->fMaxDistance; - ziplineResponse->fDummy = ziplineData->fDummy; //wtf is this for? - ziplineResponse->iStX = ziplineData->iStX; - ziplineResponse->iStY = ziplineData->iStY; - ziplineResponse->iStZ = ziplineData->iStZ; - ziplineResponse->bDown = ziplineData->bDown; - ziplineResponse->iSpeed = ziplineData->iSpeed; - ziplineResponse->iAngle = ziplineData->iAngle; - ziplineResponse->iRollMax = ziplineData->iRollMax; - ziplineResponse->iRoll = ziplineData->iRoll; + ziplineResponse->iPC_ID = players[sock].plr.iID; + ziplineResponse->iCliTime = ziplineData->iCliTime; + ziplineResponse->iSvrTime = tm; + ziplineResponse->iX = ziplineData->iX; + ziplineResponse->iY = ziplineData->iY; + ziplineResponse->iZ = ziplineData->iZ; + ziplineResponse->fVX = ziplineData->fVX; + ziplineResponse->fVY = ziplineData->fVY; + ziplineResponse->fVZ = ziplineData->fVZ; + ziplineResponse->fMovDistance = ziplineData->fMovDistance; + ziplineResponse->fMaxDistance = ziplineData->fMaxDistance; + ziplineResponse->fDummy = ziplineData->fDummy; //wtf is this for? + ziplineResponse->iStX = ziplineData->iStX; + ziplineResponse->iStY = ziplineData->iStY; + ziplineResponse->iStZ = ziplineData->iStZ; + ziplineResponse->bDown = ziplineData->bDown; + ziplineResponse->iSpeed = ziplineData->iSpeed; + ziplineResponse->iAngle = ziplineData->iAngle; + ziplineResponse->iRollMax = ziplineData->iRollMax; + ziplineResponse->iRoll = ziplineData->iRoll; - otherSock->sendPacket(new CNPacketData((void*)ziplineResponse, P_FE2CL_PC_ZIPLINE, sizeof(sP_FE2CL_PC_ZIPLINE), otherSock->getFEKey())); - } + otherSock->sendPacket(new CNPacketData((void*)ziplineResponse, P_FE2CL_PC_ZIPLINE, sizeof(sP_FE2CL_PC_ZIPLINE), otherSock->getFEKey())); + } } void PlayerManager::movePlatformPlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_MOVEPLATFORM)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_MOVEPLATFORM)) + return; // ignore the malformed packet - sP_CL2FE_REQ_PC_MOVEPLATFORM* platformData = (sP_CL2FE_REQ_PC_MOVEPLATFORM*)data->buf; - updatePlayerPosition(sock, platformData->iX, platformData->iY, platformData->iZ); + sP_CL2FE_REQ_PC_MOVEPLATFORM* platformData = (sP_CL2FE_REQ_PC_MOVEPLATFORM*)data->buf; + updatePlayerPosition(sock, platformData->iX, platformData->iY, platformData->iZ); - uint64_t tm = getTime(); + uint64_t tm = getTime(); - for (CNSocket* otherSock : players[sock].viewable) { + for (CNSocket* otherSock : players[sock].viewable) { - sP_FE2CL_PC_MOVEPLATFORM* platResponse = (sP_FE2CL_PC_MOVEPLATFORM*)xmalloc(sizeof(sP_FE2CL_PC_MOVEPLATFORM)); + sP_FE2CL_PC_MOVEPLATFORM* platResponse = (sP_FE2CL_PC_MOVEPLATFORM*)xmalloc(sizeof(sP_FE2CL_PC_MOVEPLATFORM)); - platResponse->iPC_ID = players[sock].plr.iID; - platResponse->iCliTime = platformData->iCliTime; - platResponse->iSvrTime = tm; - platResponse->iX = platformData->iX; - platResponse->iY = platformData->iY; - platResponse->iZ = platformData->iZ; - platResponse->iAngle = platformData->iAngle; - platResponse->fVX = platformData->fVX; - platResponse->fVY = platformData->fVY; - platResponse->fVZ = platformData->fVZ; - platResponse->iLcX = platformData->iLcX; - platResponse->iLcY = platformData->iLcY; - platResponse->iLcZ = platformData->iLcZ; - platResponse->iSpeed = platformData->iSpeed; - platResponse->bDown = platformData->bDown; - platResponse->cKeyValue = platformData->cKeyValue; - platResponse->iPlatformID = platformData->iPlatformID; + platResponse->iPC_ID = players[sock].plr.iID; + platResponse->iCliTime = platformData->iCliTime; + platResponse->iSvrTime = tm; + platResponse->iX = platformData->iX; + platResponse->iY = platformData->iY; + platResponse->iZ = platformData->iZ; + platResponse->iAngle = platformData->iAngle; + platResponse->fVX = platformData->fVX; + platResponse->fVY = platformData->fVY; + platResponse->fVZ = platformData->fVZ; + platResponse->iLcX = platformData->iLcX; + platResponse->iLcY = platformData->iLcY; + platResponse->iLcZ = platformData->iLcZ; + platResponse->iSpeed = platformData->iSpeed; + platResponse->bDown = platformData->bDown; + platResponse->cKeyValue = platformData->cKeyValue; + platResponse->iPlatformID = platformData->iPlatformID; - otherSock->sendPacket(new CNPacketData((void*)platResponse, P_FE2CL_PC_MOVEPLATFORM, sizeof(sP_FE2CL_PC_MOVEPLATFORM), otherSock->getFEKey())); - } + otherSock->sendPacket(new CNPacketData((void*)platResponse, P_FE2CL_PC_MOVEPLATFORM, sizeof(sP_FE2CL_PC_MOVEPLATFORM), otherSock->getFEKey())); + } } void PlayerManager::moveSlopePlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_SLOPE)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_SLOPE)) + return; // ignore the malformed packet - sP_CL2FE_REQ_PC_SLOPE* slopeData = (sP_CL2FE_REQ_PC_SLOPE*)data->buf; - updatePlayerPosition(sock, slopeData->iX, slopeData->iY, slopeData->iZ); + sP_CL2FE_REQ_PC_SLOPE* slopeData = (sP_CL2FE_REQ_PC_SLOPE*)data->buf; + updatePlayerPosition(sock, slopeData->iX, slopeData->iY, slopeData->iZ); - uint64_t tm = getTime(); + uint64_t tm = getTime(); - for (CNSocket* otherSock : players[sock].viewable) { + for (CNSocket* otherSock : players[sock].viewable) { - sP_FE2CL_PC_SLOPE* slopeResponse = (sP_FE2CL_PC_SLOPE*)xmalloc(sizeof(sP_FE2CL_PC_SLOPE)); + sP_FE2CL_PC_SLOPE* slopeResponse = (sP_FE2CL_PC_SLOPE*)xmalloc(sizeof(sP_FE2CL_PC_SLOPE)); - slopeResponse->iPC_ID = players[sock].plr.iID; - slopeResponse->iCliTime = slopeData->iCliTime; - slopeResponse->iSvrTime = tm; - slopeResponse->iX = slopeData->iX; - slopeResponse->iY = slopeData->iY; - slopeResponse->iZ = slopeData->iZ; - slopeResponse->iAngle = slopeData->iAngle; - slopeResponse->fVX = slopeData->fVX; - slopeResponse->fVY = slopeData->fVY; - slopeResponse->fVZ = slopeData->fVZ; - slopeResponse->iSpeed = slopeData->iSpeed; - slopeResponse->cKeyValue = slopeData->cKeyValue; - slopeResponse->iSlopeID = slopeData->iSlopeID; + slopeResponse->iPC_ID = players[sock].plr.iID; + slopeResponse->iCliTime = slopeData->iCliTime; + slopeResponse->iSvrTime = tm; + slopeResponse->iX = slopeData->iX; + slopeResponse->iY = slopeData->iY; + slopeResponse->iZ = slopeData->iZ; + slopeResponse->iAngle = slopeData->iAngle; + slopeResponse->fVX = slopeData->fVX; + slopeResponse->fVY = slopeData->fVY; + slopeResponse->fVZ = slopeData->fVZ; + slopeResponse->iSpeed = slopeData->iSpeed; + slopeResponse->cKeyValue = slopeData->cKeyValue; + slopeResponse->iSlopeID = slopeData->iSlopeID; - otherSock->sendPacket(new CNPacketData((void*)slopeResponse, P_FE2CL_PC_SLOPE, sizeof(sP_FE2CL_PC_SLOPE), otherSock->getFEKey())); - } + otherSock->sendPacket(new CNPacketData((void*)slopeResponse, P_FE2CL_PC_SLOPE, sizeof(sP_FE2CL_PC_SLOPE), otherSock->getFEKey())); + } } void PlayerManager::gotoPlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_REQ_PC_GOTO)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_REQ_PC_GOTO)) + return; // ignore the malformed packet - sP_CL2FE_REQ_PC_GOTO* gotoData = (sP_CL2FE_REQ_PC_GOTO*)data->buf; - sP_FE2CL_REP_PC_GOTO_SUCC* response = (sP_FE2CL_REP_PC_GOTO_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_GOTO_SUCC)); + sP_CL2FE_REQ_PC_GOTO* gotoData = (sP_CL2FE_REQ_PC_GOTO*)data->buf; + sP_FE2CL_REP_PC_GOTO_SUCC* response = (sP_FE2CL_REP_PC_GOTO_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_GOTO_SUCC)); - DEBUGLOG( - std::cout << "P_CL2FE_REQ_PC_GOTO:" << std::endl; - std::cout << "\tX: " << gotoData->iToX << std::endl; - std::cout << "\tY: " << gotoData->iToY << std::endl; - std::cout << "\tZ: " << gotoData->iToZ << std::endl; - ) + DEBUGLOG( + std::cout << "P_CL2FE_REQ_PC_GOTO:" << std::endl; + std::cout << "\tX: " << gotoData->iToX << std::endl; + std::cout << "\tY: " << gotoData->iToY << std::endl; + std::cout << "\tZ: " << gotoData->iToZ << std::endl; + ) - response->iX = gotoData->iToX; - response->iY = gotoData->iToY; - response->iZ = gotoData->iToZ; + response->iX = gotoData->iToX; + response->iY = gotoData->iToY; + response->iZ = gotoData->iToZ; - sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_REP_PC_GOTO_SUCC, sizeof(sP_FE2CL_REP_PC_GOTO_SUCC), sock->getFEKey())); + sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_REP_PC_GOTO_SUCC, sizeof(sP_FE2CL_REP_PC_GOTO_SUCC), sock->getFEKey())); } void PlayerManager::setSpecialPlayer(CNSocket* sock, CNPacketData* data) { - if (data->size != sizeof(sP_CL2FE_GM_REQ_PC_SET_VALUE)) - return; // ignore the malformed packet + if (data->size != sizeof(sP_CL2FE_GM_REQ_PC_SET_VALUE)) + return; // ignore the malformed packet - sP_CL2FE_GM_REQ_PC_SET_VALUE* setData = (sP_CL2FE_GM_REQ_PC_SET_VALUE*)data->buf; - sP_FE2CL_GM_REP_PC_SET_VALUE* response = (sP_FE2CL_GM_REP_PC_SET_VALUE*)xmalloc(sizeof(sP_FE2CL_GM_REP_PC_SET_VALUE)); + sP_CL2FE_GM_REQ_PC_SET_VALUE* setData = (sP_CL2FE_GM_REQ_PC_SET_VALUE*)data->buf; + sP_FE2CL_GM_REP_PC_SET_VALUE* response = (sP_FE2CL_GM_REP_PC_SET_VALUE*)xmalloc(sizeof(sP_FE2CL_GM_REP_PC_SET_VALUE)); - DEBUGLOG( - std::cout << "P_CL2FE_GM_REQ_PC_SET_VALUE:" << std::endl; - std::cout << "\tPC_ID: " << setData->iPC_ID << std::endl; - std::cout << "\tSetValueType: " << setData->iSetValueType << std::endl; - std::cout << "\tSetValue: " << setData->iSetValue << std::endl; - ) + DEBUGLOG( + std::cout << "P_CL2FE_GM_REQ_PC_SET_VALUE:" << std::endl; + std::cout << "\tPC_ID: " << setData->iPC_ID << std::endl; + std::cout << "\tSetValueType: " << setData->iSetValueType << std::endl; + std::cout << "\tSetValue: " << setData->iSetValue << std::endl; + ) - response->iPC_ID = setData->iPC_ID; - response->iSetValue = setData->iSetValue; - response->iSetValueType = setData->iSetValueType; + response->iPC_ID = setData->iPC_ID; + response->iSetValue = setData->iSetValue; + response->iSetValueType = setData->iSetValueType; - sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_GM_REP_PC_SET_VALUE, sizeof(sP_FE2CL_GM_REP_PC_SET_VALUE), sock->getFEKey())); + sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_GM_REP_PC_SET_VALUE, sizeof(sP_FE2CL_GM_REP_PC_SET_VALUE), sock->getFEKey())); } void PlayerManager::heartbeatPlayer(CNSocket* sock, CNPacketData* data) { - players[sock].lastHeartbeat = getTime(); + players[sock].lastHeartbeat = getTime(); } void PlayerManager::exitGame(CNSocket* sock, CNPacketData* data) { - sP_CL2FE_REQ_PC_EXIT* exitData = (sP_CL2FE_REQ_PC_EXIT*)data->buf; - sP_FE2CL_REP_PC_EXIT_SUCC* response = (sP_FE2CL_REP_PC_EXIT_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_EXIT_SUCC)); + sP_CL2FE_REQ_PC_EXIT* exitData = (sP_CL2FE_REQ_PC_EXIT*)data->buf; + sP_FE2CL_REP_PC_EXIT_SUCC* response = (sP_FE2CL_REP_PC_EXIT_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_EXIT_SUCC)); - response->iID = exitData->iID; - response->iExitCode = 1; + response->iID = exitData->iID; + response->iExitCode = 1; - sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_REP_PC_EXIT_SUCC, sizeof(sP_FE2CL_REP_PC_EXIT_SUCC), sock->getFEKey())); + sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_REP_PC_EXIT_SUCC, sizeof(sP_FE2CL_REP_PC_EXIT_SUCC), sock->getFEKey())); } - -void PlayerManager::updatePlayer(CNSocket* key, Player plr) { - PlayerView plrv = players[key]; - plrv.plr = plr; - - players[key] = plrv; -} - -void PlayerManager::onPlayerSpawn(CNSocket* sock, CNPacketData* data) { -} \ No newline at end of file diff --git a/src/PlayerManager.hpp b/src/PlayerManager.hpp index 0d5ffb7..34ca836 100644 --- a/src/PlayerManager.hpp +++ b/src/PlayerManager.hpp @@ -11,6 +11,7 @@ struct PlayerView { std::list viewable; + std::list viewableNPCs; Player plr; int long lastHeartbeat; }; diff --git a/src/main.cpp b/src/main.cpp index 0fc3af6..56e9055 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,7 +2,9 @@ #include "CNShardServer.hpp" #include "PlayerManager.hpp" #include "ChatManager.hpp" +#include "ItemManager.hpp" #include "NanoManager.hpp" +#include "NPCManager.hpp" #include "settings.hpp" @@ -29,7 +31,9 @@ int main() { std::cout << "[INFO] Intializing Packet Managers..." << std::endl; PlayerManager::init(); ChatManager::init(); + ItemManager::init(); NanoManager::init(); + NPCManager::init(); std::cout << "[INFO] Starting Server Threads..." << std::endl; CNLoginServer loginServer(settings::LOGINPORT); diff --git a/src/structs/0104.hpp b/src/structs/0104.hpp index e238410..bd70161 100644 --- a/src/structs/0104.hpp +++ b/src/structs/0104.hpp @@ -1,6 +1,7 @@ /* genstructs.py */ #define AEQUIP_COUNT 9 +#define AINVEN_COUNT 50 #pragma pack(push) diff --git a/src/structs/0728.hpp b/src/structs/0728.hpp index 036c23b..27bbd47 100644 --- a/src/structs/0728.hpp +++ b/src/structs/0728.hpp @@ -1,6 +1,7 @@ /* genstructs.py */ #define AEQUIP_COUNT 12 +#define AINVEN_COUNT 50 #pragma pack(push)