Exemplo n.º 1
0
        /// <see cref="IScenarioLoader.LoadScenario"/>
        public Scenario LoadScenario(IMapAccess map, byte[] data)
        {
            if (map == null)
            {
                throw new ArgumentNullException("map");
            }
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }

            /// Load the packages from the byte array.
            int      offset   = 0;
            Scenario scenario = new Scenario(map);

            while (offset < data.Length)
            {
                int       parsedBytes;
                RCPackage package = RCPackage.Parse(data, offset, data.Length - offset, out parsedBytes);
                if (package == null || !package.IsCommitted)
                {
                    throw new SimulatorException("Syntax error!");
                }
                offset += parsedBytes;
                if (package.PackageFormat.ID == ScenarioFileFormat.MINERAL_FIELD)
                {
                    IQuadTile    quadTile     = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1)));
                    MineralField mineralField = new MineralField();
                    mineralField.ResourceAmount.Write(package.ReadInt(2));
                    scenario.AddElementToScenario(mineralField);
                    mineralField.AttachToMap(quadTile);
                }
                else if (package.PackageFormat.ID == ScenarioFileFormat.VESPENE_GEYSER)
                {
                    IQuadTile     quadTile      = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1)));
                    VespeneGeyser vespeneGeyser = new VespeneGeyser();
                    vespeneGeyser.ResourceAmount.Write(package.ReadInt(2));
                    scenario.AddElementToScenario(vespeneGeyser);
                    vespeneGeyser.AttachToMap(quadTile);
                }
                else if (package.PackageFormat.ID == ScenarioFileFormat.START_LOCATION)
                {
                    IQuadTile     quadTile      = map.GetQuadTile(new RCIntVector(package.ReadShort(0), package.ReadShort(1)));
                    StartLocation startLocation = new StartLocation(package.ReadByte(2));
                    scenario.AddElementToScenario(startLocation);
                    startLocation.AttachToMap(quadTile);
                }
            }

            /// Check the constraints of the visible entities.
            foreach (Entity entity in scenario.GetElementsOnMap <Entity>(MapObjectLayerEnum.GroundObjects, MapObjectLayerEnum.AirObjects))
            {
                if (entity.CheckPlacementConstraints(entity.MapObject.QuadraticPosition.Location, new RCSet <Entity>()).Count != 0)
                {
                    throw new MapException(string.Format("Entity at {0} is voilating its placement constraints!", entity.MapObject.QuadraticPosition.Location));
                }
            }
            return(scenario);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Initializes the isometric tiles of the map structure.
        /// </summary>
        /// <param name="isotileListPackage">The package that contains the isometric tile informations.</param>
        private void LoadIsoTiles(RCPackage isotileListPackage)
        {
            string[] terrainIndexTable = isotileListPackage.ReadStringArray(0);
            byte[]   isotileInfoBytes  = isotileListPackage.ReadByteArray(1);

            int offset = 0;

            while (offset < isotileInfoBytes.Length)
            {
                int       parsedBytes;
                RCPackage package = RCPackage.Parse(isotileInfoBytes, offset, isotileInfoBytes.Length - offset, out parsedBytes);
                if (package == null || !package.IsCommitted)
                {
                    throw new MapException("Syntax error!");
                }
                offset += parsedBytes;
                if (package.PackageFormat.ID == MapFileFormat.ISOTILE)
                {
                    RCIntVector        quadCoords   = new RCIntVector(package.ReadShort(0), package.ReadShort(1));
                    TerrainCombination terrainCombo = (TerrainCombination)package.ReadByte(4);
                    string             terrainA     = terrainIndexTable[package.ReadByte(2)];
                    string             terrainB     = terrainCombo != TerrainCombination.Simple ? terrainIndexTable[package.ReadByte(3)] : null;
                    int variantIdx = package.ReadByte(5);

                    this.mapStructure.InitIsoTile(quadCoords,
                                                  terrainCombo == TerrainCombination.Simple ?
                                                  this.mapStructure.Tileset.GetIsoTileType(terrainA) :
                                                  this.mapStructure.Tileset.GetIsoTileType(terrainA, terrainB, terrainCombo),
                                                  variantIdx);
                }
            }
        }
Exemplo n.º 3
0
        /// <summary>
        /// Creates a MapHeader structure from the given RCPackage.
        /// </summary>
        /// <param name="package">The RCPackage that contains the map header informations.</param>
        /// <returns>The created MapHeader structure.</returns>
        public static MapHeader FromPackage(RCPackage package)
        {
            if (package == null)
            {
                throw new ArgumentNullException("package");
            }
            if (!package.IsCommitted)
            {
                throw new ArgumentException("The header package is not committed!", "package");
            }
            if (package.PackageType != RCPackageType.CUSTOM_DATA_PACKAGE)
            {
                throw new ArgumentException("Invalid package type!", "package");
            }
            if (package.PackageFormat.ID != MapFileFormat.MAP_HEADER)
            {
                throw new ArgumentException("Invalid package format!", "package");
            }

            MapHeader header = new MapHeader();

            header.appVersion   = new Version(package.ReadInt(0), package.ReadInt(1), package.ReadInt(2), package.ReadInt(3));
            header.mapName      = package.ReadString(4);
            header.tilesetName  = package.ReadString(5);
            header.mapSize      = new RCIntVector(package.ReadShort(6), package.ReadShort(7));
            header.maxPlayers   = package.ReadByte(8);
            header.checksumList = new List <int>(package.ReadIntArray(9));

            if (header.mapName == null)
            {
                throw new MapException("Map name information is missing!");
            }
            if (header.tilesetName == null)
            {
                throw new MapException("Tileset name information is missing!");
            }
            if (header.mapSize.X <= 0 || header.mapSize.Y <= 0)
            {
                throw new MapException("Map size cannot be negative or 0!");
            }
            if (header.maxPlayers <= 0)
            {
                throw new MapException("Maximum number of players cannot be negative or 0!");
            }
            return(header);
        }
Exemplo n.º 4
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);
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Registers the given commit arrived from the given operator.
        /// </summary>
        /// <param name="commit">The arrived commit package.</param>
        /// <param name="senderID">The sender operator.</param>
        /// <returns>True in case of success, false otherwise.</returns>
        public bool RegisterCommit(RCPackage commit, int senderID)
        {
            if (!this.initialized)
            {
                throw new DssException("DssSimulationMgr is uninitialized!");
            }

            /// If we are currently finishing the simulation --> do nothing
            if (this.hostLeft)
            {
                return(true);
            }

            if (commit == null || !commit.IsCommitted)
            {
                throw new ArgumentException("commit");
            }
            if (senderID == this.root.IdOfThisPeer)
            {
                throw new DssException("Unexpected commit sender!");
            }
            if (senderID < 0 || senderID >= this.root.OpCount)
            {
                throw new ArgumentException("senderID");
            }

            if (commit.PackageFormat.ID != DssRoot.DSS_COMMIT)
            {
                /// Package format error.
                return(false);
            }

            short senderAFT = commit.ReadShort(0);
            short senderAPT = commit.ReadShort(1);
            int   roundIdx  = commit.ReadInt(2);
            int   ticket    = commit.ReadInt(3);

            byte[] stateHash = commit.ReadByteArray(4);

            if (senderAFT < 0)
            {
                return(false);
            }
            if (senderAPT < 0)
            {
                return(false);
            }
            if (stateHash == null)
            {
                return(false);
            }

            bool success = false;

            if (roundIdx == this.nextRound.RoundIndex)
            {
                success = this.nextRound.Commit(senderID, senderAFT, senderAPT, stateHash);
                if (this.waitingForCommit && this.nextRound.IsCommitted)
                {
                    TraceManager.WriteAllTrace("WAITING FOR COMMIT END", DssTraceFilters.SIMULATION_INFO);
                    /// The missing commit has arrived, so we can continue the simulation
                    this.waitingForCommit = false;
                    /// Compute the scheduled time for the next frame
                    int nextFrameStartTime = this.currentRound.BaseTime
                                             + (this.currentRound.CurrentFrameIndex + 1) * this.currentRound.TargetFrameTime;
                    SendCommit();
                    SwapRounds();
                    /// Schedule the next frame.
                    SetNextFrameExecutionTime(Math.Max(nextFrameStartTime, DssRoot.Time));
                }
            }
            else if (roundIdx == this.nextNextRound.RoundIndex)
            {
                success = this.nextNextRound.Commit(senderID, senderAFT, senderAPT, stateHash);
            }
            else
            {
                TraceManager.WriteAllTrace(string.Format("RoundIdx mismatch! RoundIdx: {0}", roundIdx), DssTraceFilters.SIMULATION_ERROR);
            }

            if (success)
            {
                /// Create the answer for the commit and send it back to the sender.
                RCPackage commitAw = RCPackage.CreateNetworkCustomPackage(DssRoot.DSS_COMMIT_ANSWER);
                commitAw.WriteInt(0, ticket);
                this.root.LobbyIface.SendPackage(commitAw, new int[1] {
                    senderID
                });
            }
            return(success);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Continues the connection procedure to the server.
        /// </summary>
        /// <returns>
        /// In case of error this function automatically shuts down the connection, notifies the listener and
        /// returns false. Otherwise it returns true. If the line state report arrives from the server, this
        /// function automatically notifies the listener.
        /// </returns>
        private bool ContinueConnectToTheServer()
        {
            RCPackage lineStateReport = null;

            if (this.connection.ContinueConnectToTheServer(out lineStateReport))
            {
                if (lineStateReport != null)
                {
                    short            clientID       = lineStateReport.ReadShort(0);
                    byte[]           lineStateBytes = lineStateReport.ReadByteArray(1);
                    LobbyLineState[] lineStates     = new LobbyLineState[lineStateBytes.Length];
                    bool             lineStatesOK   = true;
                    for (int i = 0; i < lineStateBytes.Length; i++)
                    {
                        if (lineStateBytes[i] == (byte)LobbyLineState.Closed ||
                            lineStateBytes[i] == (byte)LobbyLineState.Engaged ||
                            lineStateBytes[i] == (byte)LobbyLineState.Opened)
                        {
                            lineStates[i] = (LobbyLineState)lineStateBytes[i];
                        }
                        else
                        {
                            lineStatesOK = false;
                        }
                    }
                    lineStatesOK = lineStatesOK && clientID > 0 && clientID < lineStateBytes.Length;
                    if (!lineStatesOK)
                    {
                        /// Line state report error --> shutdown.
                        this.connection.Shutdown();
                        if (this.Disposed != null)
                        {
                            this.Disposed(this);
                        }
                        this.listener.LobbyLost();
                        return(false);
                    }
                    else
                    {
                        /// Connection procedure finished --> send a line state report to the listener.
                        this.clientID    = clientID;
                        this.memberCount = lineStates.Length;
                        this.listener.LineStateReport(clientID, lineStates);
                        return(true);
                    }
                }
                /// No error but connection procedure not finished.
                return(true);
            }
            else
            {
                /// Connection rejected by the server or an error occured --> shutdown.
                this.connection.Shutdown();
                if (this.Disposed != null)
                {
                    this.Disposed(this);
                }
                this.listener.LobbyLost();
                return(false);
            }
        }