Merge remote-tracking branch 'upstream/master' into Test

This commit is contained in:
Onii-chan
2020-08-22 13:32:48 +02:00
21 changed files with 25667 additions and 63 deletions

View File

@@ -4,11 +4,11 @@ project(OpenFusion)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
# OpenFusion supports multiple packet/struct versions # OpenFusion supports multiple packet/struct versions
# 0104 is the default version to build which can be changed # 104 is the default version to build which can be changed
# For example: cmake -B build -DPACKET_VERSION=0728 # For example: cmake -B build -DPROTOCOL_VERSION=728
OPTION(PACKET_VERSION "The packet version to build" "0104") set(PROTOCOL_VERSION 104 CACHE STRING "The packet version to build")
ADD_DEFINITIONS(-DCNPROTO_OVERRIDE -DCNPROTO_VERSION_${PACKET_VERSION}) add_compile_definitions(PROTOCOL_VERSION=${PROTOCOL_VERSION})
# Disallow in-source builds # Disallow in-source builds
if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})

View File

@@ -1,13 +1,17 @@
CXX=clang++ CXX=clang++
# -w suppresses all warnings (the part that's commented out helps me find memory leaks, it ruins performance though!) # -w suppresses all warnings (the part that's commented out helps me find memory leaks, it ruins performance though!)
CXXFLAGS=-std=c++17 -O3 #-g3 -fsanitize=address CXXFLAGS=-std=c++17 -O3 -DPROTOCOL_VERSION=$(PROTOCOL_VERSION) #-g3 -fsanitize=address
LDFLAGS=-lpthread LDFLAGS=-lpthread
# specifies the name of our exectuable # specifies the name of our exectuable
SERVER=bin/fusion SERVER=bin/fusion
# assign protocol version
# this can be overriden by ex. make PROTOCOL_VERSION=728
PROTOCOL_VERSION?=104
# Windows-specific # Windows-specific
WIN_CXX=x86_64-w64-mingw32-g++ WIN_CXX=x86_64-w64-mingw32-g++
WIN_CXXFLAGS=-std=c++17 -O3 #-g3 -fsanitize=address WIN_CXXFLAGS=-std=c++17 -O3 -DPROTOCOL_VERSION=$(PROTOCOL_VERSION) #-g3 -fsanitize=address
WIN_LDFLAGS=-static -lws2_32 -lwsock32 WIN_LDFLAGS=-static -lws2_32 -lwsock32
WIN_SERVER=bin/winfusion.exe WIN_SERVER=bin/winfusion.exe
@@ -35,7 +39,8 @@ HDR=\
src/CNShardServer.hpp\ src/CNShardServer.hpp\
src/CNShared.hpp\ src/CNShared.hpp\
src/CNStructs.hpp\ src/CNStructs.hpp\
src/INIReader.hpp\ src/contrib/INIReader.hpp\
src/contrib/JSON.hpp\
src/NanoManager.hpp\ src/NanoManager.hpp\
src/ItemManager.hpp\ src/ItemManager.hpp\
src/NPCManager.hpp\ src/NPCManager.hpp\
@@ -49,7 +54,7 @@ all: $(SERVER)
windows: $(SERVER) windows: $(SERVER)
# Assign Windows-specific values if targeting Windows # assign Windows-specific values if targeting Windows
windows : CXX=$(WIN_CXX) windows : CXX=$(WIN_CXX)
windows : CXXFLAGS=$(WIN_CXXFLAGS) windows : CXXFLAGS=$(WIN_CXXFLAGS)
windows : LDFLAGS=$(WIN_LDFLAGS) windows : LDFLAGS=$(WIN_LDFLAGS)

1
NPCs.json Normal file

File diff suppressed because one or more lines are too long

View File

@@ -15,10 +15,24 @@ for:
matrix: matrix:
only: only:
- image: Ubuntu2004 - image: Ubuntu2004
before_build:
- mkdir -p bin
build_script: build_script:
- make - ps: |
$versions = "104", "728"
foreach ($version in $versions) {
Write-Output "Cleaning old output"
Invoke-Expression "make clean"
if ($LASTEXITCODE -ne "0") {
Write-Error "make clean failed for version $version" -ErrorAction Stop
}
Write-Output "Building version $version"
Invoke-Expression "make PROTOCOL_VERSION=$version"
if ($LASTEXITCODE -ne "0") {
Write-Error "make failed for version $version" -ErrorAction Stop
}
Rename-Item -Path "bin/fusion" -newName "$version-fusion"
Write-Output "Built version $version"
}
artifacts: artifacts:
- path: bin - path: bin
name: ubuntu20_04-bin-x64 name: ubuntu20_04-bin-x64
@@ -29,7 +43,7 @@ for:
- image: Visual Studio 2019 - image: Visual Studio 2019
build_script: build_script:
- ps: | - ps: |
$versions = "0104", "0728" $versions = "104", "728"
$configurations = "Release", "Debug" $configurations = "Release", "Debug"
# AppVeyor uses VS2019 Community # AppVeyor uses VS2019 Community
@@ -43,7 +57,7 @@ for:
Remove-Item "build" -Recurse Remove-Item "build" -Recurse
Write-Output "Deleted existing build folder" Write-Output "Deleted existing build folder"
} }
Invoke-Expression "cmake -B build -DPACKET_VERSION=$version" Invoke-Expression "cmake -B build -DPROTOCOL_VERSION=$version"
if ($LASTEXITCODE -ne "0") { if ($LASTEXITCODE -ne "0") {
Write-Error "cmake generation failed for version $version" -ErrorAction Stop Write-Error "cmake generation failed for version $version" -ErrorAction Stop
} }

View File

@@ -10,11 +10,13 @@ randomcharacters=true
[shard] [shard]
port=8002 port=8002
# you'll want to change this one # you'll want to change this one
ip=192.168.1.183 ip=127.0.0.1
# distance at which other players and NPCs become visible # distance at which other players and NPCs become visible
view=20000 view=20000
# little message players see when they enter the game # little message players see when they enter the game
motd=Welcome to OpenFusion! motd=Welcome to OpenFusion!
# NPC json data
npcdata=NPCs.json
# spawn coordinates (Z is height) # spawn coordinates (Z is height)
# the supplied defaults are at City Hall # the supplied defaults are at City Hall

View File

@@ -91,6 +91,7 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) {
loginSessions[sock].characters[UID].z = charInfo->iZ; loginSessions[sock].characters[UID].z = charInfo->iZ;
loginSessions[sock].characters[UID].PCStyle = charInfo->sPC_Style; loginSessions[sock].characters[UID].PCStyle = charInfo->sPC_Style;
loginSessions[sock].characters[UID].PCStyle2 = charInfo->sPC_Style2; loginSessions[sock].characters[UID].PCStyle2 = charInfo->sPC_Style2;
loginSessions[sock].characters[UID].IsGM = false;
for (int i = 0; i < AEQUIP_COUNT; i++) { for (int i = 0; i < AEQUIP_COUNT; i++) {
// setup equips // setup equips
@@ -188,6 +189,18 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) {
std::cout << "\tiEquipLBID: " << (int)character->sOn_Item.iEquipLBID << std::endl; std::cout << "\tiEquipLBID: " << (int)character->sOn_Item.iEquipLBID << std::endl;
std::cout << "\tiEquipFootID: " << (int)character->sOn_Item.iEquipFootID << std::endl; std::cout << "\tiEquipFootID: " << (int)character->sOn_Item.iEquipFootID << std::endl;
) )
int64_t UID = character->PCStyle.iPC_UID;
// commented and disabled for now
//bool BecomeGM;
//if (U16toU8(character->PCStyle.szFirstName) == settings::GMPASS) {
// BecomeGM = true;
// U8toU16("GM",character->PCStyle.szFirstName);
//} else {
// BecomeGM = false;
//}
character->PCStyle.iNameCheck = 1; character->PCStyle.iNameCheck = 1;
response->sPC_Style = character->PCStyle; response->sPC_Style = character->PCStyle;
@@ -197,7 +210,6 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) {
response->iLevel = 1; response->iLevel = 1;
response->sOn_Item = character->sOn_Item; response->sOn_Item = character->sOn_Item;
int64_t UID = character->PCStyle.iPC_UID;
loginSessions[sock].characters[UID] = Player(); loginSessions[sock].characters[UID] = Player();
loginSessions[sock].characters[UID].level = 1; loginSessions[sock].characters[UID].level = 1;
loginSessions[sock].characters[UID].FEKey = sock->getFEKey(); loginSessions[sock].characters[UID].FEKey = sock->getFEKey();
@@ -214,6 +226,7 @@ void CNLoginServer::handlePacket(CNSocket* sock, CNPacketData* data) {
loginSessions[sock].characters[UID].Equip[2].iType = 2; loginSessions[sock].characters[UID].Equip[2].iType = 2;
loginSessions[sock].characters[UID].Equip[3].iID = character->sOn_Item.iEquipFootID; // foot! loginSessions[sock].characters[UID].Equip[3].iID = character->sOn_Item.iEquipFootID; // foot!
loginSessions[sock].characters[UID].Equip[3].iType = 3; loginSessions[sock].characters[UID].Equip[3].iType = 3;
loginSessions[sock].characters[UID].IsGM = false;
sock->sendPacket(new CNPacketData((void*)response, P_LS2CL_REP_CHAR_CREATE_SUCC, sizeof(sP_LS2CL_REP_CHAR_CREATE_SUCC), sock->getEKey())); sock->sendPacket(new CNPacketData((void*)response, P_LS2CL_REP_CHAR_CREATE_SUCC, sizeof(sP_LS2CL_REP_CHAR_CREATE_SUCC), sock->getEKey()));
break; break;

View File

@@ -73,11 +73,18 @@ CNSocket::CNSocket(SOCKET s, PacketHandler ph): sock(s), pHandler(ph) {
bool CNSocket::sendData(uint8_t* data, int size) { bool CNSocket::sendData(uint8_t* data, int size) {
int sentBytes = 0; int sentBytes = 0;
int maxTries = 10;
while (sentBytes < size) { while (sentBytes < size) {
int sent = send(sock, (buffer_t*)(data + sentBytes), size - sentBytes, 0); // no flags defined int sent = send(sock, (buffer_t*)(data + sentBytes), size - sentBytes, 0); // no flags defined
if (SOCKETERROR(sent)) if (SOCKETERROR(sent)) {
if (errno == 11 && maxTries > 0) {
maxTries--;
continue; // try again
}
std::cout << "[FATAL] SOCKET ERROR: " << errno << std::endl;
return false; // error occured while sending bytes return false; // error occured while sending bytes
}
sentBytes += sent; sentBytes += sent;
} }
@@ -116,6 +123,11 @@ void CNSocket::kill() {
} }
void CNSocket::sendPacket(CNPacketData* pak) { void CNSocket::sendPacket(CNPacketData* pak) {
if (!alive) {
delete pak;
return;
}
int tmpSize = pak->size + sizeof(uint32_t); int tmpSize = pak->size + sizeof(uint32_t);
uint8_t* tmpBuf = (uint8_t*)xmalloc(tmpSize); uint8_t* tmpBuf = (uint8_t*)xmalloc(tmpSize);
@@ -127,10 +139,12 @@ void CNSocket::sendPacket(CNPacketData* pak) {
CNSocketEncryption::encryptData((uint8_t*)tmpBuf, (uint8_t*)(&pak->key), tmpSize); CNSocketEncryption::encryptData((uint8_t*)tmpBuf, (uint8_t*)(&pak->key), tmpSize);
// send packet size // send packet size
sendData((uint8_t*)&tmpSize, sizeof(uint32_t)); if (!sendData((uint8_t*)&tmpSize, sizeof(uint32_t)))
kill();
// send packet data! // send packet data!
sendData(tmpBuf, tmpSize); if (alive && !sendData(tmpBuf, tmpSize))
kill();
delete pak; delete pak;
free(tmpBuf); // free tmp buffer free(tmpBuf); // free tmp buffer

View File

@@ -24,6 +24,8 @@ enum SHARDPACKETID {
P_CL2FE_REQ_SEND_FREECHAT_MESSAGE = 318767111, P_CL2FE_REQ_SEND_FREECHAT_MESSAGE = 318767111,
P_CL2FE_REQ_PC_AVATAR_EMOTES_CHAT = 318767184, P_CL2FE_REQ_PC_AVATAR_EMOTES_CHAT = 318767184,
P_CL2FE_REQ_ITEM_MOVE = 318767114, P_CL2FE_REQ_ITEM_MOVE = 318767114,
P_CL2FE_REQ_PC_ITEM_DELETE = 318767129,
P_CL2FE_REQ_PC_GIVE_ITEM = 318767130,
P_CL2FE_REQ_PC_EXIT = 318767106, P_CL2FE_REQ_PC_EXIT = 318767106,
// shard 2 client // shard 2 client
@@ -50,7 +52,10 @@ enum SHARDPACKETID {
P_FE2CL_REP_PC_AVATAR_EMOTES_CHAT = 822083730, P_FE2CL_REP_PC_AVATAR_EMOTES_CHAT = 822083730,
P_FE2CL_PC_ITEM_MOVE_SUCC = 822083610, P_FE2CL_PC_ITEM_MOVE_SUCC = 822083610,
P_FE2CL_PC_EQUIP_CHANGE = 822083611, P_FE2CL_PC_EQUIP_CHANGE = 822083611,
P_FE2CL_REP_PC_ITEM_DELETE_SUCC = 822083641,
P_FE2CL_REP_PC_GIVE_ITEM_SUCC = 822083681,
P_FE2CL_REP_PC_EXIT_SUCC = 822083589, P_FE2CL_REP_PC_EXIT_SUCC = 822083589,
P_FE2CL_REP_PC_CHANGE_LEVEL = 822083786,
P_FE2CL_PC_MOTD_LOGIN = 822083793 P_FE2CL_PC_MOTD_LOGIN = 822083793
}; };

View File

@@ -1,8 +1,12 @@
#include "CNStructs.hpp" #include "CNStructs.hpp"
std::string U16toU8(char16_t* src) { std::string U16toU8(char16_t* src) {
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert; try {
return convert.to_bytes(src); std::wstring_convert<std::codecvt_utf8_utf16<char16_t>,char16_t> convert;
return convert.to_bytes(src);
} catch(std::exception e) {
return "";
}
} }
// returns number of char16_t that was written at des // returns number of char16_t that was written at des

View File

@@ -1,4 +1,4 @@
/* /*
CNStructs.hpp - defines some basic structs & useful methods for packets used by FusionFall based on the version defined CNStructs.hpp - defines some basic structs & useful methods for packets used by FusionFall based on the version defined
*/ */
@@ -21,9 +21,9 @@
#include <time.h> #include <time.h>
#endif #endif
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <locale> #include <locale>
#include <codecvt> #include <codecvt>
// TODO: rewrite U16toU8 & U8toU16 to not use codecvt // TODO: rewrite U16toU8 & U8toU16 to not use codecvt
@@ -31,18 +31,15 @@ std::string U16toU8(char16_t* src);
int U8toU16(std::string src, char16_t* des); // returns number of char16_t that was written at des int U8toU16(std::string src, char16_t* des); // returns number of char16_t that was written at des
uint64_t getTime(); uint64_t getTime();
// The CNPROTO_OVERRIDE definition is defined by cmake if you use it. // The PROTOCOL_VERSION definition is defined by the build system.
// If you don't use cmake, feel free to comment this out and change it around. #if !defined(PROTOCOL_VERSION)
// 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) #elif PROTOCOL_VERSION == 728
#include "structs/0728.hpp" #include "structs/0728.hpp"
#elif PROTOCOL_VERSION == 104
#include "structs/0104.hpp"
#else
#error Invalid PROTOCOL_VERSION
#endif #endif
#endif #endif

View File

@@ -6,7 +6,8 @@
void ItemManager::init() { void ItemManager::init() {
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_ITEM_MOVE, itemMoveHandler);
REGISTER_SHARD_PACKET(P_FE2CL_PC_EQUIP_CHANGE, itemMoveHandler); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_ITEM_DELETE, itemDeleteHandler);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GIVE_ITEM, itemGMGiveHandler);
} }
void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) { void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) {
@@ -16,22 +17,20 @@ void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) {
sP_CL2FE_REQ_ITEM_MOVE* itemmove = (sP_CL2FE_REQ_ITEM_MOVE*)data->buf; 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)); 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]; PlayerView& plr = PlayerManager::players[sock];
sItemBase fromItem; sItemBase fromItem;
sItemBase toItem; sItemBase toItem;
// eFrom 0 means from equip // eFrom 0 means from equip
if (itemmove->eFrom == 0) { if (itemmove->eFrom == 0) {
// unequiping an item // unequiping an item
std::cout << "unequipting item" << std::endl;
fromItem = plr.plr.Equip[itemmove->iFromSlotNum]; fromItem = plr.plr.Equip[itemmove->iFromSlotNum];
} else { } else {
fromItem = plr.plr.Inven[itemmove->iFromSlotNum]; fromItem = plr.plr.Inven[itemmove->iFromSlotNum];
} }
// eTo 0 means to equip // eTo 0 means to equip
if (itemmove->eTo == 0) { if (itemmove->eTo == 0) {
std::cout << "equipting item" << std::endl;
// equiping an item // equiping an item
toItem = plr.plr.Equip[itemmove->iToSlotNum]; toItem = plr.plr.Equip[itemmove->iToSlotNum];
plr.plr.Equip[itemmove->iToSlotNum] = fromItem; plr.plr.Equip[itemmove->iToSlotNum] = fromItem;
@@ -45,26 +44,23 @@ void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) {
} else { } else {
plr.plr.Inven[itemmove->iFromSlotNum] = toItem; plr.plr.Inven[itemmove->iFromSlotNum] = toItem;
} }
if (itemmove->eFrom == 0 || itemmove->eTo == 0) { if (itemmove->eFrom == 0 || itemmove->eTo == 0) {
for (CNSocket* otherSock : plr.viewable) { for (CNSocket* otherSock : plr.viewable) {
sP_FE2CL_PC_EQUIP_CHANGE* resp2 = (sP_FE2CL_PC_EQUIP_CHANGE*)xmalloc(sizeof(sP_FE2CL_PC_EQUIP_CHANGE)); sP_FE2CL_PC_EQUIP_CHANGE* resp2 = (sP_FE2CL_PC_EQUIP_CHANGE*)xmalloc(sizeof(sP_FE2CL_PC_EQUIP_CHANGE));
resp2->iPC_ID = plr.plr.iID; resp2->iPC_ID = plr.plr.iID;
if (itemmove->eFrom == 0) { if (itemmove->eFrom == 0) {
resp2->iEquipSlotNum = itemmove->iFromSlotNum; resp2->iEquipSlotNum = itemmove->iFromSlotNum;
resp2->EquipSlotItem = toItem; resp2->EquipSlotItem = toItem;
} } else {
else {
resp2->iEquipSlotNum = itemmove->iToSlotNum; resp2->iEquipSlotNum = itemmove->iToSlotNum;
resp2->EquipSlotItem = fromItem; resp2->EquipSlotItem = fromItem;
} }
otherSock->sendPacket(new CNPacketData((void*)resp2, P_FE2CL_PC_EQUIP_CHANGE, sizeof(sP_FE2CL_PC_EQUIP_CHANGE), otherSock->getFEKey())); 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->eTo = itemmove->eFrom;
resp->iToSlotNum = itemmove->iFromSlotNum; resp->iToSlotNum = itemmove->iFromSlotNum;
resp->ToSlotItem = toItem; resp->ToSlotItem = toItem;
@@ -73,4 +69,61 @@ void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) {
resp->FromSlotItem = fromItem; resp->FromSlotItem = fromItem;
sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_PC_ITEM_MOVE_SUCC, sizeof(sP_FE2CL_PC_ITEM_MOVE_SUCC), sock->getFEKey())); sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_PC_ITEM_MOVE_SUCC, sizeof(sP_FE2CL_PC_ITEM_MOVE_SUCC), sock->getFEKey()));
}
void ItemManager::itemDeleteHandler(CNSocket* sock, CNPacketData* data) {
if (data->size != sizeof(sP_CL2FE_REQ_PC_ITEM_DELETE))
return; // ignore the malformed packet
sP_CL2FE_REQ_PC_ITEM_DELETE* itemdel = (sP_CL2FE_REQ_PC_ITEM_DELETE*)data->buf;
sP_FE2CL_REP_PC_ITEM_DELETE_SUCC* resp = (sP_FE2CL_REP_PC_ITEM_DELETE_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_ITEM_DELETE_SUCC));
PlayerView& plr = PlayerManager::players[sock];
resp->eIL = itemdel->eIL;
resp->iSlotNum = itemdel->iSlotNum;
// so, im not sure what this eIL thing does since you always delete items in inventory and not equips
plr.plr.Inven[itemdel->iSlotNum].iID = 0;
plr.plr.Inven[itemdel->iSlotNum].iType = 0;
plr.plr.Inven[itemdel->iSlotNum].iOpt = 0;
sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_PC_ITEM_DELETE_SUCC, sizeof(sP_FE2CL_REP_PC_ITEM_DELETE_SUCC), sock->getFEKey()));
}
void ItemManager::itemGMGiveHandler(CNSocket* sock, CNPacketData* data) {
if (data->size != sizeof(sP_CL2FE_REQ_PC_GIVE_ITEM))
return; // ignore the malformed packet
sP_CL2FE_REQ_PC_GIVE_ITEM* itemreq = (sP_CL2FE_REQ_PC_GIVE_ITEM*)data->buf;
PlayerView& plr = PlayerManager::players[sock];
// Commented and disabled for future use
//if (!plr.plr.IsGM) {
// TODO: send fail packet
// return;
//}
if (itemreq->eIL == 2) {
// Quest item, not a real item, handle this later, stubbed for now
// sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_PC_GIVE_ITEM_FAIL, sizeof(sP_FE2CL_REP_PC_GIVE_ITEM_FAIL), sock->getFEKey()));
} else if (itemreq->eIL == 1) {
sP_FE2CL_REP_PC_GIVE_ITEM_SUCC* resp = (sP_FE2CL_REP_PC_GIVE_ITEM_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_GIVE_ITEM_SUCC));
resp->eIL = itemreq->eIL;
resp->iSlotNum = itemreq->iSlotNum;
resp->Item = itemreq->Item;
plr.plr.Inven[itemreq->iSlotNum] = itemreq->Item;
plr.plr.level = 36;
sock->sendPacket(new CNPacketData((void*)resp, P_FE2CL_REP_PC_GIVE_ITEM_SUCC, sizeof(sP_FE2CL_REP_PC_GIVE_ITEM_SUCC), sock->getFEKey()));
sP_FE2CL_REP_PC_CHANGE_LEVEL* resp2 = (sP_FE2CL_REP_PC_CHANGE_LEVEL*)xmalloc(sizeof(sP_FE2CL_REP_PC_CHANGE_LEVEL));
resp2->iPC_ID = plr.plr.iID;
resp2->iPC_Level = 36;
sock->sendPacket(new CNPacketData((void*)resp2, P_FE2CL_REP_PC_CHANGE_LEVEL, sizeof(sP_FE2CL_REP_PC_CHANGE_LEVEL), sock->getFEKey()));
}
} }

View File

@@ -6,6 +6,8 @@
namespace ItemManager { namespace ItemManager {
void init(); void init();
void itemMoveHandler(CNSocket* sock, CNPacketData* data); void itemMoveHandler(CNSocket* sock, CNPacketData* data);
void itemDeleteHandler(CNSocket* sock, CNPacketData* data);
void itemGMGiveHandler(CNSocket* sock, CNPacketData* data);
} }
#endif #endif

View File

@@ -19,7 +19,7 @@ public:
appearanceData.iBarkerType = 0; appearanceData.iBarkerType = 0;
// hopefully no collisions happen :eyes: // hopefully no collisions happen :eyes:
appearanceData.iNPC_ID = (int32_t)getTime(); appearanceData.iNPC_ID = (int32_t)rand();
}; };
}; };

View File

@@ -4,19 +4,41 @@
#include <cmath> #include <cmath>
#include <algorithm> #include <algorithm>
#include <list> #include <list>
#include <fstream>
#include "contrib/JSON.hpp"
std::map<int32_t, BaseNPC> NPCManager::NPCs; std::map<int32_t, BaseNPC> NPCManager::NPCs;
void NPCManager::init() { void NPCManager::init() {
/* BaseNPC test(settings::SPAWN_X, settings::SPAWN_Y, settings::SPAWN_Z, 727); // load NPCs from NPCs.json into our NPC manager
NPCs[test.appearanceData.iNPC_ID] = test; */
try {
std::ifstream inFile("NPCs.json");
nlohmann::json jsonData;
// read file into jsonData
inFile >> jsonData;
for (auto& npc : jsonData) {
BaseNPC tmp(npc["x"], npc["y"], npc["z"], npc["id"]);
NPCManager::NPCs[tmp.appearanceData.iNPC_ID] = tmp;
}
std::cout << "populated " << NPCs.size() << " NPCs" << std::endl;
}
catch (const std::exception& err) {
std::cerr << "[WARN] Malformed NPC.json file! Reason:" << std::endl << err.what() << std::endl;
}
} }
#undef CHECKNPC
void NPCManager::updatePlayerNPCS(CNSocket* sock, PlayerView& view) { void NPCManager::updatePlayerNPCS(CNSocket* sock, PlayerView& view) {
std::list<int32_t> yesView; std::list<int32_t> yesView;
std::list<int32_t> noView; std::list<int32_t> noView;
for (auto pair : NPCs) { for (auto& pair : NPCs) {
int diffX = abs(view.plr.x - pair.second.appearanceData.iX); int diffX = abs(view.plr.x - pair.second.appearanceData.iX);
int diffY = abs(view.plr.y - pair.second.appearanceData.iY); int diffY = abs(view.plr.y - pair.second.appearanceData.iY);

View File

@@ -22,6 +22,7 @@ struct Player {
int x, y, z, angle; int x, y, z, angle;
sItemBase Equip[AEQUIP_COUNT]; sItemBase Equip[AEQUIP_COUNT];
sItemBase Inven[AINVEN_COUNT]; sItemBase Inven[AINVEN_COUNT];
bool IsGM;
}; };
#endif #endif

View File

@@ -36,7 +36,7 @@ void PlayerManager::addPlayer(CNSocket* key, Player plr) {
players[key].plr = plr; players[key].plr = plr;
players[key].lastHeartbeat = 0; players[key].lastHeartbeat = 0;
std::cout << U16toU8(plr.PCStyle.szFirstName) << U16toU8(plr.PCStyle.szLastName) << " has joined!" << std::endl; std::cout << U16toU8(plr.PCStyle.szFirstName) << " " << U16toU8(plr.PCStyle.szLastName) << " has joined!" << std::endl;
std::cout << players.size() << " players" << std::endl; std::cout << players.size() << " players" << std::endl;
} }
@@ -157,6 +157,7 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
sP_CL2FE_REQ_PC_ENTER* enter = (sP_CL2FE_REQ_PC_ENTER*)data->buf; 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_FE2CL_REP_PC_ENTER_SUCC* response = (sP_FE2CL_REP_PC_ENTER_SUCC*)xmalloc(sizeof(sP_FE2CL_REP_PC_ENTER_SUCC));
sP_FE2CL_PC_MOTD_LOGIN* motd = (sP_FE2CL_PC_MOTD_LOGIN*)xmalloc(sizeof(sP_FE2CL_PC_MOTD_LOGIN));
// TODO: check if serialkey exists, if it doesn't send sP_FE2CL_REP_PC_ENTER_FAIL // TODO: check if serialkey exists, if it doesn't send sP_FE2CL_REP_PC_ENTER_FAIL
Player plr = CNSharedData::getPlayer(enter->iEnterSerialKey); Player plr = CNSharedData::getPlayer(enter->iEnterSerialKey);
@@ -188,6 +189,23 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
for (int i = 0; i < AEQUIP_COUNT; i++) for (int i = 0; i < AEQUIP_COUNT; i++)
response->PCLoadData2CL.aEquip[i] = plr.Equip[i]; response->PCLoadData2CL.aEquip[i] = plr.Equip[i];
// protocol-agnostic sItemBase usage
sItemBase item;
memset(&item, 0, sizeof(sItemBase));
item.iID = 495;
for (int i = 0; i < AINVEN_COUNT; i++) {
switch (i) {
case 6: case 8: case 11: case 13: case 20:
case 24: case 26: case 27: case 28:
plr.Inven[i] = item;
break;
default:
memset(&plr.Inven[i], 0, sizeof(sItemBase));
}
response->PCLoadData2CL.aInven[i] = plr.Inven[i];
}
// don't ask.. // don't ask..
for (int i = 1; i < 37; i++) { for (int i = 1; i < 37; i++) {
response->PCLoadData2CL.aNanoBank[i].iID = i; response->PCLoadData2CL.aNanoBank[i].iID = i;
@@ -205,10 +223,15 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
plr.SerialKey = enter->iEnterSerialKey; plr.SerialKey = enter->iEnterSerialKey;
plr.HP = response->PCLoadData2CL.iHP; plr.HP = response->PCLoadData2CL.iHP;
motd->iType = 1;
U8toU16(settings::MOTDSTRING, (char16_t*)motd->szSystemMsg);
sock->setEKey(CNSocketEncryption::createNewKey(response->uiSvrTime, response->iID + 1, response->PCLoadData2CL.iFusionMatter + 1)); sock->setEKey(CNSocketEncryption::createNewKey(response->uiSvrTime, response->iID + 1, response->PCLoadData2CL.iFusionMatter + 1));
sock->setFEKey(plr.FEKey); 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()));
// transmit MOTD after entering the game, so the client hopefully changes modes on time
sock->sendPacket(new CNPacketData((void*)motd, P_FE2CL_PC_MOTD_LOGIN, sizeof(sP_FE2CL_PC_MOTD_LOGIN), sock->getFEKey()));
addPlayer(sock, plr); addPlayer(sock, plr);
} }
@@ -219,20 +242,15 @@ void PlayerManager::loadPlayer(CNSocket* sock, CNPacketData* data) {
sP_CL2FE_REQ_PC_LOADING_COMPLETE* complete = (sP_CL2FE_REQ_PC_LOADING_COMPLETE*)data->buf; 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_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( DEBUGLOG(
std::cout << "P_CL2FE_REQ_PC_LOADING_COMPLETE:" << std::endl; std::cout << "P_CL2FE_REQ_PC_LOADING_COMPLETE:" << std::endl;
std::cout << "\tPC_ID: " << complete->iPC_ID << 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);
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*)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) { void PlayerManager::movePlayer(CNSocket* sock, CNPacketData* data) {

25447
src/contrib/JSON.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -28,6 +28,7 @@ int main() {
} }
#endif #endif
settings::init(); settings::init();
std::cout << "[INFO] Protocol version: " << PROTOCOL_VERSION << std::endl;
std::cout << "[INFO] Intializing Packet Managers..." << std::endl; std::cout << "[INFO] Intializing Packet Managers..." << std::endl;
PlayerManager::init(); PlayerManager::init();
ChatManager::init(); ChatManager::init();
@@ -50,4 +51,4 @@ int main() {
WSACleanup(); WSACleanup();
#endif #endif
return 0; return 0;
} }

View File

@@ -1,6 +1,6 @@
#include <iostream> #include <iostream>
#include "settings.hpp" #include "settings.hpp"
#include "INIReader.hpp" #include "contrib/INIReader.hpp"
// defaults :) // defaults :)
int settings::LOGINPORT = 8001; int settings::LOGINPORT = 8001;
@@ -14,7 +14,8 @@ int settings::VIEWDISTANCE = 20000;
int settings::SPAWN_X = 179213; int settings::SPAWN_X = 179213;
int settings::SPAWN_Y = 268451; int settings::SPAWN_Y = 268451;
int settings::SPAWN_Z = -4210; int settings::SPAWN_Z = -4210;
std::string settings::GMPASS = "pass";
std::string settings::NPCJSON = "NPCs.json";
std::string settings::MOTDSTRING = "Welcome to OpenFusion!"; std::string settings::MOTDSTRING = "Welcome to OpenFusion!";
void settings::init() { void settings::init() {
@@ -37,6 +38,8 @@ void settings::init() {
SPAWN_X = reader.GetInteger("shard", "spawnx", SPAWN_X); SPAWN_X = reader.GetInteger("shard", "spawnx", SPAWN_X);
SPAWN_Y = reader.GetInteger("shard", "spawny", SPAWN_Y); SPAWN_Y = reader.GetInteger("shard", "spawny", SPAWN_Y);
SPAWN_Z = reader.GetInteger("shard", "spawnz", SPAWN_Z); SPAWN_Z = reader.GetInteger("shard", "spawnz", SPAWN_Z);
MOTDSTRING = reader.Get("shard", "motd", "Welcome to OpenFusion!"); GMPASS = reader.Get("login", "pass", GMPASS);
NPCJSON = reader.Get("shard", "npcdata", NPCJSON);
MOTDSTRING = reader.Get("shard", "motd", MOTDSTRING);
} }

View File

@@ -11,6 +11,8 @@ namespace settings {
extern int SPAWN_Y; extern int SPAWN_Y;
extern int SPAWN_Z; extern int SPAWN_Z;
extern std::string MOTDSTRING; extern std::string MOTDSTRING;
extern std::string NPCJSON;
extern std::string GMPASS;
void init(); void init();
} }