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

This commit is contained in:
Onii-chan
2020-08-21 12:24:55 +02:00
23 changed files with 806 additions and 554 deletions

6
.gitignore vendored
View File

@@ -1,7 +1,11 @@
.vscode
.vscode/
bin/*
notes.txt
config.ini
*.o
tags
*~
CMakeFiles/
CMakeCache.txt
build/
.vs/

48
CMakeLists.txt Normal file
View File

@@ -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()

View File

@@ -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.

View File

@@ -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\

View File

@@ -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"

65
appveyor.yml Normal file
View File

@@ -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

View File

@@ -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]

View File

@@ -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;

View File

@@ -6,15 +6,11 @@
#include <map>
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_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,
@@ -27,18 +23,14 @@ enum SHARDPACKETID {
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,
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_REP_PC_GOTO_SUCC = 822083633,
P_FE2CL_REQ_LIVE_CHECK = 822083792,
P_FE2CL_PC_NEW = 822083587,
P_FE2CL_PC_MOVE = 822083592,
@@ -50,10 +42,14 @@ enum SHARDPACKETID {
P_FE2CL_PC_ZIPLINE = 822083703,
P_FE2CL_PC_MOVEPLATFORM = 822083704,
P_FE2CL_PC_SLOPE = 822083705,
P_FE2CL_REP_PC_GOTO_SUCC = 822083633,
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
};

View File

@@ -5,13 +5,19 @@
#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 <iostream>
#include <stdio.h>
#include <stdint.h>
// Can't use this in MSVC.
#ifndef _MSC_VER
#include <sys/time.h>
#else
// Can't use this in MSVC.
#include <time.h>
#endif
#include <cstring>
@@ -25,8 +31,13 @@ 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();
// 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"

View File

@@ -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];

76
src/ItemManager.cpp Normal file
View File

@@ -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()));
}

11
src/ItemManager.hpp Normal file
View File

@@ -0,0 +1,11 @@
#ifndef _IM_HPP
#define _IM_HPP
#include "CNShardServer.hpp"
namespace ItemManager {
void init();
void itemMoveHandler(CNSocket* sock, CNPacketData* data);
}
#endif

26
src/NPC.hpp Normal file
View File

@@ -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

View File

@@ -1,5 +1,64 @@
#include "NPCManager.hpp"
#include "settings.hpp"
#include <cmath>
#include <algorithm>
#include <list>
std::map<int32_t, BaseNPC> 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<int32_t> yesView;
std::list<int32_t> 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<int32_t>::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;
}

View File

@@ -2,13 +2,16 @@
#define _NPCMANAGER_HPP
#include "CNProtocol.hpp"
#include "PlayerManager.hpp"
#include "NPC.hpp"
#include <map>
namespace NPCManager {
extern std::map<int32_t, BaseNPC> NPCs;
void init();
void updatePlayerNPCS(CNSocket* sock, PlayerView& plr);
}
#endif

View File

@@ -5,21 +5,12 @@
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()));
}
void NanoManager::nanoSummonHandler(CNSocket* sock, CNPacketData* data) {
if (data->size != sizeof(sP_CL2FE_REQ_NANO_ACTIVE))
return; // malformed packet
sP_CL2FE_REQ_NANO_ACTIVE* nano = (sP_CL2FE_REQ_NANO_ACTIVE*)data->buf;
PlayerView plr = PlayerManager::players[sock];
@@ -30,74 +21,3 @@ void NanoManager::nanoSummonHandler(CNSocket* sock, CNPacketData* data) {
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);
}

View File

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

View File

@@ -1,6 +1,6 @@
#include "CNProtocol.hpp"
#include "NanoManager.hpp"
#include "PlayerManager.hpp"
#include "NPCManager.hpp"
#include "CNShardServer.hpp"
#include "CNShared.hpp"
@@ -28,7 +28,6 @@ void PlayerManager::init() {
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);
}
void PlayerManager::addPlayer(CNSocket* key, Player plr) {
@@ -83,15 +82,14 @@ void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) {
if (diffX < settings::VIEWDISTANCE && diffY < settings::VIEWDISTANCE) {
yesView.push_back(pair.first);
}
else {
} else {
noView.push_back(pair.first);
}
}
std::list<CNSocket*> cachedview(players[sock].viewable); // copies the viewable
for (CNSocket* otherSock : cachedview) {
std::list<CNSocket*>::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
@@ -104,15 +102,16 @@ void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) {
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()));
players[sock].viewable.remove(otherSock);
players[sock].viewable.erase(i++);
players[otherSock].viewable.remove(sock);
}
continue;
}
cachedview = players[sock].viewable;
++i;
}
for (CNSocket* otherSock : yesView) {
if (std::find(cachedview.begin(), cachedview.end(), otherSock) == cachedview.end()) {
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
sP_FE2CL_PC_NEW* newPlayer = (sP_FE2CL_PC_NEW*)xmalloc(sizeof(sP_FE2CL_PC_NEW)); // current connection to other player
@@ -148,6 +147,8 @@ void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) {
players[otherSock].viewable.push_back(sock);
}
}
NPCManager::updatePlayerNPCS(sock, players[sock]);
}
void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
@@ -187,16 +188,13 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
for (int i = 0; i < AEQUIP_COUNT; i++)
response->PCLoadData2CL.aEquip[i] = plr.Equip[i];
//assign 37 nanos with something.hardcoded for now...
// don't ask..
for (int i = 1; i < 37; i++) {
response->PCLoadData2CL.aNanoBank[i].iID = i;
response->PCLoadData2CL.aNanoBank[i].iSkillID = 2;
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;
@@ -543,13 +541,3 @@ void PlayerManager::exitGame(CNSocket* sock, CNPacketData* data) {
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) {
}

View File

@@ -11,6 +11,7 @@
struct PlayerView {
std::list<CNSocket*> viewable;
std::list<int32_t> viewableNPCs;
Player plr;
int long lastHeartbeat;
};

View File

@@ -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);

View File

@@ -1,6 +1,7 @@
/* genstructs.py */
#define AEQUIP_COUNT 9
#define AINVEN_COUNT 50
#pragma pack(push)

View File

@@ -1,6 +1,7 @@
/* genstructs.py */
#define AEQUIP_COUNT 12
#define AINVEN_COUNT 50
#pragma pack(push)