bool redisGetSession (Redis *self, RedisSessionKey *key, Session *session) { GameSession *gameSession = &session->game; SocketSession *socketSession = &session->socket; AccountSession *accountSession = &gameSession->accountSession; RedisSocketSessionKey *socketKey = &key->socketKey; // Search for the Socket Session if (!redisGetSocketSession(self, socketKey, socketSession)) { error("Cannot get Socket Session."); return false; } if (!socketSession->authenticated) { // This is the first time the client connect. // Initialize an empty game session CommanderInfo commanderInfo; commanderInfoInit (&commanderInfo); gameSessionInit (gameSession, &commanderInfo); dbg("Welcome, SOCKET_%s ! A new session has been initialized for you.", socketKey->sessionKey); } else { // Get account session RedisAccountSessionKey accountKey = { .accountId = socketSession->accountId }; if (!redisGetAccountSession(self, &accountKey, accountSession)) { error("Cannot get Account Session."); return false; } // The client already exist in the game, get Game Session RedisGameSessionKey gameKey = { .routerId = socketSession->routerId, .mapId = socketSession->mapId, .accountId = socketSession->accountId }; if (!redisGetGameSession(self, &gameKey, gameSession)) { error("Cannot get Game Session."); return false; } // dbg("Welcome back, SOCKET_%s !", sessionKey); } return true; } bool redisUpdateSession (Redis *self, Session *session) { RedisSocketSessionKey socketKey = { .routerId = session->socket.routerId, .sessionKey = session->socket.sessionKey }; if (!redisUpdateSocketSession (self, &socketKey, &session->socket)) { error("Cannot update the socket session."); return false; } RedisGameSessionKey gameKey = { .routerId = session->socket.routerId, .mapId = session->socket.mapId, .accountId = session->socket.accountId }; if (!(redisUpdateGameSession(self, &gameKey, session->socket.sessionKey, &session->game))) { error("Cannot update the game session"); return false; } if (session->socket.accountId > 0) { RedisAccountSessionKey accountKey = { .accountId = session->socket.accountId }; if (!(redisUpdateAccountSession(self, &accountKey, &session->game.accountSession))) { error("Cannot update the account session"); return false; } } return true; } bool redisFlushSession (Redis *self, RedisSessionKey *key) { RedisSocketSessionKey *socketKey = &key->socketKey; // Retrieve the entire SocketSession SocketSession socketSession; if (!(redisGetSocketSession(self, socketKey, &socketSession))) { error("Cannot get the SocketSession for %s.", socketKey->sessionKey); return false; } // Flush Account Session RedisAccountSessionKey accountKey = { .accountId = socketSession.accountId }; if (!(redisFlushAccountSession (self, &accountKey))) { error("Cannot flush the Account Session associated with the Socket Session."); return false; } // Flush the game session RedisGameSessionKey gameKey = { .routerId = socketSession.routerId, .mapId = socketSession.mapId, .accountId = socketSession.accountId }; if (!(redisFlushGameSession (self, &gameKey))) { error("Cannot flush the Game Session associated with the Socket Session."); return false; } // Flush the socket session if (!(redisFlushSocketSession (self, socketKey))) { error("Cannot flush the Game Session associated with the Socket Session."); return false; } return true; }
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; }
bool redisGetGameSessionBySocketId (Redis *self, uint16_t routerId, uint8_t *sessionKey, GameSession *gameSession) { SocketSession socketSession; RedisSocketSessionKey socketKey = { .routerId = routerId, .sessionKey = sessionKey }; if (!(redisGetSocketSession(self, &socketKey, &socketSession))) { error("Cannot get the socket session of the client."); return false; } RedisGameSessionKey gameKey = { .routerId = socketSession.routerId, .mapId = socketSession.mapId, .accountId = socketSession.accountId }; if (!(redisGetGameSession(self, &gameKey, gameSession))) { error("Cannot get the game session of the client."); return false; } return true; } bool redisUpdateGameSession(Redis *self, RedisGameSessionKey *key, uint8_t *socketId, GameSession *gameSession) { bool result = true; redisReply *reply = NULL; CommanderInfo *cInfo = &gameSession->commanderSession.currentCommander.info; CommanderAppearance *appearance = &cInfo->appearance; CommanderEquipment *equipment = &appearance->equipment; reply = redisCommandDbg(self, "HMSET zone%x:map%x:acc%llx" // Account " " REDIS_GAME_SESSION_account_sessionKey_str " %s" " " REDIS_GAME_SESSION_account_login_str " %s" " " REDIS_GAME_SESSION_account_privilege_str " %x" // Barrack " " REDIS_GAME_SESSION_barrack_charactersCreatedCount_str " %x" // Commander " " REDIS_GAME_SESSION_commander_mapId_str " %x" " " REDIS_GAME_SESSION_commander_commanderName_str " %s" " " REDIS_GAME_SESSION_commander_familyName_str " %s" " " REDIS_GAME_SESSION_commander_accountId_str " %llx" " " REDIS_GAME_SESSION_commander_classId_str " %x" " " REDIS_GAME_SESSION_commander_unk4_str " %x" " " REDIS_GAME_SESSION_commander_jobId_str " %x" " " REDIS_GAME_SESSION_commander_gender_str " %x" " " REDIS_GAME_SESSION_commander_unk5_str " %x" " " REDIS_GAME_SESSION_commander_level_str " %x" " " REDIS_GAME_SESSION_commander_hairId_str " %x" " " REDIS_GAME_SESSION_commander_pose_str " %x" // Equipment " " REDIS_GAME_SESSION_equipment_head_top_str " %x" " " REDIS_GAME_SESSION_equipment_head_middle_str " %x" " " REDIS_GAME_SESSION_equipment_itemUnk1_str " %x" " " REDIS_GAME_SESSION_equipment_body_armor_str " %x" " " REDIS_GAME_SESSION_equipment_gloves_str " %x" " " REDIS_GAME_SESSION_equipment_boots_str " %x" " " REDIS_GAME_SESSION_equipment_itemUnk2_str " %x" " " REDIS_GAME_SESSION_equipment_bracelet_str " %x" " " REDIS_GAME_SESSION_equipment_weapon_str " %x" " " REDIS_GAME_SESSION_equipment_shield_str " %x" " " REDIS_GAME_SESSION_equipment_costume_str " %x" " " REDIS_GAME_SESSION_equipment_itemUnk3_str " %x" " " REDIS_GAME_SESSION_equipment_itemUnk4_str " %x" " " REDIS_GAME_SESSION_equipment_itemUnk5_str " %x" " " REDIS_GAME_SESSION_equipment_leg_armor_str " %x" " " REDIS_GAME_SESSION_equipment_itemUnk6_str " %x" " " REDIS_GAME_SESSION_equipment_itemUnk7_str " %x" " " REDIS_GAME_SESSION_equipment_ring_left_str " %x" " " REDIS_GAME_SESSION_equipment_ring_right_str " %x" " " REDIS_GAME_SESSION_equipment_necklace_str " %x" // CommanderInfo Info " " REDIS_GAME_SESSION_info_posX_str " %f" " " REDIS_GAME_SESSION_info_posY_str " %f" " " REDIS_GAME_SESSION_info_posZ_str " %f" " " REDIS_GAME_SESSION_info_currentXP_str " %x" " " REDIS_GAME_SESSION_info_maxXP_str " %x" " " REDIS_GAME_SESSION_info_pcId_str " %x" " " REDIS_GAME_SESSION_info_socialInfoId_str " %llx" " " REDIS_GAME_SESSION_info_commanderId_str " %llx" " " REDIS_GAME_SESSION_info_currentHP_str " %x" " " REDIS_GAME_SESSION_info_maxHP_str " %x" " " REDIS_GAME_SESSION_info_currentSP_str " %x" " " REDIS_GAME_SESSION_info_maxSP_str " %x" " " REDIS_GAME_SESSION_info_currentStamina_str " %x" " " REDIS_GAME_SESSION_info_maxStamina_str " %x" " " REDIS_GAME_SESSION_info_unk6_str " %x" " " REDIS_GAME_SESSION_info_unk7_str " %x" , key->routerId, key->mapId, key->accountId, // Account socketId, gameSession->accountSession.login, gameSession->accountSession.privilege, // Barrack gameSession->barrackSession.charactersCreatedCount, // Commander gameSession->commanderSession.mapId, CHECK_REDIS_EMPTY_STRING(appearance->commanderName), CHECK_REDIS_EMPTY_STRING(appearance->familyName), key->accountId, appearance->classId, appearance->unk4, appearance->jobId, appearance->gender, appearance->unk5, appearance->level, appearance->hairId, appearance->pose, // Equipment equipment->head_top, equipment->head_middle, equipment->itemUnk1, equipment->body_armor, equipment->gloves, equipment->boots, equipment->itemUnk2, equipment->bracelet, equipment->weapon, equipment->shield, equipment->costume, equipment->itemUnk3, equipment->itemUnk4, equipment->itemUnk5, equipment->leg_armor, equipment->itemUnk6, equipment->itemUnk7, equipment->ring_left, equipment->ring_right, equipment->necklace, // CommanderInfo info cInfo->pos.x, cInfo->pos.y, cInfo->pos.z, cInfo->currentXP, cInfo->maxXP, cInfo->pcId, cInfo->socialInfoId, cInfo->commanderId, cInfo->currentHP, cInfo->maxHP, cInfo->currentSP, cInfo->maxSP, cInfo->currentStamina, cInfo->maxStamina, cInfo->unk6, cInfo->unk7 ); if (!reply) { error("Redis error encountered : The request is invalid."); result = false; goto cleanup; } switch (reply->type) { case REDIS_REPLY_ERROR: error("Redis error encountered : %s", reply->str); result = false; goto cleanup; break; case REDIS_REPLY_STATUS: // info("Redis status : %s", reply->str); break; default : error("Unexpected Redis status. (%d)", reply->type); result = false; goto cleanup; break; } cleanup: if (reply) { redisReplyDestroy(&reply); } return result; }
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; }
bool redisGetGameSessionBySocketId(Redis *self, RouterId_t routerId, uint8_t *sessionKey, GameSession *gameSession) { SocketSession socketSession; RedisSocketSessionKey socketKey = { .routerId = routerId, .sessionKey = sessionKey }; if (!(redisGetSocketSession(self, &socketKey, &socketSession))) { error("Cannot get the socket session of the client."); return false; } RedisGameSessionKey gameKey = { .routerId = socketSession.routerId, .mapId = socketSession.mapId, .accountId = socketSession.accountId }; if (!(redisGetGameSession(self, &gameKey, gameSession))) { error("Cannot get the game session of the client."); return false; } return true; } bool redisUpdateGameSession(Redis *self, RedisGameSessionKey *key, uint8_t *socketId, GameSession *gameSession) { bool result = true; size_t repliesCount = 3; redisReply *replies[repliesCount]; Commander *commander = NULL; // Initialize replies void *noReply = (void *) -1; for (int i = 0; i < repliesCount; i++) { replies[i] = noReply; } commander = gameSession->commanderSession.currentCommander; // Account replies[0] = redisCommandDbg(self, "HMSET zone%x:map%x:acc%llx" " " REDIS_SESSION_account_sessionKey_str " %s" " " REDIS_SESSION_account_accountName_str " %s" " " REDIS_SESSION_account_privilege_str " %x" " " REDIS_SESSION_account_commandersCountMax_str " %x", key->routerId, key->mapId, key->accountId, socketId, gameSession->accountSession.accountName, gameSession->accountSession.privilege, gameSession->accountSession.commandersCountMax ); // Commander if (commander) { replies[1] = redisCommandDbg(self, "HMSET zone%x:map%x:acc%llx" " " REDIS_SESSION_commander_mapId_str " %x" " " REDIS_SESSION_commander_commanderName_str " %s" " " REDIS_SESSION_commander_familyName_str " %s" " " REDIS_SESSION_commander_accountId_str " %llx" " " REDIS_SESSION_commander_classId_str " %x" " " REDIS_SESSION_commander_jobId_str " %x" " " REDIS_SESSION_commander_gender_str " %x" " " REDIS_SESSION_commander_level_str " %x" " " REDIS_SESSION_commander_hairId_str " %x" " " REDIS_SESSION_commander_pose_str " %x" " " REDIS_SESSION_commander_posX_str " %f" " " REDIS_SESSION_commander_posY_str " %f" " " REDIS_SESSION_commander_posZ_str " %f" " " REDIS_SESSION_commander_currentXP_str " %x" " " REDIS_SESSION_commander_maxXP_str " %x" " " REDIS_SESSION_commander_pcId_str " %x" " " REDIS_SESSION_commander_socialInfoId_str " %llx" " " REDIS_SESSION_commander_commanderId_str " %llx" " " REDIS_SESSION_commander_currentHP_str " %x" " " REDIS_SESSION_commander_maxHP_str " %x" " " REDIS_SESSION_commander_currentSP_str " %x" " " REDIS_SESSION_commander_maxSP_str " %x" " " REDIS_SESSION_commander_currentStamina_str " %x" " " REDIS_SESSION_commander_maxStamina_str " %x", key->routerId, key->mapId, key->accountId, commander->mapId, CHECK_REDIS_EMPTY_STRING(commander->commanderName), CHECK_REDIS_EMPTY_STRING(commander->familyName), key->accountId, commander->classId, commander->jobId, commander->gender, commander->level, commander->hairId, commander->pose, commander->pos.x, commander->pos.y, commander->pos.z, commander->currentXP, commander->maxXP, commander->pcId, commander->socialInfoId, commander->commanderId, commander->currentHP, commander->maxHP, commander->currentSP, commander->maxSP, commander->currentStamina, commander->maxStamina ); replies[2] = redisCommandDbg(self, "HMSET zone%x:map%x:acc%llx" " " REDIS_SESSION_EQSLOT_HAT_str " %x" " " REDIS_SESSION_EQSLOT_HAT_L_str " %x" " " REDIS_SESSION_EQSLOT_UNKOWN1_str " %x" " " REDIS_SESSION_EQSLOT_BODY_ARMOR_str " %x" " " REDIS_SESSION_EQSLOT_GLOVES_str " %x" " " REDIS_SESSION_EQSLOT_BOOTS_str " %x" " " REDIS_SESSION_EQSLOT_HELMET_str " %x" " " REDIS_SESSION_EQSLOT_BRACELET_str " %x" " " REDIS_SESSION_EQSLOT_WEAPON_str " %x" " " REDIS_SESSION_EQSLOT_SHIELD_str " %x" " " REDIS_SESSION_EQSLOT_COSTUME_str " %x" " " REDIS_SESSION_EQSLOT_UNKOWN3_str " %x" " " REDIS_SESSION_EQSLOT_UNKOWN4_str " %x" " " REDIS_SESSION_EQSLOT_UNKOWN5_str " %x" " " REDIS_SESSION_EQSLOT_LEG_ARMOR_str " %x" " " REDIS_SESSION_EQSLOT_UNKOWN6_str " %x" " " REDIS_SESSION_EQSLOT_UNKOWN7_str " %x" " " REDIS_SESSION_EQSLOT_RING_LEFT_str " %x" " " REDIS_SESSION_EQSLOT_RING_RIGHT_str " %x" " " REDIS_SESSION_EQSLOT_NECKLACE_str " %x" , key->routerId, key->mapId, key->accountId, // Equipment itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_HAT]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_HAT_L]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_UNKOWN1]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_BODY_ARMOR]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_GLOVES]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_BOOTS]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_HELMET]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_BRACELET]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_WEAPON]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_SHIELD]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_COSTUME]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_UNKOWN3]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_UNKOWN4]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_UNKOWN5]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_LEG_ARMOR]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_UNKOWN6]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_UNKOWN7]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_RING_LEFT]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_RING_RIGHT]), itemGetId((Item *) commander->inventory.equippedItems[EQSLOT_NECKLACE]) ); } for (int i = 0; i < repliesCount; i++) { redisReply *reply = replies[i]; if (reply != noReply) { if (!reply) { error("Redis error encountered : The request is invalid."); result = false; goto cleanup; } switch (reply->type) { case REDIS_REPLY_ERROR: error("Redis error encountered : %s", reply->str); result = false; goto cleanup; break; case REDIS_REPLY_STATUS: // Ok break; default : error("Unexpected Redis status. (%d)", reply->type); result = false; goto cleanup; break; } } } cleanup: for (int i = 0; i < repliesCount; i++) { redisReply *reply = replies[i]; if (reply && reply != noReply) { redisReplyDestroy(&reply); } } return result; }