/// <summary> /// Internal use only, fetches the correct handler for a given handler name. One packet name may map to multiple handler names. /// </summary> /// <param name="parserName">The packet handler to fetch</param> /// <returns></returns> private GamePacketParser GetPacketParser(String parserName) { if (parserName == "ErrorMessage") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Message"] = nmsg.ReadString(); return props; } } ; else if (parserName == "MOTD") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Message"] = nmsg.ReadString(); return props; } } ; else if (parserName == "Ping") { return delegate(NetworkMessage nmsg) { return new Packet(parserName); } } ; else if (parserName == "PlayerLogin") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); Player = new ClientPlayer(nmsg.ReadU32()); props["DrawSpeed"] = nmsg.ReadU16(); props["CanReportBugs"] = nmsg.ReadByte() != 0; props["Player"] = Player; KnownCreatures[Player.ID] = Player; return props; } } ; else if (parserName == "MapDescription") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); CurrentPosition = ReadMapPosition(nmsg); props["Center"] = CurrentPosition; props["Tiles"] = ReadMapDescription(nmsg, CurrentPosition.X - 8, CurrentPosition.Y - 6, CurrentPosition.Z, 18, 14); return props; } } ; else if (parserName == "UpdateInventory") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Slot"] = (int)nmsg.ReadByte(); props["Thing"] = ReadThing(nmsg); return props; } } ; else if (parserName == "ClearInventory") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Slot"] = (int)nmsg.ReadByte(); return props; } } ; else if (parserName == "OpenContainer") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); int ContainerID = (int)nmsg.ReadByte(); props["ContainerID"] = ContainerID; int ClientID = nmsg.ReadU16(); ItemType it = GameData.GetItemType(ClientID); if (it == null) { Log.Warning("OpenContainer contains unrecognized item type (" + ClientID.ToString() + ").", this); it = ItemType.NullType; } props["Thing"] = new ClientContainer(it, ContainerID); props["Name"] = nmsg.ReadString(); props["Volume"] = (int)nmsg.ReadByte(); props["IsChild"] = nmsg.ReadByte() != 0; int ItemCount = nmsg.ReadByte(); props["ItemCount"] = (int)ItemCount; List <ClientItem> contents = new List <ClientItem>(); for (int i = 0; i < ItemCount; ++i) { contents.Add((ClientItem)ReadThing(nmsg)); } props["Contents"] = contents; return props; } } ; else if (parserName == "CloseContainer") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["ContainerID"] = (int)nmsg.ReadByte(); return props; } } ; else if (parserName == "ContainerAddItem") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["ContainerID"] = (int)nmsg.ReadByte(); props["Item"] = ReadItem(nmsg); return props; } } ; else if (parserName == "ContainerTransformItem") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["ContainerID"] = (int)nmsg.ReadByte(); props["Slot"] = (int)nmsg.ReadByte(); props["Item"] = ReadItem(nmsg); return props; } } ; else if (parserName == "ContainerRemoveItem") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["ContainerID"] = (int)nmsg.ReadByte(); props["Slot"] = (int)nmsg.ReadByte(); return props; } } ; else if (parserName == "UpdateStats") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Health"] = (int)nmsg.ReadU16(); props["MaxHealth"] = (int)nmsg.ReadU16(); props["Capacity"] = (int)nmsg.ReadU16(); props["Experience"] = (int)nmsg.ReadU32(); props["Level"] = (int)nmsg.ReadByte(); props["LevelPercent"] = (int)nmsg.ReadByte(); props["Mana"] = (int)nmsg.ReadU16(); props["MaxMana"] = (int)nmsg.ReadU16(); props["MagicLevel"] = (int)nmsg.ReadByte(); props["MagicLevelPercent"] = (int)nmsg.ReadByte(); // TODO: Stamina for some versions //int soul = nmsg.ReadByte(); //int staminaMinutes = nmsg.ReadU16(); return props; } } ; else if (parserName == "UpdateSkills") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Fist"] = (int)nmsg.ReadByte(); props["FistPercent"] = (int)nmsg.ReadByte(); props["Club"] = (int)nmsg.ReadByte(); props["ClubPercent"] = (int)nmsg.ReadByte(); props["Sword"] = (int)nmsg.ReadByte(); props["SwordPercent"] = (int)nmsg.ReadByte(); props["Axe"] = (int)nmsg.ReadByte(); props["AxePercent"] = (int)nmsg.ReadByte(); props["Dist"] = (int)nmsg.ReadByte(); props["DistPercent"] = (int)nmsg.ReadByte(); props["Shield"] = (int)nmsg.ReadByte(); props["ShieldPercent"] = (int)nmsg.ReadByte(); props["Fish"] = (int)nmsg.ReadByte(); props["FishPercent"] = (int)nmsg.ReadByte(); return props; } } ; else if (parserName == "PlayerIcons") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["ConditionState"] = (ConditionState)nmsg.ReadByte(); return props; } } ; else if (parserName == "CancelAttack") { return delegate(NetworkMessage nmsg) { return new Packet(parserName); } } ; else if (parserName == "CancelWalk") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Direction"] = (Direction)nmsg.ReadByte(); return props; } } ; else if (parserName == "Death") { return delegate(NetworkMessage nmsg) { return new Packet(parserName); } } ; else if (parserName == "CanReport") { return delegate(NetworkMessage nmsg) { return new Packet(parserName); } } ; else if (parserName == "MoveNorth") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); CurrentPosition.Y--; props["Center"] = CurrentPosition; props["Tiles"] = ReadMapDescription(nmsg, CurrentPosition.X - 8, CurrentPosition.Y - 6, CurrentPosition.Z, 18, 1); return props; } } ; else if (parserName == "MoveSouth") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); CurrentPosition.Y++; props["Center"] = CurrentPosition; props["Tiles"] = ReadMapDescription(nmsg, CurrentPosition.X - 8, CurrentPosition.Y + 7, CurrentPosition.Z, 18, 1); return props; } } ; else if (parserName == "MoveWest") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); CurrentPosition.X--; props["Center"] = CurrentPosition; props["Tiles"] = ReadMapDescription(nmsg, CurrentPosition.X - 8, CurrentPosition.Y - 6, CurrentPosition.Z, 1, 14); return props; } } ; else if (parserName == "MoveEast") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); CurrentPosition.X++; props["Center"] = CurrentPosition; props["Tiles"] = ReadMapDescription(nmsg, CurrentPosition.X + 9, CurrentPosition.Y - 6, CurrentPosition.Z, 1, 14); return props; } } ; else if (parserName == "FloorUp") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); List <ClientTile> Tiles = new List <ClientTile>(); int skipTiles = 0; CurrentPosition.Z--; if (CurrentPosition.Z == 7) { for (int i = 5; i >= 0; i--) { Tiles.AddRange(ReadFloorDescription(nmsg, ref skipTiles, CurrentPosition.X - 8, CurrentPosition.Y - 6, i, 18, 14, 8 - i)); } } else if (CurrentPosition.Z > 7) { Tiles.AddRange(ReadFloorDescription(nmsg, ref skipTiles, CurrentPosition.X - 8, CurrentPosition.Y - 6, CurrentPosition.Z - 2, 18, 14, 3)); } CurrentPosition.X++; CurrentPosition.Y++; props["Tiles"] = Tiles; props["Center"] = CurrentPosition; return props; } } ; else if (parserName == "FloorDown") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); List <ClientTile> Tiles = new List <ClientTile>(); int skipTiles = 0; CurrentPosition.Z++; if (CurrentPosition.Z == 8) { int j = -1; for (int i = CurrentPosition.Z; i < CurrentPosition.Z + 3; ++i, --j) { Tiles.AddRange(ReadFloorDescription(nmsg, ref skipTiles, CurrentPosition.X - 8, CurrentPosition.Y - 6, i, 18, 14, j)); } } else if (CurrentPosition.Z > 8 && CurrentPosition.Z < 14) { Tiles.AddRange(ReadFloorDescription(nmsg, ref skipTiles, CurrentPosition.X - 8, CurrentPosition.Y - 6, CurrentPosition.Z + 2, 18, 14, -3)); } CurrentPosition.X--; CurrentPosition.Y--; props["Tiles"] = Tiles; props["Center"] = CurrentPosition; return props; } } ; else if (parserName == "RefreshTile") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); MapPosition pos = ReadMapPosition(nmsg); props["Position"] = pos; props["Clear"] = false; if (nmsg.PeekU16() == 0xFF01) { nmsg.ReadU16(); props["Clear"] = true; return props; } else { props["NewTile"] = ReadTileDescription(nmsg, pos); // Skip extra bytes after data (it signifies the end of data) nmsg.ReadU16(); return props; } } } ; else if (parserName == "AddThing") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Position"] = ReadMapPosition(nmsg); props["Thing"] = ReadThing(nmsg); props["Push"] = true; // TODO: >= 8.53, push thing should be false return props; } } ; else if (parserName == "TransformThing") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Position"] = ReadMapPosition(nmsg); props["StackIndex"] = (int)nmsg.ReadByte(); if (nmsg.PeekU16() == 0x63) { nmsg.Skip(2); // CreatureTurn2 props["Thing"] = KnownCreatures[nmsg.ReadU32()]; props["Direction"] = (Direction)nmsg.ReadByte(); } else { props["Thing"] = ReadThing(nmsg); } return props; } } ; else if (parserName == "RemoveThing") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Position"] = ReadMapPosition(nmsg); props["StackIndex"] = (int)nmsg.ReadByte(); return props; } } ; else if (parserName == "CreatureMove") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["OldPosition"] = ReadMapPosition(nmsg); props["OldStackIndex"] = (int)nmsg.ReadByte(); props["Position"] = ReadMapPosition(nmsg); if ((int)props["OldStackIndex"] > 9) { Log.Warning("CreatureMove - Old stack pos out of range.", this); } props["Push"] = true; // TODO: >= 8.53, pushThing = false return props; } } ; else if (parserName == "WorldLight") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Level"] = (int)nmsg.ReadByte(); props["Color"] = (int)nmsg.ReadByte(); return props; } } ; else if (parserName == "Effect") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Position"] = ReadMapPosition(nmsg); props["Effect"] = 1 + (int)nmsg.ReadByte(); return props; } } ; else if (parserName == "AnimatedText") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Position"] = ReadMapPosition(nmsg); props["Color"] = (int)nmsg.ReadByte(); props["Text"] = nmsg.ReadString(); return props; } } ; else if (parserName == "ShootEffect") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["From"] = ReadMapPosition(nmsg); props["To"] = ReadMapPosition(nmsg); props["Effect"] = (int)nmsg.ReadByte(); return props; } } ; else if (parserName == "SquareEffect") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Creature"] = KnownCreatures[nmsg.ReadU32()]; props["Color"] = nmsg.ReadByte(); return props; } } ; else if (parserName == "CreatureHealth") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Creature"] = KnownCreatures[nmsg.ReadU32()]; props["Health"] = (int)nmsg.ReadByte(); return props; } } ; else if (parserName == "CreatureLight") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Creature"] = KnownCreatures[nmsg.ReadU32()]; props["Level"] = (int)nmsg.ReadByte(); props["Color"] = (int)nmsg.ReadByte(); return props; } } ; else if (parserName == "CreatureRefresh") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Creature"] = KnownCreatures[nmsg.ReadU32()]; return props; } } ; else if (parserName == "CreatureTurn") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Creature"] = KnownCreatures[nmsg.ReadU32()]; props["Direction"] = (Direction)nmsg.ReadByte(); return props; } } ; else if (parserName == "CreatureSpeed") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Creature"] = KnownCreatures[nmsg.ReadU32()]; props["Speed"] = (int)nmsg.ReadU16(); return props; } } ; else if (parserName == "CreatureSkull") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Creature"] = KnownCreatures[nmsg.ReadU32()]; props["Skull"] = (CreatureSkull)nmsg.ReadByte(); return props; } } ; else if (parserName == "CreatureShield") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["Creature"] = KnownCreatures[nmsg.ReadU32()]; props["PartyShield"] = (PartyShield)nmsg.ReadByte(); return props; } } ; else if (parserName == "CreatureSpeak") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); ClientMessage Message = new ClientMessage(); //props["Creature"] = KnownCreatures[nmsg.ReadU32()]; Message.Speaker = nmsg.ReadString(); //props["Level"] = nmsg.ReadU16(); Message.Type = (MessageType)nmsg.ReadByte(); switch (Message.Type) { case MessageType.Say: case MessageType.Whisper: case MessageType.Yell: case MessageType.MonsterSay: case MessageType.MonsterYell: case MessageType.PrivateNPCToPlayer: case MessageType.PrivatePlayerToNPC: { props["Position"] = ReadMapPosition(nmsg); Message.Text = nmsg.ReadString(); break; } case MessageType.ChannelAnonymousRed: case MessageType.ChannelOrange: case MessageType.ChannelRed: case MessageType.ChannelYellow: { props["ChannelID"] = nmsg.ReadU16(); Message.Text = nmsg.ReadString(); break; } case MessageType.Private: case MessageType.Broadcast: case MessageType.PrivateRed: { Message.Text = nmsg.ReadString(); break; } case MessageType.ReportRuleViolation: { Message.Time = Common.UnixTime(nmsg.ReadU32()); // time Message.Text = nmsg.ReadString(); break; } case MessageType.RuleViolationGameMaster: case MessageType.RuleViolationPlayer: { Message.Text = nmsg.ReadString(); break; } default: Log.Warning("Unknown speak class " + (int)props["MessageType"], this); return null; } props["Message"] = Message; return props; } } ; else if (parserName == "ChannelList") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); int count = nmsg.ReadByte(); props["ChannelCount"] = count; while (count > 0) { int channelID = nmsg.ReadU16(); string channelName = nmsg.ReadString(); --count; } return null; } } ; else if (parserName == "OpenChannel") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["ChannelID"] = nmsg.ReadU16(); props["ChannelName"] = nmsg.ReadString(); return props; } } ; else if (parserName == "OpenPrivateChat") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["PlayerName"] = nmsg.ReadString(); return props; } } ; else if (parserName == "TextMessage") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); MessageType Type = (MessageType)nmsg.ReadByte(); String Text = nmsg.ReadString(); props["Message"] = new ClientMessage(Type, DateTime.Now, Text); return props; } } ; else if (parserName == "VIPState") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["CreatureID"] = nmsg.ReadU32(); props["Name"] = nmsg.ReadString(); props["Online"] = nmsg.ReadByte() != 0; return props; } } ; else if (parserName == "VIPLogin") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["CreatureID"] = nmsg.ReadU32(); return props; } } ; else if (parserName == "VIPLogout") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); props["CreatureID"] = nmsg.ReadU32(); return props; } } ; else if (parserName == "RuleViolationChannel") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); return props; } } ; else if (parserName == "RuleViolationRemove") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); return props; } } ; else if (parserName == "RuleViolationCancel") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); return props; } } ; else if (parserName == "RuleViolationLock") { return delegate(NetworkMessage nmsg) { Packet props = new Packet(parserName); return props; } } ; throw new System.ArgumentException("Unknown packet handler."); }