private void ParseTileArea(OtFileReader reader, OtFileNode otbNode, bool replaceTiles, ISet<ulong> tileLocations)
        {
            OtPropertyReader props = reader.GetPropertyReader(otbNode);

            int baseX = props.ReadUInt16();
            int baseY = props.ReadUInt16();
            int baseZ = props.ReadByte();

            OtFileNode nodeTile = otbNode.Child;

            while (nodeTile != null)
            {
                if (nodeTile.Type == (long)OtMapNodeTypes.TILE ||
                    nodeTile.Type == (long)OtMapNodeTypes.HOUSETILE)
                {
                    props = reader.GetPropertyReader(nodeTile);

                    var tileLocation = new Location(baseX + props.ReadByte(), baseY + props.ReadByte(), baseZ);

                    var tile = new OtTile(tileLocation);

                    if (nodeTile.Type == (long)OtMapNodeTypes.HOUSETILE)
                    {
                        tile.HouseId = props.ReadUInt32();
                    }

                    while (props.PeekChar() != -1)
                    {
                        byte attribute = props.ReadByte();
                        switch ((OtMapAttribute)attribute)
                        {
                            case OtMapAttribute.TILE_FLAGS:
                                {
                                    tile.Flags = props.ReadUInt32();
                                    break;
                                }
                            case OtMapAttribute.ITEM:
                                {
                                    ushort itemId = props.ReadUInt16();

                                    var itemType = Items.GetItem(itemId);
                                    if (itemType == null)
                                    {
                                        throw new Exception("Unkonw item type " + itemId + " in position " + tileLocation + ".");
                                    }

                                    var item = OtItem.Create(itemType);
                                    tile.InternalAddItem(item);

                                    break;
                                }
                            default:
                                throw new Exception(string.Format("{0} Unknown tile attribute.", tileLocation));
                        }
                    }

                    OtFileNode nodeItem = nodeTile.Child;

                    while (nodeItem != null)
                    {
                        if (nodeItem.Type == (long)OtMapNodeTypes.ITEM)
                        {
                            props = reader.GetPropertyReader(nodeItem);

                            ushort itemId = props.ReadUInt16();

                            var itemType = Items.GetItem(itemId);
                            if (itemType == null)
                            {
                                throw new Exception("Unkonw item type " + itemId + " in position " + tileLocation + ".");
                            }

                            var item = OtItem.Create(itemType);
                            item.Deserialize(reader, nodeItem, props, Items);

                            tile.InternalAddItem(item);
                        }
                        else
                        {
                            throw new Exception(string.Format("{0} Unknown node type.", tileLocation));
                        }
                        nodeItem = nodeItem.Next;
                    }

                    var index = tileLocation.ToIndex();
                    var hasTile = HasTile(index);

                    if (!hasTile)
                    {
                        SetTile(tile);
                        tileLocations.Add(tileLocation.ToIndex());
                    }
                    else if (replaceTiles)
                        SetTile(tile);
                }

                nodeTile = nodeTile.Next;
            }
        }
 public OtTile GetTile(Location location)
 {
     return GetTile(location.ToIndex());
 }
 public bool HasTile(Location location)
 {
     return HasTile(location.ToIndex());
 }
        public void AddCreature(OtCreature creature)
        {
            if (!creatures.ContainsKey(creature.Id))
            {
                var spawnLocation = new Location(creature.Location.X - (creature.Location.X % SPAWN_SIZE) + SPAWN_RADIUS,
                    creature.Location.Y - (creature.Location.Y % SPAWN_SIZE) + SPAWN_RADIUS, creature.Location.Z);
                var spawnIndex = spawnLocation.ToIndex();

                if (!spawns.ContainsKey(spawnIndex))
                    spawns.Add(spawnIndex, new OtSpawn(spawnLocation, SPAWN_RADIUS));

                var spwan = spawns[spawnIndex];

                if (spwan.AddCreature(creature))
                {
                    if (creature.Type == CreatureType.NPC)
                        npcCount++;
                    else if (creature.Type == CreatureType.MONSTER)
                        monsterCount++;

                    creatures.Add(creature.Id, creature);
                }
            }
        }