Exemple #1
0
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;
}
Exemple #2
0
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);
    }
}
Exemple #3
0
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);
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}