mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-21 21:20:04 +00:00
huge refactoring, chunking added
This commit is contained in:
parent
001564a257
commit
f4db0830ba
2
Makefile
2
Makefile
@ -46,6 +46,7 @@ CXXSRC=\
|
||||
src/settings.cpp\
|
||||
src/TransportManager.cpp\
|
||||
src/TableData.cpp\
|
||||
src/ChunkManager.cpp\
|
||||
|
||||
# headers (for timestamp purposes)
|
||||
CHDR=\
|
||||
@ -81,6 +82,7 @@ CXXHDR=\
|
||||
src/settings.hpp\
|
||||
src/TransportManager.hpp\
|
||||
src/TableData.hpp\
|
||||
src/ChunkManager.hpp\
|
||||
|
||||
COBJ=$(CSRC:.c=.o)
|
||||
CXXOBJ=$(CXXSRC:.cpp=.o)
|
||||
|
@ -23,16 +23,13 @@ void ChatManager::chatHandler(CNSocket* sock, CNPacketData* data) {
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC, sizeof(sP_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC));
|
||||
|
||||
// send to visible players
|
||||
for (CNSocket* otherSock : plr.viewable) {
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC, sizeof(sP_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC));
|
||||
}
|
||||
PlayerManager::sendToViewable(sock, (void*)&resp, P_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC, sizeof(sP_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC));
|
||||
}
|
||||
|
||||
void ChatManager::menuChatHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_SEND_MENUCHAT_MESSAGE))
|
||||
return; // malformed packet
|
||||
sP_CL2FE_REQ_SEND_MENUCHAT_MESSAGE* chat = (sP_CL2FE_REQ_SEND_MENUCHAT_MESSAGE*)data->buf;
|
||||
PlayerView& plr = PlayerManager::players[sock];
|
||||
|
||||
// send to client
|
||||
INITSTRUCT(sP_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC, resp);
|
||||
@ -42,9 +39,7 @@ void ChatManager::menuChatHandler(CNSocket* sock, CNPacketData* data) {
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC, sizeof(sP_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC));
|
||||
|
||||
// send to visible players
|
||||
for (CNSocket* otherSock : plr.viewable) {
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC, sizeof(sP_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC));
|
||||
}
|
||||
PlayerManager::sendToViewable(sock, (void*)&resp, P_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC, sizeof(sP_FE2CL_REP_SEND_MENUCHAT_MESSAGE_SUCC));
|
||||
}
|
||||
|
||||
void ChatManager::emoteHandler(CNSocket* sock, CNPacketData* data) {
|
||||
@ -63,7 +58,5 @@ void ChatManager::emoteHandler(CNSocket* sock, CNPacketData* data) {
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_AVATAR_EMOTES_CHAT, sizeof(sP_FE2CL_REP_PC_AVATAR_EMOTES_CHAT));
|
||||
|
||||
// send to visible players (players within render distance)
|
||||
for (CNSocket* otherSock : plr.viewable) {
|
||||
otherSock->sendPacket((void*)&resp, P_FE2CL_REP_PC_AVATAR_EMOTES_CHAT, sizeof(sP_FE2CL_REP_PC_AVATAR_EMOTES_CHAT));
|
||||
}
|
||||
PlayerManager::sendToViewable(sock, (void*)&resp, P_FE2CL_REP_PC_AVATAR_EMOTES_CHAT, sizeof(sP_FE2CL_REP_PC_AVATAR_EMOTES_CHAT));
|
||||
}
|
||||
|
93
src/ChunkManager.cpp
Normal file
93
src/ChunkManager.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "ChunkManager.hpp"
|
||||
#include "PlayerManager.hpp"
|
||||
#include "NPCManager.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
std::map<std::pair<int, int>, Chunk*> ChunkManager::chunks;
|
||||
|
||||
void ChunkManager::init() {} // stubbed
|
||||
void ChunkManager::cleanup() {
|
||||
// cleans up all the allocated chunks
|
||||
for (auto& pair : chunks) {
|
||||
delete pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
void ChunkManager::addNPC(int posX, int posY, int32_t id) {
|
||||
std::pair<int, int> pos = grabChunk(posX, posY);
|
||||
|
||||
// make chunk if it doesn't exist!
|
||||
if (chunks.find(pos) == chunks.end()) {
|
||||
chunks[pos] = new Chunk();
|
||||
chunks[pos]->players = std::set<CNSocket*>();
|
||||
chunks[pos]->NPCs = std::set<int32_t>();
|
||||
}
|
||||
|
||||
Chunk* chunk = chunks[pos];
|
||||
|
||||
chunk->NPCs.insert(id);
|
||||
|
||||
NPCManager::addNPC(grabChunks(pos.first, pos.second), id);
|
||||
}
|
||||
|
||||
void ChunkManager::addPlayer(int posX, int posY, CNSocket* sock) {
|
||||
std::pair<int, int> pos = grabChunk(posX, posY);
|
||||
|
||||
// make chunk if it doesn't exist!
|
||||
if (chunks.find(pos) == chunks.end()) {
|
||||
chunks[pos] = new Chunk();
|
||||
chunks[pos]->players = std::set<CNSocket*>();
|
||||
chunks[pos]->NPCs = std::set<int32_t>();
|
||||
}
|
||||
|
||||
Chunk* chunk = chunks[pos];
|
||||
|
||||
chunk->players.insert(sock);
|
||||
|
||||
// TODO: update view for all players in surrounding chunks
|
||||
}
|
||||
|
||||
std::pair<int, int> ChunkManager::grabChunk(int posX, int posY) {
|
||||
return std::make_pair<int, int>(posX / (settings::PLAYERDISTANCE / 3), posY / (settings::PLAYERDISTANCE / 3));
|
||||
}
|
||||
|
||||
std::vector<Chunk*> ChunkManager::grabChunks(int chunkX, int chunkY) {
|
||||
std::vector<Chunk*> delta;
|
||||
delta.reserve(9);
|
||||
|
||||
for (int i = -1; i < 2; i++) {
|
||||
for (int z = -1; z < 2; z++) {
|
||||
std::pair<int, int> pos(chunkX+i, chunkY+z);
|
||||
|
||||
// if chunk exists, add it to the delta
|
||||
if (chunks.find(pos) != chunks.end()) {
|
||||
delta.push_back(chunks[pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
||||
|
||||
// returns the chunks that aren't shared (only from from)
|
||||
std::vector<Chunk*> ChunkManager::getDeltaChunks(std::vector<Chunk*> from, std::vector<Chunk*> to) {
|
||||
std::vector<Chunk*> delta;
|
||||
|
||||
for (Chunk* i : from) {
|
||||
bool found = false;
|
||||
|
||||
// search for it in the other array
|
||||
for (Chunk* z : to) {
|
||||
if (i == z) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// add it to the vector if we didn't find it!
|
||||
if (!found)
|
||||
delta.push_back(i);
|
||||
}
|
||||
|
||||
return delta;
|
||||
}
|
27
src/ChunkManager.hpp
Normal file
27
src/ChunkManager.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "CNProtocol.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
||||
class Chunk {
|
||||
public:
|
||||
std::set<CNSocket*> players;
|
||||
std::set<int32_t> NPCs;
|
||||
};
|
||||
|
||||
namespace ChunkManager {
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
extern std::map<std::pair<int, int>, Chunk*> chunks;
|
||||
|
||||
void addNPC(int posX, int posY, int32_t id);
|
||||
void addPlayer(int posX, int posY, CNSocket* sock);
|
||||
std::pair<int, int> grabChunk(int posX, int posY);
|
||||
std::vector<Chunk*> grabChunks(int chunkX, int chunkY);
|
||||
std::vector<Chunk*> getDeltaChunks(std::vector<Chunk*> from, std::vector<Chunk*> to);
|
||||
}
|
@ -112,9 +112,7 @@ void ItemManager::itemMoveHandler(CNSocket* sock, CNPacketData* data) {
|
||||
plr.plr->iPCState = 0;
|
||||
|
||||
// send equip event to other players
|
||||
for (CNSocket* otherSock : plr.viewable) {
|
||||
otherSock->sendPacket((void*)&equipChange, P_FE2CL_PC_EQUIP_CHANGE, sizeof(sP_FE2CL_PC_EQUIP_CHANGE));
|
||||
}
|
||||
PlayerManager::sendToViewable(sock, (void*)&equipChange, P_FE2CL_PC_EQUIP_CHANGE, sizeof(sP_FE2CL_PC_EQUIP_CHANGE));
|
||||
}
|
||||
|
||||
// send response
|
||||
|
@ -77,8 +77,7 @@ void MobManager::pcAttackNpcs(CNSocket *sock, CNPacketData *data) {
|
||||
resp1->iPC_ID = plr->iID;
|
||||
|
||||
// send to other players
|
||||
for (CNSocket *s : PlayerManager::players[sock].viewable)
|
||||
s->sendPacket((void*)respbuf, P_FE2CL_PC_ATTACK_NPCs, resplen);
|
||||
PlayerManager::sendToViewable(sock, (void*)respbuf, P_FE2CL_PC_ATTACK_NPCs, resplen);
|
||||
}
|
||||
|
||||
void MobManager::combatBegin(CNSocket *sock, CNPacketData *data) {} // stub
|
||||
@ -138,15 +137,12 @@ void MobManager::killMob(CNSocket *sock, Mob *mob) {
|
||||
giveReward(sock);
|
||||
MissionManager::mobKilled(sock, mob->appearanceData.iNPCType);
|
||||
|
||||
PlayerView& plrv = PlayerManager::players[sock];
|
||||
|
||||
INITSTRUCT(sP_FE2CL_NPC_EXIT, pkt);
|
||||
|
||||
pkt.iNPC_ID = mob->appearanceData.iNPC_ID;
|
||||
|
||||
sock->sendPacket(&pkt, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
for (CNSocket *s : plrv.viewable)
|
||||
s->sendPacket(&pkt, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
PlayerManager::sendToViewable(sock, (void*)&pkt, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
}
|
||||
|
||||
void MobManager::deadStep(Mob *mob, time_t currTime) {
|
||||
|
@ -27,6 +27,34 @@ void NPCManager::init() {
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_VENDOR_BATTERY_BUY, npcVendorBuyBattery);
|
||||
}
|
||||
|
||||
void NPCManager::addNPC(std::vector<Chunk*> viewableChunks, int32_t id) {
|
||||
BaseNPC* npc = NPCs[id];
|
||||
|
||||
// create struct
|
||||
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
||||
enterData.NPCAppearanceData = npc->appearanceData;
|
||||
|
||||
for (Chunk* chunk : viewableChunks) {
|
||||
for (CNSocket* sock : chunk->players) {
|
||||
// send to socket
|
||||
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NPCManager::removeNPC(std::vector<Chunk*> viewableChunks, int32_t id) {
|
||||
// create struct
|
||||
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
||||
exitData.iNPC_ID = id;
|
||||
|
||||
for (Chunk* chunk : viewableChunks) {
|
||||
for (CNSocket* sock : chunk->players) {
|
||||
// send to socket
|
||||
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NPCManager::npcVendorBuy(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_VENDOR_ITEM_BUY))
|
||||
return; // malformed packet
|
||||
@ -251,64 +279,6 @@ void NPCManager::npcVendorBuyBattery(CNSocket* sock, CNPacketData* data) {
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_VENDOR_BATTERY_BUY_SUCC, sizeof(sP_FE2CL_REP_PC_VENDOR_BATTERY_BUY_SUCC));
|
||||
}
|
||||
|
||||
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::NPCDISTANCE && diffY < settings::NPCDISTANCE) {
|
||||
// if it's a mob and it's dead (or otherwise not there), skip it.
|
||||
if (MobManager::Mobs.find(pair.first) != MobManager::Mobs.end()) {
|
||||
Mob *mob = (Mob*) pair.second;
|
||||
if (mob->state == MobState::DEAD || mob->state == MobState::INACTIVE)
|
||||
continue;
|
||||
}
|
||||
|
||||
yesView.push_back(pair.first);
|
||||
}
|
||||
else {
|
||||
noView.push_back(pair.first);
|
||||
}
|
||||
}
|
||||
|
||||
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
||||
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
|
||||
|
||||
exitData.iNPC_ID = id;
|
||||
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
|
||||
// remove from view
|
||||
view.viewableNPCs.erase(i++);
|
||||
}
|
||||
else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
||||
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
|
||||
|
||||
enterData.NPCAppearanceData = NPCs[id]->appearanceData;
|
||||
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||
|
||||
// add to viewable
|
||||
view.viewableNPCs.push_back(id);
|
||||
}
|
||||
}
|
||||
|
||||
PlayerManager::players[sock].viewableNPCs = view.viewableNPCs;
|
||||
}
|
||||
|
||||
void NPCManager::npcBarkHandler(CNSocket* sock, CNPacketData* data) {} // stubbed for now
|
||||
|
||||
void NPCManager::npcSummonHandler(CNSocket* sock, CNPacketData* data) {
|
||||
@ -330,9 +300,7 @@ void NPCManager::npcSummonHandler(CNSocket* sock, CNPacketData* data) {
|
||||
resp.NPCAppearanceData.iY = plr->y;
|
||||
resp.NPCAppearanceData.iZ = plr->z;
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||
for (CNSocket *s : PlayerManager::players[sock].viewable)
|
||||
s->sendPacket((void*)&resp, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||
ChunkManager::addNPC(plr->x, plr->y, resp.NPCAppearanceData.iNPC_ID);
|
||||
}
|
||||
|
||||
void NPCManager::npcWarpHandler(CNSocket* sock, CNPacketData* data) {
|
||||
@ -353,8 +321,8 @@ void NPCManager::npcWarpHandler(CNSocket* sock, CNPacketData* data) {
|
||||
resp.iZ = Warps[warpNpc->iWarpID].z;
|
||||
|
||||
// force player & NPC reload
|
||||
plrv.viewable.clear();
|
||||
plrv.viewableNPCs.clear();
|
||||
plrv.currentChunks.clear();
|
||||
plrv.chunkPos = std::make_pair<int, int>(0, 0);
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_NPC_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC));
|
||||
}
|
||||
|
@ -20,6 +20,9 @@ namespace NPCManager {
|
||||
extern std::vector<WarpLocation> RespawnPoints;
|
||||
void init();
|
||||
|
||||
void addNPC(std::vector<Chunk*> viewableChunks, int32_t);
|
||||
void removeNPC(std::vector<Chunk*> viewableChunks, int32_t);
|
||||
|
||||
void npcBarkHandler(CNSocket* sock, CNPacketData* data);
|
||||
void npcSummonHandler(CNSocket* sock, CNPacketData* data);
|
||||
void npcWarpHandler(CNSocket* sock, CNPacketData* data);
|
||||
@ -30,6 +33,4 @@ namespace NPCManager {
|
||||
void npcVendorSell(CNSocket* sock, CNPacketData* data);
|
||||
void npcVendorBuyback(CNSocket* sock, CNPacketData* data);
|
||||
void npcVendorBuyBattery(CNSocket* sock, CNPacketData* data);
|
||||
|
||||
void updatePlayerNPCS(CNSocket* sock, PlayerView& plr);
|
||||
}
|
||||
|
@ -169,8 +169,7 @@ void NanoManager::addNano(CNSocket* sock, int16_t nanoId, int16_t slot) {
|
||||
resp2.iPC_Level = level;
|
||||
|
||||
// Update other players' perception of the player's level
|
||||
for (CNSocket* s : PlayerManager::players[sock].viewable)
|
||||
s->sendPacket((void*)&resp2, P_FE2CL_REP_PC_CHANGE_LEVEL, sizeof(sP_FE2CL_REP_PC_CHANGE_LEVEL));
|
||||
PlayerManager::sendToViewable(sock, (void*)&resp2, P_FE2CL_REP_PC_CHANGE_LEVEL, sizeof(sP_FE2CL_REP_PC_CHANGE_LEVEL));
|
||||
}
|
||||
|
||||
void NanoManager::summonNano(CNSocket *sock, int slot) {
|
||||
@ -196,8 +195,7 @@ void NanoManager::summonNano(CNSocket *sock, int slot) {
|
||||
else
|
||||
pkt1.Nano = plr->Nanos[nanoId];
|
||||
|
||||
for (CNSocket* s : PlayerManager::players[sock].viewable)
|
||||
s->sendPacket((void*)&pkt1, P_FE2CL_NANO_ACTIVE, sizeof(sP_FE2CL_NANO_ACTIVE));
|
||||
PlayerManager::sendToViewable(sock, (void*)&pkt1, P_FE2CL_NANO_ACTIVE, sizeof(sP_FE2CL_NANO_ACTIVE));
|
||||
|
||||
// update player
|
||||
plr->activeNano = nanoId;
|
||||
|
@ -43,7 +43,8 @@ void PlayerManager::addPlayer(CNSocket* key, Player plr) {
|
||||
memcpy(p, &plr, sizeof(Player));
|
||||
|
||||
players[key] = PlayerView();
|
||||
players[key].viewable = std::list<CNSocket*>();
|
||||
players[key].chunkPos = std::make_pair<int, int>(0, 0);
|
||||
players[key].currentChunks = std::vector<Chunk*>();
|
||||
players[key].plr = p;
|
||||
players[key].lastHeartbeat = 0;
|
||||
|
||||
@ -54,88 +55,63 @@ void PlayerManager::addPlayer(CNSocket* key, Player plr) {
|
||||
}
|
||||
|
||||
void PlayerManager::removePlayer(CNSocket* key) {
|
||||
PlayerView cachedView = players[key];
|
||||
PlayerView& view = players[key];
|
||||
|
||||
// if players have them in their viewable lists, remove it
|
||||
for (auto& pair : players) {
|
||||
if (pair.first == key)
|
||||
continue;
|
||||
|
||||
PlayerView& otherPlayer = pair.second;
|
||||
otherPlayer.viewable.remove(key); // gone
|
||||
|
||||
std::cout << "PlayerId = " << otherPlayer.plr->iID << " removed from " << otherPlayer.plr->iID << "'s viewable list" << std::endl;
|
||||
|
||||
// now send PC_EXIT packet
|
||||
INITSTRUCT(sP_FE2CL_PC_EXIT, exitPacket);
|
||||
exitPacket.iID = players[key].plr->iID;
|
||||
|
||||
pair.first->sendPacket((void*)&exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT));
|
||||
}
|
||||
// remove players from all chunks
|
||||
removePlayerFromChunks(view.currentChunks, key);
|
||||
|
||||
std::cout << U16toU8(cachedView.plr->PCStyle.szFirstName) << " " << U16toU8(cachedView.plr->PCStyle.szLastName) << " (PlayerId = " << key->plr->iID << ") has left!" << std::endl;
|
||||
// remove from chunk
|
||||
if (ChunkManager::chunks.find(view.chunkPos) != ChunkManager::chunks.end())
|
||||
ChunkManager::chunks[view.chunkPos]->players.erase(key);
|
||||
|
||||
std::cout << U16toU8(view.plr->PCStyle.szFirstName) << " " << U16toU8(view.plr->PCStyle.szLastName) << " (PlayerId = " << view.plr->iID << ") has left!" << std::endl;
|
||||
|
||||
key->plr = nullptr;
|
||||
delete cachedView.plr;
|
||||
delete view.plr;
|
||||
players.erase(key);
|
||||
|
||||
std::cout << players.size() << " players" << std::endl;
|
||||
}
|
||||
|
||||
void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z, int angle) {
|
||||
players[sock].plr->angle = angle;
|
||||
updatePlayerPosition(sock, X, Y, Z);
|
||||
void PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket* sock) {
|
||||
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
||||
INITSTRUCT(sP_FE2CL_PC_EXIT, exitPlayer);
|
||||
|
||||
// for chunks that need the player to be removed from
|
||||
for (Chunk* chunk : chunks) {
|
||||
|
||||
// remove NPCs
|
||||
for (int32_t id : chunk->NPCs) {
|
||||
exitData.iNPC_ID = id;
|
||||
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
}
|
||||
|
||||
// remove players from eachother
|
||||
for (CNSocket* otherSock : chunk->players) {
|
||||
exitPlayer.iID = players[sock].plr->iID;
|
||||
otherSock->sendPacket((void*)&exitPlayer, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT));
|
||||
exitPlayer.iID = players[otherSock].plr->iID;
|
||||
sock->sendPacket((void*)&exitPlayer, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT));
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
std::vector<CNSocket*> noView;
|
||||
std::vector<CNSocket*> 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
|
||||
|
||||
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::PLAYERDISTANCE && diffY < settings::PLAYERDISTANCE) {
|
||||
yesView.push_back(pair.first);
|
||||
}
|
||||
else {
|
||||
noView.push_back(pair.first);
|
||||
}
|
||||
}
|
||||
|
||||
INITSTRUCT(sP_FE2CL_PC_EXIT, exitPacket);
|
||||
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
|
||||
exitPacket.iID = players[sock].plr->iID;
|
||||
otherSock->sendPacket((void*)&exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT));
|
||||
exitPacket.iID = players[otherSock].plr->iID;
|
||||
sock->sendPacket((void*)&exitPacket, P_FE2CL_PC_EXIT, sizeof(sP_FE2CL_PC_EXIT));
|
||||
|
||||
// remove them from the viewable list
|
||||
players[sock].viewable.erase(i++);
|
||||
players[otherSock].viewable.remove(sock);
|
||||
continue;
|
||||
}
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
void PlayerManager::addPlayerToChunks(std::vector<Chunk*> chunks, CNSocket* sock) {
|
||||
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
||||
INITSTRUCT(sP_FE2CL_PC_NEW, newPlayer);
|
||||
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
|
||||
|
||||
for (Chunk* chunk : chunks) {
|
||||
// add npcs
|
||||
for (int32_t id : chunk->NPCs) {
|
||||
enterData.NPCAppearanceData = NPCManager::NPCs[id]->appearanceData;
|
||||
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||
}
|
||||
|
||||
// add players
|
||||
for (CNSocket* otherSock : chunk->players) {
|
||||
Player *otherPlr = players[otherSock].plr;
|
||||
Player *plr = players[sock].plr;
|
||||
|
||||
@ -166,28 +142,43 @@ void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) {
|
||||
memcpy(newPlayer.PCAppearanceData.ItemEquip, otherPlr->Equip, sizeof(sItemBase) * AEQUIP_COUNT);
|
||||
|
||||
sock->sendPacket((void*)&newPlayer, P_FE2CL_PC_NEW, sizeof(sP_FE2CL_PC_NEW));
|
||||
|
||||
players[sock].viewable.push_back(otherSock);
|
||||
players[otherSock].viewable.push_back(sock);
|
||||
}
|
||||
}
|
||||
|
||||
NPCManager::updatePlayerNPCS(sock, players[sock]);
|
||||
}
|
||||
|
||||
void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z, int angle) {
|
||||
players[sock].plr->angle = angle;
|
||||
updatePlayerPosition(sock, X, Y, Z);
|
||||
}
|
||||
|
||||
std::list<CNSocket*> PlayerManager::getNearbyPlayers(int x, int y, int dist) {
|
||||
std::list<CNSocket*> plrs;
|
||||
void PlayerManager::updatePlayerPosition(CNSocket* sock, int X, int Y, int Z) {
|
||||
PlayerView& view = players[sock];
|
||||
view.plr->x = X;
|
||||
view.plr->y = Y;
|
||||
view.plr->z = Z;
|
||||
|
||||
for (auto pair : players) {
|
||||
int diffX = abs(pair.second.plr->x - x);
|
||||
int diffY = abs(pair.second.plr->x - x);
|
||||
std::pair<int, int> newPos = ChunkManager::grabChunk(X, Y);
|
||||
|
||||
if (diffX < dist && diffY < dist)
|
||||
plrs.push_back(pair.first);
|
||||
}
|
||||
// nothing to be done
|
||||
if (newPos == view.chunkPos)
|
||||
return;
|
||||
|
||||
return plrs;
|
||||
// add player to chunk
|
||||
std::vector<Chunk*> allChunks = ChunkManager::grabChunks(newPos.first, newPos.second);
|
||||
|
||||
// first, remove all the old npcs & players from the old chunks
|
||||
removePlayerFromChunks(ChunkManager::getDeltaChunks(view.currentChunks, allChunks), sock);
|
||||
|
||||
// now, add all the new npcs & players!
|
||||
addPlayerToChunks(ChunkManager::getDeltaChunks(allChunks, view.currentChunks), sock);
|
||||
|
||||
// remove us from that old stinky chunk (+ a sanity check)
|
||||
if (ChunkManager::chunks.find(view.chunkPos) != ChunkManager::chunks.end())
|
||||
ChunkManager::chunks[view.chunkPos]->players.erase(sock);
|
||||
|
||||
ChunkManager::addPlayer(X, Y, sock); // takes care of adding the player to the chunk if it exists or not
|
||||
view.chunkPos = newPos;
|
||||
view.currentChunks = allChunks;
|
||||
}
|
||||
|
||||
void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
@ -267,6 +258,17 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
addPlayer(sock, plr);
|
||||
}
|
||||
|
||||
void PlayerManager::sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size) {
|
||||
for (Chunk* chunk : players[sock].currentChunks) {
|
||||
for (CNSocket* otherSock : chunk->players) {
|
||||
if (otherSock == sock)
|
||||
continue;
|
||||
|
||||
otherSock->sendPacket(buf, type, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerManager::loadPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_LOADING_COMPLETE))
|
||||
return; // ignore the malformed packet
|
||||
@ -315,9 +317,7 @@ void PlayerManager::movePlayer(CNSocket* sock, CNPacketData* data) {
|
||||
moveResponse.iCliTime = moveData->iCliTime; // maybe don't send this??? seems unneeded...
|
||||
moveResponse.iSvrTime = tm;
|
||||
|
||||
for (CNSocket* otherSock : players[sock].viewable) {
|
||||
otherSock->sendPacket((void*)&moveResponse, P_FE2CL_PC_MOVE, sizeof(sP_FE2CL_PC_MOVE));
|
||||
}
|
||||
sendToViewable(sock, (void*)&moveResponse, P_FE2CL_PC_MOVE, sizeof(sP_FE2CL_PC_MOVE));
|
||||
}
|
||||
|
||||
void PlayerManager::stopPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
@ -340,9 +340,7 @@ void PlayerManager::stopPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
stopResponse.iCliTime = stopData->iCliTime; // maybe don't send this??? seems unneeded...
|
||||
stopResponse.iSvrTime = tm;
|
||||
|
||||
for (CNSocket* otherSock : players[sock].viewable) {
|
||||
otherSock->sendPacket((void*)&stopResponse, P_FE2CL_PC_STOP, sizeof(sP_FE2CL_PC_STOP));
|
||||
}
|
||||
sendToViewable(sock, (void*)&stopResponse, P_FE2CL_PC_STOP, sizeof(sP_FE2CL_PC_STOP));
|
||||
}
|
||||
|
||||
void PlayerManager::jumpPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
@ -371,9 +369,7 @@ void PlayerManager::jumpPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
jumpResponse.iCliTime = jumpData->iCliTime; // maybe don't send this??? seems unneeded...
|
||||
jumpResponse.iSvrTime = tm;
|
||||
|
||||
for (CNSocket* otherSock : players[sock].viewable) {
|
||||
otherSock->sendPacket((void*)&jumpResponse, P_FE2CL_PC_JUMP, sizeof(sP_FE2CL_PC_JUMP));
|
||||
}
|
||||
sendToViewable(sock, (void*)&jumpResponse, P_FE2CL_PC_JUMP, sizeof(sP_FE2CL_PC_JUMP));
|
||||
}
|
||||
|
||||
void PlayerManager::jumppadPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
@ -400,9 +396,7 @@ void PlayerManager::jumppadPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
jumppadResponse.iCliTime = jumppadData->iCliTime;
|
||||
jumppadResponse.iSvrTime = tm;
|
||||
|
||||
for (CNSocket* otherSock : players[sock].viewable) {
|
||||
otherSock->sendPacket((void*)&jumppadResponse, P_FE2CL_PC_JUMPPAD, sizeof(sP_FE2CL_PC_JUMPPAD));
|
||||
}
|
||||
sendToViewable(sock, (void*)&jumppadResponse, P_FE2CL_PC_JUMPPAD, sizeof(sP_FE2CL_PC_JUMPPAD));
|
||||
}
|
||||
|
||||
void PlayerManager::launchPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
@ -430,9 +424,7 @@ void PlayerManager::launchPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
launchResponse.iCliTime = launchData->iCliTime;
|
||||
launchResponse.iSvrTime = tm;
|
||||
|
||||
for (CNSocket* otherSock : players[sock].viewable) {
|
||||
otherSock->sendPacket((void*)&launchResponse, P_FE2CL_PC_LAUNCHER, sizeof(sP_FE2CL_PC_LAUNCHER));
|
||||
}
|
||||
sendToViewable(sock, (void*)&launchResponse, P_FE2CL_PC_LAUNCHER, sizeof(sP_FE2CL_PC_LAUNCHER));
|
||||
}
|
||||
|
||||
void PlayerManager::ziplinePlayer(CNSocket* sock, CNPacketData* data) {
|
||||
@ -467,9 +459,7 @@ void PlayerManager::ziplinePlayer(CNSocket* sock, CNPacketData* data) {
|
||||
ziplineResponse.iRollMax = ziplineData->iRollMax;
|
||||
ziplineResponse.iRoll = ziplineData->iRoll;
|
||||
|
||||
for (CNSocket* otherSock : players[sock].viewable) {
|
||||
otherSock->sendPacket((void*)&ziplineResponse, P_FE2CL_PC_ZIPLINE, sizeof(sP_FE2CL_PC_ZIPLINE));
|
||||
}
|
||||
sendToViewable(sock, (void*)&ziplineResponse, P_FE2CL_PC_ZIPLINE, sizeof(sP_FE2CL_PC_ZIPLINE));
|
||||
}
|
||||
|
||||
void PlayerManager::movePlatformPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
@ -501,9 +491,7 @@ void PlayerManager::movePlatformPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
platResponse.cKeyValue = platformData->cKeyValue;
|
||||
platResponse.iPlatformID = platformData->iPlatformID;
|
||||
|
||||
for (CNSocket* otherSock : players[sock].viewable) {
|
||||
otherSock->sendPacket((void*)&platResponse, P_FE2CL_PC_MOVEPLATFORM, sizeof(sP_FE2CL_PC_MOVEPLATFORM));
|
||||
}
|
||||
sendToViewable(sock, (void*)&platResponse, P_FE2CL_PC_MOVEPLATFORM, sizeof(sP_FE2CL_PC_MOVEPLATFORM));
|
||||
}
|
||||
|
||||
void PlayerManager::moveSlopePlayer(CNSocket* sock, CNPacketData* data) {
|
||||
@ -531,9 +519,7 @@ void PlayerManager::moveSlopePlayer(CNSocket* sock, CNPacketData* data) {
|
||||
slopeResponse.cKeyValue = slopeData->cKeyValue;
|
||||
slopeResponse.iSlopeID = slopeData->iSlopeID;
|
||||
|
||||
for (CNSocket* otherSock : players[sock].viewable) {
|
||||
otherSock->sendPacket((void*)&slopeResponse, P_FE2CL_PC_SLOPE, sizeof(sP_FE2CL_PC_SLOPE));
|
||||
}
|
||||
sendToViewable(sock, (void*)&slopeResponse, P_FE2CL_PC_SLOPE, sizeof(sP_FE2CL_PC_SLOPE));
|
||||
}
|
||||
|
||||
void PlayerManager::gotoPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
@ -556,8 +542,8 @@ void PlayerManager::gotoPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
response.iZ = plrv.plr->z = gotoData->iToZ;
|
||||
|
||||
// force player & NPC reload
|
||||
plrv.viewable.clear();
|
||||
plrv.viewableNPCs.clear();
|
||||
plrv.chunkPos = std::make_pair<int, int>(0, 0);
|
||||
plrv.currentChunks.clear();
|
||||
|
||||
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_GOTO_SUCC, sizeof(sP_FE2CL_REP_PC_GOTO_SUCC));
|
||||
}
|
||||
@ -668,12 +654,10 @@ void PlayerManager::revivePlayer(CNSocket* sock, CNPacketData* data) {
|
||||
resp2.PCRegenDataForOtherPC.iAngle = plr->angle;
|
||||
resp2.PCRegenDataForOtherPC.Nano = plr->Nanos[plr->activeNano];
|
||||
|
||||
for (CNSocket *s : players[sock].viewable)
|
||||
s->sendPacket((void*)&resp2, P_FE2CL_PC_REGEN, sizeof(sP_FE2CL_PC_REGEN));
|
||||
sendToViewable(sock, (void*)&resp2, P_FE2CL_PC_REGEN, sizeof(sP_FE2CL_PC_REGEN));
|
||||
}
|
||||
|
||||
void PlayerManager::enterPlayerVehicle(CNSocket* sock, CNPacketData* data) {
|
||||
|
||||
PlayerView& plr = PlayerManager::players[sock];
|
||||
|
||||
if (plr.plr->Equip[8].iID > 0) {
|
||||
@ -686,10 +670,11 @@ void PlayerManager::enterPlayerVehicle(CNSocket* sock, CNPacketData* data) {
|
||||
response2.iPC_ID = plr.plr->iID;
|
||||
response2.iState = 8;
|
||||
|
||||
for (CNSocket* otherSock : plr.viewable) {
|
||||
for (Chunk* chunk : players[sock].currentChunks) {
|
||||
for (CNSocket* otherSock : chunk->players) {
|
||||
otherSock->sendPacket((void*)&response2, P_FE2CL_PC_STATE_CHANGE, sizeof(sP_FE2CL_PC_STATE_CHANGE));
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
INITSTRUCT(sP_FE2CL_PC_VEHICLE_ON_FAIL, response);
|
||||
sock->sendPacket((void*)&response, P_FE2CL_PC_VEHICLE_ON_FAIL, sizeof(sP_FE2CL_PC_VEHICLE_ON_FAIL));
|
||||
@ -709,9 +694,7 @@ void PlayerManager::exitPlayerVehicle(CNSocket* sock, CNPacketData* data) {
|
||||
response2.iPC_ID = plr.plr->iID;
|
||||
response2.iState = 0;
|
||||
|
||||
for (CNSocket* otherSock : plr.viewable) {
|
||||
otherSock->sendPacket((void*)&response2, P_FE2CL_PC_STATE_CHANGE, sizeof(sP_FE2CL_PC_STATE_CHANGE));
|
||||
}
|
||||
sendToViewable(sock, (void*)&response2, P_FE2CL_PC_STATE_CHANGE, sizeof(sP_FE2CL_PC_STATE_CHANGE));
|
||||
}
|
||||
|
||||
void PlayerManager::setSpecialSwitchPlayer(CNSocket* sock, CNPacketData* data) {
|
||||
|
@ -4,15 +4,17 @@
|
||||
#include "CNProtocol.hpp"
|
||||
#include "CNStructs.hpp"
|
||||
#include "CNShardServer.hpp"
|
||||
#include "ChunkManager.hpp"
|
||||
|
||||
#include <utility>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
struct WarpLocation;
|
||||
|
||||
struct PlayerView {
|
||||
std::list<CNSocket*> viewable;
|
||||
std::list<int32_t> viewableNPCs;
|
||||
std::pair<int, int> chunkPos;
|
||||
std::vector<Chunk*> currentChunks;
|
||||
Player *plr;
|
||||
time_t lastHeartbeat;
|
||||
};
|
||||
@ -25,9 +27,13 @@ namespace PlayerManager {
|
||||
void addPlayer(CNSocket* key, Player plr);
|
||||
void removePlayer(CNSocket* key);
|
||||
|
||||
void removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket* sock);
|
||||
void addPlayerToChunks(std::vector<Chunk*> chunks, CNSocket* sock);
|
||||
|
||||
void updatePlayerPosition(CNSocket* sock, int X, int Y, int Z);
|
||||
void updatePlayerPosition(CNSocket* sock, int X, int Y, int Z, int angle);
|
||||
std::list<CNSocket*> getNearbyPlayers(int X, int Y, int dist);
|
||||
|
||||
void sendToViewable(CNSocket* sock, void* buf, uint32_t type, size_t size);
|
||||
|
||||
void enterPlayer(CNSocket* sock, CNPacketData* data);
|
||||
void loadPlayer(CNSocket* sock, CNPacketData* data);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "settings.hpp"
|
||||
#include "MissionManager.hpp"
|
||||
#include "MobManager.hpp"
|
||||
#include "ChunkManager.hpp"
|
||||
|
||||
#include "contrib/JSON.hpp"
|
||||
|
||||
@ -27,9 +28,10 @@ void TableData::init() {
|
||||
|
||||
// Temporary fix, IDs will be pulled from json later
|
||||
tmp->appearanceData.iNPC_ID = i;
|
||||
i++;
|
||||
|
||||
NPCManager::NPCs[tmp->appearanceData.iNPC_ID] = tmp;
|
||||
NPCManager::NPCs[i] = tmp;
|
||||
ChunkManager::addNPC(npc["x"], npc["y"], i);
|
||||
i++;
|
||||
|
||||
if (npc["id"] == 641 || npc["id"] == 642)
|
||||
NPCManager::RespawnPoints.push_back({ npc["x"], npc["y"], ((int)npc["z"]) + RESURRECT_HEIGHT });
|
||||
@ -153,6 +155,7 @@ void TableData::init() {
|
||||
|
||||
NPCManager::NPCs[i] = tmp;
|
||||
MobManager::Mobs[i] = (Mob*)NPCManager::NPCs[i];
|
||||
ChunkManager::addNPC(npc["iX"], npc["iY"], i);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
@ -137,8 +137,8 @@ void TransportManager::transportWarpHandler(CNSocket* sock, CNPacketData* data)
|
||||
* same map tile you were already in, but we might as well force an NPC reload.
|
||||
*/
|
||||
PlayerView& plrv = PlayerManager::players[sock];
|
||||
plrv.viewable.clear();
|
||||
plrv.viewableNPCs.clear();
|
||||
plrv.currentChunks.clear();
|
||||
plrv.chunkPos = std::make_pair<int, int>(0, 0);
|
||||
|
||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC));
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "TransportManager.hpp"
|
||||
#include "Database.hpp"
|
||||
#include "TableData.hpp"
|
||||
#include "ChunkManager.hpp"
|
||||
|
||||
#include "settings.hpp"
|
||||
|
||||
@ -48,9 +49,8 @@ void terminate(int arg) {
|
||||
shardThread->join();
|
||||
}
|
||||
|
||||
#if defined(__SANITIZE_ADDRESS__)
|
||||
TableData::cleanup();
|
||||
#endif
|
||||
ChunkManager::cleanup();
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user