Exemple #1
0
        /// <see cref="IMapLoader.NewMap"/>
        public IMapAccess NewMap(string mapName, ITileSet tileset, string defaultTerrain, RCIntVector size)
        {
            if (!this.initThreadStarted)
            {
                throw new InvalidOperationException("Component has not yet been started!");
            }
            this.initThread.Join();

            if (mapName == null)
            {
                throw new ArgumentNullException("mapName");
            }
            if (tileset == null)
            {
                throw new ArgumentNullException("tileset");
            }
            if (defaultTerrain == null)
            {
                throw new ArgumentNullException("defaultTerrain");
            }
            if (size == RCIntVector.Undefined)
            {
                throw new ArgumentNullException("size");
            }

            MapAccess retObj = new MapAccess(mapName, this.mapStructure);

            this.mapStructure.BeginOpen(tileset, size, defaultTerrain);
            this.mapStructure.EndOpen();
            return(retObj);
        }
Exemple #2
0
        /// <see cref="IMapEditor.RemoveTerrainObject"/>
        public void RemoveTerrainObject(IMapAccess targetMap, ITerrainObject terrainObject)
        {
            if (targetMap == null)
            {
                throw new ArgumentNullException("targetMap");
            }
            if (terrainObject == null)
            {
                throw new ArgumentNullException("terrainObject");
            }
            if (targetMap != terrainObject.ParentMap)
            {
                throw new InvalidOperationException("The map of the terrain object must equal with the target map!");
            }

            /// TODO: Avoid this downcast!
            MapAccess targetMapObj = targetMap as MapAccess;

            if (targetMapObj == null)
            {
                throw new ArgumentException("The given map cannot be handled by the MapEditor!", "targetMap");
            }

            /// Undo the cell data changesets of the removed terrain object.
            foreach (ICellDataChangeSet changeset in terrainObject.Type.CellDataChangesets)
            {
                changeset.Undo(terrainObject);
            }
            targetMapObj.DetachTerrainObject(terrainObject);
        }
Exemple #3
0
        /// <summary>
        /// Initializes the terrain objects of the map.
        /// </summary>
        /// <param name="terrainObjListPackage">The package that contains the terrain object informations.</param>
        /// <param name="map">Reference to the map.</param>
        private void LoadTerrainObjects(RCPackage terrainObjListPackage, IMapAccess map)
        {
            /// TODO: Avoid this downcast!
            MapAccess mapObj = map as MapAccess;

            if (mapObj == null)
            {
                throw new ArgumentException("The given map cannot be handled by the MapEditor!", "map");
            }

            string[] terrainObjIndexTable = terrainObjListPackage.ReadStringArray(0);
            byte[]   terrainObjInfoBytes  = terrainObjListPackage.ReadByteArray(1);

            int offset = 0;

            while (offset < terrainObjInfoBytes.Length)
            {
                int       parsedBytes;
                RCPackage package = RCPackage.Parse(terrainObjInfoBytes, offset, terrainObjInfoBytes.Length - offset, out parsedBytes);
                if (package == null || !package.IsCommitted)
                {
                    throw new MapException("Syntax error!");
                }
                offset += parsedBytes;
                if (package.PackageFormat.ID == MapFileFormat.TERRAINOBJ)
                {
                    RCIntVector        quadCoords     = new RCIntVector(package.ReadShort(0), package.ReadShort(1));
                    ITerrainObjectType terrainObjType = this.mapStructure.Tileset.GetTerrainObjectType(terrainObjIndexTable[package.ReadByte(2)]);

                    /// TODO: Might be better to create the TerrainObject with a factory?
                    ITerrainObject newObj = new TerrainObject(map, terrainObjType, quadCoords);
                    foreach (ICellDataChangeSet changeset in newObj.Type.CellDataChangesets)
                    {
                        changeset.Apply(newObj);
                    }
                    mapObj.AttachTerrainObject(newObj);
                }
            }

            /// Check the constraints of the terrain objects.
            List <ITerrainObject> terrainObjects = new List <ITerrainObject>(map.TerrainObjects);

            foreach (ITerrainObject terrainObj in terrainObjects)
            {
                mapObj.DetachTerrainObject(terrainObj);
                if (terrainObj.Type.CheckConstraints(map, terrainObj.MapCoords).Count != 0)
                {
                    throw new MapException(string.Format("Terrain object at {0} is voilating the tileset constraints!", terrainObj.MapCoords));
                }
                if (terrainObj.Type.CheckTerrainObjectIntersections(map, terrainObj.MapCoords).Count != 0)
                {
                    throw new MapException(string.Format("Terrain object at {0} intersects other terrain objects!", terrainObj.MapCoords));
                }
                mapObj.AttachTerrainObject(terrainObj);
            }
        }
Exemple #4
0
        /// <see cref="IMapEditor.PlaceTerrainObject"/>
        public ITerrainObject PlaceTerrainObject(IMapAccess targetMap, IQuadTile targetTile, ITerrainObjectType type)
        {
            if (targetMap == null)
            {
                throw new ArgumentNullException("targetMap");
            }
            if (targetTile == null)
            {
                throw new ArgumentNullException("targetTile");
            }
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }
            if (targetMap.Tileset != type.Tileset)
            {
                throw new InvalidOperationException("The tileset of the terrain object type must be the same as the tileset of the map!");
            }

            /// TODO: Avoid this downcast!
            MapAccess targetMapObj = targetMap as MapAccess;

            if (targetMapObj == null)
            {
                throw new ArgumentException("The given map cannot be handled by the MapEditor!", "targetMap");
            }

            if (type.CheckConstraints(targetMap, targetTile.MapCoords).Count != 0)
            {
                return(null);
            }
            if (type.CheckTerrainObjectIntersections(targetMap, targetTile.MapCoords).Count != 0)
            {
                return(null);
            }

            /// TODO: Might be better to create the TerrainObject with a factory?
            ITerrainObject newObj = new TerrainObject(targetMap, type, targetTile.MapCoords);

            foreach (ICellDataChangeSet changeset in newObj.Type.CellDataChangesets)
            {
                changeset.Apply(newObj);
            }
            targetMapObj.AttachTerrainObject(newObj);
            return(newObj);
        }
Exemple #5
0
        /// <see cref="IMapLoader.LoadMap"/>
        public IMapAccess LoadMap(ITileSet tileset, byte[] data)
        {
            if (!this.initThreadStarted)
            {
                throw new InvalidOperationException("Component has not yet been started!");
            }
            this.initThread.Join();

            if (tileset == null)
            {
                throw new ArgumentNullException("tileset");
            }
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            /// Load the packages from the byte array.
            RCPackage mapHeaderPackage      = null;
            RCPackage isotileListPackage    = null;
            RCPackage terrainObjListPackage = null;
            int       offset = 0;

            while (offset < data.Length)
            {
                int       parsedBytes;
                RCPackage package = RCPackage.Parse(data, offset, data.Length - offset, out parsedBytes);
                if (package == null || !package.IsCommitted)
                {
                    throw new MapException("Syntax error!");
                }
                offset += parsedBytes;
                if (package.PackageFormat.ID == MapFileFormat.MAP_HEADER)
                {
                    mapHeaderPackage = package;
                }
                else if (package.PackageFormat.ID == MapFileFormat.ISOTILE_LIST)
                {
                    isotileListPackage = package;
                }
                else if (package.PackageFormat.ID == MapFileFormat.TERRAINOBJ_LIST)
                {
                    terrainObjListPackage = package;
                }
            }

            /// Validate the packages.
            if (mapHeaderPackage == null)
            {
                throw new MapException("Syntax error: map header is missing!");
            }
            if (isotileListPackage == null)
            {
                throw new MapException("Syntax error: isometric-tile-list is missing!");
            }
            if (terrainObjListPackage == null)
            {
                throw new MapException("Syntax error: terrain-object-list is missing!");
            }

            /// Validate the map header.
            MapHeader mapHeader = MapHeader.FromPackage(mapHeaderPackage);

            if (mapHeader.AppVersion > new Version(ConstantsTable.Get <string>("RC.App.Version")))
            {
                throw new MapException(string.Format("Incompatible map version: {0}!", mapHeader.AppVersion));
            }
            if (mapHeader.TilesetName != tileset.Name)
            {
                throw new ArgumentException(string.Format("The given tileset '{0}' has to equal with the map tileset '{1}'!", tileset.Name, mapHeader.TilesetName), "tileset");
            }
            if (mapHeader.MapSize.X > MapStructure.MAX_MAPSIZE || mapHeader.MapSize.Y > MapStructure.MAX_MAPSIZE)
            {
                throw new MapException(string.Format("Map size exceeds the limits: {0}x{0}!", MapStructure.MAX_MAPSIZE));
            }

            MapAccess retObj = new MapAccess(mapHeader.MapName, this.mapStructure);

            this.mapStructure.BeginOpen(tileset, mapHeader.MapSize);
            this.LoadIsoTiles(isotileListPackage);
            this.mapStructure.EndOpen();

            this.LoadTerrainObjects(terrainObjListPackage, retObj);

            // TODO: validate MapHeader.MaxPlayers!
            // TODO: validate the MapHeader checksums!
            return(retObj);
        }