public void ActivateGameStateAsync(GameState state, bool preservePreviousStates = false) { logger.Debug("Activating new game state {0}", state.Name); //_inActivationProcess filter that only one Activation can be requested at a time ! //state.IsActivationRequested filter the case where the requested state is already on an Activation process (Cannot request it twice) if (_inActivationProcess == false || state.IsActivationRequested == false) { state.WithPreservePreviousStates = preservePreviousStates; _inActivationProcess = true; state.IsActivationRequested = true; state.PreviousGameState = _currentState; #if DEBUG logger.Debug("State requested for activation : {0}", state.Name); #endif //If ALL the components inside the states are already initiazed, switch directly the States if (state.GameComponents.Count > 0 && state.IsInitialized) { SetCurrentState(state); return; } #if DEBUG logger.Debug("State Initialization requested in Async Mode : {0}", state.Name); #endif AsyncStateInitResults.Add(ThreadsManager.RunAsync(() => InitializeComponentsAsync(state))); } else { logger.Warn("State : '{0}' requested to be activated while another activation requested is in initialization state, the request is dropped", state.Name); } }
public override void FTSUpdate(GameTime timeSpent) { _brightness = _worldclock.ClockTime.SmartTimeInterpolation(0.2f); if ((Math.Abs(_smallOffset.X) > CloudBlockSize || Math.Abs(_smallOffset.Y) > CloudBlockSize) && (_threadState == null || _threadState.IsCompleted) && _newCloudGenerated == false ) { // rebuild the grid in thread _threadState = ThreadsManager.RunAsync(FormClouds); } if (_newCloudGenerated) { if (Math.Abs((int)(_smallOffset.X / CloudBlockSize)) > 0) { _smallOffset.X = _smallOffset.X % CloudBlockSize; } if (Math.Abs((int)(_smallOffset.Y / CloudBlockSize)) > 0) { _smallOffset.Y = _smallOffset.Y % CloudBlockSize; } _instancedBuffer.SetInstancedData(_d3DEngine.Device.ImmediateContext, _clouds.ToArray()); _cloudBlocksCount = _clouds.Count; _clouds.Clear(); _newCloudGenerated = false; } }
/// <summary> /// All Components used by this GameState should be Added in the GameState here /// This will be called in a multithreaded way ! /// </summary> public virtual void Initialize(DeviceContext context) { //Call the Initialized from each Registered component, if needed ! //Will be thread dispatched ! List <Task> _startedTask = new List <Task>(); GameComponents.ForEach(gc => { if (gc.IsInitialized == false) { //Start the Initialize() _startedTask.Add(ThreadsManager.RunAsync(gc.Initialize)); } }); Task.WaitAll(_startedTask.ToArray()); //Call the LoadContents from each Registered component, if needed ! //!! Those methods are not Thread Safe !! => cannot thread dispatch them, can only run once at a time in this thread context foreach (var gc in GameComponents.Where(x => x.IsDefferedLoadContent)) { if (gc.IsInitialized == false) { gc.LoadContent(context); gc.IsInitialized = true; } } IsDirty = false; }
public void ProcessMessageEntityIn(ProtocolMessageEventArgs <EntityInMessage> e) { //Only take into account static entity if (e.Message.Link.IsStatic) { ThreadsManager.RunAsync(() => AddEntity((IStaticEntity)e.Message.Entity, e.Message.SourceEntityId), singleConcurrencyRun: true); } }
public void PrepareStateAsync(GameState state) { #if DEBUG logger.Debug("State Initialization requested (by Prepare) : {0}", state.Name); #endif state.PreviousGameState = _currentState; AsyncStateInitResults.Add(ThreadsManager.RunAsync(() => InitializeComponentsAsync(state), singleConcurrencyRun: true)); }
public void RefreshWorldListAsync() { _savedGameList.Items.Clear(); _savedGameList.SelectItem(-1); _savedGameList.Items.Add("Loading..."); NeedShowResults = false; ThreadsManager.RunAsync(RefreshWorldList); }
public void ProcessMessageEntityOut(ProtocolMessageEventArgs <EntityOutMessage> e) { // Only take into account static entity if (e.Message.Link.IsStatic) { //The server change modification will be queued inside a single concurrency thread pool. (Only one running at the same time) ThreadsManager.RunAsync(() => RemoveEntity(e.Message.Link, e.Message.TakerEntityId), singleConcurrencyRun: true); } }
private void LoadMissingModels(WorldConfiguration configuration, VoxelModelManager voxelModelManager) { ThreadsManager.RunAsync(() => { voxelModelManager.Initialize(); var availableModels = voxelModelManager.Enumerate().Select(m => m.VoxelModel.Name).ToList(); var neededModels = configuration.GetUsedModelsNames().Where(m => !availableModels.Contains(m)).ToList(); foreach (var neededModel in neededModels) { voxelModelManager.DownloadModel(neededModel); } }); }
//The state is enabled, start loading other components in background while the Loading is shown public override void OnEnabled(GameState previousState) { if (PreviousGameState != this) { ThreadsManager.RunAsync(GameplayInitializeAsync); } var serverComponent = _ioc.Get <ServerComponent>(); serverComponent.ConnectionStatusChanged += serverComponent_ConnectionStausChanged; base.OnEnabled(previousState); }
public void ReplaceBlocks(Vector3I[] position, byte[] blockId, BlockTag[] tags, bool isNetworkChange) { //Single block to change ============================================= if (blockId.Length == 1) { ThreadsManager.RunAsync(() => ReplaceBlockThreaded(position[0], blockId[0], isNetworkChange, tags != null ? tags[0] : null), singleConcurrencyRun: true); return; } //Multiple blocks to change ============================================= Dictionary <VisualChunk, List <TerraCubePositionTag> > blockPerChunk = new Dictionary <VisualChunk, List <TerraCubePositionTag> >(); List <TerraCubePositionTag> blockList; //Multiple block to changes at once //Split the various blocks by chunks for (int i = 0; i < blockId.Length; i++) { BlockTag tag = tags != null ? tags[i] : null; VisualChunk impactedChunk; if (_worldChunks.GetSafeChunk(position[i].X, position[i].Z, out impactedChunk)) { if (!blockPerChunk.TryGetValue(impactedChunk, out blockList)) { blockList = new List <TerraCubePositionTag>(); blockPerChunk[impactedChunk] = blockList; } blockList.Add(new TerraCubePositionTag(position[i], blockId[i], tag)); } } //Create a thread for working on the update per chunk ! foreach (var blocks in blockPerChunk) { ThreadsManager.RunAsync(() => ReplaceChunkBlocksThreaded(blocks.Key, blocks.Value, isNetworkChange), singleConcurrencyRun: true); } }
public bool ReplaceBlock(int cubeArrayIndex, ref Vector3I cubeCoordinates, byte replacementCubeId, bool isNetworkChanged, BlockTag blockTag = null) { VisualChunk impactedChunk = _worldChunks.GetChunk(cubeCoordinates.X, cubeCoordinates.Z); if (impactedChunk.State != ChunkState.DisplayInSyncWithMeshes && isNetworkChanged) { return(false); } try { // Check if the cube is not already the same ? ! ? var existingCube = _cubesHolder.Cubes[cubeArrayIndex]; var inChunkPos = BlockHelper.GlobalToInternalChunkPosition(cubeCoordinates); if (existingCube.Id == replacementCubeId) { // tag change event // some tags changes requires chunk mesh rebuild (LiquidTag), some not (DamageTag) // we will update the mesh only if at least one tag (current or previous) requires mesh update var needChunkMeshUpdate = false; var oldTag = impactedChunk.BlockData.GetTag(inChunkPos); if (oldTag != null && oldTag.RequireChunkMeshUpdate) { needChunkMeshUpdate = true; } if (blockTag != null && blockTag.RequireChunkMeshUpdate) { needChunkMeshUpdate = true; } if (!needChunkMeshUpdate) { impactedChunk.BlockData.SetTag(blockTag, inChunkPos); return(true); } } // Change the cube in the big array impactedChunk.BlockData.SetBlock(inChunkPos, replacementCubeId, blockTag); // Start Chunk Visual Impact to decide what needs to be redraw, will be done in async mode, // quite heavy, will also restart light computations for the impacted chunk range. var cube = new TerraCubeWithPosition(cubeCoordinates, replacementCubeId, _visualWorldParameters.WorldParameters.Configuration.BlockProfiles[replacementCubeId]); #if PERFTEST if (Utopia.Worlds.Chunks.WorldChunks.perf.Actif == false) { Utopia.Worlds.Chunks.WorldChunks.perf.Actif = true; Utopia.Worlds.Chunks.WorldChunks.perf.CollectedData = new List <string>(); Utopia.Worlds.Chunks.WorldChunks.perf.AddData("Started New User Action"); Utopia.Worlds.Chunks.WorldChunks.perf.sw.Restart(); } #endif impactedChunk.UpdateOrder = !cube.BlockProfile.IsBlockingLight ? 1 : 2; //Compute the Range impacted by the cube change var cubeRange = new Range3I { Position = new Vector3I(cube.Position.X, 0, cube.Position.Z), Size = Vector3I.One }; ThreadsManager.RunAsync(() => CheckImpact(impactedChunk, cubeRange), ThreadsManager.ThreadTaskPriority.High); // Raise event for sound OnBlockReplaced(new LandscapeBlockReplacedEventArgs { IsLocalPLayerAction = !isNetworkChanged, Position = cubeCoordinates, NewBlockType = replacementCubeId, PreviousBlock = existingCube }); return(true); } finally { // Save the modified Chunk in local buffer DB SendChunkForBuffering(impactedChunk); } }
//Multiple blocks replace logic public bool ReplaceChunkBlocks(VisualChunk impactedChunk, List <TerraCubePositionTag> blocks, bool isNetworkChanged) { if (impactedChunk.State != ChunkState.DisplayInSyncWithMeshes && isNetworkChanged) { return(false); } Vector2I Min = new Vector2I(int.MaxValue, int.MaxValue); Vector2I Max = new Vector2I(int.MinValue, int.MinValue); foreach (var block in blocks) { var existingCube = _cubesHolder.Cubes[_cubesHolder.Index(ref block.Position)]; var inChunkPos = BlockHelper.GlobalToInternalChunkPosition(block.Position); //Cube not changed - Check Tags if (existingCube.Id == block.Cube.Id) { var needChunkMeshUpdate = false; var oldTag = impactedChunk.BlockData.GetTag(inChunkPos); if (oldTag != null && oldTag.RequireChunkMeshUpdate) { needChunkMeshUpdate = true; } if (block.Tag != null && block.Tag.RequireChunkMeshUpdate) { needChunkMeshUpdate = true; } if (!needChunkMeshUpdate) { impactedChunk.BlockData.SetTag(block.Tag, inChunkPos); continue; } } if (Min.X > block.Position.X) { Min.X = block.Position.X; } if (Min.Y > block.Position.Z) { Min.Y = block.Position.Z; } if (Max.X < block.Position.X) { Max.X = block.Position.X; } if (Max.Y < block.Position.Z) { Max.Y = block.Position.Z; } // Change the cube in the big array impactedChunk.BlockData.SetBlock(inChunkPos, block.Cube.Id, block.Tag); } //Compute the Range impacted by the cube change var cubeRange = new Range3I { Position = new Vector3I(Min.X, 0, Min.Y), Size = new Vector3I((Max.X - Min.X) + 1, 0, (Max.Y - Min.Y) + 1) }; impactedChunk.UpdateOrder = 1; ThreadsManager.RunAsync(() => CheckImpact(impactedChunk, cubeRange), ThreadsManager.ThreadTaskPriority.High); // Save the modified Chunk in local buffer DB SendChunkForBuffering(impactedChunk); return(true); }