private void Simulate() { long nextTick = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond; if (_state == SimulationState.ShuttingDown) { _state = SimulationState.Shutdown; } //Server Game loop while (_state == SimulationState.Running) { Tick++; lock (_lock) { //Tick all active chunks foreach ((string _, Chunk chunk) in World.ChunkIndex) { //Tick all entities in active chunks foreach ((string _, SimulationEntity entity) in chunk.Entities.ToList()) { entity.Tick(this);//entity components are processed here } //randomly choose three tiles in the chunk to tick for (int i = 0; i < 3; i++) { int xBlock = _random.Next(World.WorldOptions.ChunkSize); int yBlock = _random.Next(World.WorldOptions.ChunkSize); TileComponentManager.TickTile(World, chunk, xBlock, yBlock); } } // Run all of the components to simulate gameplay. GameMode?.Update(this); } //This is the communication aspect SendUpdates(); //Maintain the tick rate here nextTick += _tickSpeed; int sleepTime = (int)(nextTick - DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond); if (sleepTime >= 0) { OnSimulationTick?.Invoke(); Thread.Sleep(sleepTime); } else { OnSimulationOverLoad?.Invoke($"{sleepTime}TPS"); } } }
/// <summary> /// Constructs a simulation /// </summary> /// <param name="gameMode"></param> /// <param name="worldOptions">Given world options that is given to the world manager</param> /// <param name="tickSpeed">A optional parameter used for indicating the ticks per second. (20tps is the default)</param> public Simulation(SimulationGameMode gameMode, WorldOptions worldOptions, int tickSpeed = 20) { _lock = new object(); GameMode = gameMode; _state = SimulationState.Shutdown; _tickSpeed = 1000 / tickSpeed; _random = new Random(); Tick = 0; ConnectedClients = 0; World = new WorldManager(worldOptions); SimulationDistance = 3; //entities _entitiesIndex = new Dictionary <string, SimulationEntity>(); _playerEntitiesIndex = new Dictionary <string, SimulationEntity>(); TileComponentManager.LoadTileComponents(); }