mirror of
				https://github.com/OpenFusionProject/OpenFusion.git
				synced 2025-10-31 00:30:15 +00:00 
			
		
		
		
	Compare commits
	
		
			5 Commits
		
	
	
		
			8568fd1c46
			...
			cd55f1641c
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cd55f1641c | |||
|   | bc8882d2e8 | ||
|   | 359de79eaa | ||
| ae327cc104 | |||
| 6ffde9bb44 | 
							
								
								
									
										29
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,36 +1,49 @@ | |||||||
| # build | # build | ||||||
| FROM debian:stable-slim AS build | FROM alpine:3 as build | ||||||
|  |  | ||||||
| WORKDIR /usr/src/app | WORKDIR /usr/src/app | ||||||
|  |  | ||||||
| RUN apt-get -y update && apt-get install -y \ | RUN apk update && apk upgrade && apk add \ | ||||||
|  | linux-headers \ | ||||||
| git \ | git \ | ||||||
| clang \ | clang18 \ | ||||||
| make \ | make \ | ||||||
| libsqlite3-dev | sqlite-dev | ||||||
|  |  | ||||||
| COPY src ./src | COPY src ./src | ||||||
| COPY vendor ./vendor | COPY vendor ./vendor | ||||||
| COPY .git ./.git | COPY .git ./.git | ||||||
| COPY Makefile CMakeLists.txt version.h.in ./ | COPY Makefile CMakeLists.txt version.h.in ./ | ||||||
|  |  | ||||||
|  | RUN sed -i 's/^CC=clang$/&-18/' Makefile | ||||||
|  | RUN sed -i 's/^CXX=clang++$/&-18/' Makefile | ||||||
|  |  | ||||||
| RUN make nosandbox -j$(nproc) | RUN make nosandbox -j$(nproc) | ||||||
|  |  | ||||||
| # prod | # prod | ||||||
| FROM debian:stable-slim | FROM alpine:3 | ||||||
|  |  | ||||||
|  | ENV AUTHENTICATION_PORT 23000 | ||||||
|  | ENV MONITORING_PORT 8003 | ||||||
|  | ENV SHARDING_PORT 23001 | ||||||
|  |  | ||||||
| WORKDIR /usr/src/app | WORKDIR /usr/src/app | ||||||
|  |  | ||||||
| RUN apt-get -y update && apt-get install -y \ | RUN apk update && apk upgrade && apk add \ | ||||||
| libsqlite3-dev | libstdc++ \ | ||||||
|  | sqlite-dev | ||||||
|  |  | ||||||
| COPY --from=build /usr/src/app/bin/fusion /bin/fusion | COPY --from=build /usr/src/app/bin/fusion /bin/fusion | ||||||
| COPY sql ./sql | COPY sql ./sql | ||||||
|  |  | ||||||
|  | EXPOSE $AUTHENTICATION_PORT | ||||||
|  | EXPOSE $MONITORING_PORT | ||||||
|  | EXPOSE $SHARDING_PORT | ||||||
|  |  | ||||||
| CMD ["/bin/fusion"] | CMD ["/bin/fusion"] | ||||||
|  |  | ||||||
| EXPOSE 23000/tcp | EXPOSE 23000/tcp | ||||||
| EXPOSE 23001/tcp | EXPOSE 23001/tcp | ||||||
| EXPOSE 8001/tcp | EXPOSE 8003/tcp | ||||||
|  |  | ||||||
| LABEL Name=openfusion Version=1.6.0 | LABEL Name=openfusion Version=1.6.0 | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| @@ -115,6 +115,7 @@ CXXHDR=\ | |||||||
| 	src/settings.hpp\ | 	src/settings.hpp\ | ||||||
| 	src/Transport.hpp\ | 	src/Transport.hpp\ | ||||||
| 	src/TableData.hpp\ | 	src/TableData.hpp\ | ||||||
|  | 	src/Bucket.hpp\ | ||||||
| 	src/Chunking.hpp\ | 	src/Chunking.hpp\ | ||||||
| 	src/Buddies.hpp\ | 	src/Buddies.hpp\ | ||||||
| 	src/Groups.hpp\ | 	src/Groups.hpp\ | ||||||
|   | |||||||
| @@ -334,8 +334,8 @@ void Abilities::useNanoSkill(CNSocket* sock, SkillData* skill, sNano& nano, std: | |||||||
|     size_t resplen = sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC); |     size_t resplen = sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC); | ||||||
|     for(SkillResult& sr : results) |     for(SkillResult& sr : results) | ||||||
|         resplen += sr.size; |         resplen += sr.size; | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     sP_FE2CL_NANO_SKILL_USE_SUCC* pkt = (sP_FE2CL_NANO_SKILL_USE_SUCC*)respbuf; |     sP_FE2CL_NANO_SKILL_USE_SUCC* pkt = (sP_FE2CL_NANO_SKILL_USE_SUCC*)respbuf; | ||||||
|     pkt->iPC_ID = plr->iID; |     pkt->iPC_ID = plr->iID; | ||||||
| @@ -379,8 +379,8 @@ void Abilities::useNPCSkill(EntityRef npc, int skillID, std::vector<ICombatant*> | |||||||
|     size_t resplen = sizeof(sP_FE2CL_NPC_SKILL_HIT); |     size_t resplen = sizeof(sP_FE2CL_NPC_SKILL_HIT); | ||||||
|     for(SkillResult& sr : results) |     for(SkillResult& sr : results) | ||||||
|         resplen += sr.size; |         resplen += sr.size; | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     sP_FE2CL_NPC_SKILL_HIT* pkt = (sP_FE2CL_NPC_SKILL_HIT*)respbuf; |     sP_FE2CL_NPC_SKILL_HIT* pkt = (sP_FE2CL_NPC_SKILL_HIT*)respbuf; | ||||||
|     pkt->iNPC_ID = npc.id; |     pkt->iNPC_ID = npc.id; | ||||||
|   | |||||||
							
								
								
									
										40
									
								
								src/Bucket.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/Bucket.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <array> | ||||||
|  | #include <optional> | ||||||
|  |  | ||||||
|  | #include <assert.h> | ||||||
|  |  | ||||||
|  | template<class T, size_t N> | ||||||
|  | class Bucket { | ||||||
|  |     std::array<T, N> buf; | ||||||
|  |     size_t sz; | ||||||
|  | public: | ||||||
|  |     Bucket() { | ||||||
|  |         sz = 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void add(const T& item) { | ||||||
|  |         assert(sz < N); | ||||||
|  |         buf[sz++] = item; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     std::optional<T> get(size_t idx) const { | ||||||
|  |         if (idx < sz) { | ||||||
|  |             return buf[idx]; | ||||||
|  |         } | ||||||
|  |         return std::nullopt; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     size_t size() const { | ||||||
|  |         return sz; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     bool isFull() const { | ||||||
|  |         return sz == N; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void clear() { | ||||||
|  |         sz = 0; | ||||||
|  |     } | ||||||
|  | }; | ||||||
| @@ -41,9 +41,9 @@ void Buddies::sendBuddyList(CNSocket* sock) { | |||||||
|  |  | ||||||
|     // initialize response struct |     // initialize response struct | ||||||
|     size_t resplen = sizeof(sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC) + buddyCnt * sizeof(sBuddyBaseInfo); |     size_t resplen = sizeof(sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC) + buddyCnt * sizeof(sBuddyBaseInfo); | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|  |  | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC* resp = (sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC*)respbuf; |     sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC* resp = (sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC*)respbuf; | ||||||
|     sBuddyBaseInfo* respdata = (sBuddyBaseInfo*)(respbuf + sizeof(sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC)); |     sBuddyBaseInfo* respdata = (sBuddyBaseInfo*)(respbuf + sizeof(sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC)); | ||||||
|   | |||||||
| @@ -178,9 +178,9 @@ void Buffs::tickDrain(EntityRef self, Buff* buff, int mult) { | |||||||
|     int dealt = combatant->takeDamage(buff->getLastSource(), damage); |     int dealt = combatant->takeDamage(buff->getLastSource(), damage); | ||||||
|  |  | ||||||
|     size_t resplen = sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK) + sizeof(sSkillResult_Damage); |     size_t resplen = sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK) + sizeof(sSkillResult_Damage); | ||||||
|     assert(resplen < CN_PACKET_BUFFER_SIZE - 8); |     assert(resplen < CN_PACKET_BODY_SIZE); | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK *pkt = (sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK*)respbuf; |     sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK *pkt = (sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK*)respbuf; | ||||||
|     pkt->iID = self.id; |     pkt->iID = self.id; | ||||||
|   | |||||||
							
								
								
									
										163
									
								
								src/Chunking.cpp
									
									
									
									
									
								
							
							
						
						
									
										163
									
								
								src/Chunking.cpp
									
									
									
									
									
								
							| @@ -1,7 +1,9 @@ | |||||||
| #include "Chunking.hpp" | #include "Chunking.hpp" | ||||||
|  |  | ||||||
|  | #include "Player.hpp" | ||||||
| #include "MobAI.hpp" | #include "MobAI.hpp" | ||||||
| #include "NPCManager.hpp" | #include "NPCManager.hpp" | ||||||
|  | #include "Bucket.hpp" | ||||||
|  |  | ||||||
| #include <assert.h> | #include <assert.h> | ||||||
|  |  | ||||||
| @@ -11,6 +13,12 @@ using namespace Chunking; | |||||||
|  * The initial chunkPos value before a player is placed into the world. |  * The initial chunkPos value before a player is placed into the world. | ||||||
|  */ |  */ | ||||||
| const ChunkPos Chunking::INVALID_CHUNK = {}; | const ChunkPos Chunking::INVALID_CHUNK = {}; | ||||||
|  | constexpr size_t MAX_PC_PER_AROUND = (CN_PACKET_BODY_SIZE - sizeof(int32_t)) / sizeof(sPCAppearanceData); | ||||||
|  | constexpr size_t MAX_NPC_PER_AROUND = (CN_PACKET_BODY_SIZE - sizeof(int32_t)) / sizeof(sNPCAppearanceData); | ||||||
|  | constexpr size_t MAX_SHINY_PER_AROUND = (CN_PACKET_BODY_SIZE - sizeof(int32_t)) / sizeof(sShinyAppearanceData); | ||||||
|  | constexpr size_t MAX_TRANSPORTATION_PER_AROUND = (CN_PACKET_BODY_SIZE - sizeof(int32_t)) / sizeof(sTransportationAppearanceData); | ||||||
|  | constexpr size_t MAX_IDS_PER_AROUND_DEL = (CN_PACKET_BODY_SIZE - sizeof(int32_t)) / sizeof(int32_t); | ||||||
|  | constexpr size_t MAX_TRANSPORTATION_IDS_PER_AROUND_DEL = MAX_IDS_PER_AROUND_DEL - 1; // 1 less for eTT | ||||||
|  |  | ||||||
| std::map<ChunkPos, Chunk*> Chunking::chunks; | std::map<ChunkPos, Chunk*> Chunking::chunks; | ||||||
|  |  | ||||||
| @@ -75,11 +83,80 @@ void Chunking::untrackEntity(ChunkPos chunkPos, const EntityRef ref) { | |||||||
|         deleteChunk(chunkPos); |         deleteChunk(chunkPos); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | template<class T, size_t N> | ||||||
|  | static void sendAroundPackets(const EntityRef recipient, std::vector<Bucket<T, N>>& buckets, uint32_t packetId) { | ||||||
|  |     assert(recipient.kind == EntityKind::PLAYER); | ||||||
|  |  | ||||||
|  |     uint8_t pktBuf[CN_PACKET_BODY_SIZE]; | ||||||
|  |     for (const auto& bucket : buckets) { | ||||||
|  |         memset(pktBuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |         int count = bucket.size(); | ||||||
|  |         *((int32_t*)pktBuf) = count; | ||||||
|  |         T* data = (T*)(pktBuf + sizeof(int32_t)); | ||||||
|  |         for (size_t i = 0; i < count; i++) { | ||||||
|  |             data[i] = bucket.get(i).value(); | ||||||
|  |         } | ||||||
|  |         recipient.sock->sendPacket(pktBuf, packetId, sizeof(int32_t) + (count * sizeof(T))); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<size_t N> | ||||||
|  | static void sendAroundDelPackets(const EntityRef recipient, std::vector<Bucket<int32_t, N>>& buckets, uint32_t packetId) { | ||||||
|  |     assert(recipient.kind == EntityKind::PLAYER); | ||||||
|  |  | ||||||
|  |     uint8_t pktBuf[CN_PACKET_BODY_SIZE]; | ||||||
|  |     for (const auto& bucket : buckets) { | ||||||
|  |         memset(pktBuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |         int count = bucket.size(); | ||||||
|  |         assert(count <= N); | ||||||
|  |  | ||||||
|  |         size_t baseSize; | ||||||
|  |         if (packetId == P_FE2CL_AROUND_DEL_TRANSPORTATION) { | ||||||
|  |             sP_FE2CL_AROUND_DEL_TRANSPORTATION* pkt = (sP_FE2CL_AROUND_DEL_TRANSPORTATION*)pktBuf; | ||||||
|  |             pkt->eTT = 3; | ||||||
|  |             pkt->iCnt = count; | ||||||
|  |             baseSize = sizeof(sP_FE2CL_AROUND_DEL_TRANSPORTATION); | ||||||
|  |         } else { | ||||||
|  |             *((int32_t*)pktBuf) = count; | ||||||
|  |             baseSize = sizeof(int32_t); | ||||||
|  |         } | ||||||
|  |         int32_t* ids = (int32_t*)(pktBuf + baseSize); | ||||||
|  |  | ||||||
|  |         for (size_t i = 0; i < count; i++) { | ||||||
|  |             ids[i] = bucket.get(i).value(); | ||||||
|  |         } | ||||||
|  |         recipient.sock->sendPacket(pktBuf, packetId, baseSize + (count * sizeof(int32_t))); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<class T, size_t N> | ||||||
|  | static void bufferAppearanceData(std::vector<Bucket<T, N>>& buckets, const T& data) { | ||||||
|  |     if (buckets.empty()) | ||||||
|  |         buckets.push_back({}); | ||||||
|  |     auto& bucket = buckets[buckets.size() - 1]; | ||||||
|  |     bucket.add(data); | ||||||
|  |     if (bucket.isFull()) | ||||||
|  |         buckets.push_back({}); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | template<size_t N> | ||||||
|  | static void bufferIdForDisappearance(std::vector<Bucket<int32_t, N>>& buckets, int32_t id) { | ||||||
|  |     if (buckets.empty()) | ||||||
|  |         buckets.push_back({}); | ||||||
|  |     auto& bucket = buckets[buckets.size() - 1]; | ||||||
|  |     bucket.add(id); | ||||||
|  |     if (bucket.isFull()) | ||||||
|  |         buckets.push_back({}); | ||||||
|  | } | ||||||
|  |  | ||||||
| void Chunking::addEntityToChunks(std::set<Chunk*> chnks, const EntityRef ref) { | void Chunking::addEntityToChunks(std::set<Chunk*> chnks, const EntityRef ref) { | ||||||
|     Entity *ent = ref.getEntity(); |     Entity *ent = ref.getEntity(); | ||||||
|     bool alive = ent->isExtant(); |     bool alive = ent->isExtant(); | ||||||
|  |  | ||||||
|     // TODO: maybe optimize this, potentially using AROUND packets? |     std::vector<Bucket<sPCAppearanceData, MAX_PC_PER_AROUND>> pcAppearances; | ||||||
|  |     std::vector<Bucket<sNPCAppearanceData, MAX_NPC_PER_AROUND>> npcAppearances; | ||||||
|  |     std::vector<Bucket<sShinyAppearanceData, MAX_SHINY_PER_AROUND>> shinyAppearances; | ||||||
|  |     std::vector<Bucket<sTransportationAppearanceData, MAX_TRANSPORTATION_PER_AROUND>> transportationAppearances; | ||||||
|     for (Chunk *chunk : chnks) { |     for (Chunk *chunk : chnks) { | ||||||
|         for (const EntityRef otherRef : chunk->entities) { |         for (const EntityRef otherRef : chunk->entities) { | ||||||
|             // skip oneself |             // skip oneself | ||||||
| @@ -95,7 +172,38 @@ void Chunking::addEntityToChunks(std::set<Chunk*> chnks, const EntityRef ref) { | |||||||
|  |  | ||||||
|             // notify this *player* of the existence of all visible Entities |             // notify this *player* of the existence of all visible Entities | ||||||
|             if (ref.kind == EntityKind::PLAYER && other->isExtant()) { |             if (ref.kind == EntityKind::PLAYER && other->isExtant()) { | ||||||
|                 other->enterIntoViewOf(ref.sock); |                 sPCAppearanceData pcData; | ||||||
|  |                 sNPCAppearanceData npcData; | ||||||
|  |                 sShinyAppearanceData eggData; | ||||||
|  |                 sTransportationAppearanceData busData; | ||||||
|  |                 switch(otherRef.kind) { | ||||||
|  |                 case EntityKind::PLAYER: | ||||||
|  |                     pcData = dynamic_cast<Player*>(other)->getAppearanceData(); | ||||||
|  |                     bufferAppearanceData(pcAppearances, pcData); | ||||||
|  |                     break; | ||||||
|  |                 case EntityKind::SIMPLE_NPC: | ||||||
|  |                     npcData = dynamic_cast<BaseNPC*>(other)->getAppearanceData(); | ||||||
|  |                     bufferAppearanceData(npcAppearances, npcData); | ||||||
|  |                     break; | ||||||
|  |                 case EntityKind::COMBAT_NPC: | ||||||
|  |                     npcData = dynamic_cast<CombatNPC*>(other)->getAppearanceData(); | ||||||
|  |                     bufferAppearanceData(npcAppearances, npcData); | ||||||
|  |                     break; | ||||||
|  |                 case EntityKind::MOB: | ||||||
|  |                     npcData = dynamic_cast<Mob*>(other)->getAppearanceData(); | ||||||
|  |                     bufferAppearanceData(npcAppearances, npcData); | ||||||
|  |                     break; | ||||||
|  |                 case EntityKind::EGG: | ||||||
|  |                     eggData = dynamic_cast<Egg*>(other)->getShinyAppearanceData(); | ||||||
|  |                     bufferAppearanceData(shinyAppearances, eggData); | ||||||
|  |                     break; | ||||||
|  |                 case EntityKind::BUS: | ||||||
|  |                     busData = dynamic_cast<Bus*>(other)->getTransportationAppearanceData(); | ||||||
|  |                     bufferAppearanceData(transportationAppearances, busData); | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // for mobs, increment playersInView |             // for mobs, increment playersInView | ||||||
| @@ -105,13 +213,27 @@ void Chunking::addEntityToChunks(std::set<Chunk*> chnks, const EntityRef ref) { | |||||||
|                 ((Mob*)other)->playersInView++; |                 ((Mob*)other)->playersInView++; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (ref.kind == EntityKind::PLAYER) { | ||||||
|  |         if (!pcAppearances.empty()) | ||||||
|  |             sendAroundPackets(ref, pcAppearances, P_FE2CL_PC_AROUND); | ||||||
|  |         if (!npcAppearances.empty()) | ||||||
|  |             sendAroundPackets(ref, npcAppearances, P_FE2CL_NPC_AROUND); | ||||||
|  |         if (!shinyAppearances.empty()) | ||||||
|  |             sendAroundPackets(ref, shinyAppearances, P_FE2CL_SHINY_AROUND); | ||||||
|  |         if (!transportationAppearances.empty()) | ||||||
|  |             sendAroundPackets(ref, transportationAppearances, P_FE2CL_TRANSPORTATION_AROUND); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void Chunking::removeEntityFromChunks(std::set<Chunk*> chnks, const EntityRef ref) { | void Chunking::removeEntityFromChunks(std::set<Chunk*> chnks, const EntityRef ref) { | ||||||
|     Entity *ent = ref.getEntity(); |     Entity *ent = ref.getEntity(); | ||||||
|     bool alive = ent->isExtant(); |     bool alive = ent->isExtant(); | ||||||
|  |  | ||||||
|     // TODO: same as above |     std::vector<Bucket<int32_t, MAX_IDS_PER_AROUND_DEL>> pcDisappearances; | ||||||
|  |     std::vector<Bucket<int32_t, MAX_IDS_PER_AROUND_DEL>> npcDisappearances; | ||||||
|  |     std::vector<Bucket<int32_t, MAX_IDS_PER_AROUND_DEL>> shinyDisappearances; | ||||||
|  |     std::vector<Bucket<int32_t, MAX_TRANSPORTATION_IDS_PER_AROUND_DEL>> transportationDisappearances; | ||||||
|     for (Chunk *chunk : chnks) { |     for (Chunk *chunk : chnks) { | ||||||
|         for (const EntityRef otherRef : chunk->entities) { |         for (const EntityRef otherRef : chunk->entities) { | ||||||
|             // skip oneself |             // skip oneself | ||||||
| @@ -127,7 +249,29 @@ void Chunking::removeEntityFromChunks(std::set<Chunk*> chnks, const EntityRef re | |||||||
|  |  | ||||||
|             // notify this *player* of the departure of all visible Entities |             // notify this *player* of the departure of all visible Entities | ||||||
|             if (ref.kind == EntityKind::PLAYER && other->isExtant()) { |             if (ref.kind == EntityKind::PLAYER && other->isExtant()) { | ||||||
|                 other->disappearFromViewOf(ref.sock); |                 int32_t id; | ||||||
|  |                 switch(otherRef.kind) { | ||||||
|  |                 case EntityKind::PLAYER: | ||||||
|  |                     id = dynamic_cast<Player*>(other)->iID; | ||||||
|  |                     bufferIdForDisappearance(pcDisappearances, id); | ||||||
|  |                     break; | ||||||
|  |                 case EntityKind::SIMPLE_NPC: | ||||||
|  |                 case EntityKind::COMBAT_NPC: | ||||||
|  |                 case EntityKind::MOB: | ||||||
|  |                     id = dynamic_cast<BaseNPC*>(other)->id; | ||||||
|  |                     bufferIdForDisappearance(npcDisappearances, id); | ||||||
|  |                     break; | ||||||
|  |                 case EntityKind::EGG: | ||||||
|  |                     id = dynamic_cast<Egg*>(other)->id; | ||||||
|  |                     bufferIdForDisappearance(shinyDisappearances, id); | ||||||
|  |                     break; | ||||||
|  |                 case EntityKind::BUS: | ||||||
|  |                     id = dynamic_cast<Bus*>(other)->id; | ||||||
|  |                     bufferIdForDisappearance(transportationDisappearances, id); | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // for mobs, decrement playersInView |             // for mobs, decrement playersInView | ||||||
| @@ -137,6 +281,17 @@ void Chunking::removeEntityFromChunks(std::set<Chunk*> chnks, const EntityRef re | |||||||
|                 ((Mob*)other)->playersInView--; |                 ((Mob*)other)->playersInView--; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     if (ref.kind == EntityKind::PLAYER) { | ||||||
|  |         if (!pcDisappearances.empty()) | ||||||
|  |             sendAroundDelPackets(ref, pcDisappearances, P_FE2CL_AROUND_DEL_PC); | ||||||
|  |         if (!npcDisappearances.empty()) | ||||||
|  |             sendAroundDelPackets(ref, npcDisappearances, P_FE2CL_AROUND_DEL_NPC); | ||||||
|  |         if (!shinyDisappearances.empty()) | ||||||
|  |             sendAroundDelPackets(ref, shinyDisappearances, P_FE2CL_AROUND_DEL_SHINY); | ||||||
|  |         if (!transportationDisappearances.empty()) | ||||||
|  |             sendAroundDelPackets(ref, transportationDisappearances, P_FE2CL_AROUND_DEL_TRANSPORTATION); | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static void emptyChunk(ChunkPos chunkPos) { | static void emptyChunk(ChunkPos chunkPos) { | ||||||
|   | |||||||
| @@ -539,9 +539,9 @@ static void dealGooDamage(CNSocket *sock) { | |||||||
|         return; // ignore completely |         return; // ignore completely | ||||||
|  |  | ||||||
|     size_t resplen = sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK) + sizeof(sSkillResult_DotDamage); |     size_t resplen = sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK) + sizeof(sSkillResult_DotDamage); | ||||||
|     assert(resplen < CN_PACKET_BUFFER_SIZE - 8); |     assert(resplen < CN_PACKET_BODY_SIZE); | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK *pkt = (sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK*)respbuf; |     sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK *pkt = (sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK*)respbuf; | ||||||
|     sSkillResult_DotDamage *dmg = (sSkillResult_DotDamage*)(respbuf + sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK)); |     sSkillResult_DotDamage *dmg = (sSkillResult_DotDamage*)(respbuf + sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK)); | ||||||
| @@ -633,9 +633,9 @@ static void pcAttackChars(CNSocket *sock, CNPacketData *data) { | |||||||
|  |  | ||||||
|     // initialize response struct |     // initialize response struct | ||||||
|     size_t resplen = sizeof(sP_FE2CL_PC_ATTACK_CHARs_SUCC) + pkt->iTargetCnt * sizeof(sAttackResult); |     size_t resplen = sizeof(sP_FE2CL_PC_ATTACK_CHARs_SUCC) + pkt->iTargetCnt * sizeof(sAttackResult); | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|  |  | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     sP_FE2CL_PC_ATTACK_CHARs_SUCC *resp = (sP_FE2CL_PC_ATTACK_CHARs_SUCC*)respbuf; |     sP_FE2CL_PC_ATTACK_CHARs_SUCC *resp = (sP_FE2CL_PC_ATTACK_CHARs_SUCC*)respbuf; | ||||||
|     sAttackResult *respdata = (sAttackResult*)(respbuf+sizeof(sP_FE2CL_PC_ATTACK_CHARs_SUCC)); |     sAttackResult *respdata = (sAttackResult*)(respbuf+sizeof(sP_FE2CL_PC_ATTACK_CHARs_SUCC)); | ||||||
| @@ -847,9 +847,9 @@ static void projectileHit(CNSocket* sock, CNPacketData* data) { | |||||||
|      */ |      */ | ||||||
|  |  | ||||||
|     size_t resplen = sizeof(sP_FE2CL_PC_GRENADE_STYLE_HIT) + pkt->iTargetCnt * sizeof(sAttackResult); |     size_t resplen = sizeof(sP_FE2CL_PC_GRENADE_STYLE_HIT) + pkt->iTargetCnt * sizeof(sAttackResult); | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|  |  | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     sP_FE2CL_PC_GRENADE_STYLE_HIT* resp = (sP_FE2CL_PC_GRENADE_STYLE_HIT*)respbuf; |     sP_FE2CL_PC_GRENADE_STYLE_HIT* resp = (sP_FE2CL_PC_GRENADE_STYLE_HIT*)respbuf; | ||||||
|     sAttackResult* respdata = (sAttackResult*)(respbuf + sizeof(sP_FE2CL_PC_GRENADE_STYLE_HIT)); |     sAttackResult* respdata = (sAttackResult*)(respbuf + sizeof(sP_FE2CL_PC_GRENADE_STYLE_HIT)); | ||||||
|   | |||||||
							
								
								
									
										15
									
								
								src/Eggs.cpp
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								src/Eggs.cpp
									
									
									
									
									
								
							| @@ -87,8 +87,8 @@ void Eggs::eggBuffPlayer(CNSocket* sock, int skillId, int eggId, int duration) { | |||||||
|  |  | ||||||
|     // initialize response struct |     // initialize response struct | ||||||
|     size_t resplen = sizeof(sP_FE2CL_NPC_SKILL_HIT) + result.size; |     size_t resplen = sizeof(sP_FE2CL_NPC_SKILL_HIT) + result.size; | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     sP_FE2CL_NPC_SKILL_HIT* pkt = (sP_FE2CL_NPC_SKILL_HIT*)respbuf; |     sP_FE2CL_NPC_SKILL_HIT* pkt = (sP_FE2CL_NPC_SKILL_HIT*)respbuf; | ||||||
|     pkt->iNPC_ID = eggId; |     pkt->iNPC_ID = eggId; | ||||||
| @@ -126,15 +126,6 @@ static void eggStep(CNServer* serv, time_t currTime) { | |||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void Eggs::npcDataToEggData(int x, int y, int z, sNPCAppearanceData* npc, sShinyAppearanceData* egg) { |  | ||||||
|     egg->iX = x; |  | ||||||
|     egg->iY = y; |  | ||||||
|     egg->iZ = z; |  | ||||||
|     // client doesn't care about egg->iMapNum |  | ||||||
|     egg->iShinyType = npc->iNPCType; |  | ||||||
|     egg->iShiny_ID = npc->iNPC_ID; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void eggPickup(CNSocket* sock, CNPacketData* data) { | static void eggPickup(CNSocket* sock, CNPacketData* data) { | ||||||
|     auto pickup = (sP_CL2FE_REQ_SHINY_PICKUP*)data->buf; |     auto pickup = (sP_CL2FE_REQ_SHINY_PICKUP*)data->buf; | ||||||
|     Player* plr = PlayerManager::getPlayer(sock); |     Player* plr = PlayerManager::getPlayer(sock); | ||||||
| @@ -192,7 +183,7 @@ static void eggPickup(CNSocket* sock, CNPacketData* data) { | |||||||
|     // drop |     // drop | ||||||
|     if (type->dropCrateId != 0) { |     if (type->dropCrateId != 0) { | ||||||
|         const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); |         const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); | ||||||
|         assert(resplen < CN_PACKET_BUFFER_SIZE - 8); |         assert(resplen < CN_PACKET_BODY_SIZE); | ||||||
|         // we know it's only one trailing struct, so we can skip full validation |         // we know it's only one trailing struct, so we can skip full validation | ||||||
|  |  | ||||||
|         uint8_t respbuf[resplen]; // not a variable length array, don't worry |         uint8_t respbuf[resplen]; // not a variable length array, don't worry | ||||||
|   | |||||||
| @@ -15,5 +15,4 @@ namespace Eggs { | |||||||
|     void init(); |     void init(); | ||||||
|  |  | ||||||
|     void eggBuffPlayer(CNSocket* sock, int skillId, int eggId, int duration); |     void eggBuffPlayer(CNSocket* sock, int skillId, int eggId, int duration); | ||||||
|     void npcDataToEggData(int x, int y, int z, sNPCAppearanceData* npc, sShinyAppearanceData* egg); |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -70,11 +70,7 @@ void Bus::enterIntoViewOf(CNSocket *sock) { | |||||||
|     INITSTRUCT(sP_FE2CL_TRANSPORTATION_ENTER, pkt); |     INITSTRUCT(sP_FE2CL_TRANSPORTATION_ENTER, pkt); | ||||||
|  |  | ||||||
|     // TODO: Potentially decouple this from BaseNPC? |     // TODO: Potentially decouple this from BaseNPC? | ||||||
|     pkt.AppearanceData = { |     pkt.AppearanceData = getTransportationAppearanceData(); | ||||||
|         3, id, type, |  | ||||||
|         x, y, z |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     sock->sendPacket(pkt, P_FE2CL_TRANSPORTATION_ENTER); |     sock->sendPacket(pkt, P_FE2CL_TRANSPORTATION_ENTER); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -82,12 +78,22 @@ void Egg::enterIntoViewOf(CNSocket *sock) { | |||||||
|     INITSTRUCT(sP_FE2CL_SHINY_ENTER, pkt); |     INITSTRUCT(sP_FE2CL_SHINY_ENTER, pkt); | ||||||
|  |  | ||||||
|     // TODO: Potentially decouple this from BaseNPC? |     // TODO: Potentially decouple this from BaseNPC? | ||||||
|     pkt.ShinyAppearanceData = { |     pkt.ShinyAppearanceData = getShinyAppearanceData(); | ||||||
|  |     sock->sendPacket(pkt, P_FE2CL_SHINY_ENTER); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | sTransportationAppearanceData Bus::getTransportationAppearanceData() { | ||||||
|  |     return sTransportationAppearanceData { | ||||||
|  |         3, id, type, | ||||||
|  |         x, y, z | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | sShinyAppearanceData Egg::getShinyAppearanceData() { | ||||||
|  |     return sShinyAppearanceData { | ||||||
|         id, type, 0, // client doesn't care about map num |         id, type, 0, // client doesn't care about map num | ||||||
|         x, y, z |         x, y, z | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     sock->sendPacket(pkt, P_FE2CL_SHINY_ENTER); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| sNano* Player::getActiveNano() { | sNano* Player::getActiveNano() { | ||||||
|   | |||||||
| @@ -161,6 +161,8 @@ struct Egg : public BaseNPC { | |||||||
|  |  | ||||||
|     virtual void enterIntoViewOf(CNSocket *sock) override; |     virtual void enterIntoViewOf(CNSocket *sock) override; | ||||||
|     virtual void disappearFromViewOf(CNSocket *sock) override; |     virtual void disappearFromViewOf(CNSocket *sock) override; | ||||||
|  |  | ||||||
|  |     sShinyAppearanceData getShinyAppearanceData(); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct Bus : public BaseNPC { | struct Bus : public BaseNPC { | ||||||
| @@ -172,4 +174,6 @@ struct Bus : public BaseNPC { | |||||||
|  |  | ||||||
|     virtual void enterIntoViewOf(CNSocket *sock) override; |     virtual void enterIntoViewOf(CNSocket *sock) override; | ||||||
|     virtual void disappearFromViewOf(CNSocket *sock) override; |     virtual void disappearFromViewOf(CNSocket *sock) override; | ||||||
|  |  | ||||||
|  |     sTransportationAppearanceData getTransportationAppearanceData(); | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -87,8 +87,8 @@ void Groups::addToGroup(Group* group, EntityRef member) { | |||||||
|         size_t pcCount = pcs.size(); |         size_t pcCount = pcs.size(); | ||||||
|         size_t npcCount = npcs.size(); |         size_t npcCount = npcs.size(); | ||||||
|  |  | ||||||
|         uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |         uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|         memset(respbuf, 0, CN_PACKET_BUFFER_SIZE); |         memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|         sP_FE2CL_PC_GROUP_JOIN* pkt = (sP_FE2CL_PC_GROUP_JOIN*)respbuf; |         sP_FE2CL_PC_GROUP_JOIN* pkt = (sP_FE2CL_PC_GROUP_JOIN*)respbuf; | ||||||
|  |  | ||||||
|         pkt->iID_NewMember = PlayerManager::getPlayer(member.sock)->iID; |         pkt->iID_NewMember = PlayerManager::getPlayer(member.sock)->iID; | ||||||
| @@ -143,8 +143,8 @@ bool Groups::removeFromGroup(Group* group, EntityRef member) { | |||||||
|         size_t pcCount = pcs.size(); |         size_t pcCount = pcs.size(); | ||||||
|         size_t npcCount = npcs.size(); |         size_t npcCount = npcs.size(); | ||||||
|  |  | ||||||
|         uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |         uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|         memset(respbuf, 0, CN_PACKET_BUFFER_SIZE); |         memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|         sP_FE2CL_PC_GROUP_LEAVE* pkt = (sP_FE2CL_PC_GROUP_LEAVE*)respbuf; |         sP_FE2CL_PC_GROUP_LEAVE* pkt = (sP_FE2CL_PC_GROUP_LEAVE*)respbuf; | ||||||
|  |  | ||||||
|         pkt->iID_LeaveMember = PlayerManager::getPlayer(member.sock)->iID; |         pkt->iID_LeaveMember = PlayerManager::getPlayer(member.sock)->iID; | ||||||
| @@ -288,8 +288,8 @@ void Groups::groupTickInfo(CNSocket* sock) { | |||||||
|     size_t pcCount = pcs.size(); |     size_t pcCount = pcs.size(); | ||||||
|     size_t npcCount = npcs.size(); |     size_t npcCount = npcs.size(); | ||||||
|  |  | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|     memset(respbuf, 0, CN_PACKET_BUFFER_SIZE); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|     sP_FE2CL_PC_GROUP_MEMBER_INFO* pkt = (sP_FE2CL_PC_GROUP_MEMBER_INFO*)respbuf; |     sP_FE2CL_PC_GROUP_MEMBER_INFO* pkt = (sP_FE2CL_PC_GROUP_MEMBER_INFO*)respbuf; | ||||||
|  |  | ||||||
|     pkt->iID = plr->iID; |     pkt->iID = plr->iID; | ||||||
|   | |||||||
| @@ -46,7 +46,7 @@ static void nanoCapsuleHandler(CNSocket* sock, int slot, sItemBase *chest) { | |||||||
|  |  | ||||||
|     // in order to remove capsule form inventory, we have to send item reward packet with empty item |     // in order to remove capsule form inventory, we have to send item reward packet with empty item | ||||||
|     const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); |     const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); | ||||||
|     assert(resplen < CN_PACKET_BUFFER_SIZE - 8); |     assert(resplen < CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     // we know it's only one trailing struct, so we can skip full validation |     // we know it's only one trailing struct, so we can skip full validation | ||||||
|     uint8_t respbuf[resplen]; // not a variable length array, don't worry |     uint8_t respbuf[resplen]; // not a variable length array, don't worry | ||||||
| @@ -475,8 +475,8 @@ static void itemUseHandler(CNSocket* sock, CNPacketData* data) { | |||||||
|     if (gumball.iOpt == 0) |     if (gumball.iOpt == 0) | ||||||
|         gumball = {}; |         gumball = {}; | ||||||
|  |  | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     sP_FE2CL_REP_PC_ITEM_USE_SUCC *resp = (sP_FE2CL_REP_PC_ITEM_USE_SUCC*)respbuf; |     sP_FE2CL_REP_PC_ITEM_USE_SUCC *resp = (sP_FE2CL_REP_PC_ITEM_USE_SUCC*)respbuf; | ||||||
|     sSkillResult_Buff *respdata = (sSkillResult_Buff*)(respbuf+sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC)); |     sSkillResult_Buff *respdata = (sSkillResult_Buff*)(respbuf+sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC)); | ||||||
| @@ -556,7 +556,7 @@ static void chestOpenHandler(CNSocket *sock, CNPacketData *data) { | |||||||
|  |  | ||||||
|     // item giving packet |     // item giving packet | ||||||
|     const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); |     const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); | ||||||
|     assert(resplen < CN_PACKET_BUFFER_SIZE - 8); |     assert(resplen < CN_PACKET_BODY_SIZE); | ||||||
|     // we know it's only one trailing struct, so we can skip full validation |     // we know it's only one trailing struct, so we can skip full validation | ||||||
|  |  | ||||||
|     uint8_t respbuf[resplen]; // not a variable length array, don't worry |     uint8_t respbuf[resplen]; // not a variable length array, don't worry | ||||||
| @@ -645,7 +645,7 @@ void Items::checkItemExpire(CNSocket* sock, Player* player) { | |||||||
|     */ |     */ | ||||||
|  |  | ||||||
|     const size_t resplen = sizeof(sP_FE2CL_PC_DELETE_TIME_LIMIT_ITEM) + sizeof(sTimeLimitItemDeleteInfo2CL); |     const size_t resplen = sizeof(sP_FE2CL_PC_DELETE_TIME_LIMIT_ITEM) + sizeof(sTimeLimitItemDeleteInfo2CL); | ||||||
|     assert(resplen < CN_PACKET_BUFFER_SIZE - 8); |     assert(resplen < CN_PACKET_BODY_SIZE); | ||||||
|     // we know it's only one trailing struct, so we can skip full validation |     // we know it's only one trailing struct, so we can skip full validation | ||||||
|     uint8_t respbuf[resplen]; // not a variable length array, don't worry |     uint8_t respbuf[resplen]; // not a variable length array, don't worry | ||||||
|     auto packet = (sP_FE2CL_PC_DELETE_TIME_LIMIT_ITEM*)respbuf; |     auto packet = (sP_FE2CL_PC_DELETE_TIME_LIMIT_ITEM*)respbuf; | ||||||
| @@ -715,7 +715,7 @@ static void giveSingleDrop(CNSocket *sock, Mob* mob, int mobDropId, const DropRo | |||||||
|     Player *plr = PlayerManager::getPlayer(sock); |     Player *plr = PlayerManager::getPlayer(sock); | ||||||
|  |  | ||||||
|     const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); |     const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); | ||||||
|     assert(resplen < CN_PACKET_BUFFER_SIZE - 8); |     assert(resplen < CN_PACKET_BODY_SIZE); | ||||||
|     // we know it's only one trailing struct, so we can skip full validation |     // we know it's only one trailing struct, so we can skip full validation | ||||||
|  |  | ||||||
|     uint8_t respbuf[resplen]; // not a variable length array, don't worry |     uint8_t respbuf[resplen]; // not a variable length array, don't worry | ||||||
|   | |||||||
| @@ -64,7 +64,7 @@ static bool isQuestItemFull(CNSocket* sock, int itemId, int itemCount) { | |||||||
| static void dropQuestItem(CNSocket *sock, int task, int count, int id, int mobid) { | static void dropQuestItem(CNSocket *sock, int task, int count, int id, int mobid) { | ||||||
|     std::cout << "Altered item id " << id << " by " << count << " for task id " << task << std::endl; |     std::cout << "Altered item id " << id << " by " << count << " for task id " << task << std::endl; | ||||||
|     const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); |     const size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + sizeof(sItemReward); | ||||||
|     assert(resplen < CN_PACKET_BUFFER_SIZE); |     assert(resplen < CN_PACKET_BODY_SIZE); | ||||||
|     // we know it's only one trailing struct, so we can skip full validation |     // we know it's only one trailing struct, so we can skip full validation | ||||||
|  |  | ||||||
|     Player *plr = PlayerManager::getPlayer(sock); |     Player *plr = PlayerManager::getPlayer(sock); | ||||||
| @@ -152,14 +152,14 @@ static int giveMissionReward(CNSocket *sock, int task, int choice=0) { | |||||||
|         plr->Inven[slots[i]] = { 999, 999, 999, 0 }; // temp item; overwritten later |         plr->Inven[slots[i]] = { 999, 999, 999, 0 }; // temp item; overwritten later | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|     size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + nrewards * sizeof(sItemReward); |     size_t resplen = sizeof(sP_FE2CL_REP_REWARD_ITEM) + nrewards * sizeof(sItemReward); | ||||||
|     assert(resplen < CN_PACKET_BUFFER_SIZE); |     assert(resplen < CN_PACKET_BODY_SIZE); | ||||||
|     sP_FE2CL_REP_REWARD_ITEM *resp = (sP_FE2CL_REP_REWARD_ITEM *)respbuf; |     sP_FE2CL_REP_REWARD_ITEM *resp = (sP_FE2CL_REP_REWARD_ITEM *)respbuf; | ||||||
|     sItemReward *item = (sItemReward *)(respbuf + sizeof(sP_FE2CL_REP_REWARD_ITEM)); |     sItemReward *item = (sItemReward *)(respbuf + sizeof(sP_FE2CL_REP_REWARD_ITEM)); | ||||||
|  |  | ||||||
|     // don't forget to zero the buffer! |     // don't forget to zero the buffer! | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     // update player |     // update player | ||||||
|     plr->money += reward->money; |     plr->money += reward->money; | ||||||
|   | |||||||
| @@ -238,8 +238,8 @@ static void dealCorruption(Mob *mob, std::vector<int> targetData, int skillID, i | |||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; |     uint8_t respbuf[CN_PACKET_BODY_SIZE]; | ||||||
|     memset(respbuf, 0, resplen); |     memset(respbuf, 0, CN_PACKET_BODY_SIZE); | ||||||
|  |  | ||||||
|     sP_FE2CL_NPC_SKILL_CORRUPTION_HIT *resp = (sP_FE2CL_NPC_SKILL_CORRUPTION_HIT*)respbuf; |     sP_FE2CL_NPC_SKILL_CORRUPTION_HIT *resp = (sP_FE2CL_NPC_SKILL_CORRUPTION_HIT*)respbuf; | ||||||
|     sCAttackResult *respdata = (sCAttackResult*)(respbuf+sizeof(sP_FE2CL_NPC_SKILL_CORRUPTION_HIT)); |     sCAttackResult *respdata = (sCAttackResult*)(respbuf+sizeof(sP_FE2CL_NPC_SKILL_CORRUPTION_HIT)); | ||||||
|   | |||||||
| @@ -95,14 +95,14 @@ inline constexpr bool isOutboundPacketID(uint32_t id) { | |||||||
| // for outbound packets | // for outbound packets | ||||||
| inline constexpr bool validOutVarPacket(size_t base, size_t npayloads, size_t plsize) { | inline constexpr bool validOutVarPacket(size_t base, size_t npayloads, size_t plsize) { | ||||||
|     // check for multiplication overflow |     // check for multiplication overflow | ||||||
|     if (npayloads > 0 && (CN_PACKET_BUFFER_SIZE - 8) / (size_t)npayloads < plsize) |     if (npayloads > 0 && (CN_PACKET_BODY_SIZE) / (size_t)npayloads < plsize) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|     // it's safe to multiply |     // it's safe to multiply | ||||||
|     size_t trailing = npayloads * plsize; |     size_t trailing = npayloads * plsize; | ||||||
|  |  | ||||||
|     // does it fit in a packet? |     // does it fit in a packet? | ||||||
|     if (base + trailing > CN_PACKET_BUFFER_SIZE - 8) |     if (base + trailing > CN_PACKET_BODY_SIZE) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|     // everything is a-ok! |     // everything is a-ok! | ||||||
| @@ -112,14 +112,14 @@ inline constexpr bool validOutVarPacket(size_t base, size_t npayloads, size_t pl | |||||||
| // for inbound packets | // for inbound packets | ||||||
| inline constexpr bool validInVarPacket(size_t base, size_t npayloads, size_t plsize, size_t datasize) { | inline constexpr bool validInVarPacket(size_t base, size_t npayloads, size_t plsize, size_t datasize) { | ||||||
|     // check for multiplication overflow |     // check for multiplication overflow | ||||||
|     if (npayloads > 0 && (CN_PACKET_BUFFER_SIZE - 8) / (size_t)npayloads < plsize) |     if (npayloads > 0 && CN_PACKET_BODY_SIZE / (size_t)npayloads < plsize) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|     // it's safe to multiply |     // it's safe to multiply | ||||||
|     size_t trailing = npayloads * plsize; |     size_t trailing = npayloads * plsize; | ||||||
|  |  | ||||||
|     // make sure size is exact |     // make sure size is exact | ||||||
|     // datasize has already been validated against CN_PACKET_BUFFER_SIZE |     // datasize has already been validated against CN_PACKET_BODY_SIZE | ||||||
|     if (datasize != base + trailing) |     if (datasize != base + trailing) | ||||||
|         return false; |         return false; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -29,8 +29,8 @@ | |||||||
| #define INITSTRUCT(T, x) T x; \ | #define INITSTRUCT(T, x) T x; \ | ||||||
|     memset(&x, 0, sizeof(T)); |     memset(&x, 0, sizeof(T)); | ||||||
|  |  | ||||||
| #define INITVARPACKET(_buf, _Pkt, _pkt, _Trailer, _trailer) uint8_t _buf[CN_PACKET_BUFFER_SIZE]; \ | #define INITVARPACKET(_buf, _Pkt, _pkt, _Trailer, _trailer) uint8_t _buf[CN_PACKET_BODY_SIZE]; \ | ||||||
|     memset(&_buf, 0, CN_PACKET_BUFFER_SIZE); \ |     memset(&_buf, 0, CN_PACKET_BODY_SIZE); \ | ||||||
|     auto _pkt = (_Pkt*)_buf; \ |     auto _pkt = (_Pkt*)_buf; \ | ||||||
|     auto _trailer = (_Trailer*)(_pkt + 1); |     auto _trailer = (_Trailer*)(_pkt + 1); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,6 +1,8 @@ | |||||||
| /* enum definitions from the client */ | /* enum definitions from the client */ | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include "core/CNStructs.hpp" | ||||||
|  |  | ||||||
| // floats | // floats | ||||||
| const float VALUE_BATTERY_EMPTY_PENALTY = 0.5f; | const float VALUE_BATTERY_EMPTY_PENALTY = 0.5f; | ||||||
| const float CN_EP_RANK_1 = 0.8f; | const float CN_EP_RANK_1 = 0.8f; | ||||||
| @@ -410,7 +412,13 @@ enum { | |||||||
|     SEND_ANYCAST_NEW = 3, |     SEND_ANYCAST_NEW = 3, | ||||||
|     SEND_BROADCAST = 4, |     SEND_BROADCAST = 4, | ||||||
|  |  | ||||||
|  | #if PROTOCOL_VERSION == 728 | ||||||
|  |     CN_PACKET_BUFFER_SIZE = 8192, | ||||||
|  | #elif PROTOCOL_VERSION == 1013 | ||||||
|  |     CN_PACKET_BUFFER_SIZE = 8192, | ||||||
|  | #else | ||||||
|     CN_PACKET_BUFFER_SIZE = 4096, |     CN_PACKET_BUFFER_SIZE = 4096, | ||||||
|  | #endif | ||||||
|  |  | ||||||
|     P_CL2LS_REQ_LOGIN = 0x12000001,		// 301989889 |     P_CL2LS_REQ_LOGIN = 0x12000001,		// 301989889 | ||||||
|     P_CL2LS_REQ_CHECK_CHAR_NAME = 0x12000002,		// 301989890 |     P_CL2LS_REQ_CHECK_CHAR_NAME = 0x12000002,		// 301989890 | ||||||
| @@ -934,3 +942,8 @@ enum { | |||||||
|  |  | ||||||
|     N_PACKETS = N_CL2LS + N_CL2FE + N_FE2CL + N_LS2CL |     N_PACKETS = N_CL2LS + N_CL2FE + N_FE2CL + N_LS2CL | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Usable space in the packet buffer = CN_PACKET_BUFFER_SIZE - type - size | ||||||
|  |  */ | ||||||
|  | constexpr size_t CN_PACKET_BODY_SIZE = CN_PACKET_BUFFER_SIZE - 2 * sizeof(int32_t); | ||||||
|   | |||||||
| @@ -235,7 +235,7 @@ std::map<uint32_t, PacketDesc> Packets::packets = { | |||||||
|     PACKET(P_FE2CL_REP_PC_EXIT_FAIL), |     PACKET(P_FE2CL_REP_PC_EXIT_FAIL), | ||||||
|     PACKET(P_FE2CL_REP_PC_EXIT_SUCC), |     PACKET(P_FE2CL_REP_PC_EXIT_SUCC), | ||||||
|     PACKET(P_FE2CL_PC_EXIT), |     PACKET(P_FE2CL_PC_EXIT), | ||||||
|     PACKET(P_FE2CL_PC_AROUND), |     VAR_PACKET(P_FE2CL_PC_AROUND, iPCCnt, sPCAppearanceData), | ||||||
|     PACKET(P_FE2CL_PC_MOVE), |     PACKET(P_FE2CL_PC_MOVE), | ||||||
|     PACKET(P_FE2CL_PC_STOP), |     PACKET(P_FE2CL_PC_STOP), | ||||||
|     PACKET(P_FE2CL_PC_JUMP), |     PACKET(P_FE2CL_PC_JUMP), | ||||||
| @@ -243,9 +243,9 @@ std::map<uint32_t, PacketDesc> Packets::packets = { | |||||||
|     PACKET(P_FE2CL_NPC_EXIT), |     PACKET(P_FE2CL_NPC_EXIT), | ||||||
|     PACKET(P_FE2CL_NPC_MOVE), |     PACKET(P_FE2CL_NPC_MOVE), | ||||||
|     PACKET(P_FE2CL_NPC_NEW), |     PACKET(P_FE2CL_NPC_NEW), | ||||||
|     PACKET(P_FE2CL_NPC_AROUND), |     VAR_PACKET(P_FE2CL_NPC_AROUND, iNPCCnt, sNPCAppearanceData), | ||||||
|     PACKET(P_FE2CL_AROUND_DEL_PC), |     VAR_PACKET(P_FE2CL_AROUND_DEL_PC, iPCCnt, int32_t), | ||||||
|     PACKET(P_FE2CL_AROUND_DEL_NPC), |     VAR_PACKET(P_FE2CL_AROUND_DEL_NPC, iNPCCnt, int32_t), | ||||||
|     PACKET(P_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC), |     PACKET(P_FE2CL_REP_SEND_FREECHAT_MESSAGE_SUCC), | ||||||
|     PACKET(P_FE2CL_REP_SEND_FREECHAT_MESSAGE_FAIL), |     PACKET(P_FE2CL_REP_SEND_FREECHAT_MESSAGE_FAIL), | ||||||
|     VAR_PACKET(P_FE2CL_PC_ATTACK_NPCs_SUCC, iNPCCnt, sAttackResult), |     VAR_PACKET(P_FE2CL_PC_ATTACK_NPCs_SUCC, iNPCCnt, sAttackResult), | ||||||
| @@ -387,8 +387,8 @@ std::map<uint32_t, PacketDesc> Packets::packets = { | |||||||
|     PACKET(P_FE2CL_TRANSPORTATION_EXIT), |     PACKET(P_FE2CL_TRANSPORTATION_EXIT), | ||||||
|     PACKET(P_FE2CL_TRANSPORTATION_MOVE), |     PACKET(P_FE2CL_TRANSPORTATION_MOVE), | ||||||
|     PACKET(P_FE2CL_TRANSPORTATION_NEW), |     PACKET(P_FE2CL_TRANSPORTATION_NEW), | ||||||
|     PACKET(P_FE2CL_TRANSPORTATION_AROUND), |     VAR_PACKET(P_FE2CL_TRANSPORTATION_AROUND, iCnt, sTransportationAppearanceData), | ||||||
|     PACKET(P_FE2CL_AROUND_DEL_TRANSPORTATION), |     VAR_PACKET(P_FE2CL_AROUND_DEL_TRANSPORTATION, iCnt, int32_t), | ||||||
|     PACKET(P_FE2CL_REP_EP_RANK_LIST), |     PACKET(P_FE2CL_REP_EP_RANK_LIST), | ||||||
|     PACKET(P_FE2CL_REP_EP_RANK_DETAIL), |     PACKET(P_FE2CL_REP_EP_RANK_DETAIL), | ||||||
|     PACKET(P_FE2CL_REP_EP_RANK_PC_INFO), |     PACKET(P_FE2CL_REP_EP_RANK_PC_INFO), | ||||||
| @@ -404,8 +404,8 @@ std::map<uint32_t, PacketDesc> Packets::packets = { | |||||||
|     PACKET(P_FE2CL_SHINY_ENTER), |     PACKET(P_FE2CL_SHINY_ENTER), | ||||||
|     PACKET(P_FE2CL_SHINY_EXIT), |     PACKET(P_FE2CL_SHINY_EXIT), | ||||||
|     PACKET(P_FE2CL_SHINY_NEW), |     PACKET(P_FE2CL_SHINY_NEW), | ||||||
|     PACKET(P_FE2CL_SHINY_AROUND), |     VAR_PACKET(P_FE2CL_SHINY_AROUND, iShinyCnt, sShinyAppearanceData), | ||||||
|     PACKET(P_FE2CL_AROUND_DEL_SHINY), |     VAR_PACKET(P_FE2CL_AROUND_DEL_SHINY, iShinyCnt, int32_t), | ||||||
|     PACKET(P_FE2CL_REP_SHINY_PICKUP_FAIL), |     PACKET(P_FE2CL_REP_SHINY_PICKUP_FAIL), | ||||||
|     PACKET(P_FE2CL_REP_SHINY_PICKUP_SUCC), |     PACKET(P_FE2CL_REP_SHINY_PICKUP_SUCC), | ||||||
|     PACKET(P_FE2CL_PC_MOVETRANSPORTATION), |     PACKET(P_FE2CL_PC_MOVETRANSPORTATION), | ||||||
|   | |||||||
| @@ -1,6 +1,8 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
|  | #include <stdint.h> | ||||||
| #include <string> | #include <string> | ||||||
|  | #include <time.h> | ||||||
|  |  | ||||||
| namespace settings { | namespace settings { | ||||||
|     extern int VERBOSITY; |     extern int VERBOSITY; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user