Example #1
0
void ItemHandler::handleMessage(MessageIn &msg)
{
    switch (msg.getId())
    {
    case GPMSG_ITEM_APPEAR:
    case GPMSG_ITEMS:
    {
        while (msg.getUnreadLength())
        {
            int itemId = msg.readInt16();
            int x = msg.readInt16();
            int y = msg.readInt16();
            int id = (x << 16) | y; // dummy id

            if (itemId)
            {
                floorItemManager->create(id, itemId, x / 32, y / 32, engine->getCurrentMap());
            }
            else if (FloorItem *item = floorItemManager->findById(id))
            {
                floorItemManager->destroy(item);
            }
        }
    }
    break;
    }
}
Example #2
0
void ChatHandler::handleEnterChannelResponse(MessageIn &msg)
{
    if(msg.readInt8() == ERRMSG_OK)
    {
        short channelId = msg.readInt16();
        std::string channelName = msg.readString();
        std::string announcement = msg.readString();
        Channel *channel = new Channel(channelId, channelName, announcement);
        channelManager->addChannel(channel);
        ChatTab *tab = channel->getTab();
        tab->chatLog(strprintf(_("Topic: %s"), announcement.c_str()), BY_CHANNEL);

        std::string user;
        std::string userModes;
        tab->chatLog(_("Players in this channel:"), BY_CHANNEL);
        while(msg.getUnreadLength())
        {
            user = msg.readString();
            if (user == "")
                return;
            userModes = msg.readString();
            if (userModes.find('o') != std::string::npos)
            {
                user = "******" + user;
            }
            tab->chatLog(user, BY_CHANNEL);
        }

    }
    else
    {
        localChatTab->chatLog(_("Error joining channel."), BY_SERVER);
    }
}
Example #3
0
void InventoryHandler::handleMessage(MessageIn &msg)
{
    switch (msg.getId())
    {
        case GPMSG_INVENTORY_FULL:
            player_node->clearInventory();
            // no break!

        case GPMSG_INVENTORY:
            while (msg.getUnreadLength())
            {
                int slot = msg.readInt8();
                if (slot == 255)
                {
                    player_node->setMoney(msg.readInt32());
                    continue;
                }

                int id = msg.readInt16();
                if (slot < EQUIPMENT_SIZE)
                {
                    player_node->mEquipment->setEquipment(slot, id);
                }
                else if (slot >= 32 && slot < 32 + INVENTORY_SIZE)
                {
                    int amount = id ? msg.readInt8() : 0;
                    player_node->setInvItem(slot - 32, id, amount);
                }
            };
            break;
    }
}
Example #4
0
void ItemHandler::handleMessage(MessageIn &msg)
{
    switch (msg.getId())
    {
        case GPMSG_ITEM_APPEAR:
        case GPMSG_ITEMS:
        {
            while (msg.getUnreadLength())
            {
                int itemId = msg.readInt16();
                int x = msg.readInt16();
                int y = msg.readInt16();
                int id = (x << 16) | y; // dummy id

                if (itemId)
                {
                    actorSpriteManager->createItem(id, itemId, Vector(x, y));
                }
                else if (FloorItem *item = actorSpriteManager->findItem(id))
                {
                    actorSpriteManager->destroy(item);
                }
            }
        } break;
    }
}
Example #5
0
void EffectHandler::handleShake(MessageIn &msg)
{
    int16_t intensityX = 0;
    int16_t intensityY = 0;
    float decay;
    int duration;

    switch (msg.getUnreadLength())
    {
    case 4:
        intensityX =  msg.readInt16();
        intensityY =  msg.readInt16();
        viewport->shakeScreen(intensityX, intensityY);
        break;
    case 6:
        intensityX =  msg.readInt16();
        intensityY =  msg.readInt16();
        decay =  msg.readInt16() / 10000.0f;
        viewport->shakeScreen(intensityX, intensityY, decay);
        break;
    case 8:
        intensityX =  msg.readInt16();
        intensityY =  msg.readInt16();
        decay =  msg.readInt16() / 10000.0f;
        duration =  msg.readInt16();
        viewport->shakeScreen(intensityX, intensityY, decay, duration);
        break;
    default:
        logger->log("Warning: Received GPMSG_SHAKE message with unexpected length of %d bytes", msg.getUnreadLength());
    }
}
Example #6
0
void LoginHandler::readUpdateHost(MessageIn &msg)
{
    // Set the update host when included in the message
    if (msg.getUnreadLength() > 0)
    {
        mLoginData->updateHost = msg.readString();
    }
}
void BuySellHandler::handleMessage(MessageIn &msg)
{
    Being *being = beingManager->findBeing(msg.readInt16());
    if (!being || being->getType() != Being::NPC)
    {
        return;
    }

    current_npc = being->getId();

    switch (msg.getId())
    {
        case GPMSG_NPC_BUY:
            buyDialog->reset();
            buyDialog->setMoney(player_node->getMoney());
            buyDialog->setVisible(true);

            while (msg.getUnreadLength())
            {
                int itemId = msg.readInt16();
                int amount = msg.readInt16();
                int value = msg.readInt16();
                buyDialog->addItem(itemId, amount, value);
            }
            break;

        case GPMSG_NPC_SELL:
            sellDialog->setMoney(player_node->getMoney());
            sellDialog->reset();
            sellDialog->setVisible(true);

            while (msg.getUnreadLength())
            {
                int itemId = msg.readInt16();
                int amount = msg.readInt16();
                int value = msg.readInt16();
                sellDialog->addItem(new Item(itemId, amount, false), value);
            }
            break;
    }
}
Example #8
0
void GameServerHandler::syncDatabase(MessageIn &msg)
{
    // It is safe to perform the following updates in a transaction
    dal::PerformTransaction transaction(storage->database());

    while (msg.getUnreadLength() > 0)
    {
        int msgType = msg.readInt8();
        switch (msgType)
        {
            case SYNC_CHARACTER_POINTS:
            {
                LOG_DEBUG("received SYNC_CHARACTER_POINTS");
                int charId = msg.readInt32();
                int charPoints = msg.readInt32();
                int corrPoints = msg.readInt32();
                storage->updateCharacterPoints(charId, charPoints, corrPoints);
            } break;

            case SYNC_CHARACTER_ATTRIBUTE:
            {
                LOG_DEBUG("received SYNC_CHARACTER_ATTRIBUTE");
                int    charId = msg.readInt32();
                int    attrId = msg.readInt32();
                double base   = msg.readDouble();
                double mod    = msg.readDouble();
                storage->updateAttribute(charId, attrId, base, mod);
            } break;

            case SYNC_CHARACTER_SKILL:
            {
                LOG_DEBUG("received SYNC_CHARACTER_SKILL");
                int charId = msg.readInt32();
                int skillId = msg.readInt8();
                int skillValue = msg.readInt32();
                storage->updateExperience(charId, skillId, skillValue);
            } break;

            case SYNC_ONLINE_STATUS:
            {
                LOG_DEBUG("received SYNC_ONLINE_STATUS");
                int charId = msg.readInt32();
                bool online = (msg.readInt8() == 1);
                storage->setOnlineStatus(charId, online);
            }
        }
    }

    transaction.commit();
}
Example #9
0
void ChatHandler::handleWhoResponse(MessageIn &msg)
{
    std::string userNick;

    while(msg.getUnreadLength())
    {
        userNick = msg.readString();
        if (userNick == "")
        {
            break;
        }
        localChatTab->chatLog(userNick, BY_SERVER);
    }
}
Example #10
0
void ChatHandler::handleListChannelsResponse(MessageIn &msg)
{
    localChatTab->chatLog(_("Listing channels."), BY_SERVER);
    while(msg.getUnreadLength())
    {
        std::string channelName = msg.readString();
        if (channelName == "")
            return;
        std::ostringstream numUsers;
        numUsers << msg.readInt16();
        channelName += " - ";
        channelName += numUsers.str();
        localChatTab->chatLog(channelName, BY_SERVER);
    }
    localChatTab->chatLog(_("End of channel list."), BY_SERVER);
}
Example #11
0
void AccountConnection::sendPost(Character *c, MessageIn &msg)
{
    // send message to account server with id of sending player,
    // the id of receiving player, the letter receiver and contents, and attachments
    LOG_DEBUG("Sending GCMSG_STORE_POST.");
    MessageOut out(GCMSG_STORE_POST);
    out.writeInt32(c->getDatabaseID());
    out.writeString(msg.readString()); // name of receiver
    out.writeString(msg.readString()); // content of letter
    while (msg.getUnreadLength()) // attachments
    {
        // write the item id and amount for each attachment
        out.writeInt32(msg.readInt16());
        out.writeInt32(msg.readInt16());
    }
    send(out);
}
Example #12
0
void ChatHandler::handleListChannelUsersResponse(MessageIn &msg)
{
    std::string channelName = msg.readString();
    std::string userNick;
    std::string userModes;
    Channel *channel = channelManager->findByName(channelName);
    channel->getTab()->chatLog(_("Players in this channel:"), BY_CHANNEL);
    while(msg.getUnreadLength())
    {
        userNick = msg.readString();
        if (userNick == "")
        {
            break;
        }
        userModes = msg.readString();
        if (userModes.find('o') != std::string::npos)
        {
            userNick = "@" + userNick;
        }
        localChatTab->chatLog(userNick, BY_CHANNEL, channel);
    }
}
Example #13
0
void CharacterComponent::deserialize(Entity &entity, MessageIn &msg)
{
    auto *beingComponent = entity.getComponent<BeingComponent>();

    // general character properties
    setAccountLevel(msg.readInt8());
    beingComponent->setGender(ManaServ::getGender(msg.readInt8()));
    setHairStyle(msg.readInt8());
    setHairColor(msg.readInt8());
    setAttributePoints(msg.readInt16());
    setCorrectionPoints(msg.readInt16());

    // character attributes
    unsigned attrSize = msg.readInt16();
    for (unsigned i = 0; i < attrSize; ++i)
    {
        unsigned id = msg.readInt16();
        double base = msg.readDouble();
        auto *attributeInfo = attributeManager->getAttributeInfo(id);
        if (attributeInfo)
            beingComponent->setAttribute(entity, attributeInfo, base);
    }

    // status effects currently affecting the character
    int statusSize = msg.readInt16();

    for (int i = 0; i < statusSize; i++)
    {
        int status = msg.readInt16();
        int time = msg.readInt16();
        beingComponent->applyStatusEffect(status, time);
    }

    // location
    auto *map = MapManager::getMap(msg.readInt16());
    entity.setMap(map);

    Point temporaryPoint;
    temporaryPoint.x = msg.readInt16();
    temporaryPoint.y = msg.readInt16();
    entity.getComponent<ActorComponent>()->setPosition(entity, temporaryPoint);

    // kill count
    int killSize = msg.readInt16();
    for (int i = 0; i < killSize; i++)
    {
        int monsterId = msg.readInt16();
        int kills = msg.readInt32();
        setKillCount(monsterId, kills);
    }

    // character abilities
    int abilitiesSize = msg.readInt16();
    for (int i = 0; i < abilitiesSize; i++)
    {
        const int id = msg.readInt32();
        entity.getComponent<AbilityComponent>()->giveAbility(id);
    }

    // questlog
    int questlogSize = msg.readInt16();
    for (int i = 0; i < questlogSize; ++i) {
        unsigned id = msg.readInt16();
        QuestState state = (QuestState) msg.readInt8();
        std::string title = msg.readString();
        std::string description = msg.readString();

        setQuestlog(id, state, title, description);
    }

    Possessions &poss = getPossessions();

    // Loads inventory - must be last because size isn't transmitted
    InventoryData inventoryData;
    EquipData equipmentData;
    while (msg.getUnreadLength())
    {
        InventoryItem i;
        i.slot          = msg.readInt16();
        i.itemId        = msg.readInt16();
        i.amount        = msg.readInt16();
        bool isEquipped = msg.readInt8() != 0;
        inventoryData.insert(std::make_pair(i.slot, i));
        if (isEquipped)
            equipmentData.insert(i.slot);
    }
    poss.setInventory(inventoryData);
    poss.setEquipment(equipmentData);
}
Example #14
0
void PlayerHandler::handleMessage(MessageIn &msg)
{
    switch (msg.getId())
    {
        case GPMSG_PLAYER_MAP_CHANGE:
            handleMapChangeMessage(msg);
            break;

        case GPMSG_PLAYER_SERVER_CHANGE:
        {   // TODO: Fix the servers to test this
            netToken = msg.readString(32);
            std::string address = msg.readString();
            int port = msg.readInt16();
            logger->log("Changing server to %s:%d", address.c_str(), port);

            gameServer.hostname = address;
            gameServer.port = port;

            gameServerConnection->disconnect();
            Client::setState(STATE_CHANGE_MAP);
            local_player->setMap(0);
        } break;

        case GPMSG_PLAYER_ATTRIBUTE_CHANGE:
        {
            while (msg.getUnreadLength())
            {
                int attrId = msg.readInt16();
                double base = msg.readInt32() / 256.0;
                double value = msg.readInt32() / 256.0;

                // Set the core player attribute the stat
                // depending on attribute link.
                int playerInfoId =
                                  Attributes::getPlayerInfoIdFromAttrId(attrId);
                if (playerInfoId > -1)
                {
                    PlayerInfo::setAttribute(playerInfoId, value);
                }
                else
                {
                    PlayerInfo::setStatBase(attrId, base);
                    PlayerInfo::setStatMod(attrId, value - base);
                }
            }
        } break;

        case GPMSG_PLAYER_EXP_CHANGE:
        {
            logger->log("EXP Update");
            while (msg.getUnreadLength())
            {
                int skill = msg.readInt16();
                int current = msg.readInt32();
                int next = msg.readInt32();
                int level = msg.readInt16();

                PlayerInfo::setStatExperience(skill, current, next);
                PlayerInfo::setStatBase(skill, level);
            }
        } break;

        case GPMSG_LEVELUP:
        {
            PlayerInfo::setAttribute(LEVEL, msg.readInt16());
            PlayerInfo::setAttribute(CHAR_POINTS, msg.readInt16());
            PlayerInfo::setAttribute(CORR_POINTS, msg.readInt16());
            Particle* effect = particleEngine->addEffect(
                                               paths.getStringValue("particles")
                                     + paths.getStringValue("levelUpEffectFile")
                                                         ,0, 0);
            local_player->controlParticle(effect);
        } break;


        case GPMSG_LEVEL_PROGRESS:
        {
            PlayerInfo::setAttribute(EXP, msg.readInt8());
        } break;


        case GPMSG_RAISE_ATTRIBUTE_RESPONSE:
        {
            int errCode = msg.readInt8();
            int attrNum = msg.readInt16();
            switch (errCode)
            {
                case ATTRIBMOD_OK:
                {
                    // feel(acknowledgment);
                } break;
                case ATTRIBMOD_INVALID_ATTRIBUTE:
                {
                    logger->log("Warning: Server denied increase of attribute %d (unknown attribute) ", attrNum);
                } break;
                case ATTRIBMOD_NO_POINTS_LEFT:
                {
                    // when the server says "you got no points" it
                    // has to be correct. The server is always right!
                    // undo attribute change and set points to 0
                    logger->log("Warning: Server denied increase of attribute %d (no points left) ", attrNum);
                    int attrValue = PlayerInfo::getStatBase(attrNum) - 1;
                    PlayerInfo::setAttribute(CHAR_POINTS, 0);
                    PlayerInfo::setStatBase(attrNum, attrValue);
                } break;
                case ATTRIBMOD_DENIED:
                {
                    // undo attribute change
                    logger->log("Warning: Server denied increase of attribute %d (reason unknown) ", attrNum);
                    int points = PlayerInfo::getAttribute(CHAR_POINTS) - 1;
                    PlayerInfo::setAttribute(CHAR_POINTS, points);

                    int attrValue = PlayerInfo::getStatBase(attrNum) - 1;
                    PlayerInfo::setStatBase(attrNum, attrValue);
                } break;
            }
        } break;

        case GPMSG_LOWER_ATTRIBUTE_RESPONSE:
        {
            int errCode = msg.readInt8();
            int attrNum = msg.readInt16();
            switch (errCode)
            {
                case ATTRIBMOD_OK:
                {
                    // feel(acknowledgment);
                } break;
                case ATTRIBMOD_INVALID_ATTRIBUTE:
                {
                    logger->log("Warning: Server denied reduction of attribute %d (unknown attribute) ", attrNum);
                } break;
                case ATTRIBMOD_NO_POINTS_LEFT:
                {
                    // when the server says "you got no points" it
                    // has to be correct. The server is always right!
                    // undo attribute change and set points to 0
                    logger->log("Warning: Server denied reduction of attribute %d (no points left) ", attrNum);
                    int attrValue = PlayerInfo::getStatBase(attrNum) + 1;
                    // TODO are these right?
                    PlayerInfo::setAttribute(CHAR_POINTS, 0);
                    PlayerInfo::setAttribute(CORR_POINTS, 0);
                    PlayerInfo::setStatBase(attrNum, attrValue);
                } break;
                case ATTRIBMOD_DENIED:
                {
                    // undo attribute change
                    logger->log("Warning: Server denied reduction of attribute %d (reason unknown) ", attrNum);
                    int charaPoints = PlayerInfo::getAttribute(CHAR_POINTS) - 1;
                    PlayerInfo::setAttribute(CHAR_POINTS, charaPoints);

                    int correctPoints = PlayerInfo::getAttribute(CORR_POINTS) + 1;
                    PlayerInfo::setAttribute(CORR_POINTS, correctPoints);

                    int attrValue = PlayerInfo::getStatBase(attrNum) + 1;
                    PlayerInfo::setStatBase(attrNum, attrValue);
                } break;
            }

        } break;

        case GPMSG_SPECIAL_STATUS :
        {
            while (msg.getUnreadLength())
            {
                // { B specialID, L current, L max, L recharge }
                int id = msg.readInt8();
                int current = msg.readInt32();
                int max = msg.readInt32();
                int recharge = msg.readInt32();
                PlayerInfo::setSpecialStatus(id, current, max, recharge);
            }
        } break;
        /*
        case SMSG_PLAYER_ARROW_MESSAGE:
            {
                Sint16 type = msg.readInt16();

                switch (type)
                {
                    case 0:
                        localChatTab->chatLog(_("Equip arrows first."),
                                             BY_SERVER);
                        break;
                    default:
                        logger->log("0x013b: Unhandled message %i", type);
                        break;
                }
            }
            break;
        */
    }
}
Example #15
0
void ServerHandler::processMessage(NetComputer *comp, MessageIn &msg)
{
    GameServer *server = static_cast<GameServer *>(comp);

    switch (msg.getId())
    {
        case GAMSG_REGISTER:
        {
            LOG_DEBUG("GAMSG_REGISTER");
            // TODO: check the credentials of the game server
            server->address = msg.readString();
            server->port = msg.readInt16();
            const std::string password = msg.readString();

            // checks the version of the remote item database with our local copy
            unsigned int dbversion = msg.readInt32();
            LOG_INFO("Game server uses itemsdatabase with version " << dbversion);

            LOG_DEBUG("AGMSG_REGISTER_RESPONSE");
            MessageOut outMsg(AGMSG_REGISTER_RESPONSE);
            if (dbversion == storage->getItemDatabaseVersion())
            {
                LOG_DEBUG("Item databases between account server and "
                    "gameserver are in sync");
                outMsg.writeInt16(DATA_VERSION_OK);
            }
            else
            {
                LOG_DEBUG("Item database of game server has a wrong version");
                outMsg.writeInt16(DATA_VERSION_OUTDATED);
            }
            if (password == Configuration::getValue("net_password", "changeMe"))
            {
                outMsg.writeInt16(PASSWORD_OK);

                // transmit global world state variables
                std::map<std::string, std::string> variables;
                variables = storage->getAllWorldStateVars(Storage::WorldMap);
                for (std::map<std::string, std::string>::iterator i = variables.begin();
                     i != variables.end();
                     i++)
                {
                    outMsg.writeString(i->first);
                    outMsg.writeString(i->second);
                }

                comp->send(outMsg);
            }
            else
            {
                LOG_INFO("The password given by " << server->address << ':' << server->port << " was bad.");
                outMsg.writeInt16(PASSWORD_BAD);
                comp->disconnect(outMsg);
                break;
            }

            LOG_INFO("Game server " << server->address << ':' << server->port
                     << " wants to register " << (msg.getUnreadLength() / 2)
                     << " maps.");

            while (msg.getUnreadLength())
            {
                int id = msg.readInt16();
                LOG_INFO("Registering map " << id << '.');
                if (GameServer *s = getGameServerFromMap(id))
                {
                    LOG_ERROR("Server Handler: map is already registered by "
                              << s->address << ':' << s->port << '.');
                }
                else
                {
                    MessageOut outMsg(AGMSG_ACTIVE_MAP);

                    // Map variables
                    outMsg.writeInt16(id);
                    std::map<std::string, std::string> variables;
                    variables = storage->getAllWorldStateVars(id);

                     // Map vars number
                    outMsg.writeInt16(variables.size());

                    for (std::map<std::string, std::string>::iterator i = variables.begin();
                         i != variables.end();
                         i++)
                    {
                        outMsg.writeString(i->first);
                        outMsg.writeString(i->second);
                    }

                    // Persistent Floor Items
                    std::list<FloorItem> items;
                    items = storage->getFloorItemsFromMap(id);

                    outMsg.writeInt16(items.size()); //number of floor items

                    // Send each map item: item_id, amount, pos_x, pos_y
                    for (std::list<FloorItem>::iterator i = items.begin();
                         i != items.end(); ++i)
                    {
                        outMsg.writeInt32(i->getItemId());
                        outMsg.writeInt16(i->getItemAmount());
                        outMsg.writeInt16(i->getPosX());
                        outMsg.writeInt16(i->getPosY());
                    }

                    comp->send(outMsg);
                    MapStatistics &m = server->maps[id];
                    m.nbEntities = 0;
                    m.nbMonsters = 0;
                }
            }
        } break;

        case GAMSG_PLAYER_DATA:
        {
            LOG_DEBUG("GAMSG_PLAYER_DATA");
            int id = msg.readInt32();
            if (Character *ptr = storage->getCharacter(id, NULL))
            {
                deserializeCharacterData(*ptr, msg);
                if (!storage->updateCharacter(ptr))
                {
                    LOG_ERROR("Failed to update character "
                              << id << '.');
                }
                delete ptr;
            }
            else
            {
                LOG_ERROR("Received data for non-existing character "
                          << id << '.');
            }
        } break;

        case GAMSG_PLAYER_SYNC:
        {
            LOG_DEBUG("GAMSG_PLAYER_SYNC");
            GameServerHandler::syncDatabase(msg);
        } break;

        case GAMSG_REDIRECT:
        {
            LOG_DEBUG("GAMSG_REDIRECT");
            int id = msg.readInt32();
            std::string magic_token(utils::getMagicToken());
            if (Character *ptr = storage->getCharacter(id, NULL))
            {
                int mapId = ptr->getMapId();
                if (GameServer *s = getGameServerFromMap(mapId))
                {
                    registerGameClient(s, magic_token, ptr);
                    MessageOut result(AGMSG_REDIRECT_RESPONSE);
                    result.writeInt32(id);
                    result.writeString(magic_token, MAGIC_TOKEN_LENGTH);
                    result.writeString(s->address);
                    result.writeInt16(s->port);
                    comp->send(result);
                }
                else
                {
                    LOG_ERROR("Server Change: No game server for map " <<
                              mapId << '.');
                }
                delete ptr;
            }
            else
            {
                LOG_ERROR("Received data for non-existing character "
                          << id << '.');
            }
        } break;

        case GAMSG_PLAYER_RECONNECT:
        {
            LOG_DEBUG("GAMSG_PLAYER_RECONNECT");
            int id = msg.readInt32();
            std::string magic_token = msg.readString(MAGIC_TOKEN_LENGTH);

            if (Character *ptr = storage->getCharacter(id, NULL))
            {
                int accountID = ptr->getAccountID();
                AccountClientHandler::prepareReconnect(magic_token, accountID);
                delete ptr;
            }
            else
            {
                LOG_ERROR("Received data for non-existing character "
                          << id << '.');
            }
        } break;

        case GAMSG_GET_VAR_CHR:
        {
            int id = msg.readInt32();
            std::string name = msg.readString();
            std::string value = storage->getQuestVar(id, name);
            MessageOut result(AGMSG_GET_VAR_CHR_RESPONSE);
            result.writeInt32(id);
            result.writeString(name);
            result.writeString(value);
            comp->send(result);
        } break;

        case GAMSG_SET_VAR_CHR:
        {
            int id = msg.readInt32();
            std::string name = msg.readString();
            std::string value = msg.readString();
            storage->setQuestVar(id, name, value);
        } break;

        case GAMSG_SET_VAR_WORLD:
        {
            std::string name = msg.readString();
            std::string value = msg.readString();
            // save the new value to the database
            storage->setWorldStateVar(name, value, Storage::WorldMap);
            // relay the new value to all gameservers
            for (ServerHandler::NetComputers::iterator i = clients.begin();
                i != clients.end();
                i++)
            {
                MessageOut varUpdateMessage(AGMSG_SET_VAR_WORLD);
                varUpdateMessage.writeString(name);
                varUpdateMessage.writeString(value);
                (*i)->send(varUpdateMessage);
            }
        } break;

        case GAMSG_SET_VAR_MAP:
        {
            int mapid = msg.readInt32();
            std::string name = msg.readString();
            std::string value = msg.readString();
            storage->setWorldStateVar(name, value, mapid);
        } break;

        case GAMSG_BAN_PLAYER:
        {
            int id = msg.readInt32();
            int duration = msg.readInt32();
            storage->banCharacter(id, duration);
        } break;

        case GAMSG_CHANGE_PLAYER_LEVEL:
        {
            int id = msg.readInt32();
            int level = msg.readInt16();
            storage->setPlayerLevel(id, level);
        } break;

        case GAMSG_CHANGE_ACCOUNT_LEVEL:
        {
            int id = msg.readInt32();
            int level = msg.readInt16();

            // get the character so we can get the account id
            Character *c = storage->getCharacter(id, NULL);
            if (c)
            {
                storage->setAccountLevel(c->getAccountID(), level);
            }
        } break;

        case GAMSG_STATISTICS:
        {
            while (msg.getUnreadLength())
            {
                int mapId = msg.readInt16();
                ServerStatistics::iterator i = server->maps.find(mapId);
                if (i == server->maps.end())
                {
                    LOG_ERROR("Server " << server->address << ':'
                              << server->port << " should not be sending stati"
                              "stics for map " << mapId << '.');
                    // Skip remaining data.
                    break;
                }
                MapStatistics &m = i->second;
                m.nbEntities = msg.readInt16();
                m.nbMonsters = msg.readInt16();
                int nb = msg.readInt16();
                m.players.resize(nb);
                for (int j = 0; j < nb; ++j)
                {
                    m.players[j] = msg.readInt32();
                }
            }
        } break;

        case GCMSG_REQUEST_POST:
        {
            // Retrieve the post for user
            LOG_DEBUG("GCMSG_REQUEST_POST");
            MessageOut result(CGMSG_POST_RESPONSE);

            // get the character id
            int characterId = msg.readInt32();

            // send the character id of sender
            result.writeInt32(characterId);

            // get the character based on the id
            Character *ptr = storage->getCharacter(characterId, NULL);
            if (!ptr)
            {
                // Invalid character
                LOG_ERROR("Error finding character id for post");
                break;
            }

            // get the post for that character
            Post *post = postalManager->getPost(ptr);

            // send the post if valid
            if (post)
            {
                for (unsigned int i = 0; i < post->getNumberOfLetters(); ++i)
                {
                    // get each letter, send the sender's name,
                    // the contents and any attachments
                    Letter *letter = post->getLetter(i);
                    result.writeString(letter->getSender()->getName());
                    result.writeString(letter->getContents());
                    std::vector<InventoryItem> items = letter->getAttachments();
                    for (unsigned int j = 0; j < items.size(); ++j)
                    {
                        result.writeInt16(items[j].itemId);
                        result.writeInt16(items[j].amount);
                    }
                }

                // clean up
                postalManager->clearPost(ptr);
            }

            comp->send(result);
        } break;

        case GCMSG_STORE_POST:
        {
            // Store the letter for the user
            LOG_DEBUG("GCMSG_STORE_POST");
            MessageOut result(CGMSG_STORE_POST_RESPONSE);

            // get the sender and receiver
            int senderId = msg.readInt32();
            std::string receiverName = msg.readString();

            // for sending it back
            result.writeInt32(senderId);

            // get their characters
            Character *sender = storage->getCharacter(senderId, NULL);
            Character *receiver = storage->getCharacter(receiverName);
            if (!sender || !receiver)
            {
                // Invalid character
                LOG_ERROR("Error finding character id for post");
                result.writeInt8(ERRMSG_INVALID_ARGUMENT);
                break;
            }

            // get the letter contents
            std::string contents = msg.readString();

            std::vector< std::pair<int, int> > items;
            while (msg.getUnreadLength())
            {
                items.push_back(std::pair<int, int>(msg.readInt16(), msg.readInt16()));
            }

            // save the letter
            LOG_DEBUG("Creating letter");
            Letter *letter = new Letter(0, sender, receiver);
            letter->addText(contents);
            for (unsigned int i = 0; i < items.size(); ++i)
            {
                InventoryItem item;
                item.itemId = items[i].first;
                item.amount = items[i].second;
                letter->addAttachment(item);
            }
            postalManager->addLetter(letter);

            result.writeInt8(ERRMSG_OK);
            comp->send(result);
        } break;

        case GAMSG_TRANSACTION:
        {
            LOG_DEBUG("TRANSACTION");
            int id = msg.readInt32();
            int action = msg.readInt32();
            std::string message = msg.readString();

            Transaction trans;
            trans.mCharacterId = id;
            trans.mAction = action;
            trans.mMessage = message;
            storage->addTransaction(trans);
        } break;

        case GCMSG_PARTY_INVITE:
            chatHandler->handlePartyInvite(msg);
            break;

        case GAMSG_CREATE_ITEM_ON_MAP:
        {
            int mapId = msg.readInt32();
            int itemId = msg.readInt32();
            int amount = msg.readInt16();
            int posX = msg.readInt16();
            int posY = msg.readInt16();

            LOG_DEBUG("Gameserver create item " << itemId
                << " on map " << mapId);

            storage->addFloorItem(mapId, itemId, amount, posX, posY);
        } break;

        case GAMSG_REMOVE_ITEM_ON_MAP:
        {
            int mapId = msg.readInt32();
            int itemId = msg.readInt32();
            int amount = msg.readInt16();
            int posX = msg.readInt16();
            int posY = msg.readInt16();

            LOG_DEBUG("Gameserver removed item " << itemId
                << " from map " << mapId);

            storage->removeFloorItem(mapId, itemId, amount, posX, posY);
        } break;

        case GAMSG_ANNOUNCE:
        {
            const std::string message = msg.readString();
            const int senderId = msg.readInt16();
            const std::string senderName = msg.readString();
            chatHandler->handleAnnounce(message, senderId, senderName);
        } break;

        default:
            LOG_WARN("ServerHandler::processMessage, Invalid message type: "
                     << msg.getId());
            MessageOut result(XXMSG_INVALID);
            comp->send(result);
            break;
    }
}
Example #16
0
void AccountConnection::processMessage(MessageIn &msg)
{
    LOG_DEBUG("Received message " << msg << " from account server");

    switch (msg.getId())
    {
        case AGMSG_REGISTER_RESPONSE:
        {
            if (msg.readInt16() != DATA_VERSION_OK)
            {
                LOG_ERROR("Item database is outdated! Please update to "
                          "prevent inconsistencies");
                stop();  // Disconnect gracefully from account server.
                // Stop gameserver to prevent inconsistencies.
                exit(EXIT_DB_EXCEPTION);
            }
            else
            {
                LOG_DEBUG("Local item database is "
                          "in sync with account server.");
            }
            if (msg.readInt16() != PASSWORD_OK)
            {
                LOG_ERROR("This game server sent a invalid password");
                stop();
                exit(EXIT_BAD_CONFIG_PARAMETER);
            }

            // read world state variables
            while (msg.getUnreadLength())
            {
                std::string key = msg.readString();
                std::string value = msg.readString();
                if (!key.empty() && !value.empty())
                {
                    GameState::setVariableFromDbserver(key, value);
                }
            }

        } break;

        case AGMSG_PLAYER_ENTER:
        {
            std::string token = msg.readString(MAGIC_TOKEN_LENGTH);
            Character *ptr = new Character(msg);
            gameHandler->addPendingCharacter(token, ptr);
        } break;

        case AGMSG_ACTIVE_MAP:
        {
            int mapId = msg.readInt16();
            if (MapManager::activateMap(mapId))
            {
                // Set map variables
                MapComposite *m = MapManager::getMap(mapId);
                int mapVarsNumber = msg.readInt16();
                for(int i = 0; i < mapVarsNumber; ++i)
                {
                    std::string key = msg.readString();
                    std::string value = msg.readString();
                    if (!key.empty() && !value.empty())
                        m->setVariableFromDbserver(key, value);
                }

                // Recreate potential persistent floor items
                LOG_DEBUG("Recreate persistant items on map " << mapId);
                int floorItemsNumber = msg.readInt16();

                for (int i = 0; i < floorItemsNumber; ++i)
                {
                    int itemId = msg.readInt32();
                    int amount = msg.readInt16();
                    int posX = msg.readInt16();
                    int posY = msg.readInt16();

                    if (ItemClass *ic = itemManager->getItem(itemId))
                    {
                        Item *item = new Item(ic, amount);
                        item->setMap(m);
                        Point dst(posX, posY);
                        item->setPosition(dst);

                        if (!GameState::insertOrDelete(item))
                        {
                            // The map is full.
                            LOG_WARN("Couldn't add floor item(s) " << itemId
                                << " into map " << mapId);
                            return;
                        }
                    }
                }
            }
        } break;

        case AGMSG_SET_VAR_WORLD:
        {
            std::string key = msg.readString();
            std::string value = msg.readString();
            GameState::setVariableFromDbserver(key, value);
            LOG_DEBUG("Global variable \"" << key << "\" has changed to \""
                      << value << "\"");
        } break;

        case AGMSG_REDIRECT_RESPONSE:
        {
            int id = msg.readInt32();
            std::string token = msg.readString(MAGIC_TOKEN_LENGTH);
            std::string address = msg.readString();
            int port = msg.readInt16();
            gameHandler->completeServerChange(id, token, address, port);
        } break;

        case AGMSG_GET_VAR_CHR_RESPONSE:
        {
            int id = msg.readInt32();
            std::string name = msg.readString();
            std::string value = msg.readString();
            recoveredQuestVar(id, name, value);
        } break;

        case CGMSG_CHANGED_PARTY:
        {
            // Character DB id
            int charid = msg.readInt32();
            // Party id, 0 for none
            int partyid = msg.readInt32();
            gameHandler->updateCharacter(charid, partyid);
        } break;

        case CGMSG_POST_RESPONSE:
        {
            // get the character
            Character *character = postMan->getCharacter(msg.readInt32());

            // check character is still valid
            if (!character)
            {
                break;
            }

            std::string sender = msg.readString();
            std::string letter = msg.readString();

            postMan->gotPost(character, sender, letter);

        } break;

        case CGMSG_STORE_POST_RESPONSE:
        {
            // get character
            Character *character = postMan->getCharacter(msg.readInt32());

            // check character is valid
            if (!character)
            {
                break;
            }

            // TODO: Get NPC to tell character if the sending of post
            // was successful or not

        } break;

        default:
            LOG_WARN("Invalid message type");
            break;
    }
}
Example #17
0
void GuildHandler::handleMessage(MessageIn &msg)
{
    switch (msg.getId())
    {
        case CPMSG_GUILD_CREATE_RESPONSE:
        {
            logger->log("Received CPMSG_GUILD_CREATE_RESPONSE");
            if(msg.readInt8() == ERRMSG_OK)
            {
                // TODO - Acknowledge guild was created
                localChatTab->chatLog(_("Guild created."));
                joinedGuild(msg);
            }
            else
            {
                localChatTab->chatLog(_("Error creating guild."));
            }
        } break;

        case CPMSG_GUILD_INVITE_RESPONSE:
        {
            logger->log("Received CPMSG_GUILD_INVITE_RESPONSE");
            if(msg.readInt8() == ERRMSG_OK)
            {
                // TODO - Acknowledge invite was sent
                localChatTab->chatLog(_("Invite sent."));
            }
        } break;

        case CPMSG_GUILD_ACCEPT_RESPONSE:
        {
            logger->log("Received CPMSG_GUILD_ACCEPT_RESPONSE");
            if(msg.readInt8() == ERRMSG_OK)
            {
                // TODO - Acknowledge accepted into guild
                joinedGuild(msg);
            }
        } break;

        case CPMSG_GUILD_GET_MEMBERS_RESPONSE:
        {
            logger->log("Received CPMSG_GUILD_GET_MEMBERS_RESPONSE");
            if(msg.readInt8() == ERRMSG_OK)
            {
                std::string guildMember;
                bool online;
                std::string guildName;
                Guild *guild;

                short guildId = msg.readInt16();
                guild = player_node->getGuild(guildId);

                if (!guild)
                    return;

                guildName = guild->getName();

                while(msg.getUnreadLength())
                {
                    guildMember = msg.readString();
                    online = msg.readInt8();
                    if(guildMember != "")
                    {
                        guild->addMember(guildMember);
                        guildWindow->setOnline(guildName, guildMember, online);
                    }
                }

                guildWindow->updateTab();
            }
        } break;

        case CPMSG_GUILD_UPDATE_LIST:
        {
            logger->log("Received CPMSG_GUILD_UPDATE_LIST");
            short guildId = msg.readInt16();
            std::string guildMember = msg.readString();
            char eventId = msg.readInt8();

            Guild *guild = player_node->getGuild(guildId);
            if (guild)
            {
                switch(eventId)
                {
                    case GUILD_EVENT_NEW_PLAYER:
                        guild->addMember(guildMember);
                        guildWindow->setOnline(guild->getName(), guildMember,
                                               true);
                        break;

                    case GUILD_EVENT_LEAVING_PLAYER:
                        guild->removeMember(guildMember);
                        break;

                    case GUILD_EVENT_ONLINE_PLAYER:
                        guildWindow->setOnline(guild->getName(), guildMember,
                                               true);
                        break;

                    case GUILD_EVENT_OFFLINE_PLAYER:
                        guildWindow->setOnline(guild->getName(), guildMember,
                                               false);
                        break;

                    default:
                        logger->log("Invalid guild event");
                }
            }
            guildWindow->updateTab();


        } break;

        case CPMSG_GUILD_INVITED:
        {
            logger->log("Received CPMSG_GUILD_INVITED");
            std::string inviterName = msg.readString();
            std::string guildName = msg.readString();

            // Open a dialog asking if the player accepts joining the guild.
            guildWindow->openAcceptDialog(inviterName, guildName);
        } break;

        case CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE:
        {
            logger->log("Received CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE");

            if (msg.readInt8() == ERRMSG_OK)
            {
                // promotion succeeded
                localChatTab->chatLog(_("Member was promoted successfully."));
            }
            else
            {
                // promotion failed
                localChatTab->chatLog(_("Failed to promote member."));
            }
        }

        case CPMSG_GUILD_REJOIN:
        {
            logger->log("Received CPMSG_GUILD_REJOIN");

            joinedGuild(msg);
        } break;

        case CPMSG_GUILD_QUIT_RESPONSE:
        {
            logger->log("Received CPMSG_GUILD_QUIT_RESPONSE");

            if (msg.readInt8() == ERRMSG_OK)
            {
                // Must remove tab first, as it wont find the guild
                // name after its removed from the player
                int guildId = msg.readInt16();
                Guild *guild = player_node->getGuild(guildId);
                if (guild)
                {
                    Channel *channel = channelManager->findByName(guild->getName());
                    channelManager->removeChannel(channel);
                    guildWindow->removeTab(guildId);
                    player_node->removeGuild(guildId);
                }
            }
        } break;
    }
}
Example #18
0
void AccountHandler::handleCharacterCreateMessage(AccountClient &client,
                                                  MessageIn &msg)
{
    std::string name = msg.readString();
    int hairStyle = msg.readInt8();
    int hairColor = msg.readInt8();
    int gender = msg.readInt8();

    // Avoid creation of character from old clients.
    int slot = -1;
    if (msg.getUnreadLength() > 7)
        slot = msg.readInt8();

    MessageOut reply(APMSG_CHAR_CREATE_RESPONSE);

    Account *acc = client.getAccount();
    if (!acc)
    {
        reply.writeInt8(ERRMSG_NO_LOGIN);
    }
    else if (!stringFilter->filterContent(name))
    {
        reply.writeInt8(ERRMSG_INVALID_ARGUMENT);
    }
    else if (stringFilter->findDoubleQuotes(name))
    {
        reply.writeInt8(ERRMSG_INVALID_ARGUMENT);
    }
    else if (hairStyle > mNumHairStyles)
    {
        reply.writeInt8(CREATE_INVALID_HAIRSTYLE);
    }
    else if (hairColor > mNumHairColors)
    {
        reply.writeInt8(CREATE_INVALID_HAIRCOLOR);
    }
    else if (gender > mNumGenders)
    {
        reply.writeInt8(CREATE_INVALID_GENDER);
    }
    else if ((name.length() < mMinNameLength) ||
             (name.length() > mMaxNameLength))
    {
        reply.writeInt8(ERRMSG_INVALID_ARGUMENT);
    }
    else
    {
        if (storage->doesCharacterNameExist(name))
        {
            reply.writeInt8(CREATE_EXISTS_NAME);
            client.send(reply);
            return;
        }

        // An account shouldn't have more
        // than <account_maxCharacters> characters.
        Characters &chars = acc->getCharacters();
        if (slot < 1 || slot > mMaxCharacters
            || !acc->isSlotEmpty((unsigned int) slot))
        {
            reply.writeInt8(CREATE_INVALID_SLOT);
            client.send(reply);
            return;
        }

        if ((int)chars.size() >= mMaxCharacters)
        {
            reply.writeInt8(CREATE_TOO_MUCH_CHARACTERS);
            client.send(reply);
            return;
        }

        // TODO: Add race, face and maybe special attributes.

        // Customization of character's attributes...
        std::vector<int> attributes = std::vector<int>(mModifiableAttributes.size(), 0);
        for (unsigned int i = 0; i < mModifiableAttributes.size(); ++i)
            attributes[i] = msg.readInt16();

        int totalAttributes = 0;
        for (unsigned int i = 0; i < mModifiableAttributes.size(); ++i)
        {
            // For good total attributes check.
            totalAttributes += attributes.at(i);

            // For checking if all stats are >= min and <= max.
            if (attributes.at(i) < mAttributeMinimum
                || attributes.at(i) > mAttributeMaximum)
            {
                reply.writeInt8(CREATE_ATTRIBUTES_OUT_OF_RANGE);
                client.send(reply);
                return;
            }
        }

        if (totalAttributes > mStartingPoints)
        {
            reply.writeInt8(CREATE_ATTRIBUTES_TOO_HIGH);
        }
        else if (totalAttributes < mStartingPoints)
        {
            reply.writeInt8(CREATE_ATTRIBUTES_TOO_LOW);
        }
        else
        {
            Character *newCharacter = new Character(name);

            // Set the initial attributes provided by the client
            for (unsigned int i = 0; i < mModifiableAttributes.size(); ++i)
            {
                newCharacter->mAttributes.insert(
                            std::make_pair(mModifiableAttributes.at(i), attributes[i]));
            }

            newCharacter->mAttributes.insert(mDefaultAttributes.begin(),
                                             mDefaultAttributes.end());
            newCharacter->setAccount(acc);
            newCharacter->setCharacterSlot(slot);
            newCharacter->setLevel(1);

            // Init GP value to avoid flawed ones.
            AttributeMap::iterator itr =
                newCharacter->mAttributes.find(ATTR_GP);
            if (itr != newCharacter->mAttributes.end())
            {
                itr->second.base = 0;
                itr->second.modified = 0;
            }

            newCharacter->setCharacterPoints(0);
            newCharacter->setCorrectionPoints(0);
            newCharacter->setGender(gender);
            newCharacter->setHairStyle(hairStyle);
            newCharacter->setHairColor(hairColor);
            newCharacter->setMapId(Configuration::getValue("char_startMap", 1));
            Point startingPos(Configuration::getValue("char_startX", 1024),
                              Configuration::getValue("char_startY", 1024));
            newCharacter->setPosition(startingPos);
            acc->addCharacter(newCharacter);

            LOG_INFO("Character " << name << " was created for "
                     << acc->getName() << "'s account.");

            storage->flush(acc); // flush changes

            // log transaction
            Transaction trans;
            trans.mCharacterId = newCharacter->getDatabaseID();
            trans.mAction = TRANS_CHAR_CREATE;
            trans.mMessage = acc->getName() + " created character ";
            trans.mMessage.append("called " + name);
            storage->addTransaction(trans);

            reply.writeInt8(ERRMSG_OK);
            client.send(reply);

            // Send new characters infos back to client
            sendCharacterData(client, *chars[slot]);
            return;
        }
    }

    client.send(reply);
}