Beispiel #1
0
        private static void HandleReplaceCube(GameSession session, PacketReader packet)
        {
            CoordB coord = packet.Read <CoordB>();

            packet.Skip(1);
            int    replacementItemId  = packet.ReadInt();
            long   replacementItemUid = packet.ReadLong();
            byte   unk       = packet.ReadByte();
            long   unk2      = packet.ReadLong(); // maybe part of rotation?
            float  zRotation = packet.ReadFloat();
            CoordF rotation  = new CoordF();

            rotation.Z = zRotation;

            int plotNumber = MapMetadataStorage.GetPlotNumber(session.Player.MapId, coord);

            if (plotNumber < 0)
            {
                return;
            }
            //TODO: Add and remove appropriate items to warehouse inventory and furnishing inventory

            //TODO: If itemUid is not found, send player to purchase the item
            Item item = new Item(replacementItemId);

            Cube cube = new Cube(item, plotNumber);

            IFieldObject <Cube> fieldCube = session.FieldManager.RequestFieldObject(cube);

            fieldCube.Coord    = coord.ToFloat();
            fieldCube.Rotation = rotation;

            session.FieldManager.BroadcastPacket(ResponseCubePacket.ReplaceCube(session.FieldPlayer, fieldCube));
            session.FieldManager.AddCube(fieldCube, session.FieldPlayer);
        }
Beispiel #2
0
    public static PacketWriter SendCubes(List <Cube> cubes)
    {
        PacketWriter packetWriter = PacketWriter.Of(SendOp.FUNCTION_CUBE);

        packetWriter.Write(FunctionCubeMode.SendCubes);
        packetWriter.WriteInt(cubes.Count);
        foreach (Cube cube in cubes)
        {
            packetWriter.WriteUnicodeString($"4_{CoordB.AsHexadecimal(cube.CoordF.ToByte())}");
            switch (cube.Item.HousingCategory)
            {
            case ItemHousingCategory.Farming:
            case ItemHousingCategory.Ranching:
                packetWriter.WriteInt(1);
                break;

            default:
                packetWriter.WriteInt();
                break;
            }

            packetWriter.WriteByte();
        }

        return(packetWriter);
    }
Beispiel #3
0
 public readonly CoordB ToByte()
 {
     return(CoordB.From(
                (sbyte)(X / Block.BLOCK_SIZE),
                (sbyte)(Y / Block.BLOCK_SIZE),
                (sbyte)(Z / Block.BLOCK_SIZE)));
 }
Beispiel #4
0
        private static void HandleRemoveCube(GameSession session, PacketReader packet)
        {
            CoordB coord = packet.Read <CoordB>();

            // TODO: Find cube in coord
            // TODO: Handle Furnishing/Warehouse inventories

            session.Send(ResponseCubePacket.RemoveCube(session.FieldPlayer, coord));
        }
Beispiel #5
0
    public static PacketWriter RemoveCube(LiftableObject liftableObject)
    {
        PacketWriter pWriter = PacketWriter.Of(SendOp.LIFTABLE);

        pWriter.Write(LiftableMode.RemoveCube);
        pWriter.WriteString($"4_{CoordB.AsHexadecimal(liftableObject.Position.ToByte())}");

        return(pWriter);
    }
    public static PacketWriter FailLikeSkill(long characterId, CoordB coordB)
    {
        PacketWriter packetWriter = PacketWriter.Of(SendOp.FunctionCube);

        packetWriter.Write(FunctionCubeMode.FailLifeSkill);
        packetWriter.WriteLong(characterId);
        packetWriter.WriteUnicodeString($"4_{coordB.AsHexadecimal()}");
        packetWriter.WriteLong(TimeInfo.Now());

        return(packetWriter);
    }
Beispiel #7
0
        public static Packet FailLikeSkill(long characterId, CoordB coordB)
        {
            PacketWriter packetWriter = PacketWriter.Of(SendOp.FUNCTION_CUBE);

            packetWriter.WriteEnum(FunctionCubeMode.FailLifeSkill);
            packetWriter.WriteLong(characterId);
            packetWriter.WriteUnicodeString($"4_{CoordBAsHexadimal(coordB)}");
            packetWriter.WriteLong(DateTimeOffset.Now.ToUnixTimeSeconds());

            return(packetWriter);
        }
Beispiel #8
0
    public static long AsHexadecimal(CoordB coordB)
    {
        /// Get the block coord, transform to hexa, reverse and then transform to long
        /// Example: (-1, -1, 1)
        /// Reverse and transform to hexadecimal as string: '1FFFF'
        /// Convert the string above to long: 65535
        byte[] coords = coordB.ToArray();
        string coordRevertedAsString = $"{coords[2]}{coords[1]:X2}{coords[0]:X2}";

        return(Convert.ToInt64(coordRevertedAsString, 16));
    }
    public static PacketWriter UpdateFunctionCube(CoordB coordB, int status, byte unkByte)
    {
        PacketWriter packetWriter = PacketWriter.Of(SendOp.FunctionCube);

        packetWriter.Write(FunctionCubeMode.Add);
        packetWriter.WriteUnicodeString($"4_{coordB.AsHexadecimal()}");
        packetWriter.WriteInt(status);
        packetWriter.WriteByte(unkByte);

        return(packetWriter);
    }
    public static PacketWriter UseFurniture(long characterId, CoordB coordB, bool inUse)
    {
        PacketWriter packetWriter = PacketWriter.Of(SendOp.FunctionCube);

        packetWriter.Write(FunctionCubeMode.Furniture);
        packetWriter.WriteLong(characterId);
        packetWriter.WriteUnicodeString($"4_{coordB.AsHexadecimal()}");
        packetWriter.WriteBool(inUse);

        return(packetWriter);
    }
Beispiel #11
0
        public static Packet UseFurniture(long characterId, CoordB coordB, bool inUse)
        {
            PacketWriter packetWriter = PacketWriter.Of(SendOp.FUNCTION_CUBE);

            packetWriter.WriteEnum(FunctionCubeMode.Furniture);
            packetWriter.WriteLong(characterId);
            packetWriter.WriteUnicodeString($"4_{CoordBAsHexadimal(coordB)}");
            packetWriter.WriteBool(inUse);

            return(packetWriter);
        }
Beispiel #12
0
        public static Packet UpdateFunctionCube(CoordB coordB, int status, byte unkByte)
        {
            PacketWriter packetWriter = PacketWriter.Of(SendOp.FUNCTION_CUBE);

            packetWriter.WriteEnum(FunctionCubeMode.Add);
            packetWriter.WriteUnicodeString($"4_{CoordBAsHexadimal(coordB)}");
            packetWriter.WriteInt(status);
            packetWriter.WriteByte(unkByte);

            return(packetWriter);
        }
Beispiel #13
0
    public static PacketWriter UpdateEntityByCoord(LiftableObject liftableObject)
    {
        PacketWriter pWriter = PacketWriter.Of(SendOp.LIFTABLE);

        pWriter.Write(LiftableMode.UpdateEntity);
        pWriter.WriteString($"4_{CoordB.AsHexadecimal(liftableObject.Position.ToByte())}");
        pWriter.WriteByte();
        pWriter.WriteInt(liftableObject.Enabled ? 1 : 0); // 1 = enable, 0 = disable
        pWriter.Write(liftableObject.State);

        return(pWriter);
    }
Beispiel #14
0
        private static void HandleUseCube(GameSession session, PacketReader packet)
        {
            string coord = packet.ReadUnicodeString();
            byte   unk   = packet.ReadByte();

            string coordHexa = long.Parse(coord.Split('_')[1]).ToString("X2");

            if (coordHexa.Length == 5)
            {
                coordHexa = "0" + coordHexa;
            }
            CoordB coordB = CoordB.From((sbyte)Convert.ToByte(coordHexa[4..], 16),
Beispiel #15
0
    public static PacketWriter SuccessLifeSkill(long characterId, CoordB coordB, int status)
    {
        PacketWriter packetWriter = PacketWriter.Of(SendOp.FUNCTION_CUBE);

        packetWriter.Write(FunctionCubeMode.SuccessLifeSkill);
        packetWriter.WriteLong(characterId);
        packetWriter.WriteUnicodeString($"4_{CoordB.AsHexadecimal(coordB)}");
        packetWriter.WriteLong(TimeInfo.Now());
        packetWriter.WriteInt(status);

        return(packetWriter);
    }
        public static Packet RemoveCube(IFieldObject <Player> player, CoordB coord)
        {
            PacketWriter pWriter = PacketWriter.Of(SendOp.RESPONSE_CUBE);

            pWriter.WriteEnum(ResponseCubePacketMode.RemoveCube);
            pWriter.WriteByte();
            pWriter.WriteInt(player.ObjectId);
            pWriter.WriteInt(player.ObjectId);
            pWriter.Write(coord);
            pWriter.WriteByte();
            pWriter.WriteByte();
            return(pWriter);
        }
        public static Packet Pickup(GameSession session, int weaponId, CoordB coords)
        {
            PacketWriter pWriter = PacketWriter.Of(SendOp.RESPONSE_CUBE);

            pWriter.WriteEnum(ResponseCubePacketMode.Pickup);
            pWriter.WriteZero(1);
            pWriter.WriteInt(session.FieldPlayer.ObjectId);
            pWriter.Write(coords);
            pWriter.WriteZero(1);
            pWriter.WriteInt(weaponId);
            pWriter.WriteInt(GuidGenerator.Int()); // Item uid

            return(pWriter);
        }
        public static int GetWeaponObjectItemId(int mapId, CoordB coord)
        {
            MapWeaponObject weaponObject = WeaponObjects.GetValueOrDefault(mapId).FirstOrDefault(x => x.Coord == coord);

            if (weaponObject == null)
            {
                return(0);
            }

            Random random = RandomProvider.Get();
            int    index  = random.Next(weaponObject.WeaponItemIds.Count);

            return(weaponObject.WeaponItemIds[index]);
        }
        public static Packet RemoveCube(int ownerObjectId, int fieldPlayerObjectId, CoordB coord)
        {
            PacketWriter pWriter = PacketWriter.Of(SendOp.RESPONSE_CUBE);

            pWriter.WriteEnum(ResponseCubePacketMode.RemoveCube);
            pWriter.WriteByte();
            pWriter.WriteInt(ownerObjectId);
            pWriter.WriteInt(fieldPlayerObjectId);
            pWriter.Write(coord);
            pWriter.WriteByte();
            pWriter.WriteByte();

            return(pWriter);
        }
Beispiel #20
0
    public static PacketWriter Drop(LiftableObject liftableObject)
    {
        PacketWriter pWriter = PacketWriter.Of(SendOp.LIFTABLE);

        pWriter.Write(LiftableMode.Drop);
        pWriter.WriteString($"4_{CoordB.AsHexadecimal(liftableObject.Position.ToByte())}");
        pWriter.WriteInt(1);
        pWriter.WriteUnicodeString(liftableObject.EffectQuestId);
        pWriter.WriteUnicodeString(liftableObject.EffectQuestState);
        pWriter.WriteUnicodeString("0");
        pWriter.WriteUnicodeString("0");
        pWriter.WriteByte(1);

        return(pWriter);
    }
    private static void HandlePickUp(GameSession session, PacketReader packet)
    {
        string id = packet.ReadString();
        IFieldActor <Player> fieldPlayer = session.Player.FieldPlayer;

        if (id.Contains('_'))
        {
            string coordHexa = long.Parse(id.Split('_')[1]).ToString("X2");
            if (coordHexa.Length == 5)
            {
                coordHexa = "0" + coordHexa;
            }

            CoordB coordB = CoordB.From(
                (sbyte)Convert.ToByte(coordHexa[4..], 16),
Beispiel #22
0
        private static void HandleAddFurnishing(GameSession session, PacketReader packet)
        {
            CoordB coord    = packet.Read <CoordB>();
            byte   padding  = packet.ReadByte();
            int    itemId   = packet.ReadInt();
            long   itemUid  = packet.ReadLong();
            byte   padding2 = packet.ReadByte();
            CoordF rotation = packet.Read <CoordF>();

            int plotNumber = MapMetadataStorage.GetPlotNumber(session.Player.MapId, coord);

            if (plotNumber < 0)
            {
                return;
            }

            // TODO: Check if player has rights to this plot

            FurnishingShopMetadata shopMetadata = FurnishingShopMetadataStorage.GetMetadata(itemId);

            if (shopMetadata == null || !shopMetadata.Buyable)
            {
                return;
            }

            if (itemUid == 0) // player needs to purchase
            {
                if (!PurchaseFurnishingItem(session, shopMetadata))
                {
                    return;
                }


                Item item = new Item(itemId);

                //TODO: Add and remove appropriate item to warehouse inventory and furnishing inventory

                Cube cube = new Cube(item, plotNumber);

                IFieldObject <Cube> fieldCube = session.FieldManager.RequestFieldObject(cube);
                fieldCube.Coord    = coord.ToFloat();
                fieldCube.Rotation = rotation;
                session.FieldManager.AddCube(fieldCube, session.FieldPlayer);
            }
        }
Beispiel #23
0
    private static void HandleSendPortalSettings(GameSession session, PacketReader packet)
    {
        CoordB coordB = packet.Read <CoordB>();

        // 50400158 = Portal Cube
        IFieldObject <Cube> cube = session.FieldManager.State.Cubes.Values
                                   .FirstOrDefault(x => x.Coord == coordB.ToFloat() && x.Value.Item.Id == 50400158);

        if (cube is null)
        {
            return;
        }

        List <Cube> otherPortals = session.FieldManager.State.Cubes.Values
                                   .Where(x => x.Value.Item.Id == 50400158 && x.Value.Uid != cube.Value.Uid)
                                   .Select(x => x.Value).ToList();

        session.Send(HomeActionPacket.SendCubePortalSettings(cube.Value, otherPortals));
    }
        public static int GetPlotNumber(int mapId, CoordB coord)
        {
            CoordS      coordS      = coord.ToShort();
            MapMetadata mapMetadata = GetMetadata(mapId);

            for (int i = 0; i < 20; i++) // checking 20 blocks in the same Z axis
            {
                mapMetadata.Blocks.TryGetValue(coordS, out MapBlock block);
                if (block == null)
                {
                    coordS.Z -= Block.BLOCK_SIZE;
                    continue;
                }

                if (block.SaleableGroup > 0)
                {
                    return(block.SaleableGroup);
                }
                coordS.Z -= Block.BLOCK_SIZE;
            }
            return(0);
        }
        private static void HandlePickup(GameSession session, PacketReader packet)
        {
            byte[] coords = packet.Read(3);

            // Convert to signed byte array
            sbyte[] sCoords = Array.ConvertAll(coords, b => unchecked ((sbyte)b));
            // Default to rainbow tree
            int weaponId = 18000004;

            // Find matching mapObject
            foreach (MapObject mapObject in MapEntityStorage.GetObjects(session.Player.MapId))
            {
                if (mapObject.Coord.Equals(CoordB.From(sCoords[0], sCoords[1], sCoords[2])))
                {
                    weaponId = mapObject.WeaponId;
                    break;
                }
            }

            // Pickup item then set battle state to true
            session.Send(ResponseCubePacket.Pickup(session, weaponId, coords));
            session.Send(UserBattlePacket.UserBattle(session.FieldPlayer, true));
        }
Beispiel #26
0
        public static int GetPlotNumber(int mapId, CoordB coord)
        {
            CoordS          coordS = coord.ToShort();
            List <MapBlock> blocks = new List <MapBlock>();
            MapMetadata     mapD   = GetMetadata(mapId);

            for (int i = 0; i < 20; i++) // checking 20 blocks in the same Z axis
            {
                MapBlock block = mapD.Blocks.FirstOrDefault(x => x.Coord == coordS);
                if (block == null)
                {
                    coordS.Z -= Block.BLOCK_SIZE;
                    continue;
                }

                if (block.SaleableGroup > 0)
                {
                    return(block.SaleableGroup);
                }
                coordS.Z -= Block.BLOCK_SIZE;
            }
            return(0);
        }
Beispiel #27
0
    private static void HandleChangePortalSettings(GameSession session, PacketReader packet)
    {
        packet.ReadByte();
        CoordB coordB = packet.Read <CoordB>();

        packet.ReadByte();

        IFieldObject <Cube> fieldCube = session.FieldManager.State.Cubes.Values.FirstOrDefault(x => x.Coord == coordB.ToFloat());

        if (fieldCube is null)
        {
            return;
        }
        Cube cube = fieldCube.Value;

        cube.PortalSettings.PortalName        = packet.ReadUnicodeString();
        cube.PortalSettings.Method            = (UGCPortalMethod)packet.ReadByte();
        cube.PortalSettings.Destination       = (UGCPortalDestination)packet.ReadByte();
        cube.PortalSettings.DestinationTarget = packet.ReadUnicodeString();

        DatabaseManager.Cubes.Update(cube);

        UpdateAllPortals(session);
    }
Beispiel #28
0
 public bool Equals(CoordB other)
 {
     return(X == other.X && Y == other.Y && Z == other.Z);
 }
Beispiel #29
0
 public static sbyte Distance(CoordB left, CoordB right)
 {
     return((left - right).Length());
 }
        protected override List <MapEntityMetadata> Parse()
        {
            // Iterate over preset objects to later reference while iterating over exported maps
            Dictionary <string, string> mapObjects = new Dictionary <string, string>();

            foreach (PackFileEntry entry in Resources.ExportedFiles)
            {
                if (!entry.Name.StartsWith("flat/presets/presets object/"))
                {
                    continue;
                }

                // Check if file is valid
                string objStr = entry.Name.ToLower();
                if (string.IsNullOrEmpty(objStr))
                {
                    continue;
                }
                if (mapObjects.ContainsKey(objStr))
                {
                    //Console.WriteLine($"Duplicate {entry.Name} was already added as {mapObjects[objStr]}");
                    continue;
                }

                // Parse XML
                XmlDocument document      = Resources.ExportedMemFile.GetDocument(entry.FileHeader);
                XmlElement  root          = document.DocumentElement;
                XmlNodeList objProperties = document.SelectNodes("/model/property");

                string objectName = root.Attributes["name"].Value.ToLower();

                foreach (XmlNode node in objProperties)
                {
                    // Storing only weapon item code for now, but there are other uses
                    if (node.Attributes["name"].Value.Contains("ObjectWeaponItemCode"))
                    {
                        string weaponId = node?.FirstChild.Attributes["value"].Value ?? "0";

                        if (!weaponId.Equals("0"))
                        {
                            mapObjects.Add(objectName, weaponId);
                        }
                    }
                }
            }

            // Iterate over map xblocks
            List <MapEntityMetadata>    entities = new List <MapEntityMetadata>();
            Dictionary <string, string> maps     = new Dictionary <string, string>();

            foreach (PackFileEntry entry in Resources.ExportedFiles)
            {
                if (!entry.Name.StartsWith("xblock/"))
                {
                    continue;
                }

                string mapIdStr = Regex.Match(entry.Name, @"\d{8}").Value;
                if (string.IsNullOrEmpty(mapIdStr))
                {
                    continue;
                }
                int mapId = int.Parse(mapIdStr);
                if (maps.ContainsKey(mapIdStr))
                {
                    //Console.WriteLine($"Duplicate {entry.Name} was already added as {maps[mapIdStr]}");
                    continue;
                }
                maps.Add(mapIdStr, entry.Name);

                MapEntityMetadata metadata    = new MapEntityMetadata(mapId);
                XmlDocument       document    = Resources.ExportedMemFile.GetDocument(entry.FileHeader);
                XmlNodeList       mapEntities = document.SelectNodes("/game/entitySet/entity");

                foreach (XmlNode node in mapEntities)
                {
                    string modelName = node.Attributes["modelName"].Value.ToLower();

                    XmlNode blockCoord  = node.SelectSingleNode("property[@name='Position']");
                    CoordS  boundingBox = CoordS.Parse(blockCoord?.FirstChild.Attributes["value"].Value ?? "0, 0, 0");
                    if (node.Attributes["name"].Value.Contains("MS2Bounding0"))
                    {
                        if (metadata.BoundingBox0.Equals(CoordS.From(0, 0, 0)))
                        {
                            metadata.BoundingBox0 = boundingBox;
                        }
                    }
                    else if (node.Attributes["name"].Value.Contains("MS2Bounding1"))
                    {
                        if (metadata.BoundingBox1.Equals(CoordS.From(0, 0, 0)))
                        {
                            metadata.BoundingBox1 = boundingBox;
                        }
                    }
                    else if (node.Attributes["name"].Value.Contains("SpawnPointPC"))
                    {
                        XmlNode playerCoord    = node.SelectSingleNode("property[@name='Position']");
                        XmlNode playerRotation = node.SelectSingleNode("property[@name='Rotation']");

                        string playerPositionValue = playerCoord?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";
                        string playerRotationValue = playerRotation?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";

                        metadata.PlayerSpawns.Add(new MapPlayerSpawn(CoordS.Parse(playerPositionValue), CoordS.Parse(playerRotationValue)));
                    }
                    else if (mapObjects.ContainsKey(modelName))
                    {
                        string nameCoord = node.Attributes["name"].Value.ToLower();

                        Match coordMatch = Regex.Match(nameCoord, @"[\-]?\d+[,]\s[\-]?\d+[,]\s[\-]?\d+");

                        if (!coordMatch.Success)
                        {
                            continue;
                        }

                        CoordB coord = CoordB.Parse(coordMatch.Value, ", ");
                        metadata.Objects.Add(new MapObject(coord, int.Parse(mapObjects[modelName])));
                    }
                }

                //XmlNodeList nodes = document.SelectNodes("/game/entitySet/entity/property[@name='NpcList']");
                XmlNodeList nodes = document.SelectNodes("/game/entitySet/entity/property");
                foreach (XmlNode node in nodes)
                {
                    if (node.Attributes["name"].Value == "NpcList")
                    {
                        if (node.FirstChild != null)
                        {
                            XmlNode parent = node.ParentNode;
                            try
                            {
                                XmlNode coordNode    = parent.SelectSingleNode("property[@name='Position']");
                                XmlNode rotationNode = parent.SelectSingleNode("property[@name='Rotation']");

                                int    npcId         = int.Parse(node.FirstChild.Attributes["index"].Value);
                                string positionValue = coordNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";
                                string rotationValue = rotationNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";

                                CoordS position = CoordS.Parse(positionValue);
                                CoordS rotation = CoordS.Parse(rotationValue);
                                metadata.Npcs.Add(new MapNpc(npcId, position, rotation));
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex);
                                Console.WriteLine(mapId);
                                Console.WriteLine("Failed NPC " + parent.InnerXml);
                            }
                        }
                    }
                    else if (node.Attributes["name"].Value == "PortalID")
                    {
                        XmlNode parent = node.ParentNode;
                        try
                        {
                            XmlNode visibleNode        = parent.SelectSingleNode("property[@name='IsVisible']");
                            XmlNode enabledNode        = parent.SelectSingleNode("property[@name='PortalEnable']");
                            XmlNode minimapVisibleNode = parent.SelectSingleNode("property[@name='MinimapIconVisible']");
                            XmlNode targetNode         = parent.SelectSingleNode("property[@name='TargetFieldSN']");
                            XmlNode coordNode          = parent.SelectSingleNode("property[@name='Position']");
                            XmlNode rotationNode       = parent.SelectSingleNode("property[@name='Rotation']");
                            if (targetNode == null)
                            {
                                continue;
                            }

                            if (!bool.TryParse(visibleNode?.FirstChild.Attributes["value"].Value,
                                               out bool visibleValue))
                            {
                                visibleValue = true;
                            }
                            if (!bool.TryParse(enabledNode?.FirstChild.Attributes["value"].Value,
                                               out bool enabledValue))
                            {
                                enabledValue = true;
                            }
                            if (!bool.TryParse(minimapVisibleNode?.FirstChild.Attributes["value"].Value,
                                               out bool minimapVisibleValue))
                            {
                                minimapVisibleValue = true;
                            }

                            int    target        = int.Parse(targetNode.FirstChild.Attributes["value"].Value);
                            int    portalId      = int.Parse(node.FirstChild.Attributes["value"].Value);
                            string positionValue = coordNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";
                            string rotationValue = rotationNode?.FirstChild.Attributes["value"].Value ?? "0, 0, 0";


                            MapPortalFlag flags = visibleValue ? MapPortalFlag.Visible : MapPortalFlag.None;
                            flags |= enabledValue ? MapPortalFlag.Enabled : MapPortalFlag.None;
                            flags |= minimapVisibleValue ? MapPortalFlag.MinimapVisible : MapPortalFlag.None;

                            CoordS position = CoordS.Parse(positionValue);
                            CoordS rotation = CoordS.Parse(rotationValue);
                            metadata.Portals.Add(new MapPortal(portalId, flags, target, position, rotation));
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex);
                            Console.WriteLine(mapId);
                            Console.WriteLine("Failed NPC " + parent.InnerXml);
                        }
                    }
                }

                // No data on this map
                if (metadata.Npcs.Count == 0 && metadata.Portals.Count == 0 && metadata.PlayerSpawns.Count == 0)
                {
                    continue;
                }

                entities.Add(metadata);
            }

            return(entities);
        }