summaryrefslogblamecommitdiff
path: root/src/net/ea/guildhandler.cpp
blob: ebbb93eaf09f979ede5eefbeffc11795236899b2 (plain) (tree)
1
2
3
4


                                                
                                                    


















                                                                         
                         
                          
 
                              
                             
 
                                    
                                     
 



                                
                          
                          
                              

                                  
 



                  

                             







                              
                      

 

                                                                         
 

 


                                                                              
 

 

                                                                     
 

 
                                                                        
 
                                         




                      
                                                              



                                 
                                                              



                                                          
                                                              



                                    
                                                                            



                               
                                                            



                  
                                                                        
 
                                                                



                                                             












                                                           



                                  
                                          
                                                        
                                                   
                                          
                                                          
                                                     
                                          

                                                                 
                                          
                                                            
                                              
                                          
                                                         
                                                 
                                          
                                                           
                                               
                                          

                                                             
                                          
                                                            
                                              
                                          
                                                          
                                                     

     
                                                                    


                     
                           

 
                                                                     
 
                                       

                   
                                        


                                   


                                                


     
                                                                    
 
                                       

                   
                                         







                                 

                      

                                   











                                                          
 
                                                                    




                                 
                                                                           



                               
                             
             
                                                                   
                                             









                                                            


                             


                    
                     
     

                                           
     

                                                              

 
                                                                     






                                 
                                       

                   
                                        


                                   

                                                                      



                                  
                                                                     
 
                                       

                   
                                        


                                   



                                     


     
                                                                         
 





                                     

 
                                                                         
 



                                                      

                
                                                                     




                           
                                                                
 
                                       
 

                                  

                    
                                                           

 
                                                                   
 

                                                      
 

                                                   

                                   
















                                                                           
     

                                    

 
                                                                
 

                                                          

                 

                                                        


     
                                                                
 
                                        
                                                     




                                                              
                                                                   
 
                                         





                  
                                                                    


                  
                                                                      


                  
                                                                    


                  
                                                                  


                  
                                                                   



                  
                                                               
 

                                                            



                                    
                     

               
                                       





                                         
                                                       
                         


                                             

                                               


        
                                                                  
                         
         
                                                           
                                         








                                            
                                                                 
 
                                              





                                                        
                                                  

                                     
                                                                   
                                      









                                                    
                                                                 
 



                                 
                                           

 
                                                                     
 

                                      

 
                                                                        
 
                             

 
                                                                     
 

                                 

 
                                                                       
 
                             

 
                                                                
 
                             

 
                                
 
                      

 
                                     



                    






































                                                                               
                  
/*
 *  The ManaPlus Client
 *  Copyright (C) 2009-2010  The Mana Developers
 *  Copyright (C) 2011-2014  The ManaPlus Developers
 *
 *  This file is part of The ManaPlus Client.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "net/ea/guildhandler.h"

#include "actormanager.h"
#include "notifymanager.h"

#include "being/localplayer.h"
#include "being/playerinfo.h"

#include "gui/windows/skilldialog.h"
#include "gui/windows/socialwindow.h"

#include "net/messagein.h"

#include "net/ea/gui/guildtab.h"

#include "utils/delete2.h"
#include "utils/gettext.h"
#include "utils/stringutils.h"

#include "resources/notifytypes.h"

#include "debug.h"

namespace Ea
{
GuildTab *guildTab = nullptr;
Guild *taGuild = nullptr;

GuildHandler::GuildHandler() :
    showBasicInfo(false)
{
}

GuildHandler::~GuildHandler()
{
    delete2(guildTab);
}

void GuildHandler::requestAlliance(const int guildId A_UNUSED,
                                   const int otherGuildId A_UNUSED) const
{
}

void GuildHandler::requestAllianceResponse(const int guildId A_UNUSED,
                                           const int otherGuildId A_UNUSED,
                                           const bool response A_UNUSED) const
{
}

void GuildHandler::endAlliance(const int guildId A_UNUSED,
                               const int otherGuildId A_UNUSED) const
{
}

void GuildHandler::processGuildCreateResponse(Net::MessageIn &msg) const
{
    const uint8_t flag = msg.readUInt8();

    switch (flag)
    {
        case 0:
            // Success
            NotifyManager::notify(NotifyTypes::GUILD_CREATED);
            break;

        case 1:
            // Already in a guild
            NotifyManager::notify(NotifyTypes::GUILD_ALREADY);
            break;

        case 2:
            // Unable to make (likely name already in use)
            NotifyManager::notify(NotifyTypes::GUILD_ALREADY);
            break;

        case 3:
            // Emperium check failed
            NotifyManager::notify(NotifyTypes::GUILD_EMPERIUM_CHECK_FAILED);
            break;

        default:
            // Unknown response
            NotifyManager::notify(NotifyTypes::GUILD_ERROR);
            break;
    }
}

void GuildHandler::processGuildMasterOrMember(Net::MessageIn &msg) const
{
    msg.readInt32();  // Type (0x57 for member, 0xd7 for master)
}

void GuildHandler::processGuildBasicInfo(Net::MessageIn &msg)
{
    const int guildId = msg.readInt32("guild id");
    const int level = msg.readInt32("guild level");
    const int members = msg.readInt32("connect member");
    const int maxMembers = msg.readInt32("max member");
    const int avgLevel = msg.readInt32("average level");
    const int exp = msg.readInt32("exp");
    const int nextExp = msg.readInt32("next exp");
    msg.skip(12, "unused");
    const int emblem = msg.readInt32("emblem id");
    std::string name = msg.readString(24, "guild name");
    std::string master = msg.readString(24, "master name");
    std::string castle = msg.readString(16, "castles");
    msg.readInt32("unused");

    if (guildTab && showBasicInfo)
    {
        showBasicInfo = false;
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild name: %s"),
            name.c_str()), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild master: %s"),
            master.c_str()), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild level: %d"), level),
            ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Online members: %d"),
            members), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Max members: %d"),
            maxMembers), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Average level: %d"),
            avgLevel), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild exp: %d"), exp),
            ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild next exp: %d"),
            nextExp), ChatMsgType::BY_SERVER);
        // TRANSLATORS: guild info message
        guildTab->chatLog(strprintf(_("Guild castle: %s"),
            castle.c_str()), ChatMsgType::BY_SERVER);
    }

    Guild *const g = Guild::getGuild(static_cast<int16_t>(guildId));
    if (!g)
        return;
    g->setName(name);
    g->setEmblemId(emblem);
}

void GuildHandler::processGuildAlianceInfo(Net::MessageIn &msg) const
{
    const int length = msg.readInt16();
    if (length < 4)
        return;
    const int count = (length - 4) / 32;

    for (int i = 0; i < count; i++)
    {
        msg.readInt32();     // 'Opposition'
        msg.readInt32();     // Other guild ID
        msg.readString(24);  // Other guild name
    }
}

void GuildHandler::processGuildMemberList(Net::MessageIn &msg) const
{
    const int length = msg.readInt16();
    if (length < 4)
        return;
    const int count = (length - 4) / 104;
    if (!taGuild)
    {
        logger->log1("!taGuild");
        return;
    }

    taGuild->clearMembers();

    int onlineNum = 0;
    int totalNum = 0;
    for (int i = 0; i < count; i++)
    {
        const int id = msg.readInt32();      // Account ID
        const int charId = msg.readInt32();  // Char ID
        msg.readInt16();                     // Hair
        msg.readInt16();                     // Hair color
        const int gender = msg.readInt16();  // Gender
        const int race = msg.readInt16();    // Class
        const int level = msg.readInt16();   // Level
        const int exp = msg.readInt32();     // Exp
        const int online = msg.readInt32();  // Online
        const int pos = msg.readInt32();     // Position
        msg.skip(50);                        // 0 unused
        std::string name = msg.readString(24);  // Name

        GuildMember *const m = taGuild->addMember(id, charId, name);
        if (m)
        {
            m->setOnline(online);
            m->setID(id);
            m->setCharId(charId);
            m->setGender(Being::intToGender(static_cast<uint8_t>(gender)));
            m->setLevel(level);
            m->setExp(exp);
            m->setPos(pos);
            m->setRace(race);
            if (actorManager)
            {
                Being *const being = actorManager->findBeingByName(
                    name, ActorType::Player);
                if (being)
                {
                    being->setGuildName(taGuild->getName());
                    if (being->getLevel() != level)
                    {
                        being->setLevel(level);
                        being->updateName();
                    }
                }
            }
            if (online)
                onlineNum ++;
            totalNum ++;
        }
    }
    taGuild->sort();
    if (actorManager)
    {
        actorManager->updatePlayerGuild();
        actorManager->updatePlayerColors();
    }
    if (socialWindow)
        socialWindow->updateGuildCounter(onlineNum, totalNum);
}

void GuildHandler::processGuildPosNameList(Net::MessageIn &msg) const
{
    if (!taGuild)
    {
        logger->log1("!taGuild");
        return;
    }

    const int length = msg.readInt16();
    if (length < 4)
        return;
    const int count = (length - 4) / 28;

    for (int i = 0; i < count; i++)
    {
        const int id = msg.readInt32();               // ID
        const std::string name = msg.readString(24);  // Position name
        taGuild->addPos(id, name);
    }
}

void GuildHandler::processGuildPosInfoList(Net::MessageIn &msg) const
{
    const int length = msg.readInt16();
    if (length < 4)
        return;
    const int count = (length - 4) / 16;

    for (int i = 0; i < count; i++)
    {
        msg.readInt32();  // ID
        msg.readInt32();  // Mode
        msg.readInt32();  // Same ID
        msg.readInt32();  // Exp mode
    }
}

void GuildHandler::processGuildPositionChanged(Net::MessageIn &msg) const
{
    msg.readInt16();     // Always 44
    msg.readInt32();     // ID
    msg.readInt32();     // Mode
    msg.readInt32();     // Same ID
    msg.readInt32();     // Exp mode
    msg.readString(24);  // Name
}

void GuildHandler::processGuildMemberPosChange(Net::MessageIn &msg) const
{
    msg.readInt16("len");
    const int accountId = msg.readInt32("account id");
    const int charId = msg.readInt32("char id");
    const int pos = msg.readInt32("position");
    if (taGuild)
    {
        GuildMember *const m = taGuild->getMember(accountId, charId);
        if (m)
            m->setPos(pos);
    }
}

void GuildHandler::processGuildEmblem(Net::MessageIn &msg) const
{
    const int length = msg.readInt16();

    msg.readInt32();  // Guild ID
    msg.readInt32();  // Emblem ID
    if (length < 12)
        return;
    msg.skip(length - 12);  // Emblem data (unknown format)
}

void GuildHandler::processGuildSkillInfo(Net::MessageIn &msg) const
{
    const int count = (msg.readInt16("len") - 6) / 37;
    msg.readInt16("skill points");

    if (skillDialog)
        skillDialog->hideSkills(SkillOwner::Guild);
    for (int i = 0; i < count; i++)
    {
        const int skillId = msg.readInt16("skill id");
        const SkillType::SkillType inf = static_cast<SkillType::SkillType>(
            msg.readInt32("inf"));
        const int level = msg.readInt16("skill level");
        const int sp = msg.readInt16("sp");
        const int range = msg.readInt16("range");
        const std::string name = msg.readString(24, "skill name");
        const int up = msg.readUInt8("up flag");
        PlayerInfo::setSkillLevel(skillId, level);
        if (skillDialog)
        {
            if (!skillDialog->updateSkill(skillId, range, up, inf, sp))
            {
                skillDialog->addSkill(SkillOwner::Guild,
                    skillId, name, level, range, up, inf, sp);
            }
        }
    }
    if (skillDialog)
        skillDialog->updateModels();
}

void GuildHandler::processGuildNotice(Net::MessageIn &msg) const
{
    const std::string msg1 = msg.readString(60);   // Mes1
    const std::string msg2 = msg.readString(120);  // Mes2
    if (guildTab)
    {
        guildTab->chatLog(msg1, ChatMsgType::BY_SERVER);
        guildTab->chatLog(msg2, ChatMsgType::BY_SERVER);
    }
}

void GuildHandler::processGuildInvite(Net::MessageIn &msg) const
{
    const int guildId = msg.readInt32();
    const std::string guildName = msg.readString(24);

    if (socialWindow)
        socialWindow->showGuildInvite(guildName, guildId, "");
}

void GuildHandler::processGuildInviteAck(Net::MessageIn &msg) const
{
    const uint8_t flag = msg.readUInt8();
    if (!guildTab)
        return;

    switch (flag)
    {
        case 0:
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_FAILED);
            break;

        case 1:
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_REJECTED);
            break;

        case 2:
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_JOINED);
            break;

        case 3:
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_FULL);
            break;

        default:
            NotifyManager::notify(NotifyTypes::GUILD_INVITE_ERROR);
            break;
    }
}

void GuildHandler::processGuildLeave(Net::MessageIn &msg) const
{
    const std::string nick = msg.readString(24);  // Name
    msg.readString(40);                           // Message

    if (taGuild)
        taGuild->removeMember(nick);

    if (!localPlayer)
        return;

    if (nick == localPlayer->getName())
    {
        if (taGuild)
        {
            taGuild->removeFromMembers();
            taGuild->clearMembers();
        }
        NotifyManager::notify(NotifyTypes::GUILD_LEFT);
        delete2(guildTab)

        if (socialWindow && taGuild)
            socialWindow->removeTab(taGuild);
        if (actorManager)
            actorManager->updatePlayerColors();
    }
    else
    {
        NotifyManager::notify(NotifyTypes::GUILD_USER_LEFT, nick);
        if (actorManager)
        {
            Being *const b = actorManager->findBeingByName(
                nick, ActorType::Player);

            if (b)
                b->clearGuilds();
            if (taGuild)
                taGuild->removeMember(nick);
        }
    }
}

void GuildHandler::processGuildMessage(Net::MessageIn &msg) const
{
    const int msgLength = msg.readInt16() - 4;

    if (msgLength <= 0)
        return;
    if (guildTab)
    {
        std::string chatMsg = msg.readString(msgLength);
        const size_t pos = chatMsg.find(" : ", 0);
        if (pos != std::string::npos)
        {
            const std::string sender_name = chatMsg.substr(0, pos);
            chatMsg.erase(0, pos + 3);
            trim(chatMsg);
            guildTab->chatLog(sender_name, chatMsg);
        }
        else
        {
            guildTab->chatLog(chatMsg);
        }
    }
}

void GuildHandler::processGuildSkillUp(Net::MessageIn &msg) const
{
    msg.readInt16();  // Skill ID
    msg.readInt16();  // Level
    msg.readInt16();  // SP
    msg.readInt16();  // 'Range'
    msg.readUInt8();  // unused? (always 1)
}

void GuildHandler::processGuildReqAlliance(Net::MessageIn &msg) const
{
    msg.readInt32();     // Account ID
    msg.readString(24);  // Name
}

void GuildHandler::processGuildReqAllianceAck(Net::MessageIn &msg) const
{
    msg.readInt32();  // Flag
}

void GuildHandler::processGuildDelAlliance(Net::MessageIn &msg) const
{
    msg.readInt32();  // Guild ID
    msg.readInt32();  // Flag
}

void GuildHandler::processGuildOppositionAck(Net::MessageIn &msg) const
{
    msg.readUInt8();  // Flag
}

void GuildHandler::processGuildBroken(Net::MessageIn &msg) const
{
    msg.readInt32();  // Flag
}

void GuildHandler::clear() const
{
    taGuild = nullptr;
}

ChatTab *GuildHandler::getTab() const
{
    return guildTab;
}

void GuildHandler::processGuildExpulsionContinue(const std::string &nick) const
{
    if (taGuild)
        taGuild->removeMember(nick);

    if (!localPlayer)
        return;

    if (nick == localPlayer->getName())
    {
        if (taGuild)
        {
            taGuild->removeFromMembers();
            taGuild->clearMembers();
        }
        NotifyManager::notify(NotifyTypes::GUILD_KICKED);
        delete2(guildTab)

        if (socialWindow && taGuild)
            socialWindow->removeTab(taGuild);
        if (actorManager)
            actorManager->updatePlayerColors();
    }
    else
    {
        NotifyManager::notify(NotifyTypes::GUILD_USER_KICKED, nick);
        if (actorManager)
        {
            Being *const b = actorManager->findBeingByName(
                nick, ActorType::Player);

            if (b)
                b->clearGuilds();
            if (taGuild)
                taGuild->removeMember(nick);
        }
    }
}

}  // namespace Ea