mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 13:30:06 +00:00
commit
4caca07856
@ -56,6 +56,17 @@ void ChunkManager::removePlayer(std::pair<int, int> chunkPos, CNSocket* sock) {
|
|||||||
// TODO: if players and NPCs are empty, free chunk and remove it from surrounding views
|
// TODO: if players and NPCs are empty, free chunk and remove it from surrounding views
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChunkManager::removeNPC(std::pair<int, int> chunkPos, int32_t id) {
|
||||||
|
if (!checkChunk(chunkPos))
|
||||||
|
return; // do nothing if chunk doesn't even exist
|
||||||
|
|
||||||
|
Chunk* chunk = chunks[chunkPos];
|
||||||
|
|
||||||
|
chunk->NPCs.erase(id); // gone
|
||||||
|
|
||||||
|
// TODO: if players and NPCs are empty, free chunk and remove it from surrounding views
|
||||||
|
}
|
||||||
|
|
||||||
bool ChunkManager::checkChunk(std::pair<int, int> chunk) {
|
bool ChunkManager::checkChunk(std::pair<int, int> chunk) {
|
||||||
return chunks.find(chunk) != chunks.end();
|
return chunks.find(chunk) != chunks.end();
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ namespace ChunkManager {
|
|||||||
void addNPC(int posX, int posY, int32_t id);
|
void addNPC(int posX, int posY, int32_t id);
|
||||||
void addPlayer(int posX, int posY, CNSocket* sock);
|
void addPlayer(int posX, int posY, CNSocket* sock);
|
||||||
void removePlayer(std::pair<int, int> chunkPos, CNSocket* sock);
|
void removePlayer(std::pair<int, int> chunkPos, CNSocket* sock);
|
||||||
|
void removeNPC(std::pair<int, int> chunkPos, int32_t id);
|
||||||
bool checkChunk(std::pair<int, int> chunk);
|
bool checkChunk(std::pair<int, int> chunk);
|
||||||
std::pair<int, int> grabChunk(int posX, int posY);
|
std::pair<int, int> grabChunk(int posX, int posY);
|
||||||
std::vector<Chunk*> grabChunks(std::pair<int, int> chunkPos);
|
std::vector<Chunk*> grabChunks(std::pair<int, int> chunkPos);
|
||||||
|
@ -16,6 +16,14 @@ const float CN_EP_RANK_3 = 0.5f;
|
|||||||
const float CN_EP_RANK_4 = 0.3f;
|
const float CN_EP_RANK_4 = 0.3f;
|
||||||
const float CN_EP_RANK_5 = 0.29f;
|
const float CN_EP_RANK_5 = 0.29f;
|
||||||
|
|
||||||
|
// NPC classes
|
||||||
|
enum NPCClass {
|
||||||
|
NPC_BASE = 0,
|
||||||
|
NPC_MOB = 1,
|
||||||
|
NPC_BUS = 2,
|
||||||
|
NPC_EGG = 3
|
||||||
|
};
|
||||||
|
|
||||||
// nano powers
|
// nano powers
|
||||||
enum {
|
enum {
|
||||||
EST_NONE = 0,
|
EST_NONE = 0,
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
class BaseNPC {
|
class BaseNPC {
|
||||||
public:
|
public:
|
||||||
sNPCAppearanceData appearanceData;
|
sNPCAppearanceData appearanceData;
|
||||||
|
NPCClass npcClass;
|
||||||
|
|
||||||
BaseNPC() {};
|
BaseNPC() {};
|
||||||
BaseNPC(int x, int y, int z, int type) {
|
BaseNPC(int x, int y, int z, int type) {
|
||||||
@ -20,4 +21,7 @@ public:
|
|||||||
// hopefully no collisions happen :eyes:
|
// hopefully no collisions happen :eyes:
|
||||||
appearanceData.iNPC_ID = (int32_t)rand();
|
appearanceData.iNPC_ID = (int32_t)rand();
|
||||||
};
|
};
|
||||||
|
BaseNPC(int x, int y, int z, int type, NPCClass classType) : BaseNPC(x, y, z, type) {
|
||||||
|
npcClass = classType;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
@ -33,15 +33,30 @@ void NPCManager::init() {
|
|||||||
void NPCManager::addNPC(std::vector<Chunk*> viewableChunks, int32_t id) {
|
void NPCManager::addNPC(std::vector<Chunk*> viewableChunks, int32_t id) {
|
||||||
BaseNPC* npc = NPCs[id];
|
BaseNPC* npc = NPCs[id];
|
||||||
|
|
||||||
// create struct
|
switch (npc->npcClass) {
|
||||||
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
case NPC_BUS:
|
||||||
enterData.NPCAppearanceData = npc->appearanceData;
|
INITSTRUCT(sP_FE2CL_TRANSPORTATION_ENTER, enterBusData);
|
||||||
|
enterBusData.AppearanceData = { 3, npc->appearanceData.iNPC_ID, npc->appearanceData.iNPCType, npc->appearanceData.iX, npc->appearanceData.iY, npc->appearanceData.iZ };
|
||||||
|
|
||||||
for (Chunk* chunk : viewableChunks) {
|
for (Chunk* chunk : viewableChunks) {
|
||||||
for (CNSocket* sock : chunk->players) {
|
for (CNSocket* sock : chunk->players) {
|
||||||
// send to socket
|
// send to socket
|
||||||
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
sock->sendPacket((void*)&enterBusData, P_FE2CL_TRANSPORTATION_ENTER, sizeof(sP_FE2CL_TRANSPORTATION_ENTER));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,21 +81,38 @@ void NPCManager::removeNPC(int32_t id) {
|
|||||||
Chunk* chunk = ChunkManager::chunks[pos];
|
Chunk* chunk = ChunkManager::chunks[pos];
|
||||||
chunk->NPCs.erase(id);
|
chunk->NPCs.erase(id);
|
||||||
|
|
||||||
// create struct
|
switch (entity->npcClass) {
|
||||||
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
case NPC_BUS:
|
||||||
exitData.iNPC_ID = id;
|
INITSTRUCT(sP_FE2CL_TRANSPORTATION_EXIT, exitBusData);
|
||||||
|
exitBusData.eTT = 3;
|
||||||
|
exitBusData.iT_ID = id;
|
||||||
|
|
||||||
// remove it from the clients
|
for (Chunk* chunk : ChunkManager::grabChunks(pos)) {
|
||||||
for (Chunk* chunk : ChunkManager::grabChunks(pos)) {
|
for (CNSocket* sock : chunk->players) {
|
||||||
for (CNSocket* sock : chunk->players) {
|
// send to socket
|
||||||
// send to socket
|
sock->sendPacket((void*)&exitBusData, P_FE2CL_TRANSPORTATION_EXIT, sizeof(sP_FE2CL_TRANSPORTATION_EXIT));
|
||||||
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
case NPC_MOB:
|
||||||
|
// remove from mob list if it's a mob
|
||||||
|
if (MobManager::Mobs.find(id) != MobManager::Mobs.end())
|
||||||
|
MobManager::Mobs.erase(id);
|
||||||
|
// fall through
|
||||||
|
default:
|
||||||
|
// create struct
|
||||||
|
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
||||||
|
exitData.iNPC_ID = id;
|
||||||
|
|
||||||
// remove from mob list if it's a mob
|
// remove it from the clients
|
||||||
if (MobManager::Mobs.find(id) != MobManager::Mobs.end())
|
for (Chunk* chunk : ChunkManager::grabChunks(pos)) {
|
||||||
MobManager::Mobs.erase(id);
|
for (CNSocket* sock : chunk->players) {
|
||||||
|
// send to socket
|
||||||
|
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// finally, remove it from the map and free it
|
// finally, remove it from the map and free it
|
||||||
NPCs.erase(id);
|
NPCs.erase(id);
|
||||||
@ -89,6 +121,24 @@ void NPCManager::removeNPC(int32_t id) {
|
|||||||
std::cout << "npc removed!" << std::endl;
|
std::cout << "npc removed!" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z) {
|
||||||
|
BaseNPC* npc = NPCs[id];
|
||||||
|
|
||||||
|
std::pair<int, int> oldPos = ChunkManager::grabChunk(npc->appearanceData.iX, npc->appearanceData.iY);
|
||||||
|
npc->appearanceData.iX = X;
|
||||||
|
npc->appearanceData.iY = Y;
|
||||||
|
npc->appearanceData.iZ = Z;
|
||||||
|
std::pair<int, int> newPos = ChunkManager::grabChunk(X, Y);
|
||||||
|
|
||||||
|
// nothing to be done
|
||||||
|
if (newPos == oldPos)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// pull NPC from old chunk and add to new chunk
|
||||||
|
ChunkManager::removeNPC(oldPos, npc->appearanceData.iNPC_ID);
|
||||||
|
ChunkManager::addNPC(X, Y, npc->appearanceData.iNPC_ID);
|
||||||
|
}
|
||||||
|
|
||||||
void NPCManager::npcVendorBuy(CNSocket* sock, CNPacketData* data) {
|
void NPCManager::npcVendorBuy(CNSocket* sock, CNPacketData* data) {
|
||||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_VENDOR_ITEM_BUY))
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_VENDOR_ITEM_BUY))
|
||||||
return; // malformed packet
|
return; // malformed packet
|
||||||
|
@ -22,6 +22,7 @@ namespace NPCManager {
|
|||||||
|
|
||||||
void addNPC(std::vector<Chunk*> viewableChunks, int32_t);
|
void addNPC(std::vector<Chunk*> viewableChunks, int32_t);
|
||||||
void removeNPC(int32_t);
|
void removeNPC(int32_t);
|
||||||
|
void updateNPCPosition(int32_t, int X, int Y, int Z);
|
||||||
|
|
||||||
void npcBarkHandler(CNSocket* sock, CNPacketData* data);
|
void npcBarkHandler(CNSocket* sock, CNPacketData* data);
|
||||||
void npcSummonHandler(CNSocket* sock, CNPacketData* data);
|
void npcSummonHandler(CNSocket* sock, CNPacketData* data);
|
||||||
|
@ -27,6 +27,7 @@ void PlayerManager::init() {
|
|||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_LAUNCHER, PlayerManager::launchPlayer);
|
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_ZIPLINE, PlayerManager::ziplinePlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVEPLATFORM, PlayerManager::movePlatformPlayer);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVEPLATFORM, PlayerManager::movePlatformPlayer);
|
||||||
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVETRANSPORTATION, PlayerManager::moveSliderPlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_SLOPE, PlayerManager::moveSlopePlayer);
|
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_REQ_PC_GOTO, PlayerManager::gotoPlayer);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SET_VALUE, PlayerManager::setSpecialPlayer);
|
REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SET_VALUE, PlayerManager::setSpecialPlayer);
|
||||||
@ -79,7 +80,6 @@ void PlayerManager::removePlayer(CNSocket* key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket* sock) {
|
void PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket* sock) {
|
||||||
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
|
||||||
INITSTRUCT(sP_FE2CL_PC_EXIT, exitPlayer);
|
INITSTRUCT(sP_FE2CL_PC_EXIT, exitPlayer);
|
||||||
|
|
||||||
// for chunks that need the player to be removed from
|
// for chunks that need the player to be removed from
|
||||||
@ -87,8 +87,20 @@ void PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket*
|
|||||||
|
|
||||||
// remove NPCs
|
// remove NPCs
|
||||||
for (int32_t id : chunk->NPCs) {
|
for (int32_t id : chunk->NPCs) {
|
||||||
exitData.iNPC_ID = id;
|
BaseNPC* npc = NPCManager::NPCs[id];
|
||||||
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
switch (npc->npcClass) {
|
||||||
|
case NPC_BUS:
|
||||||
|
INITSTRUCT(sP_FE2CL_TRANSPORTATION_EXIT, exitBusData);
|
||||||
|
exitBusData.eTT = 3;
|
||||||
|
exitBusData.iT_ID = id;
|
||||||
|
sock->sendPacket((void*)&exitBusData, P_FE2CL_TRANSPORTATION_EXIT, sizeof(sP_FE2CL_TRANSPORTATION_EXIT));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
INITSTRUCT(sP_FE2CL_NPC_EXIT, exitData);
|
||||||
|
exitData.iNPC_ID = id;
|
||||||
|
sock->sendPacket((void*)&exitData, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove players from eachother
|
// remove players from eachother
|
||||||
@ -105,14 +117,24 @@ void PlayerManager::removePlayerFromChunks(std::vector<Chunk*> chunks, CNSocket*
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlayerManager::addPlayerToChunks(std::vector<Chunk*> chunks, CNSocket* sock) {
|
void PlayerManager::addPlayerToChunks(std::vector<Chunk*> chunks, CNSocket* sock) {
|
||||||
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
|
||||||
INITSTRUCT(sP_FE2CL_PC_NEW, newPlayer);
|
INITSTRUCT(sP_FE2CL_PC_NEW, newPlayer);
|
||||||
|
|
||||||
for (Chunk* chunk : chunks) {
|
for (Chunk* chunk : chunks) {
|
||||||
// add npcs
|
// add npcs
|
||||||
for (int32_t id : chunk->NPCs) {
|
for (int32_t id : chunk->NPCs) {
|
||||||
enterData.NPCAppearanceData = NPCManager::NPCs[id]->appearanceData;
|
BaseNPC* npc = NPCManager::NPCs[id];
|
||||||
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
switch (npc->npcClass) {
|
||||||
|
case NPC_BUS:
|
||||||
|
INITSTRUCT(sP_FE2CL_TRANSPORTATION_ENTER, enterBusData);
|
||||||
|
enterBusData.AppearanceData = { 3, npc->appearanceData.iNPC_ID, npc->appearanceData.iNPCType, npc->appearanceData.iX, npc->appearanceData.iY, npc->appearanceData.iZ };
|
||||||
|
sock->sendPacket((void*)&enterBusData, P_FE2CL_TRANSPORTATION_ENTER, sizeof(sP_FE2CL_TRANSPORTATION_ENTER));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
||||||
|
enterData.NPCAppearanceData = NPCManager::NPCs[id]->appearanceData;
|
||||||
|
sock->sendPacket((void*)&enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add players
|
// add players
|
||||||
@ -528,6 +550,37 @@ void PlayerManager::movePlatformPlayer(CNSocket* sock, CNPacketData* data) {
|
|||||||
sendToViewable(sock, (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::moveSliderPlayer(CNSocket* sock, CNPacketData* data) {
|
||||||
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_MOVETRANSPORTATION))
|
||||||
|
return; // ignore the malformed packet
|
||||||
|
|
||||||
|
sP_CL2FE_REQ_PC_MOVETRANSPORTATION* sliderData = (sP_CL2FE_REQ_PC_MOVETRANSPORTATION*)data->buf;
|
||||||
|
updatePlayerPosition(sock, sliderData->iX, sliderData->iY, sliderData->iZ, sliderData->iAngle);
|
||||||
|
|
||||||
|
uint64_t tm = getTime();
|
||||||
|
|
||||||
|
INITSTRUCT(sP_FE2CL_PC_MOVETRANSPORTATION, sliderResponse);
|
||||||
|
|
||||||
|
sliderResponse.iPC_ID = players[sock].plr->iID;
|
||||||
|
sliderResponse.iCliTime = sliderData->iCliTime;
|
||||||
|
sliderResponse.iSvrTime = tm;
|
||||||
|
sliderResponse.iX = sliderData->iX;
|
||||||
|
sliderResponse.iY = sliderData->iY;
|
||||||
|
sliderResponse.iZ = sliderData->iZ;
|
||||||
|
sliderResponse.iAngle = sliderData->iAngle;
|
||||||
|
sliderResponse.fVX = sliderData->fVX;
|
||||||
|
sliderResponse.fVY = sliderData->fVY;
|
||||||
|
sliderResponse.fVZ = sliderData->fVZ;
|
||||||
|
sliderResponse.iLcX = sliderData->iLcX;
|
||||||
|
sliderResponse.iLcY = sliderData->iLcY;
|
||||||
|
sliderResponse.iLcZ = sliderData->iLcZ;
|
||||||
|
sliderResponse.iSpeed = sliderData->iSpeed;
|
||||||
|
sliderResponse.cKeyValue = sliderData->cKeyValue;
|
||||||
|
sliderResponse.iT_ID = sliderData->iT_ID;
|
||||||
|
|
||||||
|
sendToViewable(sock, (void*)&sliderResponse, P_FE2CL_PC_MOVETRANSPORTATION, sizeof(sP_FE2CL_PC_MOVETRANSPORTATION));
|
||||||
|
}
|
||||||
|
|
||||||
void PlayerManager::moveSlopePlayer(CNSocket* sock, CNPacketData* data) {
|
void PlayerManager::moveSlopePlayer(CNSocket* sock, CNPacketData* data) {
|
||||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_SLOPE))
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_SLOPE))
|
||||||
return; // ignore the malformed packet
|
return; // ignore the malformed packet
|
||||||
|
@ -44,6 +44,7 @@ namespace PlayerManager {
|
|||||||
void launchPlayer(CNSocket* sock, CNPacketData* data);
|
void launchPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void ziplinePlayer(CNSocket* sock, CNPacketData* data);
|
void ziplinePlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void movePlatformPlayer(CNSocket* sock, CNPacketData* data);
|
void movePlatformPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
|
void moveSliderPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void moveSlopePlayer(CNSocket* sock, CNPacketData* data);
|
void moveSlopePlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void gotoPlayer(CNSocket* sock, CNPacketData* data);
|
void gotoPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
void setSpecialPlayer(CNSocket* sock, CNPacketData* data);
|
void setSpecialPlayer(CNSocket* sock, CNPacketData* data);
|
||||||
|
@ -263,19 +263,7 @@ void TableData::constructPath(nlohmann::json::iterator _pathData) {
|
|||||||
for (_point++; _point != pathPoints.end(); _point++) {
|
for (_point++; _point != pathPoints.end(); _point++) {
|
||||||
point = _point.value();
|
point = _point.value();
|
||||||
WarpLocation coords = { point["iX"] , point["iY"] , point["iZ"] };
|
WarpLocation coords = { point["iX"] , point["iY"] , point["iZ"] };
|
||||||
// Calculate distance between this point and the last
|
TransportManager::lerp(&points, last, coords, pathData["iMonkeySpeed"]);
|
||||||
int dXY = hypot(last.x - coords.x, last.y - coords.y); // XY plane distance
|
|
||||||
int distanceBetween = hypot(dXY, last.z - coords.z); // total distance
|
|
||||||
int lerps = distanceBetween / (int)pathData["iMonkeySpeed"]; // integer division to ensure a whole number of in-between points
|
|
||||||
for (int i = 0; i < lerps; i++) {
|
|
||||||
WarpLocation lerp;
|
|
||||||
// lerp math
|
|
||||||
float frac = (i + 1) * 1.0f / (lerps + 1);
|
|
||||||
lerp.x = (last.x * (1.0f - frac)) + (coords.x * frac);
|
|
||||||
lerp.y = (last.y * (1.0f - frac)) + (coords.y * frac);
|
|
||||||
lerp.z = (last.z * (1.0f - frac)) + (coords.z * frac);
|
|
||||||
points.push(lerp); // add lerp'd point to the queue
|
|
||||||
}
|
|
||||||
points.push(coords); // add keyframe to the queue
|
points.push(coords); // add keyframe to the queue
|
||||||
last = coords; // update start pos
|
last = coords; // update start pos
|
||||||
}
|
}
|
||||||
|
@ -4,17 +4,31 @@
|
|||||||
#include "TransportManager.hpp"
|
#include "TransportManager.hpp"
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
std::map<int32_t, TransportRoute> TransportManager::Routes;
|
std::map<int32_t, TransportRoute> TransportManager::Routes;
|
||||||
std::map<int32_t, TransportLocation> TransportManager::Locations;
|
std::map<int32_t, TransportLocation> TransportManager::Locations;
|
||||||
std::map<int32_t, std::queue<WarpLocation>> TransportManager::SkywayPaths;
|
std::map<int32_t, std::queue<WarpLocation>> TransportManager::SkywayPaths;
|
||||||
std::unordered_map<CNSocket*, std::queue<WarpLocation>> TransportManager::SkywayQueues;
|
std::unordered_map<CNSocket*, std::queue<WarpLocation>> TransportManager::SkywayQueues;
|
||||||
|
std::unordered_map<int32_t, std::queue<WarpLocation>> TransportManager::NPCQueues;
|
||||||
|
|
||||||
void TransportManager::init() {
|
void TransportManager::init() {
|
||||||
REGISTER_SHARD_TIMER(tickSkywaySystem, 1000);
|
REGISTER_SHARD_TIMER(tickTransportationSystem, 1000);
|
||||||
|
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_REGIST_TRANSPORTATION_LOCATION, transportRegisterLocationHandler);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_REGIST_TRANSPORTATION_LOCATION, transportRegisterLocationHandler);
|
||||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_WARP_USE_TRANSPORTATION, transportWarpHandler);
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_WARP_USE_TRANSPORTATION, transportWarpHandler);
|
||||||
|
|
||||||
|
BaseNPC* bus = new BaseNPC(220447, 162431, -3650, 1, NPC_BUS);
|
||||||
|
NPCManager::NPCs[bus->appearanceData.iNPC_ID] = bus;
|
||||||
|
ChunkManager::addNPC(bus->appearanceData.iX, bus->appearanceData.iY, bus->appearanceData.iNPC_ID);
|
||||||
|
std::queue<WarpLocation> busPoints;
|
||||||
|
WarpLocation start = { bus->appearanceData.iX, bus->appearanceData.iY, -3650 };
|
||||||
|
WarpLocation end = { 220441, 188102, -3653 };
|
||||||
|
busPoints.push(start);
|
||||||
|
TransportManager::lerp(&busPoints, start, end, 1000);
|
||||||
|
busPoints.push(end);
|
||||||
|
TransportManager::lerp(&busPoints, end, start, 1000);
|
||||||
|
NPCQueues[bus->appearanceData.iNPC_ID] = busPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransportManager::transportRegisterLocationHandler(CNSocket* sock, CNPacketData* data) {
|
void TransportManager::transportRegisterLocationHandler(CNSocket* sock, CNPacketData* data) {
|
||||||
@ -174,13 +188,17 @@ void TransportManager::transportWarpHandler(CNSocket* sock, CNPacketData* data)
|
|||||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC));
|
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TransportManager::tickTransportationSystem(CNServer* serv, time_t currTime) {
|
||||||
|
stepNPCPathing();
|
||||||
|
stepSkywaySystem();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Go through every socket that has broomstick points queued up, and advance to the next point.
|
* Go through every socket that has broomstick points queued up, and advance to the next point.
|
||||||
* If the player has disconnected or finished the route, clean up and remove them from the queue.
|
* If the player has disconnected or finished the route, clean up and remove them from the queue.
|
||||||
*/
|
*/
|
||||||
void TransportManager::tickSkywaySystem(CNServer* serv, time_t currTime) {
|
void TransportManager::stepSkywaySystem() {
|
||||||
|
|
||||||
//std::cout << SkywayQueue.size();
|
|
||||||
// using an unordered map so we can remove finished players in one iteration
|
// using an unordered map so we can remove finished players in one iteration
|
||||||
std::unordered_map<CNSocket*, std::queue<WarpLocation>>::iterator it = SkywayQueues.begin();
|
std::unordered_map<CNSocket*, std::queue<WarpLocation>>::iterator it = SkywayQueues.begin();
|
||||||
while (it != SkywayQueues.end()) {
|
while (it != SkywayQueues.end()) {
|
||||||
@ -228,3 +246,94 @@ void TransportManager::tickSkywaySystem(CNServer* serv, time_t currTime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TransportManager::stepNPCPathing() {
|
||||||
|
|
||||||
|
// all NPC pathing queues
|
||||||
|
std::unordered_map<int32_t, std::queue<WarpLocation>>::iterator it = NPCQueues.begin();
|
||||||
|
while (it != NPCQueues.end()) {
|
||||||
|
|
||||||
|
std::queue<WarpLocation>* queue = &it->second;
|
||||||
|
|
||||||
|
BaseNPC* npc = nullptr;
|
||||||
|
if (NPCManager::NPCs.find(it->first) != NPCManager::NPCs.end())
|
||||||
|
npc = NPCManager::NPCs[it->first];
|
||||||
|
|
||||||
|
if (npc == nullptr) {
|
||||||
|
// pluck out dead path + update iterator
|
||||||
|
it = NPCQueues.erase(it);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
WarpLocation point = queue->front(); // get point
|
||||||
|
queue->pop(); // remove point from front of queue
|
||||||
|
|
||||||
|
// calculate displacement
|
||||||
|
int dXY = hypot(point.x - npc->appearanceData.iX, point.y - npc->appearanceData.iY); // XY plane distance
|
||||||
|
int distanceBetween = hypot(dXY, point.z - npc->appearanceData.iZ); // total distance
|
||||||
|
|
||||||
|
// update NPC location to update viewables
|
||||||
|
NPCManager::updateNPCPosition(npc->appearanceData.iNPC_ID, point.x, point.y, point.z);
|
||||||
|
|
||||||
|
// get chunks in view
|
||||||
|
auto chunk = ChunkManager::grabChunk(npc->appearanceData.iX, npc->appearanceData.iY);
|
||||||
|
auto chunks = ChunkManager::grabChunks(chunk);
|
||||||
|
|
||||||
|
switch (npc->npcClass) {
|
||||||
|
case NPC_BUS:
|
||||||
|
INITSTRUCT(sP_FE2CL_TRANSPORTATION_MOVE, busMove);
|
||||||
|
busMove.eTT = 3;
|
||||||
|
busMove.iT_ID = npc->appearanceData.iNPC_ID;
|
||||||
|
busMove.iMoveStyle = 0; // ???
|
||||||
|
busMove.iToX = point.x;
|
||||||
|
busMove.iToY = point.y;
|
||||||
|
busMove.iToZ = point.z;
|
||||||
|
busMove.iSpeed = distanceBetween; // set to distance to match how monkeys work
|
||||||
|
|
||||||
|
// send packet to players in view
|
||||||
|
for (Chunk* chunk : chunks) {
|
||||||
|
for (CNSocket* s : chunk->players) {
|
||||||
|
s->sendPacket(&busMove, P_FE2CL_TRANSPORTATION_MOVE, sizeof(sP_FE2CL_TRANSPORTATION_MOVE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
INITSTRUCT(sP_FE2CL_NPC_MOVE, move);
|
||||||
|
move.iNPC_ID = npc->appearanceData.iNPC_ID;
|
||||||
|
move.iMoveStyle = 0; // ???
|
||||||
|
move.iToX = point.x;
|
||||||
|
move.iToY = point.y;
|
||||||
|
move.iToZ = point.z;
|
||||||
|
move.iSpeed = 600; // TODO: figure out a way to make this variable
|
||||||
|
|
||||||
|
// send packet to players in view
|
||||||
|
for (Chunk* chunk : chunks) {
|
||||||
|
for (CNSocket* s : chunk->players) {
|
||||||
|
s->sendPacket(&move, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue->push(point); // move processed point to the back to maintain cycle
|
||||||
|
it++; // go to next entry in map
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Linearly interpolate between two points and insert the results into a queue.
|
||||||
|
*/
|
||||||
|
void TransportManager::lerp(std::queue<WarpLocation>* queue, WarpLocation start, WarpLocation end, int gapSize) {
|
||||||
|
int dXY = hypot(end.x - start.x, end.y - start.y); // XY plane distance
|
||||||
|
int distanceBetween = hypot(dXY, end.z - start.z); // total distance
|
||||||
|
int lerps = distanceBetween / gapSize; // integer division to ensure a whole number of in-between points
|
||||||
|
for (int i = 0; i < lerps; i++) {
|
||||||
|
WarpLocation lerp;
|
||||||
|
// lerp math
|
||||||
|
float frac = (i + 1) * 1.0f / (lerps + 1);
|
||||||
|
lerp.x = (start.x * (1.0f - frac)) + (end.x * frac);
|
||||||
|
lerp.y = (start.y * (1.0f - frac)) + (end.y * frac);
|
||||||
|
lerp.z = (start.z * (1.0f - frac)) + (end.z * frac);
|
||||||
|
queue->push(lerp); // add lerp'd point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -20,11 +20,16 @@ namespace TransportManager {
|
|||||||
extern std::map<int32_t, TransportLocation> Locations;
|
extern std::map<int32_t, TransportLocation> Locations;
|
||||||
extern std::map<int32_t, std::queue<WarpLocation>> SkywayPaths; // predefined skyway paths with points
|
extern std::map<int32_t, std::queue<WarpLocation>> SkywayPaths; // predefined skyway paths with points
|
||||||
extern std::unordered_map<CNSocket*, std::queue<WarpLocation>> SkywayQueues; // player sockets with queued broomstick points
|
extern std::unordered_map<CNSocket*, std::queue<WarpLocation>> SkywayQueues; // player sockets with queued broomstick points
|
||||||
|
extern std::unordered_map<int32_t, std::queue<WarpLocation>> NPCQueues; // NPC ids with queued pathing points
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void transportRegisterLocationHandler(CNSocket* sock, CNPacketData* data);
|
void transportRegisterLocationHandler(CNSocket*, CNPacketData*);
|
||||||
void transportWarpHandler(CNSocket* sock, CNPacketData* data);
|
void transportWarpHandler(CNSocket*, CNPacketData*);
|
||||||
|
|
||||||
void tickSkywaySystem(CNServer* serv, time_t currTime);
|
void tickTransportationSystem(CNServer*, time_t);
|
||||||
|
void stepNPCPathing();
|
||||||
|
void stepSkywaySystem();
|
||||||
|
|
||||||
|
void lerp(std::queue<WarpLocation>*, WarpLocation, WarpLocation, int);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user