General MSS fixes + tweaks

Add alert message for unpathed skyway routes
Fix overflow during lerp + add Future routes
Add documentation for MSS
Fix potential MSS registration bug
Minor tweaks + styling
Update packet broadcast
This commit is contained in:
Gent
2020-09-21 21:03:48 -04:00
parent 135424b855
commit 2c8243e136
5 changed files with 110 additions and 70 deletions

View File

@@ -8,7 +8,7 @@
std::map<int32_t, TransportRoute> TransportManager::Routes;
std::map<int32_t, TransportLocation> TransportManager::Locations;
std::map<int32_t, std::queue<WarpLocation>> TransportManager::SkywayPaths;
std::unordered_map<CNSocket*, std::queue<WarpLocation>> TransportManager::SkywayQueue;
std::unordered_map<CNSocket*, std::queue<WarpLocation>> TransportManager::SkywayQueues;
void TransportManager::init() {
REGISTER_SHARD_TIMER(tickSkywaySystem, 1000);
@@ -24,6 +24,7 @@ void TransportManager::transportRegisterLocationHandler(CNSocket* sock, CNPacket
sP_CL2FE_REQ_REGIST_TRANSPORTATION_LOCATION* transport = (sP_CL2FE_REQ_REGIST_TRANSPORTATION_LOCATION*)data->buf;
Player* plr = PlayerManager::getPlayer(sock);
bool newReg = false; // this is a new registration
//std::cout << "request to register transport, eTT " << transport->eTT << ", locID " << transport->iLocationID << ", npc " << transport->iNPC_ID << std::endl;
if (transport->eTT == 1) { // S.C.A.M.P.E.R.
if (transport->iLocationID < 1 || transport->iLocationID > 31) { // sanity check
@@ -38,8 +39,12 @@ void TransportManager::transportRegisterLocationHandler(CNSocket* sock, CNPacket
return;
}
// update registration bitfield using bit shifting + bitwise or
plr->iWarpLocationFlag |= plr->IsGM ? INT32_MAX : (1UL << (transport->iLocationID - 1));
// update registration bitfield using bitmask
uint32_t newScamperFlag = plr->iWarpLocationFlag | (plr->IsGM ? UINT32_MAX : (1UL << (transport->iLocationID - 1)));
if (newScamperFlag != plr->iWarpLocationFlag) {
plr->iWarpLocationFlag = newScamperFlag;
newReg = true;
}
} else if (transport->eTT == 2) { // Monkey Skyway System
if (transport->iLocationID < 1 || transport->iLocationID > 127) { // sanity check
std::cout << "[WARN] Skyway location ID " << transport->iLocationID << " is out of bounds" << std::endl;
@@ -54,15 +59,19 @@ 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
* this approach seems to work with initial testing, but we have yet to see a monkey ID greater than 63.
* assuming the two bitfields are just stuck together to make a longer one, do a similar operation
*/
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));
plr->aSkywayLocationFlag[0] = UINT64_MAX;
plr->aSkywayLocationFlag[1] = UINT64_MAX;
newReg = true;
} else {
int index = transport->iLocationID > 64 ? 1 : 0;
uint64_t newMonkeyFlag = plr->aSkywayLocationFlag[index] | (1ULL << (index ? transport->iLocationID - 65 : transport->iLocationID - 1));
if (newMonkeyFlag != plr->aSkywayLocationFlag[index]) {
plr->aSkywayLocationFlag[index] = newMonkeyFlag;
newReg = true;
}
}
} else {
std::cout << "[WARN] Unknown mode of transport; eTT = " << transport->eTT << std::endl;
@@ -76,8 +85,10 @@ void TransportManager::transportRegisterLocationHandler(CNSocket* sock, CNPacket
return;
}
INITSTRUCT(sP_FE2CL_REP_PC_REGIST_TRANSPORTATION_LOCATION_SUCC, resp);
if (!newReg)
return; // don't send new registration message
INITSTRUCT(sP_FE2CL_REP_PC_REGIST_TRANSPORTATION_LOCATION_SUCC, resp);
// response parameters
resp.eTT = transport->eTT;
resp.iLocationID = transport->iLocationID;
@@ -118,9 +129,7 @@ void TransportManager::transportWarpHandler(CNSocket* sock, CNPacketData* data)
TransportLocation target;
PlayerView& plrv = PlayerManager::players[sock];
std::queue<WarpLocation>* points = nullptr;
switch (route.type)
{
switch (route.type) {
case 1: // S.C.A.M.P.E.R.
target = Locations[route.end];
plr->x = target.x;
@@ -135,10 +144,20 @@ void TransportManager::transportWarpHandler(CNSocket* sock, CNPacketData* data)
plrv.chunkPos = std::make_pair<int, int>(0, 0);
break;
case 2: // Monkey Skyway
if (SkywayPaths.find(route.mssRouteNum) != SkywayPaths.end()) // sanity check
SkywayQueue[sock] = SkywayPaths[route.mssRouteNum];
else
std::cout << "[WARN] MSS route " << route.mssRouteNum << " not pathed" << std::endl;
if (SkywayPaths.find(route.mssRouteNum) != SkywayPaths.end()) { // check if route exists
SkywayQueues[sock] = SkywayPaths[route.mssRouteNum]; // set socket point queue to route
break;
}
// refund and send alert packet
plr->money += route.cost;
INITSTRUCT(sP_FE2CL_ANNOUNCE_MSG, alert);
alert.iAnnounceType = 0; // don't think this lets us make a confirm dialog
alert.iDuringTime = 3;
U8toU16("Skyway route " + std::to_string(route.mssRouteNum) + " isn't pathed yet. You will not be charged any taros.", (char16_t*)alert.szAnnounceMsg);
sock->sendPacket((void*)&alert, P_FE2CL_ANNOUNCE_MSG, sizeof(sP_FE2CL_ANNOUNCE_MSG));
std::cout << "[WARN] MSS route " << route.mssRouteNum << " not pathed" << std::endl;
break;
default:
std::cout << "[WARN] Unknown tranportation type " << route.type << std::endl;
@@ -155,19 +174,26 @@ 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));
}
/*
* 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.
*/
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()) {
// using an unordered map so we can remove finished players in one iteration
std::unordered_map<CNSocket*, std::queue<WarpLocation>>::iterator it = SkywayQueues.begin();
while (it != SkywayQueues.end()) {
std::queue<WarpLocation>* queue = &it->second;
PlayerView& plr = PlayerManager::players[it->first];
if (plr.plr == nullptr) {
// pluck out dead queue + update iterator
it = SkywayQueue.erase(it);
Player* plr = nullptr;
if(PlayerManager::players.find(it->first) != PlayerManager::players.end()) // check if socket still has a player
plr = PlayerManager::getPlayer(it->first);
if (plr == nullptr) {
// pluck out dead socket + update iterator
it = SkywayQueues.erase(it);
continue;
}
@@ -175,31 +201,28 @@ void TransportManager::tickSkywaySystem(CNServer* serv, time_t currTime) {
// send dismount packet
INITSTRUCT(sP_FE2CL_REP_PC_RIDING_SUCC, rideSucc);
INITSTRUCT(sP_FE2CL_PC_RIDING, rideBroadcast);
rideSucc.iPC_ID = plr.plr->iID;
rideSucc.iPC_ID = plr->iID;
rideSucc.eRT = 0;
rideBroadcast.iPC_ID = plr.plr->iID;
rideBroadcast.iPC_ID = plr->iID;
rideBroadcast.eRT = 0;
it->first->sendPacket((void*)&rideSucc, P_FE2CL_REP_PC_RIDING_SUCC, sizeof(sP_FE2CL_REP_PC_RIDING_SUCC));
// send packet to players in view (the client does NOT like this for some reason)
for (CNSocket* otherSock : plr.viewable)
otherSock->sendPacket((void*)&rideBroadcast, P_FE2CL_PC_RIDING, sizeof(sP_FE2CL_PC_RIDING));
it = SkywayQueue.erase(it); // remove player from tracking map + update iterator
}
else {
// send packet to players in view
PlayerManager::sendToViewable(it->first, (void*)&rideBroadcast, P_FE2CL_PC_RIDING, sizeof(sP_FE2CL_PC_RIDING));
it = SkywayQueues.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.plr->iID;
bmstk.iPC_ID = 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));
// set player location to point to get better view
// set player location to point to update viewables
PlayerManager::updatePlayerPosition(it->first, point.x, point.y, point.z);
// send packet to players in view
for(CNSocket* otherSock : plr.viewable)
otherSock->sendPacket((void*)&bmstk, P_FE2CL_PC_BROOMSTICK_MOVE, sizeof(sP_FE2CL_PC_BROOMSTICK_MOVE));
PlayerManager::sendToViewable(it->first, (void*)&bmstk, P_FE2CL_PC_BROOMSTICK_MOVE, sizeof(sP_FE2CL_PC_BROOMSTICK_MOVE));
it++; // go to next entry in map
}