public void ClientRead(ServerNetObject type, IReadMessage msg, float sendingTime)
        {
            bool isGlobalUpdate = msg.ReadBoolean();

            if (isGlobalUpdate)
            {
                foreach (LevelWall levelWall in ExtraWalls)
                {
                    if (levelWall.Body.BodyType == BodyType.Static)
                    {
                        continue;
                    }

                    Vector2 bodyPos = new Vector2(
                        msg.ReadSingle(),
                        msg.ReadSingle());
                    levelWall.MoveState = msg.ReadRangedSingle(0.0f, MathHelper.TwoPi, 16);
                    DestructibleLevelWall destructibleWall = levelWall as DestructibleLevelWall;
                    if (Vector2.DistanceSquared(bodyPos, levelWall.Body.Position) > 0.5f && (destructibleWall == null || !destructibleWall.Destroyed))
                    {
                        levelWall.Body.SetTransformIgnoreContacts(ref bodyPos, levelWall.Body.Rotation);
                    }
                }
            }
            else
            {
                int  index      = msg.ReadUInt16();
                byte damageByte = msg.ReadByte();
                if (index < ExtraWalls.Count && ExtraWalls[index] is DestructibleLevelWall destructibleWall)
                {
                    destructibleWall.SetDamage(destructibleWall.MaxHealth * damageByte / 255.0f);
                }
            }
        }
        private void CreateFragments()
        {
#if CLIENT
            SoundPlayer.PlaySound("icebreak", WorldPosition);
#endif
            //generate initial triangles (one triangle from each edge to the center of the cell)
            List <List <Vector2> > triangles = new List <List <Vector2> >();
            foreach (var cell in Cells)
            {
                foreach (GraphEdge edge in cell.Edges)
                {
                    List <Vector2> triangleVerts = new List <Vector2>
                    {
                        edge.Point1 + cell.Translation,
                        edge.Point2 + cell.Translation,
                        cell.Center
                    };
                    triangles.Add(triangleVerts);
                }
            }

            //split triangles that have edges more than 1000 units long
            Pair <int, int> longestEdge       = new Pair <int, int>(-1, -1);
            float           longestEdgeLength = 0.0f;
            do
            {
                longestEdge.First  = -1;
                longestEdge.Second = -1;
                longestEdgeLength  = 0.0f;
                for (int i = 0; i < triangles.Count; i++)
                {
                    for (int edge = 0; edge < 3; edge++)
                    {
                        float edgeLength = Vector2.Distance(triangles[i][edge], triangles[i][(edge + 1) % 3]);
                        if (edgeLength > longestEdgeLength)
                        {
                            longestEdge.First  = i;
                            longestEdge.Second = edge;
                            longestEdgeLength  = edgeLength;
                        }
                    }
                }
                if (longestEdgeLength < 1000.0f)
                {
                    break;
                }
                Vector2 p0 = triangles[longestEdge.First][longestEdge.Second];
                Vector2 p1 = triangles[longestEdge.First][(longestEdge.Second + 1) % 3];
                Vector2 p2 = triangles[longestEdge.First][(longestEdge.Second + 2) % 3];
                triangles[longestEdge.First] = new List <Vector2> {
                    p0, (p0 + p1) / 2, p2
                };
                triangles.Add(new List <Vector2> {
                    (p0 + p1) / 2, p1, p2
                });
            } while (triangles.Count < 32);

            //generate fragments
            foreach (var triangle in triangles)
            {
                Vector2 triangleCenter = (triangle[0] + triangle[1] + triangle[2]) / 3;
                triangle[0] -= triangleCenter;
                triangle[1] -= triangleCenter;
                triangle[2] -= triangleCenter;
                Vector2 simTriangleCenter = ConvertUnits.ToSimUnits(triangleCenter);

                DestructibleLevelWall fragment = new DestructibleLevelWall(triangle, Color.White, Level.Loaded, giftWrap: true);
                fragment.Damage                   = fragment.MaxHealth;
                fragment.Body.Position            = simTriangleCenter;
                fragment.Body.BodyType            = BodyType.Dynamic;
                fragment.Body.FixedRotation       = false;
                fragment.Body.LinearDamping       = Rand.Range(0.2f, 0.3f);
                fragment.Body.AngularDamping      = Rand.Range(0.1f, 0.2f);
                fragment.Body.GravityScale        = 0.1f;
                fragment.Body.Mass               *= 10.0f;
                fragment.Body.CollisionCategories = Physics.CollisionNone;
                fragment.Body.CollidesWith        = Physics.CollisionWall;
                fragment.FadeOutDuration          = 20.0f;

                Vector2 bodyDiff = simTriangleCenter - Body.Position;
                fragment.Body.LinearVelocity  = (bodyDiff + Rand.Vector(0.5f)).ClampLength(15.0f);
                fragment.Body.AngularVelocity = Rand.Range(-0.5f, 0.5f);// MathHelper.Clamp(-bodyDiff.X * 0.1f, -0.5f, 0.5f);

                Level.Loaded.UnsyncedExtraWalls.Add(fragment);

#if CLIENT
                for (int i = 0; i < 20; i++)
                {
                    int     startEdgeIndex = Rand.Int(3);
                    Vector2 pos1           = triangle[startEdgeIndex];
                    Vector2 pos2           = triangle[(startEdgeIndex + 1) % 3];

                    var particle = GameMain.ParticleManager.CreateParticle("iceshards",
                                                                           triangleCenter + Vector2.Lerp(pos1, pos2, Rand.Range(0.0f, 1.0f)),
                                                                           Rand.Vector(Rand.Range(50.0f, 1000.0f)) + fragment.Body.LinearVelocity * 100.0f);
                    if (particle != null)
                    {
                        particle.Size *= Rand.Range(1.0f, 5.0f);
                    }
                }
#endif
            }
        }