void handleModeChangeMessage(ChatClient client, MessageIn msg) { short channelId=msg.readInt16(); ChatChannel channel=Program.chatChannelManager.getChannel(channelId); if(channelId==0||channel!=null) { // invalid channel return; } if(channel.getUserMode(client).IndexOf('o')==-1) { // invalid permissions return; } // get the user whos mode has been changed string user=msg.readString(); // get the mode to change to byte mode=msg.readInt8(); channel.setUserMode(getClient(user), mode); // set the info to pass to all channel clients string info=client.characterName+":"+user+":"+mode; warnUsersAboutPlayerEventInChat(channel, info, (int)ChatValues.CHAT_EVENT_MODE_CHANGE); // log transaction Transaction trans=new Transaction(); trans.mCharacterId=client.characterId; trans.mAction=(uint)TransactionMembers.TRANS_CHANNEL_MODE; trans.mMessage="User mode "; trans.mMessage+=mode+" set on "+user; Program.storage.addTransaction(trans); }
public void handlePartyInvite(MessageIn msg) { string inviterName = msg.readString(); string inviteeName = msg.readString(); ChatClient inviter = getClient(inviterName); ChatClient invitee = getClient(inviteeName); if (inviter==null|| invitee==null) return; removeExpiredPartyInvites(); int maxInvitesPerTimeframe = 10; int num = mNumInvites[inviterName]; if (num >= maxInvitesPerTimeframe) { MessageOut @out=new MessageOut(Protocol.CPMSG_PARTY_REJECTED); @out.writeString(inviterName); @out.writeInt8((int)ErrorMessage.ERRMSG_LIMIT_REACHED); inviter.send(@out); return; } ++num; if (invitee.party!=null) { MessageOut @out=new MessageOut(Protocol.CPMSG_PARTY_REJECTED); @out.writeString(inviterName); @out.writeInt8((int)ErrorMessage.ERRMSG_FAILURE); inviter.send(@out); return; } mInvitations.Add(new PartyInvite(inviterName, inviteeName)); MessageOut msgout=new MessageOut(Protocol.CPMSG_PARTY_INVITED); msgout.writeString(inviterName); invitee.send(msgout); }
protected override void processMessage(MessageIn msg) { switch(msg.getId()) { case Protocol.AGMSG_REGISTER_RESPONSE: { if(msg.readInt16()!=(short)DataVersion.DATA_VERSION_OK) { Logger.Write(LogLevel.Error, "Item database is outdated! Please update to prevent inconsistencies"); stop(); //Disconnect gracefully from account server. //Stop gameserver to prevent inconsistencies. System.Environment.Exit((int)ExitValue.EXIT_DB_EXCEPTION); } else { Logger.Write(LogLevel.Debug, "Local item database is in sync with account server."); } if(msg.readInt16()!=(short)Password.PASSWORD_OK) { Logger.Write(LogLevel.Error, "This game server sent a invalid password"); stop(); System.Environment.Exit((int)ExitValue.EXIT_BAD_CONFIG_PARAMETER); } //read world state variables while(msg.getUnreadLength()>0) { string key=msg.readString(); string @value=msg.readString(); if(key!=""&&@value!="") { GameState.setVariableFromDbserver(key, @value); } } } break; case Protocol.AGMSG_PLAYER_ENTER: { string token=msg.readString(); Character ptr=new Character(msg); Program.gameHandler.addPendingCharacter(token, ptr); } break; case Protocol.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) { string key=msg.readString(); string @value=msg.readString(); if(key!=""&&@value!="") { m.setVariableFromDbserver(key, @value); } } //Recreate potential persistent floor items Logger.Write(LogLevel.Debug, "Recreate persistant items on map {0}", mapId); int floorItemsNumber=msg.readInt16(); for(int i = 0;i < floorItemsNumber;i += 4) { int itemId=msg.readInt32(); int amount=msg.readInt16(); int posX=msg.readInt16(); int posY=msg.readInt16(); ItemClass ic=Program.itemManager.getItem(itemId); if(ic!=null) { Item item=new Item(ic, amount); item.setMap(m); Point dst=new Point(posX, posY); item.setPosition(dst); if(!GameState.insertOrDelete((Thing)item)) { // The map is full. Logger.Write(LogLevel.Debug, "Couldn't add floor item(s) {0} into map {1}", itemId, mapId); return; } } } } break; } case Protocol.AGMSG_SET_VAR_WORLD: { string key=msg.readString(); string @value=msg.readString(); GameState.setVariableFromDbserver(key, value); Logger.Write(LogLevel.Debug, "Global variable \"{0}\" has changed to \"{1}\"", key, @value); } break; case Protocol.AGMSG_REDIRECT_RESPONSE: { int id=msg.readInt32(); string token=msg.readString(); string address=msg.readString(); int port=msg.readInt16(); Program.gameHandler.completeServerChange(id, token, address, port); } break; case Protocol.AGMSG_GET_VAR_CHR_RESPONSE: { int id=msg.readInt32(); string name=msg.readString(); string @value=msg.readString(); Quest.recoveredQuestVar(id, name, @value); } break; case Protocol.CGMSG_CHANGED_PARTY: { // Character DB id int charid=msg.readInt32(); // Party id, 0 for none int partyid=msg.readInt32(); Program.gameHandler.updateCharacter(charid, partyid); } break; case Protocol.CGMSG_POST_RESPONSE: { // get the character Character character=Program.postMan.getCharacter(msg.readInt32()); // check character is still valid if(character==null) { break; } string sender=msg.readString(); string letter=msg.readString(); Program.postMan.gotPost(character, sender, letter); } break; case Protocol.CGMSG_STORE_POST_RESPONSE: { // get character Character character=Program.postMan.getCharacter(msg.readInt32()); // check character is valid if(character==null) { break; } //TODO: Get NPC to tell character if the sending of post //was successful or not } break; default: { Logger.Write(LogLevel.Warning, "Invalid message type"); break; } } }
void handleTopicChange(ChatClient client, MessageIn msg) { short channelId=msg.readInt16(); string topic=msg.readString(); ChatChannel channel=Program.chatChannelManager.getChannel(channelId); if(!Program.guildManager.doesExist(channel.getName())) { Program.chatChannelManager.setChannelTopic(channelId, topic); } else { guildChannelTopicChange(channel, (int)client.characterId, topic); } // log transaction Transaction trans=new Transaction(); trans.mCharacterId=client.characterId; trans.mAction=(uint)TransactionMembers.TRANS_CHANNEL_TOPIC; trans.mMessage="User changed topic to "+topic; trans.mMessage+=(" in "+channel.getName()); Program.storage.addTransaction(trans); }
void handleLoginRandTriggerMessage(AccountClient client, MessageIn msg) { string salt=getRandomString(4); string username=msg.readString(); ISL.Server.Account.Account acc=Program.storage.getAccount(username); if(acc!=null) { acc.setRandomSalt(salt); mPendingAccounts.Add(acc); } MessageOut reply=new MessageOut(Protocol.APMSG_LOGIN_RNDTRGR_RESPONSE); reply.writeString(salt); client.send(reply); }
bool mUpdateLevelProgress; /**< Flag raised when percent to next level changed */ #endregion Fields #region Constructors public Character(MessageIn msg) : base(ThingType.OBJECT_CHARACTER) { //mTransactionHandler(NULL), mDatabaseID=-1; mLevel=1; mRecalculateLevel=true; mTransaction=TransactionType.TRANS_NONE; mExperience=new Dictionary<int, int>(); Dictionary<int, List<AttributeInfoType>> attr=Program.attributeManager.getAttributeScope(ScopeType.CharacterScope); Logger.Write(LogLevel.Debug, "Character creation: initialisation of {0} attributes.", attr.Count); foreach(KeyValuePair<int, List<AttributeInfoType>> pair in attr) { mAttributes.Add((uint)pair.Key, new Attribute(pair.Value)); } // Get character data. mDatabaseID=msg.readInt32(); setName(msg.readString()); deserializeCharacterData(msg); mOld=getPosition(); //TODO Ermitteln was hier eigentlich passieren sollte //Inventory(this).initialize(); modifiedAllAttribute(); setSize(16); // Give the character some specials for testing. //TODO: Get from quest vars and equipment giveSpecial(1); giveSpecial(2); giveSpecial(3); }
void handleGuildCreate(ChatClient client, MessageIn msg) { MessageOut reply=new MessageOut(Protocol.CPMSG_GUILD_CREATE_RESPONSE); // Check if guild already exists and if so, return error string guildName = msg.readString(); if (!Program.guildManager.doesExist(guildName)) { // check the player hasnt already created a guild if(Program.guildManager.alreadyOwner((int)client.characterId)) { reply.writeInt8((int)ErrorMessage.ERRMSG_LIMIT_REACHED); } else { // Guild doesnt already exist so create it Guild guild=Program.guildManager.createGuild(guildName, (int)client.characterId); reply.writeInt8((int)ErrorMessage.ERRMSG_OK); reply.writeString(guildName); reply.writeInt16(guild.getId()); reply.writeInt16(guild.getUserPermissions((int)client.characterId)); // Send autocreated channel id ChatChannel channel = joinGuildChannel(guildName, client); reply.writeInt16(channel.getId()); } } else { reply.writeInt8((int)ErrorMessage.ERRMSG_ALREADY_TAKEN); } client.send(reply); }
void handleCharacterCreateMessage(AccountClient client, MessageIn msg) { 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) // { int slot=msg.readInt8(); // } MessageOut reply=new MessageOut(Protocol.APMSG_CHAR_CREATE_RESPONSE); ISL.Server.Account.Account acc=client.getAccount(); if(acc==null) { reply.writeInt8((byte)ErrorMessage.ERRMSG_NO_LOGIN); } else if(!Program.stringFilter.filterContent(name)) { reply.writeInt8((byte)ErrorMessage.ERRMSG_INVALID_ARGUMENT); } else if(Program.stringFilter.findDoubleQuotes(name)) { reply.writeInt8((byte)ErrorMessage.ERRMSG_INVALID_ARGUMENT); } else if(hairStyle>mNumHairStyles) { reply.writeInt8((byte)Create.CREATE_INVALID_HAIRSTYLE); } else if(hairColor>mNumHairColors) { reply.writeInt8((byte)Create.CREATE_INVALID_HAIRCOLOR); } else if(gender>mNumGenders) { reply.writeInt8((byte)Create.CREATE_INVALID_GENDER); } else if((name.Length<mMinNameLength)|| (name.Length>mMaxNameLength)) { reply.writeInt8((byte)ErrorMessage.ERRMSG_INVALID_ARGUMENT); } else { if(Program.storage.doesCharacterNameExist(name)) { reply.writeInt8((byte)Create.CREATE_EXISTS_NAME); client.send(reply); return; } // An account shouldn't have more // than <account_maxCharacters> characters. Dictionary<uint, ISL.Server.Account.Character> chars=acc.getCharacters(); if(slot<1||slot>mMaxCharacters||!acc.isSlotEmpty((uint)slot)) { reply.writeInt8((byte)Create.CREATE_INVALID_SLOT); client.send(reply); return; } if((int)chars.Count>=mMaxCharacters) { reply.writeInt8((byte)Create.CREATE_TOO_MUCH_CHARACTERS); client.send(reply); return; } // TODO: Add race, face and maybe special attributes. // Customization of character's attributes... List<int> attributes=new List<int>(); //std::vector<int>(mModifiableAttributes.size(), 0); for(uint i = 0;i < mModifiableAttributes.Count;++i) { attributes.Add(msg.readInt16()); } int totalAttributes=0; for(uint i = 0;i < mModifiableAttributes.Count;++i) { // For good total attributes check. totalAttributes+=attributes[(int)i]; // For checking if all stats are >= min and <= max. if(attributes[(int)i]<mAttributeMinimum ||attributes[(int)i]>mAttributeMaximum) { reply.writeInt8((byte)Create.CREATE_ATTRIBUTES_OUT_OF_RANGE); client.send(reply); return; } } if(totalAttributes>mStartingPoints) { reply.writeInt8((byte)Create.CREATE_ATTRIBUTES_TOO_HIGH); } else if(totalAttributes<mStartingPoints) { reply.writeInt8((byte)Create.CREATE_ATTRIBUTES_TOO_LOW); } else { Character newCharacter=new Character(name); // Set the initial attributes provided by the client for(uint i = 0;i < mModifiableAttributes.Count;++i) { //TODO schauen was hier genau passieren muss //newCharacter.mAttributes.Add((uint)(mModifiableAttributes[(int)i]), mModifiableAttributes[i]); //newCharacter.mAttributes.Add((uint)mModifiableAttributes[(int)i], attributes[(int)i]); } foreach(KeyValuePair<uint, Attribute> defaultAttributePair in mDefaultAttributes) { //TODO schauen was hier genau passieren muss // newCharacter.mAttributes.Add(defaultAttributePair.Key, defaultAttributePair.Value); } newCharacter.setAccount(acc); newCharacter.setCharacterSlot((uint)slot); newCharacter.setGender(gender); newCharacter.setHairStyle(hairStyle); newCharacter.setHairColor(hairColor); newCharacter.setMapId(Configuration.getValue("char_startMap", 1)); Point startingPos=new Point(Configuration.getValue("char_startX", 1024), Configuration.getValue("char_startY", 1024)); newCharacter.setPosition(startingPos); acc.addCharacter(newCharacter); Logger.Write(LogLevel.Information, "Character {0} was created for {1}'s account.", name, acc.getName()); Program.storage.flush(acc); // flush changes // log transaction Transaction trans=new Transaction(); trans.mCharacterId=(uint)newCharacter.getDatabaseID(); trans.mAction=(uint)TransactionMembers.TRANS_CHAR_CREATE; trans.mMessage=acc.getName()+" created character "; trans.mMessage+="called "+name; Program.storage.addTransaction(trans); reply.writeInt8((byte)ErrorMessage.ERRMSG_OK); client.send(reply); // Send new characters infos back to client sendCharacterData(client, chars[(uint)slot]); return; } } client.send(reply); }
void handleEnterChannelMessage(ChatClient client, MessageIn msg) { MessageOut reply=new MessageOut(Protocol.CPMSG_ENTER_CHANNEL_RESPONSE); string channelName=msg.readString(); string givenPassword=msg.readString(); ChatChannel channel=null; if(Program.chatChannelManager.channelExists(channelName)|| Program.chatChannelManager.tryNewPublicChannel(channelName)) { channel=Program.chatChannelManager.getChannel(channelName); } if(channel!=null) { reply.writeInt8((int)ErrorMessage.ERRMSG_INVALID_ARGUMENT); } else if(channel.getPassword()!=null&&channel.getPassword()!=givenPassword) { // Incorrect password (should probably have its own return value) reply.writeInt8((int)ErrorMessage.ERRMSG_INSUFFICIENT_RIGHTS); } else if(!channel.canJoin()) { reply.writeInt8((int)ErrorMessage.ERRMSG_INVALID_ARGUMENT); } else { if(channel.addUser(client)) { reply.writeInt8((int)ErrorMessage.ERRMSG_OK); // The user entered the channel, now give him the channel // id, the announcement string and the user list. reply.writeInt16(channel.getId()); reply.writeString(channelName); reply.writeString(channel.getAnnouncement()); List<ChatClient> users=channel.getUserList(); foreach(ChatClient user in users) { reply.writeString(user.characterName); reply.writeString(channel.getUserMode(user)); } // Send an CPMSG_UPDATE_CHANNEL to warn other clients a user went // in the channel. warnUsersAboutPlayerEventInChat(channel, client.characterName, (int)ChatValues.CHAT_EVENT_NEW_PLAYER); // log transaction Transaction trans=new Transaction(); trans.mCharacterId=client.characterId; trans.mAction=(uint)TransactionMembers.TRANS_CHANNEL_JOIN; trans.mMessage="User joined "+channelName; Program.storage.addTransaction(trans); } else { reply.writeInt8((int)ErrorMessage.ERRMSG_FAILURE); } } client.send(reply); }
void handleGuildAcceptInvite(ChatClient client, MessageIn msg) { MessageOut reply=new MessageOut(Protocol.CPMSG_GUILD_ACCEPT_RESPONSE); string guildName = msg.readString(); bool error = true; // set true by default, and set false only if success // check guild exists and that member was invited // then add them as guild member // and remove from invite list Guild guild = Program.guildManager.findByName(guildName); if (guild!=null) { if (guild.checkInvited((int)client.characterId)) { // add user to guild Program.guildManager.addGuildMember(guild, (int)client.characterId); reply.writeInt8((int)ErrorMessage.ERRMSG_OK); reply.writeString(guild.getName()); reply.writeInt16(guild.getId()); reply.writeInt16(guild.getUserPermissions((int)client.characterId)); // have character join guild channel ChatChannel channel = joinGuildChannel(guild.getName(), client); reply.writeInt16(channel.getId()); sendGuildListUpdate(guildName, client.characterName, (int)GuildValues.GUILD_EVENT_NEW_PLAYER); // success! set error to false error = false; } } if (error) { reply.writeInt8((int)ErrorMessage.ERRMSG_FAILURE); } client.send(reply); }
void handleChatMessage(ChatClient client, MessageIn msg) { string text = msg.readString(); // Pass it through the slang filter (false when it contains bad words) if (!Program.stringFilter.filterContent(text)) { warnPlayerAboutBadWords(client); return; } short channelId = msg.readInt16(); ChatChannel channel = Program.chatChannelManager.getChannel(channelId); if (channel!=null) { Logger.Write(LogLevel.Debug, "{0} says in channel {1}: {2}", client.characterName, channelId, text); MessageOut result=new MessageOut(Protocol.CPMSG_PUBMSG); result.writeInt16(channelId); result.writeString(client.characterName); result.writeString(text); sendInChannel(channel, result); } // log transaction Transaction trans=new Transaction(); trans.mCharacterId = client.characterId; trans.mAction=(uint)TransactionMembers.TRANS_MSG_PUBLIC; trans.mMessage = "User said " + text; Program.storage.addTransaction(trans); }
void handleAnnounceMessage(ChatClient client, MessageIn msg) { string text=msg.readString(); if(!Program.stringFilter.filterContent(text)) { warnPlayerAboutBadWords(client); return; } if(client.accountLevel==(byte)AccessLevel.AL_ADMIN||client.accountLevel==(byte)AccessLevel.AL_GM) { // TODO: b_lindeijer: Shouldn't announcements also have a sender? Logger.Write(LogLevel.Information, "ANNOUNCE: {0}", text); MessageOut result=new MessageOut(Protocol.CPMSG_ANNOUNCEMENT); result.writeString(text); // We send the message to all players in the default channel as it is // an announcement. sendToEveryone(result); // log transaction Transaction trans=new Transaction(); trans.mCharacterId=client.characterId; trans.mAction=(uint)TransactionMembers.TRANS_MSG_ANNOUNCE; trans.mMessage="User announced "+text; Program.storage.addTransaction(trans); } else { MessageOut result=new MessageOut(Protocol.CPMSG_ERROR); result.writeInt8((int)ErrorMessage.ERRMSG_INSUFFICIENT_RIGHTS); client.send(result); Logger.Write(LogLevel.Information, "{0} couldn't make an announcement due to insufficient rights.", client.characterName); } }
protected override void processMessage(NetComputer comp, MessageIn message) { ChatClient computer=(ChatClient)(comp); MessageOut result=new MessageOut(); if(computer.characterName==null) { if(message.getId()!=Protocol.PCMSG_CONNECT) return; string magic_token=message.readString(); mTokenCollector.addPendingClient(magic_token, computer); sendGuildRejoin(computer); return; } switch(message.getId()) { case Protocol.PCMSG_CHAT: handleChatMessage(computer, message); break; case Protocol.PCMSG_ANNOUNCE: handleAnnounceMessage(computer, message); break; case Protocol.PCMSG_PRIVMSG: handlePrivMsgMessage(computer, message); break; case Protocol.PCMSG_WHO: handleWhoMessage(computer); break; case Protocol.PCMSG_ENTER_CHANNEL: handleEnterChannelMessage(computer, message); break; case Protocol.PCMSG_USER_MODE: handleModeChangeMessage(computer, message); break; case Protocol.PCMSG_KICK_USER: handleKickUserMessage(computer, message); break; //TODO hinzugef�gt, evt sollte es durchfallen case Protocol.PCMSG_QUIT_CHANNEL: handleQuitChannelMessage(computer, message); break; case Protocol.PCMSG_LIST_CHANNELS: handleListChannelsMessage(computer, message); break; case Protocol.PCMSG_LIST_CHANNELUSERS: handleListChannelUsersMessage(computer, message); break; case Protocol.PCMSG_TOPIC_CHANGE: handleTopicChange(computer, message); break; case Protocol.PCMSG_DISCONNECT: handleDisconnectMessage(computer, message); break; case Protocol.PCMSG_GUILD_CREATE: handleGuildCreate(computer, message); break; case Protocol.PCMSG_GUILD_INVITE: handleGuildInvite(computer, message); break; case Protocol.PCMSG_GUILD_ACCEPT: handleGuildAcceptInvite(computer, message); break; case Protocol.PCMSG_GUILD_GET_MEMBERS: handleGuildGetMembers(computer, message); break; case Protocol.PCMSG_GUILD_PROMOTE_MEMBER: handleGuildMemberLevelChange(computer, message); break; case Protocol.PCMSG_GUILD_KICK_MEMBER: handleGuildKickMember(computer, message); break; //TODO hinzugef�gt, evt sollte es durchfallen case Protocol.PCMSG_GUILD_QUIT: handleGuildQuit(computer, message); break; case Protocol.PCMSG_PARTY_INVITE_ANSWER: handlePartyInviteAnswer(computer, message); break; case Protocol.PCMSG_PARTY_QUIT: handlePartyQuit(computer); break; default: Logger.Write(LogLevel.Warning, "processMessage, Invalid message type {0}", message.getId()); result.writeInt16((int)Protocol.XXMSG_INVALID); break; } if(result.getLength()>0) computer.send(result); }
void handlePartyInviteAnswer(ChatClient client, MessageIn msg) { if(client.party==null) return; MessageOut outInvitee=new MessageOut(Protocol.CPMSG_PARTY_INVITE_ANSWER_RESPONSE); string inviter=msg.readString(); // check if the invite is still valid bool valid=false; removeExpiredPartyInvites(); int size=mInvitations.Count; for(int i=0; i<size; i++) { if(mInvitations[i].mInviter==inviter&&mInvitations[i].mInvitee==client.characterName) { valid=true; } } // the invitee did not accept the invitation //if (msg.readInt8();) //{ msg.readInt8(); if(!valid) return; // send rejection to inviter ChatClient inviterClient=getClient(inviter); if(inviterClient!=null) { MessageOut outmsg=new MessageOut(Protocol.CPMSG_PARTY_REJECTED); outmsg.writeString(inviter); outmsg.writeInt8((int)ErrorMessage.ERRMSG_OK); inviterClient.send(outmsg); } return; //} // if the invitation has expired, tell the inivtee about it if(!valid) { outInvitee.writeInt8((int)ErrorMessage.ERRMSG_TIME_OUT); client.send(outInvitee); return; } // check that the inviter is still in the game ChatClient c1=getClient(inviter); if(c1==null) { outInvitee.writeInt8((int)ErrorMessage.ERRMSG_FAILURE); client.send(outInvitee); return; } // if party doesnt exist, create it if(c1.party!=null) { c1.party=new Party(); //c1.party.addUser(inviter); c1.party.addUser("", inviter); //TODO Überprüfen // tell game server to update info updateInfo(c1, (int)c1.party.getId()); } outInvitee.writeInt8((int)ErrorMessage.ERRMSG_OK); List<string> users=c1.party.getUsers(); int usersSize=users.Count; for(int i=0; i<usersSize; i++) { outInvitee.writeString(users[i]); } client.send(outInvitee); // add invitee to the party c1.party.addUser(client.characterName, inviter); client.party=c1.party; // tell game server to update info updateInfo(client, (int)client.party.getId()); }
void handleGuildInvite(ChatClient client, MessageIn msg) { MessageOut reply=new MessageOut(Protocol.CPMSG_GUILD_INVITE_RESPONSE); MessageOut invite=new MessageOut(Protocol.CPMSG_GUILD_INVITED); // send an invitation from sender to character to join guild int guildId=msg.readInt16(); string character=msg.readString(); // get the chat client and the guild ChatClient invitedClient=mPlayerMap[character]; Guild guild=Program.guildManager.findById((short)guildId); if(invitedClient!=null&&guild!=null) { // check permissions of inviter, and that they arent inviting themself, // and arent someone already in the guild if(guild.canInvite((int)client.characterId)&&(client.characterName!=character)&&!guild.checkInGuild((int)invitedClient.characterId)) { // send the name of the inviter and the name of the guild // that the character has been invited to join string senderName=client.characterName; string guildName=guild.getName(); invite.writeString(senderName); invite.writeString(guildName); invite.writeInt16(guildId); invitedClient.send(invite); reply.writeInt8((int)ErrorMessage.ERRMSG_OK); // add member to list of invited members to the guild guild.addInvited((int)invitedClient.characterId); } else { reply.writeInt8((int)ErrorMessage.ERRMSG_FAILURE); } } else { reply.writeInt8((int)ErrorMessage.ERRMSG_FAILURE); } client.send(reply); }
void handlePrivMsgMessage(ChatClient client, MessageIn msg) { string user = msg.readString(); string text = msg.readString(); if (!Program.stringFilter.filterContent(text)) { warnPlayerAboutBadWords(client); return; } // We seek the player to whom the message is told and send it to her/him. sayToPlayer(client, user, text); }
void handleGuildKickMember(ChatClient client, MessageIn msg) { MessageOut reply=new MessageOut(Protocol.CPMSG_GUILD_KICK_MEMBER_RESPONSE); short guildId=msg.readInt16(); string user=msg.readString(); Guild guild=Program.guildManager.findById(guildId); Character c=Program.storage.getCharacter(user); if(guild!=null&&c!=null) { if((guild.getUserPermissions(c.getDatabaseID())&(int)(GuildAccessLevel.GAL_KICK))!=0) //TODO Überprüfen ob Vergleich so richtig rum { reply.writeInt8((int)ErrorMessage.ERRMSG_OK); } else { reply.writeInt8((int)ErrorMessage.ERRMSG_INSUFFICIENT_RIGHTS); } } else { reply.writeInt8((int)ErrorMessage.ERRMSG_INVALID_ARGUMENT); } client.send(reply); }
void handleLoginMessage(AccountClient client, MessageIn msg) { MessageOut reply=new MessageOut(Protocol.APMSG_LOGIN_RESPONSE); //Überprüfung ob es sich um einen Login Request handelt if(client.status!=AccountClientStatus.CLIENT_LOGIN) { reply.writeInt8((int)ErrorMessage.ERRMSG_FAILURE); client.send(reply); return; } int clientVersion=msg.readInt32(); if(clientVersion<ManaServ.PROTOCOL_VERSION) { reply.writeInt8((int)Login.LOGIN_INVALID_VERSION); client.send(reply); return; } // Check whether the last login attempt for this IP is still too fresh IPAddress address=client.getIP(); DateTime now=DateTime.Now; if(mLastLoginAttemptForIP.ContainsKey(address)) //TODO Schauen ob der Vergleich gegen das IPAdress Objekt funktioniert { DateTime lastAttempt=mLastLoginAttemptForIP[address]; lastAttempt.AddSeconds(1); //TODO schauen ob hier im Original wirklich Sekunden gemeint sind if(now<lastAttempt) { reply.writeInt8((int)Login.LOGIN_INVALID_TIME); client.send(reply); return; } } mLastLoginAttemptForIP[address]=now; string username=msg.readString(); string password=msg.readString(); if(Program.stringFilter.findDoubleQuotes(username)) { reply.writeInt8((int)ErrorMessage.ERRMSG_INVALID_ARGUMENT); client.send(reply); return; } uint maxClients=(uint)Configuration.getValue("net_maxClients", 1000); if(getClientCount()>=maxClients) { reply.writeInt8((int)ErrorMessage.ERRMSG_SERVER_FULL); client.send(reply); return; } // Check if the account exists ISL.Server.Account.Account acc=null; foreach(ISL.Server.Account.Account tmp in mPendingAccounts) { if(tmp.getName()==username) { acc=tmp; break; } } mPendingAccounts.Remove(acc); //TODO Überprüfen ob SHA256 das gewünschte Ergebniss liefert if(acc!=null) { if(SHA256.HashString(acc.getPassword()+acc.getRandomSalt())!=password) { reply.writeInt8((int)ErrorMessage.ERRMSG_INVALID_ARGUMENT); client.send(reply); //delete acc; return; } } if(acc.getLevel()==(int)AccessLevel.AL_BANNED) { reply.writeInt8((int)Login.LOGIN_BANNED); client.send(reply); //delete acc; return; } // The client successfully logged in... // Set lastLogin date of the account. DateTime login=DateTime.Now; acc.setLastLogin(login); Program.storage.updateLastLogin(acc); // Associate account with connection. client.setAccount(acc); client.status=AccountClientStatus.CLIENT_CONNECTED; reply.writeInt8((int)ErrorMessage.ERRMSG_OK); addServerInfo(reply); client.send(reply); // Acknowledge login // Return information about available characters Dictionary<uint, Character> chars=acc.getCharacters(); // Send characters list foreach(ISL.Server.Account.Character character in chars.Values) { sendCharacterData(client, character); } }
void handleGuildMemberLevelChange(ChatClient client, MessageIn msg) { // get the guild, the user to change the permissions, and the new permission // check theyre valid, and then change them MessageOut reply=new MessageOut(Protocol.CPMSG_GUILD_PROMOTE_MEMBER_RESPONSE); short guildId = msg.readInt16(); string user = msg.readString(); short level = msg.readInt8(); Guild guild = Program.guildManager.findById(guildId); Character c = Program.storage.getCharacter(user); if (guild!=null && c!=null) { int rights = guild.getUserPermissions(c.getDatabaseID()) | level; if(Program.guildManager.changeMemberLevel(client, guild, c.getDatabaseID(), rights)==0) { reply.writeInt8((int)ErrorMessage.ERRMSG_OK); client.send(reply); } } reply.writeInt8((int)ErrorMessage.ERRMSG_FAILURE); //TODO Muss das so oder fehlt oben ein return? client.send(reply); }
void handleRegisterMessage(AccountClient client, MessageIn msg) { int clientVersion=msg.readInt32(); string username=msg.readString(); string password=msg.readString(); string email=msg.readString(); string captcha=msg.readString(); MessageOut reply=new MessageOut(Protocol.APMSG_REGISTER_RESPONSE); if(client.status!=AccountClientStatus.CLIENT_LOGIN) { reply.writeInt8((int)ErrorMessage.ERRMSG_FAILURE); } else if(!mRegistrationAllowed) { reply.writeInt8((int)ErrorMessage.ERRMSG_FAILURE); } else if(clientVersion<ManaServ.PROTOCOL_VERSION) { reply.writeInt8((int)Register.REGISTER_INVALID_VERSION); } else if(Program.stringFilter.findDoubleQuotes(username) ||Program.stringFilter.findDoubleQuotes(email) ||username.Length<mMinNameLength ||username.Length>mMaxNameLength ||!Program.stringFilter.isEmailValid(email) ||!Program.stringFilter.filterContent(username)) { reply.writeInt8((int)ErrorMessage.ERRMSG_INVALID_ARGUMENT); } else if(Program.storage.doesUserNameExist(username)) { reply.writeInt8((int)Register.REGISTER_EXISTS_USERNAME); } else if(Program.storage.doesEmailAddressExist(SHA256.HashString(email))) { reply.writeInt8((int)Register.REGISTER_EXISTS_EMAIL); } else if(!checkCaptcha(client, captcha)) { reply.writeInt8((int)Register.REGISTER_CAPTCHA_WRONG); } else { ISL.Server.Account.Account acc=new ISL.Server.Account.Account(); acc.setName(username); acc.setPassword(SHA256.HashString(password)); // We hash email server-side for additional privacy // we ask for it again when we need it and verify it // through comparing it with the hash. acc.setEmail(SHA256.HashString(email)); acc.setLevel((int)AccessLevel.AL_PLAYER); // Set the date and time of the account registration, and the last login DateTime regdate=DateTime.Now; acc.setRegistrationDate(regdate); acc.setLastLogin(regdate); Program.storage.addAccount(acc); reply.writeInt8((int)ErrorMessage.ERRMSG_OK); addServerInfo(reply); // Associate account with connection client.setAccount(acc); client.status=AccountClientStatus.CLIENT_CONNECTED; } client.send(reply); }
void handleKickUserMessage(ChatClient client, MessageIn msg) { short channelId=msg.readInt16(); ChatChannel channel=Program.chatChannelManager.getChannel(channelId); if(channelId==0||channel!=null) { // invalid channel return; } if(channel.getUserMode(client).IndexOf('o')==-1) { // invalid permissions return; } // get the user whos being kicked string user=msg.readString(); if(channel.removeUser(getClient(user))) { string ss=client.characterName+":"+user; warnUsersAboutPlayerEventInChat(channel, ss, (int)ChatValues.CHAT_EVENT_KICKED_PLAYER); } // log transaction Transaction trans=new Transaction(); trans.mCharacterId=client.characterId; trans.mAction=(uint)TransactionMembers.TRANS_CHANNEL_KICK; trans.mMessage="User kicked "+user; Program.storage.addTransaction(trans); }
// internal GameServer getGameServerFromMap(int); //internal void GameServerHandler::dumpStatistics(std::ostream &); /// <summary> /// Processes server messages. /// </summary> /// <param name="computer"></param> /// <param name="message"></param> protected override void processMessage(NetComputer computer, MessageIn message) { MessageOut result=new MessageOut(); GameServer server=(GameServer)(computer); switch(message.getId()) { case Protocol.GAMSG_REGISTER: { Logger.Write(LogLevel.Debug, "GAMSG_REGISTER"); // TODO: check the credentials of the game server server.address=message.readString(); server.port=message.readInt16(); string password=message.readString(); // checks the version of the remote item database with our local copy uint dbversion=(uint)message.readInt32(); Logger.Write(LogLevel.Information, "Game server uses itemsdatabase with version {0}", dbversion); Logger.Write(LogLevel.Debug, "AGMSG_REGISTER_RESPONSE"); MessageOut outmessage=new MessageOut(Protocol.AGMSG_REGISTER_RESPONSE); if(dbversion==Program.storage.getItemDatabaseVersion()) { Logger.Write(LogLevel.Debug, "Item databases between account server and gameserver are in sync"); outmessage.writeInt16((int)DataVersion.DATA_VERSION_OK); } else { Logger.Write(LogLevel.Debug, "Item database of game server has a wrong version"); outmessage.writeInt16((int)DataVersion.DATA_VERSION_OUTDATED); } if(password==Configuration.getValue("net_password", "changeMe")) { outmessage.writeInt16((int)Password.PASSWORD_OK); computer.send(outmessage); // transmit global world state variables Dictionary<string, string> variables; variables=Program.storage.getAllWorldStateVars(0); foreach(KeyValuePair<string, string> pair in variables) { outmessage.writeString(pair.Key); outmessage.writeString(pair.Value); } } else { Logger.Write(LogLevel.Information, "The password given by {0}:{1} was bad.", server.address, server.port); outmessage.writeInt16((int)Password.PASSWORD_BAD); computer.disconnect(outmessage); break; } Logger.Write(LogLevel.Information, "Game server {0}:{1} wants to register {2} maps.", server.address, server.port, (message.getUnreadLength()/2)); while(message.getUnreadLength()!=0) { int id=message.readInt16(); Logger.Write(LogLevel.Information, "Registering map {0}.", id); GameServer s=GameServerHandler.getGameServerFromMap(id); if(s!=null) { Logger.Write(LogLevel.Error, "Server Handler: map is already registered by {0}:{1}.", s.address, s.port); } else { MessageOut tmpOutMsg=new MessageOut(Protocol.AGMSG_ACTIVE_MAP); // Map variables tmpOutMsg.writeInt16(id); Dictionary<string, string> variables; variables=Program.storage.getAllWorldStateVars(id); // Map vars number tmpOutMsg.writeInt16(variables.Count); foreach(KeyValuePair<string, string> pair in variables) { tmpOutMsg.writeString(pair.Key); tmpOutMsg.writeString(pair.Value); } // Persistent Floor Items List<FloorItem> items=Program.storage.getFloorItemsFromMap(id); tmpOutMsg.writeInt16(items.Count); //number of floor items // Send each map item: item_id, amount, pos_x, pos_y foreach(FloorItem i in items) { tmpOutMsg.writeInt32(i.getItemId()); tmpOutMsg.writeInt16(i.getItemAmount()); tmpOutMsg.writeInt16(i.getPosX()); tmpOutMsg.writeInt16(i.getPosY()); } computer.send(tmpOutMsg); //MapStatistics m=server.maps[(ushort)id]; //Auskommentiert da nicht klar ist wo dieser Wert gesetzt wird //m.nbThings=0; //m.nbMonsters=0; } } } break; case Protocol.GAMSG_PLAYER_DATA: { Logger.Write(LogLevel.Debug, "GAMSG_PLAYER_DATA"); int id=message.readInt32(); try { Character ptr=Program.storage.getCharacter(id, null); CharacterData.deserializeCharacterData(ptr, message); if(!Program.storage.updateCharacter(ptr)) { Logger.Write(LogLevel.Error, "Failed to update character {0}.", id); } } catch { Logger.Write(LogLevel.Error, "Received data for non-existing character {0}.", id); } } break; case Protocol.GAMSG_PLAYER_SYNC: { Logger.Write(LogLevel.Debug, "GAMSG_PLAYER_SYNC"); GameServerHandler.syncDatabase(message); } break; case Protocol.GAMSG_REDIRECT: { Logger.Write(LogLevel.Debug, "GAMSG_REDIRECT"); int id=message.readInt32(); //string magic_token(utils::getMagicToken()); string magic_token=Various.GetUniqueID(); try { Character ptr=Program.storage.getCharacter(id, null); int mapId=ptr.getMapId(); try { GameServer s=GameServerHandler.getGameServerFromMap(mapId); GameServerHandler.registerGameClient(s, magic_token, ptr); result.writeInt16((int)Protocol.AGMSG_REDIRECT_RESPONSE); result.writeInt32(id); result.writeString(magic_token); result.writeString(s.address); result.writeInt16(s.port); } catch { Logger.Write(LogLevel.Error, "Server Change: No game server for map {0}.", mapId); } } catch { Logger.Write(LogLevel.Error, "Received data for non-existing character {0}.", id); } } break; case Protocol.GAMSG_PLAYER_RECONNECT: { Logger.Write(LogLevel.Debug, "GAMSG_PLAYER_RECONNECT"); int id=message.readInt32(); string magic_token=message.readString(); //string magic_token=message.readString(ManaServ.MAGIC_TOKEN_LENGTH); try { Character ptr=Program.storage.getCharacter(id, null); int accountID=ptr.getAccountID(); AccountClientHandler.prepareReconnect(magic_token, accountID); } catch { Logger.Write(LogLevel.Error, "Received data for non-existing character {0}.", id); } } break; case Protocol.GAMSG_GET_VAR_CHR: { int id=message.readInt32(); string name=message.readString(); string value=Program.storage.getQuestVar(id, name); result.writeInt16((Int16)Protocol.AGMSG_GET_VAR_CHR_RESPONSE); result.writeInt32(id); result.writeString(name); result.writeString(value); } break; case Protocol.GAMSG_SET_VAR_CHR: { int id=message.readInt32(); string name=message.readString(); string value=message.readString(); Program.storage.setQuestVar(id, name, value); } break; case Protocol.GAMSG_SET_VAR_WORLD: { string name=message.readString(); string value=message.readString(); // save the new value to the database Program.storage.setWorldStateVar(name, value); // relay the new value to all gameservers foreach(NetComputer client in clients) { MessageOut varUpdateMessage=new MessageOut(Protocol.AGMSG_SET_VAR_WORLD); varUpdateMessage.writeString(name); varUpdateMessage.writeString(value); client.send(varUpdateMessage); } } break; case Protocol.GAMSG_SET_VAR_MAP: { int mapid=message.readInt32(); string name=message.readString(); string value=message.readString(); Program.storage.setWorldStateVar(name, mapid, value); } break; case Protocol.GAMSG_BAN_PLAYER: { int id=message.readInt32(); int duration=message.readInt32(); Program.storage.banCharacter(id, duration); } break; case Protocol.GAMSG_CHANGE_PLAYER_LEVEL: { int id=message.readInt32(); int level=message.readInt16(); Program.storage.setPlayerLevel(id, level); } break; case Protocol.GAMSG_CHANGE_ACCOUNT_LEVEL: { int id=message.readInt32(); int level=message.readInt16(); // get the character so we can get the account id Character c=Program.storage.getCharacter(id, null); if(c!=null) { Program.storage.setAccountLevel(c.getAccountID(), level); } } break; case Protocol.GAMSG_STATISTICS: { //while (message.getUnreadLength()!=0) //{ // int mapId = message.readInt16(); // ServerStatistics::iterator i = server.maps.find(mapId); // if (i == server.maps.end()) // { // Logger.Add(LogLevel.Error, "Server {0}:{1} should not be sending statistics for map {2}.", server.address, server.port, mapId); // // Skip remaining data. // break; // } // MapStatistics m = i.second; // m.nbThings =(ushort) message.readInt16(); // m.nbMonsters=(ushort)message.readInt16(); // int nb = message.readInt16(); // m.players.resize(nb); // for (int j = 0; j < nb; ++j) // { // m.players[j] = message.readInt32(); // } //} } break; case Protocol.GCMSG_REQUEST_POST: { // Retrieve the post for user Logger.Write(LogLevel.Debug, "GCMSG_REQUEST_POST"); result.writeInt16((int)Protocol.CGMSG_POST_RESPONSE); // get the character id int characterId=message.readInt32(); // send the character id of sender result.writeInt32(characterId); // get the character based on the id Character ptr=Program.storage.getCharacter(characterId, null); if(ptr!=null) { // Invalid character Logger.Write(LogLevel.Error, "Error finding character id for post"); break; } // get the post for that character Post post=Program.postalManager.getPost(ptr); // send the post if valid if(post!=null) { for(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()); List<InventoryItem> items=letter.getAttachments(); for(uint j=0; j<items.Count; ++j) { result.writeInt16((int)items[(int)j].itemId); result.writeInt16((int)items[(int)j].amount); } } // clean up Program.postalManager.clearPost(ptr); } } break; case Protocol.GCMSG_STORE_POST: { //// Store the letter for the user //Logger.Add(LogLevel.Debug, "GCMSG_STORE_POST"); //result.writeInt16((int)Protocol.CGMSG_STORE_POST_RESPONSE); //// get the sender and receiver //int senderId = message.readInt32(); //string receiverName = message.readString(); //// for sending it back //result.writeInt32(senderId); //// get their characters //Character sender = Program.storage.getCharacter(senderId, null); //Character receiver=Program.storage.getCharacter(receiverName); //if (sender!=null || receiver!=null) //{ // // Invalid character // Logger.Add(LogLevel.Error, "Error finding character id for post"); // result.writeInt8(ManaServ.ERRMSG_INVALID_ARGUMENT); // break; //} //// get the letter contents //string contents = message.readString(); //List<Pair<int>> items; //while (message.getUnreadLength()!=0) //{ // items.Add(new Pair<int>(message.readInt16(), message.readInt16())); //} //// save the letter //Logger.Add(LogLevel.Debug, "Creating letter"); //Letter letter = new Letter(0, sender, receiver); //letter.addText(contents); //for (uint i = 0; i < items.Count; ++i) //{ // InventoryItem item; // item.itemId = items[i].first; // item.amount = items[i].second; // letter.addAttachment(item); //} //Program.postalManager.addLetter(letter); //result.writeInt8(ManaServ.ERRMSG_OK); } break; case Protocol.GAMSG_TRANSACTION: { Logger.Write(LogLevel.Debug, "TRANSACTION"); int id=message.readInt32(); int action=message.readInt32(); string messageS=message.readString(); Transaction trans=new Transaction(); trans.mCharacterId=(uint)id; trans.mAction=(uint)action; trans.mMessage=messageS; Program.storage.addTransaction(trans); } break; case Protocol.GCMSG_PARTY_INVITE: Program.chatHandler.handlePartyInvite(message); break; case Protocol.GAMSG_CREATE_ITEM_ON_MAP: { int mapId=message.readInt32(); int itemId=message.readInt32(); int amount=message.readInt16(); int posX=message.readInt16(); int posY=message.readInt16(); Logger.Write(LogLevel.Debug, "Gameserver create item {0} on map {1} ", itemId, mapId); Program.storage.addFloorItem(mapId, itemId, amount, posX, posY); } break; case Protocol.GAMSG_REMOVE_ITEM_ON_MAP: { int mapId=message.readInt32(); int itemId=message.readInt32(); int amount=message.readInt16(); int posX=message.readInt16(); int posY=message.readInt16(); Logger.Write(LogLevel.Debug, "Gameserver removed item {0} from map {1}", itemId, mapId); Program.storage.removeFloorItem(mapId, itemId, amount, posX, posY); } break; default: { Logger.Write(LogLevel.Warning, "ServerHandler::processMessage, Invalid message type: {0}", message.getId()); result.writeInt16((int)Protocol.XXMSG_INVALID); break; } } // return result if(result.getLength()>0) { computer.send(result); } }
void handleListChannelUsersMessage(ChatClient client, MessageIn msg) { MessageOut reply=new MessageOut(Protocol.CPMSG_LIST_CHANNELUSERS_RESPONSE); string channelName=msg.readString(); ChatChannel channel=Program.chatChannelManager.getChannel(channelName); if(channel!=null) { reply.writeString(channel.getName()); List<ChatClient> users=channel.getUserList(); foreach(ChatClient user in users) { reply.writeString(user.characterName); reply.writeString(channel.getUserMode(user)); } client.send(reply); } // log transaction Transaction trans=new Transaction(); trans.mCharacterId=client.characterId; trans.mAction=(uint)TransactionMembers.TRANS_CHANNEL_USERLIST; Program.storage.addTransaction(trans); }
void 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 Logger.Write(LogLevel.Debug, "Sending GCMSG_STORE_POST."); MessageOut outmsg=new MessageOut(Protocol.GCMSG_STORE_POST); outmsg.writeInt32(c.getDatabaseID()); outmsg.writeString(msg.readString()); // name of receiver outmsg.writeString(msg.readString()); // content of letter while(msg.getUnreadLength()>0) // attachments { // write the item id and amount for each attachment outmsg.writeInt32(msg.readInt16()); outmsg.writeInt32(msg.readInt16()); } send(outmsg); }
protected override void processMessage(NetComputer computer, MessageIn message) { GameClient client=(GameClient)computer; if(client.status==(int)AccountClientStatus.CLIENT_LOGIN) { if(message.getId()!=Protocol.PGMSG_CONNECT) return; string magic_token=message.readString(); client.status=(int)AccountClientStatus.CLIENT_QUEUED; // Before the addPendingClient mTokenCollector.addPendingClient(magic_token, client); return; } else if(client.status!=(int)AccountClientStatus.CLIENT_CONNECTED) { return; } switch(message.getId()) { case Protocol.PGMSG_SAY: { handleSay(client, message); break; } case Protocol.PGMSG_NPC_TALK: case Protocol.PGMSG_NPC_TALK_NEXT: case Protocol.PGMSG_NPC_SELECT: case Protocol.PGMSG_NPC_NUMBER: case Protocol.PGMSG_NPC_STRING: { handleNpc(client, message); break; } case Protocol.PGMSG_PICKUP: { handlePickup(client, message); break; } case Protocol.PGMSG_USE_ITEM: { handleUseItem(client, message); break; } case Protocol.PGMSG_DROP: { handleDrop(client, message); break; } case Protocol.PGMSG_WALK: { handleWalk(client, message); break; } case Protocol.PGMSG_EQUIP: { handleEquip(client, message); break; } case Protocol.PGMSG_UNEQUIP: { handleUnequip(client, message); break; } case Protocol.PGMSG_MOVE_ITEM: { handleMoveItem(client, message); break; } case Protocol.PGMSG_ATTACK: { handleAttack(client, message); break; } case Protocol.PGMSG_USE_SPECIAL: { handleUseSpecial(client, message); break; } case Protocol.PGMSG_ACTION_CHANGE: { handleActionChange(client, message); break; } case Protocol.PGMSG_DIRECTION_CHANGE: { handleDirectionChange(client, message); break; } case Protocol.PGMSG_DISCONNECT: { handleDisconnect(client, message); break; } case Protocol.PGMSG_TRADE_REQUEST: { handleTradeRequest(client, message); break; } case Protocol.PGMSG_TRADE_CANCEL: case Protocol.PGMSG_TRADE_AGREED: case Protocol.PGMSG_TRADE_CONFIRM: case Protocol.PGMSG_TRADE_ADD_ITEM: case Protocol.PGMSG_TRADE_SET_MONEY: { handleTrade(client, message); break; } case Protocol.PGMSG_NPC_BUYSELL: { handleNpcBuySell(client, message); break; } case Protocol.PGMSG_RAISE_ATTRIBUTE: { handleRaiseAttribute(client, message); break; } case Protocol.PGMSG_LOWER_ATTRIBUTE: { handleLowerAttribute(client, message); break; } case Protocol.PGMSG_RESPAWN: { // plausibility check is done by character class client.character.respawn(); break; } case Protocol.PGMSG_NPC_POST_SEND: { handleNpcPostSend(client, message); break; } case Protocol.PGMSG_PARTY_INVITE: { handlePartyInvite(client, message); break; } default: { Logger.Write(LogLevel.Warning, "Invalid message type"); client.send(new MessageOut(Protocol.XXMSG_INVALID)); break; } } }