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);
            }
        }
Пример #2
0
        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--;
            }
        }