mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 13:30:06 +00:00
Add basic Monkey Skyway functionality
This commit is contained in:
parent
94583e534b
commit
a5c40b66f5
@ -42,6 +42,28 @@ void TableData::init() {
|
|||||||
std::cerr << "[WARN] Malformed NPCs.json file! Reason:" << err.what() << std::endl;
|
std::cerr << "[WARN] Malformed NPCs.json file! Reason:" << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// load paths
|
||||||
|
try {
|
||||||
|
std::ifstream inFile(settings::PATHJSON);
|
||||||
|
nlohmann::json pathData;
|
||||||
|
|
||||||
|
// read file into json
|
||||||
|
inFile >> pathData;
|
||||||
|
|
||||||
|
nlohmann::json pathDataSkyway = pathData["skyway"];
|
||||||
|
for (nlohmann::json::iterator skywayPath = pathDataSkyway.begin(); skywayPath != pathDataSkyway.end(); skywayPath++) {
|
||||||
|
std::vector<WarpLocation> points;
|
||||||
|
nlohmann::json pathPoints = skywayPath.value()["points"];
|
||||||
|
for (nlohmann::json::iterator point = pathPoints.begin(); point != pathPoints.end(); point++)
|
||||||
|
points.push_back({point.value()["iX"], point.value()["iY"], point.value()["iZ"] });
|
||||||
|
TransportManager::SkywayPaths[skywayPath.value()["iRouteID"]] = points;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "[INFO] Loaded " << TransportManager::SkywayPaths.size() << " skyway paths" << std::endl;
|
||||||
|
}
|
||||||
|
catch (const std::exception& err) {
|
||||||
|
std::cerr << "[WARN] Malformed paths.json file! Reason:" << err.what() << std::endl;
|
||||||
|
}
|
||||||
// load everything else from xdttable
|
// load everything else from xdttable
|
||||||
std::cout << "[INFO] Parsing xdt.json..." << std::endl;
|
std::cout << "[INFO] Parsing xdt.json..." << std::endl;
|
||||||
std::ifstream infile(settings::XDTJSON);
|
std::ifstream infile(settings::XDTJSON);
|
||||||
|
@ -3,11 +3,16 @@
|
|||||||
#include "PlayerManager.hpp"
|
#include "PlayerManager.hpp"
|
||||||
#include "TransportManager.hpp"
|
#include "TransportManager.hpp"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
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::vector<WarpLocation>> TransportManager::SkywayPaths;
|
||||||
|
std::unordered_map<CNSocket*, std::queue<WarpLocation>> TransportManager::SkywayQueue;
|
||||||
|
|
||||||
void TransportManager::init() {
|
void TransportManager::init() {
|
||||||
|
REGISTER_SHARD_TIMER(tickSkywaySystem, 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);
|
||||||
}
|
}
|
||||||
@ -34,7 +39,7 @@ void TransportManager::transportRegisterLocationHandler(CNSocket* sock, CNPacket
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update registration bitfield using bit shifting + bitwise or
|
// update registration bitfield using bit shifting + bitwise or
|
||||||
plr->iWarpLocationFlag |= (1UL << (transport->iLocationID - 1));
|
plr->iWarpLocationFlag |= plr->IsGM ? INT32_MAX : (1UL << (transport->iLocationID - 1));
|
||||||
} else if (transport->eTT == 2) { // Monkey Skyway System
|
} else if (transport->eTT == 2) { // Monkey Skyway System
|
||||||
if (transport->iLocationID < 1 || transport->iLocationID > 127) { // sanity check
|
if (transport->iLocationID < 1 || transport->iLocationID > 127) { // sanity check
|
||||||
std::cout << "[WARN] Skyway location ID " << transport->iLocationID << " is out of bounds" << std::endl;
|
std::cout << "[WARN] Skyway location ID " << transport->iLocationID << " is out of bounds" << std::endl;
|
||||||
@ -52,7 +57,13 @@ void TransportManager::transportRegisterLocationHandler(CNSocket* sock, CNPacket
|
|||||||
* assuming the two bitfields are just stuck together to make a longer one... do a similar operation, but on the respective integer
|
* assuming the two bitfields are just stuck together to make a longer one... do a similar operation, but on the respective integer
|
||||||
* this approach seems to work with initial testing, but we have yet to see a monkey ID greater than 63.
|
* this approach seems to work with initial testing, but we have yet to see a monkey ID greater than 63.
|
||||||
*/
|
*/
|
||||||
plr->aSkywayLocationFlag[transport->iLocationID > 63 ? 1 : 0] |= (1ULL << (transport->iLocationID > 63 ? transport->iLocationID - 65 : transport->iLocationID - 1));
|
if (plr->IsGM) {
|
||||||
|
plr->aSkywayLocationFlag[0] = INT64_MAX;
|
||||||
|
plr->aSkywayLocationFlag[1] = INT64_MAX;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
plr->aSkywayLocationFlag[transport->iLocationID > 63 ? 1 : 0] |= (1ULL << (transport->iLocationID > 63 ? transport->iLocationID - 65 : transport->iLocationID - 1));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cout << "[WARN] Unknown mode of transport; eTT = " << transport->eTT << std::endl;
|
std::cout << "[WARN] Unknown mode of transport; eTT = " << transport->eTT << std::endl;
|
||||||
INITSTRUCT(sP_FE2CL_REP_PC_REGIST_TRANSPORTATION_LOCATION_FAIL, failResp);
|
INITSTRUCT(sP_FE2CL_REP_PC_REGIST_TRANSPORTATION_LOCATION_FAIL, failResp);
|
||||||
@ -92,8 +103,7 @@ void TransportManager::transportWarpHandler(CNSocket* sock, CNPacketData* data)
|
|||||||
* iSlotNum -- inventory slot number
|
* iSlotNum -- inventory slot number
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (Routes.find(req->iTransporationID) == Routes.end() || Locations.find(Routes[req->iTransporationID].end) == Locations.end()
|
if (Routes.find(req->iTransporationID) == Routes.end() || Routes[req->iTransporationID].cost > plr->money) { // sanity check
|
||||||
|| Routes[req->iTransporationID].cost > plr->money) { // sanity check
|
|
||||||
INITSTRUCT(sP_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_FAIL, failResp);
|
INITSTRUCT(sP_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_FAIL, failResp);
|
||||||
|
|
||||||
failResp.iErrorCode = 0; // TODO: error code
|
failResp.iErrorCode = 0; // TODO: error code
|
||||||
@ -104,19 +114,30 @@ void TransportManager::transportWarpHandler(CNSocket* sock, CNPacketData* data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TransportRoute route = Routes[req->iTransporationID];
|
TransportRoute route = Routes[req->iTransporationID];
|
||||||
|
|
||||||
plr->money -= route.cost;
|
plr->money -= route.cost;
|
||||||
|
|
||||||
TransportLocation target = Locations[route.end];
|
TransportLocation target;
|
||||||
|
PlayerView& plrv = PlayerManager::players[sock];
|
||||||
|
std::vector<WarpLocation>* points = nullptr;
|
||||||
switch (route.type)
|
switch (route.type)
|
||||||
{
|
{
|
||||||
case 1: // S.C.A.M.P.E.R.
|
case 1: // S.C.A.M.P.E.R.
|
||||||
|
target = Locations[route.end];
|
||||||
plr->x = target.x;
|
plr->x = target.x;
|
||||||
plr->y = target.y;
|
plr->y = target.y;
|
||||||
plr->z = target.z;
|
plr->z = target.z;
|
||||||
|
/*
|
||||||
|
* Not strictly necessary since there isn't a valid SCAMPER that puts you in the
|
||||||
|
* same map tile you were already in, but we might as well force an NPC reload.
|
||||||
|
*/
|
||||||
|
plrv.viewable.clear();
|
||||||
|
plrv.viewableNPCs.clear();
|
||||||
break;
|
break;
|
||||||
case 2: // Monkey Skyway
|
case 2: // Monkey Skyway
|
||||||
// TODO: implement
|
if (SkywayPaths.find(route.mssRouteNum) != SkywayPaths.end()) // sanity check
|
||||||
|
points = &SkywayPaths[route.mssRouteNum];
|
||||||
|
else
|
||||||
|
std::cout << "[WARN] MSS route " << route.mssRouteNum << " not pathed" << std::endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
std::cout << "[WARN] Unknown tranportation type " << route.type << std::endl;
|
std::cout << "[WARN] Unknown tranportation type " << route.type << std::endl;
|
||||||
@ -124,13 +145,13 @@ void TransportManager::transportWarpHandler(CNSocket* sock, CNPacketData* data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC, resp);
|
INITSTRUCT(sP_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC, resp);
|
||||||
|
|
||||||
// response parameters
|
// response parameters
|
||||||
resp.eTT = route.type;
|
resp.eTT = route.type;
|
||||||
resp.iCandy = plr->money;
|
resp.iCandy = plr->money;
|
||||||
resp.iX = plr->x;
|
resp.iX = plr->x;
|
||||||
resp.iY = plr->y;
|
resp.iY = plr->y;
|
||||||
resp.iZ = plr->z;
|
resp.iZ = plr->z;
|
||||||
|
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Not strictly necessary since there isn't a valid SCAMPER that puts you in the
|
* Not strictly necessary since there isn't a valid SCAMPER that puts you in the
|
||||||
@ -141,6 +162,65 @@ void TransportManager::transportWarpHandler(CNSocket* sock, CNPacketData* data)
|
|||||||
PlayerManager::removePlayerFromChunks(plrv.currentChunks, sock);
|
PlayerManager::removePlayerFromChunks(plrv.currentChunks, sock);
|
||||||
plrv.currentChunks.clear();
|
plrv.currentChunks.clear();
|
||||||
plrv.chunkPos = std::make_pair<int, int>(0, 0);
|
plrv.chunkPos = std::make_pair<int, int>(0, 0);
|
||||||
|
if (points == nullptr) // no skyway path set
|
||||||
|
return;
|
||||||
|
|
||||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_TRANSPORTATION_SUCC));
|
// Interpolate
|
||||||
|
std::queue<WarpLocation> queue;
|
||||||
|
WarpLocation last = { plr->x, plr->y, plr->z }; // start pos
|
||||||
|
for (std::vector<WarpLocation>::iterator point = points->begin(); point != points->end(); point++) {
|
||||||
|
// avoiding pow here
|
||||||
|
int distanceBetween = sqrt((last.x - point->x) * (last.x - point->x) + (last.y - point->y) * (last.y - point->y) + (last.z - point->z) * (last.z - point->z));
|
||||||
|
int lerps = distanceBetween / (int)LERP_GAP; // integer division to ensure a whole number
|
||||||
|
for (int i = 0; i < lerps; i++) {
|
||||||
|
WarpLocation lerp;
|
||||||
|
float frac = 1.0f / (lerps + 1);
|
||||||
|
lerp.x = (last.x * (1.0f - frac)) + (point->x * frac);
|
||||||
|
lerp.y = (last.y * (1.0f - frac)) + (point->y * frac);
|
||||||
|
lerp.z = (last.z * (1.0f - frac)) + (point->z * frac);
|
||||||
|
queue.push(lerp); // add lerp'd point to the queue
|
||||||
|
}
|
||||||
|
queue.push(*point);
|
||||||
|
last = { point->x, point->y, point->z }; // update start pos
|
||||||
|
}
|
||||||
|
SkywayQueue[sock] = queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransportManager::tickSkywaySystem(CNServer* serv, time_t currTime) {
|
||||||
|
|
||||||
|
std::cout << SkywayQueue.size();
|
||||||
|
// using an unordered list so we can remove finished players in one iteration
|
||||||
|
std::unordered_map<CNSocket*, std::queue<WarpLocation>>::iterator it = SkywayQueue.begin();
|
||||||
|
while (it != SkywayQueue.end()) {
|
||||||
|
|
||||||
|
std::queue<WarpLocation>* queue = &it->second;
|
||||||
|
Player* plr = PlayerManager::getPlayer(it->first);
|
||||||
|
if (plr == nullptr) {
|
||||||
|
// sanity check
|
||||||
|
it = SkywayQueue.erase(it); // remove player from tracking map + update iterator
|
||||||
|
}
|
||||||
|
else if (queue->empty()) {
|
||||||
|
// send dismount packet
|
||||||
|
INITSTRUCT(sP_FE2CL_REP_PC_RIDING_SUCC, rideSucc);
|
||||||
|
rideSucc.iPC_ID = plr == nullptr ? 0 : plr->iID;
|
||||||
|
rideSucc.eRT = 0;
|
||||||
|
it->first->sendPacket((void*)&rideSucc, P_FE2CL_REP_PC_RIDING_SUCC, sizeof(sP_FE2CL_REP_PC_RIDING_SUCC));
|
||||||
|
// TODO: send packet to nearby players?
|
||||||
|
it = SkywayQueue.erase(it); // remove player from tracking map + update iterator
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WarpLocation point = queue->front(); // get point
|
||||||
|
queue->pop(); // remove point from front of queue
|
||||||
|
|
||||||
|
INITSTRUCT(sP_FE2CL_PC_BROOMSTICK_MOVE, bmstk);
|
||||||
|
bmstk.iPC_ID = plr == nullptr ? 0 : plr->iID;
|
||||||
|
bmstk.iToX = point.x;
|
||||||
|
bmstk.iToY = point.y;
|
||||||
|
bmstk.iToZ = point.z;
|
||||||
|
it->first->sendPacket((void*)&bmstk, P_FE2CL_PC_BROOMSTICK_MOVE, sizeof(sP_FE2CL_PC_BROOMSTICK_MOVE));
|
||||||
|
// TODO: send packet to nearby players?
|
||||||
|
|
||||||
|
it++; // go to next entry in map
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CNShardServer.hpp"
|
#include "CNShardServer.hpp"
|
||||||
|
#include "NPCManager.hpp"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#define LERP_GAP 5000
|
||||||
|
|
||||||
|
struct WarpLocation;
|
||||||
|
|
||||||
struct TransportRoute {
|
struct TransportRoute {
|
||||||
int type, start, end, cost, mssSpeed, mssRouteNum;
|
int type, start, end, cost, mssSpeed, mssRouteNum;
|
||||||
@ -13,9 +20,13 @@ struct TransportLocation {
|
|||||||
namespace TransportManager {
|
namespace TransportManager {
|
||||||
extern std::map<int32_t, TransportRoute> Routes;
|
extern std::map<int32_t, TransportRoute> Routes;
|
||||||
extern std::map<int32_t, TransportLocation> Locations;
|
extern std::map<int32_t, TransportLocation> Locations;
|
||||||
|
extern std::map<int32_t, std::vector<WarpLocation>> SkywayPaths;
|
||||||
|
extern std::unordered_map<CNSocket*, std::queue<WarpLocation>> SkywayQueue;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void transportRegisterLocationHandler(CNSocket* sock, CNPacketData* data);
|
void transportRegisterLocationHandler(CNSocket* sock, CNPacketData* data);
|
||||||
void transportWarpHandler(CNSocket* sock, CNPacketData* data);
|
void transportWarpHandler(CNSocket* sock, CNPacketData* data);
|
||||||
|
|
||||||
|
void tickSkywaySystem(CNServer* serv, time_t currTime);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ int settings::SPAWN_ANGLE = 130;
|
|||||||
std::string settings::NPCJSON = "tdata/NPCs.json";
|
std::string settings::NPCJSON = "tdata/NPCs.json";
|
||||||
std::string settings::XDTJSON = "tdata/xdt.json";
|
std::string settings::XDTJSON = "tdata/xdt.json";
|
||||||
std::string settings::MOBJSON = "tdata/mobs.json";
|
std::string settings::MOBJSON = "tdata/mobs.json";
|
||||||
|
std::string settings::PATHJSON = "tdata/paths.json";
|
||||||
std::string settings::MOTDSTRING = "Welcome to OpenFusion!";
|
std::string settings::MOTDSTRING = "Welcome to OpenFusion!";
|
||||||
bool settings::GM = true;
|
bool settings::GM = true;
|
||||||
|
|
||||||
@ -54,6 +55,7 @@ void settings::init() {
|
|||||||
NPCJSON = reader.Get("shard", "npcdata", NPCJSON);
|
NPCJSON = reader.Get("shard", "npcdata", NPCJSON);
|
||||||
XDTJSON = reader.Get("shard", "xdtdata", XDTJSON);
|
XDTJSON = reader.Get("shard", "xdtdata", XDTJSON);
|
||||||
MOBJSON = reader.Get("shard", "mobdata", MOBJSON);
|
MOBJSON = reader.Get("shard", "mobdata", MOBJSON);
|
||||||
|
PATHJSON = reader.Get("shard", "pathdata", PATHJSON);
|
||||||
MOTDSTRING = reader.Get("shard", "motd", MOTDSTRING);
|
MOTDSTRING = reader.Get("shard", "motd", MOTDSTRING);
|
||||||
GM = reader.GetBoolean("shard", "gm", GM);
|
GM = reader.GetBoolean("shard", "gm", GM);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ namespace settings {
|
|||||||
extern std::string NPCJSON;
|
extern std::string NPCJSON;
|
||||||
extern std::string XDTJSON;
|
extern std::string XDTJSON;
|
||||||
extern std::string MOBJSON;
|
extern std::string MOBJSON;
|
||||||
|
extern std::string PATHJSON;
|
||||||
extern bool GM;
|
extern bool GM;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
2
tdata
2
tdata
@ -1 +1 @@
|
|||||||
Subproject commit 19d9902331c94174785323d39daccc2cd23c5872
|
Subproject commit f9c5f6a245c36add9fd8663badeca96e19a5d7ed
|
Loading…
Reference in New Issue
Block a user