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); } }
public void EmitParticuleForCubeDestruction(int nbr, TerraCube cube, Vector3I CubeLocation, ref Vector3D cameraLocation) { //Check distance to emit if (MaxRenderingDistance > 0 && Vector3D.DistanceSquared(cameraLocation, new Vector3D(CubeLocation)) > _maxRenderingDistanceSquared) { return; } //GetCube Profile VisualChunk chunk = null; var profile = _visualWorldParameters.WorldParameters.Configuration.BlockProfiles[cube.Id]; //Get Chunk in case if the block is subject to BiomeColoring chunk = _worldChunk.GetChunk(CubeLocation.X, CubeLocation.Z); //Foreach Surrending Cube ByteColor blockAvgColorReceived = new ByteColor(); foreach (var surrendingCube in chunk.BlockData.ChunkCubes.GetSurroundingBlocksIndex(ref CubeLocation)) { var cubeColor = chunk.BlockData.ChunkCubes.Cubes[surrendingCube.Index].EmissiveColor; blockAvgColorReceived.A = Math.Max(blockAvgColorReceived.A, cubeColor.A); blockAvgColorReceived.R = Math.Max(blockAvgColorReceived.R, cubeColor.R); blockAvgColorReceived.G = Math.Max(blockAvgColorReceived.G, cubeColor.G); blockAvgColorReceived.B = Math.Max(blockAvgColorReceived.B, cubeColor.B); } //Get Cube color palette Color[] palette = _cubeColorSampled[cube.Id]; while (nbr > 0) { //Randomize the Velocity Vector3 finalVelocity = new Vector3(0, 1, 0); finalVelocity.X += (float)_rnd.NextDouble(-1.0, 1.0) * 1.5f; finalVelocity.Y += (float)_rnd.NextDouble() * 3f; finalVelocity.Z += (float)_rnd.NextDouble(-1.0, 1.0) * 1.5f; Vector3D CubeCenteredPosition = new Vector3D(CubeLocation.X + _rnd.NextDouble(0.2, 0.8), CubeLocation.Y + _rnd.NextDouble(0.2, 0.8), CubeLocation.Z + _rnd.NextDouble(0.2, 0.8)); //Get Color var color = palette[_rnd.Next(24)]; if (color.A < 255) { ApplyBiomeColor(ref color, profile.BiomeColorArrayTexture, chunk.BlockData.GetColumnInfo(CubeLocation.X - chunk.ChunkPositionBlockUnit.X, CubeLocation.Z - chunk.ChunkPositionBlockUnit.Y)); } _particules.Add(new ColoredParticule() { Age = 0 + (float)_rnd.NextDouble(0, 2.0), computationAge = 0, InitialPosition = CubeCenteredPosition, ParticuleColor = color, Position = new FTSValue <Vector3D>(CubeCenteredPosition), Size = new Vector2(0.1f, 0.1f), Velocity = finalVelocity, ColorReceived = blockAvgColorReceived, SpinningRotation = Quaternion.RotationAxis(Vector3.UnitY, _rnd.NextFloat(-MathHelper.Pi / 8, MathHelper.Pi / 8)) * Quaternion.RotationAxis(Vector3.UnitX, _rnd.NextFloat(-MathHelper.Pi / 16, MathHelper.Pi / 16)) * Quaternion.RotationAxis(Vector3.UnitZ, _rnd.NextFloat(-MathHelper.Pi / 16, MathHelper.Pi / 16)), RotationAngles = new FTSValue <Quaternion>(Quaternion.Identity) }); nbr--; } }