bool sessionInit(Session *self, RouterId_t routerId, uint8_t *sessionKey) { // Define a valid socket session socketSessionInit(&self->socket, SOCKET_SESSION_UNDEFINED_ACCOUNT, routerId, SOCKET_SESSION_UNDEFINED_MAP, sessionKey, false); // Initialize a dummy commander info Commander commander; commanderInit(&commander); gameSessionInit(&self->game, &commander); return true; }
void adminCmdSpawnPc(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { // add a fake commander with a fake account CommanderInfo fakePc; commanderInfoInit(&fakePc); fakePc.pos = session->game.commanderSession.currentCommander.info.pos; fakePc.appearance.accountId = r1emuGenerateRandom64(&self->seed); fakePc.socialInfoId = r1emuGenerateRandom64(&self->seed); fakePc.pcId = r1emuGenerateRandom(&self->seed); fakePc.commanderId = r1emuGenerateRandom64(&self->seed); snprintf(fakePc.appearance.familyName, sizeof(fakePc.appearance.familyName), "PcID_%x", fakePc.pcId); snprintf(fakePc.appearance.commanderName, sizeof(fakePc.appearance.commanderName), "AccountID_%llx", fakePc.appearance.accountId); // register the fake socket session SocketSession fakeSocketSession; uint32_t sessionKey = r1emuGenerateRandom(&self->seed); uint8_t sessionKeyStr[SOCKET_SESSION_ID_SIZE]; socketSessionGenSessionKey((uint8_t *)&sessionKey, sessionKeyStr); sprintf(sessionKeyStr, "%.08x", sessionKey); socketSessionInit(&fakeSocketSession, fakePc.appearance.accountId, self->info.routerId, session->socket.mapId, sessionKeyStr, true); RedisSocketSessionKey socketKey = { .routerId = self->info.routerId, .sessionKey = sessionKeyStr }; redisUpdateSocketSession(self->redis, &socketKey, &fakeSocketSession); // register the fake game session GameSession fakeGameSession; gameSessionInit(&fakeGameSession, &fakePc); accountSessionInit(&fakeGameSession.accountSession, "DummyPC", sessionKeyStr, ACCOUNT_SESSION_PRIVILEGES_ADMIN); RedisGameSessionKey gameKey = { .routerId = fakeSocketSession.routerId, .mapId = fakeSocketSession.mapId, .accountId = fakeSocketSession.accountId }; redisUpdateGameSession(self->redis, &gameKey, sessionKeyStr, &fakeGameSession); info("Fake PC spawned.(SocketID=%s, SocialID=%I64x, AccID=%I64x, PcID=%x, CommID=%I64x)", sessionKeyStr, fakePc.socialInfoId, fakePc.appearance.accountId, fakePc.pcId, fakePc.commanderId); GameEventEnterPc event = { .updatePosEvent = { .mapId = fakeSocketSession.mapId, .info = fakePc } }; workerDispatchEvent(self, sessionKeyStr, EVENT_TYPE_ENTER_PC, &event, sizeof(event)); } void adminCmdAddItem(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { uint32_t itemId = strtol(args, &args, 10); args++; uint32_t amount = strtol(args, &args, 10); uint32_t itemPosition = 1; ItemPkt item = { .uniqueId = r1emuGenerateRandom64(&self->seed), .amount = (!amount) ? 1 : amount, .inventoryIndex = INVENTORY_CAT_SIZE * INVENTORY_CAT_CONSUMABLE + itemPosition, .id = itemId }; zoneBuilderItemAdd(&item, INVENTORY_ADD_PICKUP, replyMsg); } void adminCmdJump(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { if (strlen (args) == 0) { info("Jump without argument!"); // we must add a random with the map max x/y } else { char **arg; int argc; info("Jump with argument: %s", args); arg = strSplit(args, ' '); argc = 0; while (arg[++argc] != NULL); if (argc != 3) { info("Wrong number of argument, must be 3."); } else { PositionXYZ position; position.x = atof(arg[0]); info("x = %.6f", position.x); position.y = atof(arg[1]); info("y = %.6f", position.y); position.z = atof(arg[2]); info("z = %.6f", position.z); session->game.commanderSession.currentCommander.info.pos = position; zoneBuilderSetPos(session->game.commanderSession.currentCommander.info.pcId, &position, replyMsg); } free(arg); } } void adminCmdTest(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { info("Test command launched."); size_t memSize; void *memory = dumpToMem( "[03:12:32][main.c:30 in writePacketToFile] E9 0C 73 2A 86 02 35 00 A2 4E 00 00 02 01 05 00 | ..s*..5..N......\n" "[03:12:32][main.c:30 in writePacketToFile] 4E 61 6D 65 00 0C 00 44 61 72 6B 48 6F 72 69 7A | Name...DarkHoriz\n" "[03:12:32][main.c:30 in writePacketToFile] 6F 6E 00 04 00 57 68 6F 00 0A 00 4C 6F 74 68 62 | on...Who...Lothb\n" "[03:12:32][main.c:30 in writePacketToFile] 72 6F 6F 6B 00 | rook." , NULL, &memSize ); zmsg_add(replyMsg, zframe_new(memory, memSize)); } void adminCmdWhere(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { const uint16_t MAX_LEN = 128; char message[MAX_LEN]; PositionXYZ position; position = session->game.commanderSession.currentCommander.info.pos; snprintf(message, sizeof(message), "[%hu] x = %.0f, y = %.0f, z = %.0f", session->game.commanderSession.mapId, position.x, position.y, position.z); zoneBuilderChat(&session->game.commanderSession.currentCommander.info, message, replyMsg); } void adminCmdChangeCamera(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { const uint16_t MAX_LEN = 128; char message[MAX_LEN]; PositionXYZ pos; float fspd; float ispd; info("Change Camera command used, args = %s", args); if (strlen (args) == 0) { pos.x = 0; pos.y = 0; pos.z = 0; zoneBuilderChangeCamera((uint8_t)0, &pos, (float)0, (float)0, replyMsg); } else { char **arg; int argc; arg = strSplit(args, ' '); argc = 0; while (arg[++argc] != NULL); if (argc >= 3) { pos.x = (strlen(arg[0]) == 1 && arg[0][0] == 'c') ? session->game.commanderSession.currentCommander.info.pos.x : atof(arg[0]); pos.y = (strlen(arg[1]) == 1 && arg[1][0] == 'c') ? session->game.commanderSession.currentCommander.info.pos.y : atof(arg[1]); pos.z = (strlen(arg[2]) == 1 && arg[2][0] == 'c') ? session->game.commanderSession.currentCommander.info.pos.z : atof(arg[2]); } if (argc == 3) zoneBuilderChangeCamera((uint8_t)1, &pos, (float)10, (float)0.7, replyMsg); else if (argc == 5) { fspd = atof(arg[3]); ispd = atof(arg[4]); zoneBuilderChangeCamera((uint8_t)1, &pos, fspd, ispd, replyMsg); } else { snprintf(message, sizeof(message), "Bad usage /changeCamera <x> <y> <z> {<fspd> <ispd>}"); zoneBuilderChat(&session->game.commanderSession.currentCommander.info, message, replyMsg); } free(arg); } } void adminCmdSetStamina(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { if (strlen (args) == 0) { info("Set stamina needs a argument!"); } else { char **arg; int argc; info("Set stamina with argument: %s", args); arg = strSplit(args, ' '); argc = 0; while (arg[++argc] != NULL); if (argc != 1) { info("Wrong number of arguments, must be 1."); } else { uint32_t stamina = atoi(arg[0]) * 1000; info("Setting stamina to %d.", stamina); session->game.commanderSession.currentCommander.info.currentStamina = stamina; zoneBuilderStamina(stamina, replyMsg); } free(arg); } } void adminCmdSetSP(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { if (strlen (args) == 0) { info("Set SP needs a argument!"); } else { char **arg; int argc; info("Set SP with argument: %s", args); arg = strSplit(args, ' '); argc = 0; while (arg[++argc] != NULL); if (argc != 1) { info("Wrong number of arguments, must be 1."); } else { uint32_t sp = atoi(arg[0]); info("Setting SP to %d.", sp); session->game.commanderSession.currentCommander.info.currentSP = sp; zoneBuilderUpdateSP(session->game.commanderSession.currentCommander.info.pcId, sp, replyMsg); } free(arg); } } void adminCmdSetLevel(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { if (strlen (args) == 0) { info("Set level needs a argument!"); } else { char **arg; int argc; info("Set level with argument: %s", args); arg = strSplit(args, ' '); argc = 0; while (arg[++argc] != NULL); if (argc != 1) { info("Wrong number of arguments, must be 1."); } else { uint32_t level = atoi(arg[0]); info("Setting level to %d.", level); session->game.commanderSession.currentCommander.info.appearance.level = level; zoneBuilderPCLevelUp(session->game.commanderSession.currentCommander.info.pcId, level, replyMsg); } free(arg); } }
void adminCmdSpawnPc(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { // add a fake commander with a fake account Commander fakePc; commanderInit(&fakePc); fakePc.pos = session->game.commanderSession.currentCommander->pos; fakePc.dir = session->game.commanderSession.currentCommander->dir; fakePc.accountId = r1emuGenerateRandom64(&self->seed); fakePc.socialInfoId = r1emuGenerateRandom64(&self->seed); fakePc.pcId = r1emuGenerateRandom(&self->seed); fakePc.commanderId = r1emuGenerateRandom64(&self->seed); snprintf(fakePc.familyName, sizeof(fakePc.familyName), "PcID_%x", fakePc.pcId); snprintf(fakePc.commanderName, sizeof(fakePc.commanderName), "AccountID_%llx", fakePc.accountId); // register the fake socket session SocketSession fakeSocketSession; uint32_t sessionKey = r1emuGenerateRandom(&self->seed); uint8_t sessionKeyStr[SOCKET_SESSION_ID_SIZE]; socketSessionGenSessionKey((uint8_t *)&sessionKey, sessionKeyStr); sprintf(sessionKeyStr, "%.08x", sessionKey); socketSessionInit(&fakeSocketSession, fakePc.accountId, self->info.routerId, session->socket.mapId, sessionKeyStr, true); RedisSocketSessionKey socketKey = { .routerId = self->info.routerId, .sessionKey = sessionKeyStr }; redisUpdateSocketSession(self->redis, &socketKey, &fakeSocketSession); // register the fake game session GameSession fakeGameSession; gameSessionInit(&fakeGameSession, &fakePc); accountSessionInit(&fakeGameSession.accountSession, "DummyPC", sessionKeyStr, ACCOUNT_SESSION_PRIVILEGES_ADMIN); RedisGameSessionKey gameKey = { .routerId = fakeSocketSession.routerId, .mapId = fakeSocketSession.mapId, .accountId = fakeSocketSession.accountId }; redisUpdateGameSession(self->redis, &gameKey, sessionKeyStr, &fakeGameSession); info("Fake PC spawned.(SocketID=%s, SocialID=%I64x, AccID=%I64x, PcID=%x, CommID=%I64x)", sessionKeyStr, fakePc.socialInfoId, fakePc.accountId, fakePc.pcId, fakePc.commanderId); GameEventEnterPc event = { .updatePosEvent = { .mapId = fakeSocketSession.mapId, .commander = fakePc } }; workerDispatchEvent(self, sessionKeyStr, EVENT_TYPE_ENTER_PC, &event, sizeof(event)); } void adminCmdAddItem(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { Item *newItem = NULL; ItemId_t itemId = strtol(args, &args, 10); args++; ItemAmount_t amount = strtol(args, &args, 10); amount = amount ? amount : 1; // Create new item if (!(newItem = itemFactoryCreate(itemId, amount))) { error("Item ID = %d is invalid.", itemId); return; } Inventory *inventory = &session->game.commanderSession.currentCommander->inventory; inventoryAddItem(inventory, newItem); ItemCategory_t itemCategory = itemGetCategory(newItem); ActorId_t actorId = actorGetUId(newItem); dbg("itemCategory %d", itemCategory); ItemInventoryIndex_t inventoryIndex = inventoryGetBagIndexByActorId(inventory, itemCategory, actorId); dbg("inventoryIndex %d", inventoryIndex); zoneBuilderItemAdd(newItem, inventoryIndex, INVENTORY_ADD_PICKUP, replyMsg); } void adminCmdAddSkill(Worker *self, Session *session, char *args, zmsg_t *replyMsg) { SkillId_t skillId = strtol(args, &args, 10); args++; SkillLevel_t level = strtol(args, &args, 10); skillId = skillId ? skillId : 40001; // Heal level = level ? level : 1; SkillsManager *skillsManager = &session->game.commanderSession.currentCommander->skillsManager; /* Item *newItem = itemFactoryCreate(itemId, amount); skillsManagerAddskill(skillsManager, newItem); ItemCategory_t itemCategory = itemGetCategory(newItem); ActorId_t actorId = actorGetUId(newItem); dbg("itemCategory %d", itemCategory); ItemInventoryIndex_t inventoryIndex = inventoryGetBagIndexByActorId(inventory, itemCategory, actorId); dbg("inventoryIndex %d", inventoryIndex); */ zoneBuilderSkillAdd(skillId, replyMsg); }
static PacketHandlerState zoneHandlerConnect( Worker *self, Session *session, uint8_t *packet, size_t packetSize, zmsg_t *replyMsg) { #pragma pack(push, 1) struct { uint32_t unk1; uint64_t accountId; uint64_t zoneServerId; uint8_t login[ACCOUNT_SESSION_LOGIN_MAXSIZE]; uint8_t unk4; uint32_t zoneServerIndex; uint16_t unk3; uint8_t channelListId; } *clientPacket = (void *) packet; #pragma pack(pop) // TODO : Reverse CZ_CONNECT correctly // CHECK_CLIENT_PACKET_SIZE(*clientPacket, packetSize, CZ_CONNECT); // Get the Game Session that the Barrack Server moved RedisGameSessionKey gameKey = { .routerId = self->info.routerId, .mapId = -1, .accountId = clientPacket->accountId }; if (!(redisGetGameSession(self->redis, &gameKey, &session->game))) { error("Cannot retrieve the game session."); return PACKET_HANDLER_ERROR; } // Check the client packet here(authentication) if (strncmp(session->game.accountSession.login, clientPacket->login, sizeof(session->game.accountSession.login)) != 0) { error("Wrong account authentication.(clientPacket account = <%s>, Session account = <%s>", clientPacket->login, session->game.accountSession.login); return PACKET_HANDLER_ERROR; } // Authentication OK ! // Update the Socket Session socketSessionInit(&session->socket, clientPacket->accountId, self->info.routerId, session->game.commanderSession.mapId, session->socket.sessionKey, true ); // Move the game Session to the current mapId RedisGameSessionKey fromKey = { .routerId = session->socket.routerId, .mapId = -1, .accountId = session->socket.accountId }; RedisGameSessionKey toKey = { .routerId = session->socket.routerId, .mapId = session->socket.mapId, .accountId = session->socket.accountId }; if (!(redisMoveGameSession(self->redis, &fromKey, &toKey))) { error("Cannot move the game session to the current mapId."); return PACKET_HANDLER_ERROR; } session->game.commanderSession.currentCommander.pos = PositionXYZ_decl(76.0f, 1.0f, 57.0f); zoneBuilderConnectOk( session->game.commanderSession.currentCommander.pcId, 0, // GameMode 0, // accountPrivileges &session->game.commanderSession.currentCommander, // Current commander replyMsg ); return PACKET_HANDLER_UPDATE_SESSION; } static PacketHandlerState zoneHandlerJump( Worker *self, Session *session, uint8_t *packet, size_t packetSize, zmsg_t *replyMsg) { #pragma pack(push, 1) struct { uint8_t unk1; } *clientPacket = (void *) packet; #pragma pack(pop) CHECK_CLIENT_PACKET_SIZE(*clientPacket, packetSize, CZ_JUMP); // Notify the players around GameEventJump event = { .updatePosEvent = { .mapId = session->socket.mapId, .commanderInfo = session->game.commanderSession.currentCommander }, .height = COMMANDER_HEIGHT_JUMP }; workerDispatchEvent(self, session->socket.sessionKey, EVENT_TYPE_JUMP, &event, sizeof(event)); return PACKET_HANDLER_OK; } static PacketHandlerState zoneHandlerOnAir( Worker *self, Session *session, uint8_t *packet, size_t packetSize, zmsg_t *replyMsg) { warning("CZ_ON_AIR not implemented yet."); return PACKET_HANDLER_OK; } static PacketHandlerState zoneHandlerOnGround( Worker *self, Session *session, uint8_t *packet, size_t packetSize, zmsg_t *replyMsg) { warning("CZ_ON_GROUND not implemented yet."); return PACKET_HANDLER_OK; }
static PacketHandlerState zoneHandlerConnect( Worker *self, Session *session, uint8_t *packet, size_t packetSize, zmsg_t *replyMsg) { PacketHandlerState status = PACKET_HANDLER_ERROR; #pragma pack(push, 1) struct { uint32_t unk1; uint64_t accountId; uint64_t zoneServerId; uint8_t accountName[ACCOUNT_SESSION_ACCOUNT_NAME_MAXSIZE]; uint8_t unk4; uint32_t zoneServerIndex; uint16_t unk3; uint8_t channelListId; } *clientPacket = (void *) packet; #pragma pack(pop) dbg("zoneHandlerConnect"); dbg("unk1 %x", clientPacket->unk1); dbg("accountId %d", clientPacket->accountId); dbg("zoneServerId %d", clientPacket->zoneServerId); dbg("zoneServerIndex %d", clientPacket->zoneServerIndex); dbg("unk3 %x", clientPacket->unk3); dbg("unk4 %x", clientPacket->unk4); dbg("channelListId %d", clientPacket->channelListId); dbg("accountName %s", clientPacket->accountName); // TODO : Reverse CZ_CONNECT correctly // CHECK_CLIENT_PACKET_SIZE(*clientPacket, packetSize, CZ_CONNECT); GameSession tmpGameSession; AccountSession *tmpAccountSession = &tmpGameSession.accountSession; CommanderSession *tmpCommanderSession = &tmpGameSession.commanderSession; // TODO : Get the account session from Db. RedisAccountSessionKey accountKey = { .routerId = self->info.routerId, .mapId = SOCKET_SESSION_UNDEFINED_MAP, .accountId = clientPacket->accountId }; if (!(redisGetAccountSession(self->redis, &accountKey, tmpAccountSession))) { error("Cannot retrieve the account session."); goto cleanup; } // Check the client packet here (authentication) // TODO improve it if (strncmp(tmpAccountSession->accountName, clientPacket->accountName, sizeof(tmpAccountSession->accountName)) != 0) { error("Wrong account authentication. (clientPacket account = <%s>, Session account = <%s>", clientPacket->accountName, tmpAccountSession->accountName); goto cleanup; } // === Authentication OK ! === // Get list of Commanders for this AccountId size_t commandersCount; if (!(mySqlLoadAccountCommanders(self->sqlConn, tmpAccountSession, clientPacket->accountId, &commandersCount))) { error("Cannot load commanders."); goto cleanup; } // FIXME : Determine how to get the correct commander in the commander array tmpCommanderSession->currentCommander = commanderDup(tmpAccountSession->commanders[0]); // Get the Game Session that the Barrack Server moved // TODO : Should be replaced by Db RedisGameSessionKey gameKey = accountKey; if (!(redisGetGameSession(self->redis, &gameKey, &tmpGameSession))) { error("Cannot retrieve the game session."); goto cleanup; } // Update the Socket Session socketSessionInit(&session->socket, clientPacket->accountId, self->info.routerId, tmpCommanderSession->currentCommander->mapId, session->socket.sessionKey, true ); // Move the game Session to the current mapId RedisGameSessionKey fromKey = { .routerId = session->socket.routerId, .mapId = -1, .accountId = session->socket.accountId }; RedisGameSessionKey toKey = { .routerId = session->socket.routerId, .mapId = session->socket.mapId, .accountId = session->socket.accountId }; // TODO : Should be replaced by Db if (!(redisMoveGameSession(self->redis, &fromKey, &toKey))) { error("Cannot move the game session to the current mapId."); goto cleanup; } // FIXME // Set a default position tmpCommanderSession->currentCommander->pos = PositionXYZ_decl(76.0f, 1.0f, 57.0f); // Update the session session->game = tmpGameSession; // Build a reply packet zoneBuilderConnectOk( 0, // GameMode 0, // accountPrivileges session->game.commanderSession.currentCommander, replyMsg ); status = PACKET_HANDLER_UPDATE_SESSION; cleanup: return status; } static PacketHandlerState zoneHandlerJump( Worker *self, Session *session, uint8_t *packet, size_t packetSize, zmsg_t *replyMsg) { #pragma pack(push, 1) struct { uint8_t unk1; } *clientPacket = (void *) packet; #pragma pack(pop) CHECK_CLIENT_PACKET_SIZE(*clientPacket, packetSize, CZ_JUMP); // Notify the players around GameEventJump event = { .updatePosEvent = { .mapId = session->socket.mapId, .commander = *session->game.commanderSession.currentCommander }, .height = COMMANDER_HEIGHT_JUMP }; workerDispatchEvent(self, session->socket.sessionKey, EVENT_TYPE_JUMP, &event, sizeof(event)); return PACKET_HANDLER_OK; } static PacketHandlerState zoneHandlerOnAir( Worker *self, Session *session, uint8_t *packet, size_t packetSize, zmsg_t *replyMsg) { warning("CZ_ON_AIR not implemented yet."); return PACKET_HANDLER_OK; } static PacketHandlerState zoneHandlerOnGround( Worker *self, Session *session, uint8_t *packet, size_t packetSize, zmsg_t *replyMsg) { warning("CZ_ON_GROUND not implemented yet."); return PACKET_HANDLER_OK; }