private void ParseOpenContainer(Internal.ByteArray message) { byte containerId = message.ReadUnsignedByte(); var objectIcon = ReadObjectInstance(message); string name = message.ReadString(); byte nOfSlotsPerPage = message.ReadUnsignedByte(); // capacity of shown view bool isSubContainer = message.ReadBoolean(); bool isDragAndDropEnabled = true; bool isPaginationEnabled = false; int nOfTotalObjects = 0; int indexOfFirstObject = 0; int nOfContentObjects = 0; // objects in the current shown view // if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameContainerPagination)) { isDragAndDropEnabled = message.ReadBoolean(); isPaginationEnabled = message.ReadBoolean(); nOfTotalObjects = message.ReadUnsignedShort(); indexOfFirstObject = message.ReadUnsignedShort(); nOfContentObjects = message.ReadUnsignedByte(); if (nOfContentObjects > nOfSlotsPerPage) { throw new System.Exception("ProtocolGame.ParseOpenContainer: Number of content objects " + nOfContentObjects + " exceeds number of slots per page " + nOfSlotsPerPage); } if (nOfContentObjects > nOfTotalObjects) { throw new System.Exception("Connection.readSCONTAINER: Number of content objects " + nOfContentObjects + " exceeds number of total objects " + nOfTotalObjects); } } else { nOfContentObjects = message.ReadUnsignedByte(); nOfTotalObjects = nOfContentObjects; if (nOfContentObjects > nOfSlotsPerPage) { throw new System.Exception("ProtocolGame.ParseOpenContainer: Number of content objects " + nOfContentObjects + " exceeds the capaciy " + nOfSlotsPerPage); } } var containerView = ContainerStorage.CreateContainerView(containerId, objectIcon, name, isSubContainer, isDragAndDropEnabled, isPaginationEnabled, nOfSlotsPerPage, nOfTotalObjects - nOfContentObjects, indexOfFirstObject); for (int i = 0; i < nOfContentObjects; i++) { containerView.AddObject(indexOfFirstObject + i, ReadObjectInstance(message)); } }
private void ParseBuddyGroupData(Internal.ByteArray message) { int groups = message.ReadUnsignedByte(); for (int i = 0; i < groups; i++) { message.ReadUnsignedByte(); // id message.ReadString(); // name message.ReadUnsignedByte(); // idk } message.ReadUnsignedByte(); // premium/free iirc (since free players are allowed only for 5 groups) }
private void ParseAutomapFlag(Internal.ByteArray message) { var absolutePosition = message.ReadPosition(); int icon = message.ReadUnsignedByte(); var description = message.ReadString(); bool remove = false; if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameMinimapRemove)) { remove = message.ReadBoolean(); } }
private void ParseMarketDetail(Internal.ByteArray message) { ushort objectId = message.ReadUnsignedShort(); var last = MarketDetails.Weight; if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameImbuing)) { last = MarketDetails.ImbuementSlots; } Dictionary <MarketDetails, string> details = new Dictionary <MarketDetails, string>(); for (var i = MarketDetails.First; i <= last; i++) { int strLen = message.ReadUnsignedShort(); if (strLen == 0) { continue; } details.Add(i, message.ReadString(strLen)); } int time = DateTime.Now.Second / 1000 * Constants.SecondsPerDay; int ctime = time; int count = message.ReadUnsignedByte(); for (int i = 0; i < count; i++) { uint transactions = message.ReadUnsignedInt(); uint totalPrice = message.ReadUnsignedInt(); uint maximumPrice = message.ReadUnsignedInt(); uint minimumPrice = message.ReadUnsignedInt(); ctime -= Constants.SecondsPerDay; } ctime = time; count = message.ReadUnsignedByte(); for (int i = 0; i < count; i++) { uint transactions = message.ReadUnsignedInt(); uint totalPrice = message.ReadUnsignedInt(); uint maximumPrice = message.ReadUnsignedInt(); uint minimumPrice = message.ReadUnsignedInt(); ctime -= Constants.SecondsPerDay; } }
private void ParseOwnOffer(Internal.ByteArray message) { string creatureName = message.ReadString(); var objects = new List <Appearances.ObjectInstance>(); int size = message.ReadUnsignedByte(); for (int i = 0; i < size; i++) { objects.Add(ReadObjectInstance(message)); } OpenTibiaUnity.GameManager.onRequestOwnOffer.Invoke(creatureName, objects); }
private void ParseTrackedQuestFlags(Internal.ByteArray message) { bool full = message.ReadUnsignedByte() == 1; if (full) { int unknown2 = message.ReadUnsignedByte(); int size = message.ReadUnsignedByte(); for (int i = 0; i < size; i++) { int missionId = message.ReadUnsignedShort(); string questName = message.ReadString(); string missionName = message.ReadString(); string missionDescription = message.ReadString(); } } else { int missionId = message.ReadUnsignedShort(); string questName = message.ReadString(); string missionName = message.ReadString(); } }
private void ParseOpenChannel(Internal.ByteArray message) { int channelId = message.ReadUnsignedShort(); string channelName = message.ReadString(); Chat.Channel channel = ChatStorage.AddChannel(channelId, channelName, MessageModeType.Channel); channel.CanModerate = true; if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameChannelPlayerList)) { int joinedUsers = message.ReadUnsignedShort(); for (int i = 0; i < joinedUsers; i++) { channel.PlayerJoined(message.ReadString()); } int invitedUsers = message.ReadUnsignedShort(); for (int i = 0; i < invitedUsers; i++) { channel.PlayerInvited(message.ReadString()); } } }
private void ParseOpenRewardWall(Internal.ByteArray message) { message.ReadBoolean(); // openedFromShrine message.ReadUnsignedInt(); // timestamp for the player to be able to take the reward (0 = able) message.ReadUnsignedByte(); // currentRewardIndex bool showWarningWhenCollecting = message.ReadUnsignedByte() != 0; // showWarningWhenCollecting if (showWarningWhenCollecting) { message.ReadString(); // warningMessage } message.ReadUnsignedInt(); // timestamp for the streak to expire (0 = won't expire until server save) message.ReadUnsignedShort(); // current streak message.ReadUnsignedShort(); // unknown }
private void ParseLoginSuccess(Internal.ByteArray message) { Player.ID = message.ReadUnsignedInt(); #if !UNITY_EDITOR string title = string.Format("{0} - {1}", Application.productName, Player.Name); OpenTibiaUnity.GameManager.SetApplicationTitle(title); #endif BeatDuration = message.ReadUnsignedShort(); if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameNewSpeedLaw)) { Creatures.Creature.SpeedA = message.ReadDouble(); Creatures.Creature.SpeedB = message.ReadDouble(); Creatures.Creature.SpeedC = message.ReadDouble(); } BugReportsAllowed = message.ReadBoolean(); if (OpenTibiaUnity.GameManager.ClientVersion >= 1054) { bool canChangePvPFrameRate = message.ReadBoolean(); } if (OpenTibiaUnity.GameManager.ClientVersion >= 1058) { bool exportPvPEnabled = message.ReadBoolean(); } if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameIngameStore)) { string storeLink = message.ReadString(); ushort storePackageSize = message.ReadUnsignedShort(); } if (OpenTibiaUnity.GameManager.ClientVersion >= 1149 && OpenTibiaUnity.GameManager.BuildVersion >= 6018) { bool exivaRestrictions = message.ReadBoolean(); } if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameTournament)) { bool tournamentActivated = message.ReadBoolean(); } }
private void ParseDailyRewardBasic(Internal.ByteArray message) { int count = message.ReadUnsignedByte(); for (int i = 0; i < count; i++) { var freeReward = ReadDailyReward(message); var premiumReward = ReadDailyReward(message); } count = message.ReadUnsignedByte(); for (int i = 0; i < count; i++) { string bonusName = message.ReadString(); int streakRequired = message.ReadUnsignedByte(); } message.ReadUnsignedByte(); // activeBonuses }
private Market.Offer ReadMarketOffer(Internal.ByteArray message, MarketOfferTypes offerType, ushort var) { uint timestamp = message.ReadUnsignedInt(); ushort counter = message.ReadUnsignedShort(); ushort objectId; switch (var) { case Constants.MarketRequestOwnOffers: case Constants.MarketRequestOwnHistory: objectId = message.ReadUnsignedShort(); break; default: objectId = var; break; } ushort amount = message.ReadUnsignedShort(); uint piecePrice = message.ReadUnsignedInt(); MarketOfferStates state = MarketOfferStates.Active; string character = null; switch (var) { case Constants.MarketRequestOwnOffers: break; case Constants.MarketRequestOwnHistory: state = (MarketOfferStates)message.ReadUnsignedByte(); break; default: character = message.ReadString(); break; } return(new Market.Offer(new Market.OfferId(counter, timestamp), offerType, objectId, amount, piecePrice, character, state)); }
private void ParsePrivateChannel(Internal.ByteArray message) { string channelName = message.ReadString(); ChatStorage.AddChannel(channelName, channelName, MessageModeType.PrivateTo); }
private void ParseLoginAdvice(Internal.ByteArray message) { string advice = message.ReadString(); onLoginAdvice.Invoke(advice); }
private void ParseLoginError(Internal.ByteArray message) { string error = message.ReadString(); onLoginError.Invoke(error); }
private void ParseReadyForSecondaryConnection(Internal.ByteArray message) { var sessionKey = message.ReadString(); }
private Creatures.Creature ReadCreatureInstance(Internal.ByteArray message, int type = -1, UnityEngine.Vector3Int?absolutePosition = null) { if (type == -1) { type = message.ReadUnsignedShort(); } if (type != AppearanceInstance.Creature && type != AppearanceInstance.OutdatedCreature && type != AppearanceInstance.UnknownCreature) { throw new System.Exception("ProtocolGame.ReadCreatureInstance: Invalid creature type"); } var gameManager = OpenTibiaUnity.GameManager; Creatures.Creature creature; switch (type) { case AppearanceInstance.UnknownCreature: case AppearanceInstance.OutdatedCreature: { if (type == AppearanceInstance.UnknownCreature) { uint removeID = message.ReadUnsignedInt(); uint newID = message.ReadUnsignedInt(); CreatureType creatureType; if (gameManager.ClientVersion >= 910) { creatureType = message.ReadEnum <CreatureType>(); } else { if (newID >= Constants.PlayerStartID && newID < Constants.PlayerEndID) { creatureType = CreatureType.Player; } else if (newID >= Constants.MonsterStartID && newID < Constants.MonsterEndID) { creatureType = CreatureType.Monster; } else { creatureType = CreatureType.NPC; } } if (newID == Player.ID) { creature = Player; } else { creature = new Creatures.Creature(newID); } creature = CreatureStorage.ReplaceCreature(creature, removeID); if (!creature) { throw new System.Exception("ProtocolGame.ReadCreatureInstance: Failed to append creature."); } creature.Type = creatureType; if (gameManager.ClientVersion >= 1120) { creature.SetSummonerID(creature.IsSummon ? message.ReadUnsignedInt() : 0); } creature.Name = message.ReadString(); } else { uint creatureId = message.ReadUnsignedInt(); creature = CreatureStorage.GetCreature(creatureId); if (!creature) { throw new System.Exception("ProtocolGame.ReadCreatureInstance: Outdated creature not found."); } } creature.SetSkill(SkillType.HealthPercent, message.ReadUnsignedByte()); creature.Direction = message.ReadEnum <Direction>(); creature.Outfit = ReadCreatureOutfit(message, creature.Outfit); if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GamePlayerMounts)) { creature.MountOutfit = ReadMountOutfit(message, creature.MountOutfit); } creature.Brightness = message.ReadUnsignedByte(); creature.LightColor = Colors.ColorFrom8Bit(message.ReadUnsignedByte()); creature.SetSkill(SkillType.Speed, message.ReadUnsignedShort()); creature.SetPKFlag(message.ReadEnum <PKFlag>()); creature.SetPartyFlag(message.ReadEnum <PartyFlag>()); if (gameManager.GetFeature(GameFeature.GameCreatureEmblems) && type == AppearanceInstance.UnknownCreature) { creature.SetGuildFlag(message.ReadEnum <GuildFlag>()); } if (gameManager.GetFeature(GameFeature.GameCreatureMarks)) { creature.Type = message.ReadEnum <CreatureType>(); if (gameManager.ClientVersion >= 1120) { creature.SetSummonerID(creature.IsSummon ? message.ReadUnsignedInt() : 0); } } if (gameManager.GetFeature(GameFeature.GameCreatureIcons)) { creature.SetSpeechCategory(message.ReadEnum <SpeechCategory>()); } if (gameManager.GetFeature(GameFeature.GameCreatureMarks)) { creature.Marks.SetMark(MarkType.Permenant, message.ReadUnsignedByte()); if (gameManager.GetFeature(GameFeature.GameInspectionWindow)) { message.ReadUnsignedByte(); // inspection state } if (gameManager.ClientVersion < 1185) { creature.NumberOfPvPHelpers = message.ReadUnsignedShort(); } } if (gameManager.ClientVersion >= 854) { creature.Unpassable = message.ReadUnsignedByte() != 0; } else { creature.Unpassable = true; } break; } case AppearanceInstance.Creature: { uint creatureId = message.ReadUnsignedInt(); creature = CreatureStorage.GetCreature(creatureId); if (!creature) { throw new System.Exception(string.Format("ProtocolGame.ReadCreatureInstance: Known creature not found ({0}).", creatureId)); } creature.Direction = message.ReadEnum <Direction>(); if (gameManager.ClientVersion >= 953) { creature.Unpassable = message.ReadUnsignedByte() != 0; } break; } default: throw new System.Exception("ProtocolGame.ReadCreatureInstance: unknown creature identity type."); } if (absolutePosition.HasValue) { creature.Position = absolutePosition.Value; } CreatureStorage.MarkOpponentVisible(creature, true); CreatureStorage.InvalidateOpponents(); return(creature); }
private DailyReward.DailyReward ReadDailyReward(Internal.ByteArray message) { var rewardState = message.ReadEnum <DailyRewardStates>(); var reward = new DailyReward.DailyReward(rewardState); switch (rewardState) { case DailyRewardStates.PickedItems: { reward.AllowedMaximumItems = message.ReadUnsignedByte(); int objectCount = message.ReadUnsignedByte(); for (int i = 0; i < objectCount; i++) { ushort objectId = message.ReadUnsignedShort(); string objectName = message.ReadString(); uint objectWeight = message.ReadUnsignedInt(); reward.AddItem(new DailyReward.Types.Object(objectId, objectName, objectWeight, -1)); } break; } case DailyRewardStates.FixedItems: { int itemsCount = message.ReadUnsignedByte(); for (int i = 0; i < itemsCount; i++) { var rewardType = message.ReadEnum <DailyRewardTypes>(); switch (rewardType) { case DailyRewardTypes.Object: { ushort objectId = message.ReadUnsignedShort(); string objectName = message.ReadString(); int objectAmount = message.ReadUnsignedByte(); reward.AddItem(new DailyReward.Types.Object(objectId, objectName, 0, objectAmount)); break; } case DailyRewardTypes.PreyBonusRerolls: { int amount = message.ReadUnsignedByte(); reward.AddItem(new DailyReward.Types.PreyBonusRerolls(amount)); break; } case DailyRewardTypes.FiftyPercentXpBoost: { ushort minutes = message.ReadUnsignedShort(); reward.AddItem(new DailyReward.Types.XpBoost(minutes)); break; } default: throw new System.Exception("ProtocolGame.ReadDailyReward: Invalid reward type " + (int)rewardType + "."); } } break; } } return(reward); }
private void ParseRestingAreaState(Internal.ByteArray message) { message.ReadBoolean(); // unknown message.ReadBoolean(); // unknown message.ReadString(); }
private void ParseOtclientExtendedOpcode(Internal.ByteArray message) { message.ReadUnsignedByte(); message.ReadString(); }
private void ParseTextMessage(Internal.ByteArray message) { var mode = TranslateMessageModeFromServer(message.ReadUnsignedByte()); try { switch (mode) { case MessageModeType.ChannelManagement: int channelId = message.ReadUnsignedShort(); string text = message.ReadString(); // TODO name filter //var regex = new System.Text.RegularExpressions.Regex(@"^(.+?) invites you to |^You have been excluded from the channel ([^']+)'s Channel\.$"); //var match = regex.Match(text); //string speaker = match != null && match.Success ? match.Value : null; WorldMapStorage.AddOnscreenMessage(null, -1, null, 0, mode, text); ChatStorage.AddChannelMessage(channelId, -1, null, 0, mode, text); break; case MessageModeType.Guild: case MessageModeType.PartyManagement: case MessageModeType.Party: channelId = message.ReadUnsignedShort(); text = message.ReadString(); WorldMapStorage.AddOnscreenMessage(null, -1, null, 0, mode, text); ChatStorage.AddChannelMessage(channelId, -1, null, 0, mode, text); break; case MessageModeType.Login: case MessageModeType.Admin: case MessageModeType.Game: case MessageModeType.GameHighlight: case MessageModeType.Failure: case MessageModeType.Look: case MessageModeType.Status: case MessageModeType.Loot: case MessageModeType.TradeNpc: case MessageModeType.HotkeyUse: channelId = -1; text = message.ReadString(); WorldMapStorage.AddOnscreenMessage(null, -1, null, 0, mode, text); ChatStorage.AddChannelMessage(channelId, -1, null, 0, mode, text); break; case MessageModeType.Market: text = message.ReadString(); // TODO: market break; case MessageModeType.Report: // TODO //ReportWidget.s_ReportTimestampReset(); text = message.ReadString(); WorldMapStorage.AddOnscreenMessage(null, -1, null, 0, mode, text); ChatStorage.AddChannelMessage(-1, -1, null, 0, mode, text); break; case MessageModeType.DamageDealed: case MessageModeType.DamageReceived: case MessageModeType.DamageOthers: Vector3Int absolutePosition = message.ReadPosition(); int value = message.ReadInt(); int color = message.ReadUnsignedByte(); if (value > 0) { WorldMapStorage.AddOnscreenMessage(absolutePosition, -1, null, 0, mode, value, color); } value = message.ReadInt(); color = message.ReadUnsignedByte(); if (value > 0) { WorldMapStorage.AddOnscreenMessage(absolutePosition, -1, null, 0, mode, value, color); } text = message.ReadString(); ChatStorage.AddChannelMessage(-1, -1, null, 0, mode, text); break; case MessageModeType.Heal: case MessageModeType.Mana: case MessageModeType.Exp: case MessageModeType.HealOthers: case MessageModeType.ExpOthers: absolutePosition = message.ReadPosition(); value = message.ReadInt(); color = message.ReadUnsignedByte(); WorldMapStorage.AddOnscreenMessage(absolutePosition, -1, null, 0, mode, value, color); text = message.ReadString(); ChatStorage.AddChannelMessage(-1, -1, null, 0, mode, text); break; default: text = message.ReadString(); ChatStorage.AddChannelMessage(-1, -1, null, 0, mode, text); break; } } catch (System.Exception e) { throw new System.Exception("ProtocolGame.ParseTextMessage: Failed to add message of type " + mode + ": " + e.Message + "\n" + e.StackTrace); } }
public void Parse(Internal.ByteArray message) { if (OpenTibiaUnity.GameManager.ClientVersion >= 1010) { byte worlds = message.ReadUnsignedByte(); for (int i = 0; i < worlds; i++) { var world = new World { _id = message.ReadUnsignedByte(), Name = message.ReadString(), HostName = message.ReadString(), Port = message.ReadUnsignedShort(), Preview = message.ReadBoolean() }; Worlds.Add(world); } byte characters = message.ReadUnsignedByte(); for (int i = 0; i < characters; i++) { Character character = new Character { WorldId = message.ReadUnsignedByte(), Name = message.ReadString() }; Characters.Add(character); } } else { byte characters = message.ReadUnsignedByte(); for (int i = 0; i < characters; i++) { var characterName = message.ReadString(); var worldName = message.ReadString(); var worldIpLong = message.ReadUnsignedInt(); var worldPort = message.ReadUnsignedShort(); var world = GetOrCreateWorld(worldName, worldIpLong, worldPort); var character = new Character { Name = characterName, WorldId = world._id }; Characters.Add(character); } } uint now = (uint)System.DateTime.Now.Second; if (OpenTibiaUnity.GameManager.ClientVersion >= 1077) { AccountState = message.ReadUnsignedByte(); IsPremium = message.ReadBoolean(); PremiumTimeStamp = message.ReadUnsignedInt(); if (PremiumTimeStamp > now) { PremiumDays = (ushort)((PremiumTimeStamp - now) / 86400U); } else { PremiumDays = 0; } InfinitePremium = (IsPremium && PremiumTimeStamp == 0); } else { AccountState = 0; PremiumDays = message.ReadUnsignedShort(); if (PremiumDays > 0) { PremiumTimeStamp = now + PremiumDays * 86400U; } else { PremiumTimeStamp = 0; } IsPremium = PremiumDays > 0; InfinitePremium = PremiumDays == 65535; } }
private void ParseOutfitDialog(Internal.ByteArray message) { var outfit = ReadCreatureOutfit(message); Appearances.AppearanceInstance mountOutfit = null; if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GamePlayerMounts)) { mountOutfit = ReadMountOutfit(message); } var outfitList = new List <ProtocolOutfit>(); if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameNewOutfitProtocol)) { int count; if (OpenTibiaUnity.GameManager.ClientVersion >= 1185) { count = message.ReadUnsignedShort(); } else { count = message.ReadUnsignedByte(); } for (int i = 0; i < count; i++) { ushort outfitId = message.ReadUnsignedShort(); var outfitName = message.ReadString(); int addOns = message.ReadUnsignedByte(); bool locked = true; uint offerId = 0; if (OpenTibiaUnity.GameManager.ClientVersion >= 1185) { locked = message.ReadBoolean(); if (locked) { offerId = message.ReadUnsignedInt(); } } outfitList.Add(new ProtocolOutfit() { _id = outfitId, Name = outfitName, AddOns = addOns, Locked = locked, StoreOfferId = offerId, }); } } else { ushort outfitStart, outfitEnd; if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameOutfitIdU16)) { outfitStart = message.ReadUnsignedShort(); outfitEnd = message.ReadUnsignedShort(); } else { outfitStart = message.ReadUnsignedByte(); outfitEnd = message.ReadUnsignedByte(); } for (ushort i = outfitStart; i <= outfitEnd; i++) { outfitList.Add(new ProtocolOutfit() { _id = i }); } } List <ProtocolMount> mountList = null; if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GamePlayerMounts)) { mountList = new List <ProtocolMount>(); int count; if (OpenTibiaUnity.GameManager.ClientVersion >= 1185) { count = message.ReadUnsignedShort(); } else { count = message.ReadUnsignedByte(); } for (int i = 0; i < count; i++) { ushort mountId = message.ReadUnsignedShort(); var mountName = message.ReadString(); bool locked = true; uint offerId = 0; if (OpenTibiaUnity.GameManager.ClientVersion >= 1185) { locked = message.ReadBoolean(); if (locked) { offerId = message.ReadUnsignedInt(); } } mountList.Add(new ProtocolMount() { _id = mountId, Name = mountName, Locked = locked, StoreOfferId = offerId, }); } } if (OpenTibiaUnity.GameManager.ClientVersion >= 1185) { bool tryOutfit = message.ReadBoolean(); bool mounted = message.ReadBoolean(); } OpenTibiaUnity.GameManager.onRequestOutfitDialog.Invoke(outfit, mountOutfit, outfitList, mountList); }
private void ParseTalk(Internal.ByteArray message) { uint statementId = 0; if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameMessageStatements)) { statementId = message.ReadUnsignedInt(); } string speaker = message.ReadString(); ushort speakerLevel = 0; if (OpenTibiaUnity.GameManager.GetFeature(GameFeature.GameMessageLevel)) { speakerLevel = message.ReadUnsignedShort(); } int rawMode = message.ReadUnsignedByte(); MessageModeType mode = TranslateMessageModeFromServer(rawMode); Vector3Int?absolutePosition = null; Utils.UnionStrInt channelId = null; switch (mode) { case MessageModeType.Say: case MessageModeType.Whisper: case MessageModeType.Yell: absolutePosition = message.ReadPosition(); channelId = Chat.ChatStorage.LocalChannelId; break; case MessageModeType.PrivateFrom: channelId = speaker; break; case MessageModeType.Channel: case MessageModeType.ChannelManagement: case MessageModeType.ChannelHighlight: channelId = message.ReadUnsignedShort(); break; case MessageModeType.Spell: absolutePosition = message.ReadPosition(); channelId = Chat.ChatStorage.LocalChannelId; break; case MessageModeType.NpcFromStartBlock: absolutePosition = message.ReadPosition(); break; case MessageModeType.NpcFrom: break; case MessageModeType.GamemasterBroadcast: break; case MessageModeType.GamemasterChannel: channelId = message.ReadUnsignedShort(); break; case MessageModeType.GamemasterPrivateFrom: channelId = speaker; break; case MessageModeType.BarkLow: case MessageModeType.BarkLoud: case MessageModeType.MonsterSay: case MessageModeType.MonsterYell: absolutePosition = message.ReadPosition(); channelId = -1; break; case MessageModeType.Game: break; case MessageModeType.RVRAnswer: case MessageModeType.RVRContinue: channelId = Chat.ChatStorage.RVRChannelId; break; case MessageModeType.RVRChannel: message.ReadUnsignedInt(); channelId = Chat.ChatStorage.RVRChannelId; break; default: throw new System.Exception(string.Format("ProtocolGame.ParseTalk: invalid message mode (raw = {0}, mode = {1})", rawMode, mode)); } string text = message.ReadString(); if (mode != MessageModeType.NpcFromStartBlock && mode != MessageModeType.NpcFrom) { try { WorldMapStorage.AddOnscreenMessage(absolutePosition, (int)statementId, speaker, speakerLevel, mode, text); ChatStorage.AddChannelMessage(channelId, (int)statementId, speaker, speakerLevel, mode, text); } catch (System.Exception e) { throw new System.Exception("ProtocolGame.ParseTalk: Failed to add message: " + e.Message + "\n" + e.StackTrace); } } else if (mode == MessageModeType.NpcFromStartBlock) { MessageStorage.StartMessageBlock(speaker, absolutePosition, text); } else if (mode == MessageModeType.NpcFrom) { MessageStorage.AddTextToBlock(speaker, text); } }