<commit_before>﻿using System.Collections.Generic;
using System;
using Voxalia.Shared;
using BEPUutilities;
using Voxalia.ServerGame.JointSystem;
using BEPUphysics.CollisionShapes;
using BEPUphysics.CollisionRuleManagement;
using BEPUphysics.BroadPhaseEntries;
using BEPUphysics.CollisionShapes.ConvexShapes;
using Voxalia.ServerGame.WorldSystem;
using Voxalia.Shared.Collision;
using BEPUphysics;
using Voxalia.ServerGame.NetworkSystem.PacketsOut;
using Voxalia.ServerGame.NetworkSystem;

namespace Voxalia.ServerGame.EntitySystem
{
    /// <summary>
    /// Represents a standard serverside entity that interacts with the physics world.
    /// </summary>
    public abstract class PhysicsEntity: Entity
    {
        public bool TransmitMe;

        /// <summary>
        /// Construct the physics entity.
        /// Sets its gravity to the world default and collisiongroup to Solid.
        /// </summary>
        /// <param name="tregion">The region the entity will be spawned in.</param>
        public PhysicsEntity(Region tregion)
            : base(tregion, true)
        {
            Gravity = new Location(TheRegion.PhysicsWorld.ForceUpdater.Gravity);
            CGroup = CollisionUtil.Solid;
        }

        /// <summary>
        /// The widest this entity gets at its furthest corner. Can be used to generate a bounding sphere.
        /// </summary>
        public float Widest = 1;

        /// <summary>
        /// All information on the physical version of this entity as it exists within the physics world.
        /// </summary>
        public BEPUphysics.Entities.Entity Body = null;

        /// <summary>
        /// The mass of the entity.
        /// </summary>
        internal float Mass = 0f;

        /// <summary>
        /// The friction value of the entity.
        /// </summary>
        internal float Friction = 0.5f;

        /// <summary>
        /// The bounciness (restitution coefficient) of the entity.
        /// </summary>
        internal float Bounciness = 0f;

        /// <summary>
        /// The gravity power of this entity.
        /// </summary>
        internal Location Gravity;

        /// <summary>
        /// Whether this entity can rotate. Only updated at SpawnBody().
        /// </summary>
        public bool CanRotate = true;

        /// <summary>
        /// The position, rotation, etc. of this entity.
        /// </summary>
        internal Matrix WorldTransform = Matrix.Identity;

        /// <summary>
        /// The linear velocity of this entity.
        /// </summary>
        internal Location LVel = Location.Zero;

        /// <summary>
        /// The angular velocity of this entity.
        /// </summary>
        internal Location AVel = Location.Zero;

        /// <summary>
        /// The shape of the entity.
        /// </summary>
        public EntityShape Shape = null;

        /// <summary>
        /// The best encompassing convex shape for the entity, for tracing.
        /// </summary>
        public ConvexShape ConvexEntityShape = null;
        
        public Location InternalOffset;

        /// <summary>
        /// What collision group this entity belongs to.
        /// </summary>
        public CollisionGroup CGroup;
        
        public bool netpActive = false;

        public double netdeltat = 0;

        public Location lPos = Location.NaN;
        
        /// <summary>
        /// Ticks the physics entity, currently only causing water float and transmitting to the network.
        /// </summary>
        public override void Tick()
        {
            if (NetworkMe)
            {
                bool sme = false;
                // TODO: Timer of some form, to prevent packet flood on a speedy server?
                if (Body.ActivityInformation.IsActive || (netpActive && !Body.ActivityInformation.IsActive))
                {
                    netpActive = Body.ActivityInformation.IsActive;
                    sme = true;
                }
                if (!netpActive && GetMass() > 0)
                {
                    netdeltat += TheRegion.Delta;
                    if (netdeltat > 2.0)
                    {
                        sme = true;
                    }
                }
                Location pos = GetPosition();
                if (!TransmitMe)
                {
                    sme = false;
                }
                PhysicsEntityUpdatePacketOut physupd = sme ? new PhysicsEntityUpdatePacketOut(this): null;
                foreach (PlayerEntity player in TheRegion.Players)
                {
                    bool shouldseec = player.ShouldSeePosition(pos);
                    bool shouldseel = player.ShouldSeePositionPreviously(lPos);
                    if (shouldseec && !shouldseel)
                    {
                        player.Network.SendPacket(GetSpawnPacket());
                    }
                    if (shouldseel && !shouldseec)
                    {
                        player.Network.SendPacket(new DespawnEntityPacketOut(EID));
                    }
                    if (sme && shouldseec)
                    {
                        player.Network.SendPacket(physupd);
                    }
                }
            }
        }

        public void EndTick()
        {
            lPos = GetPosition();
        }

        public override AbstractPacketOut GetSpawnPacket()
        {
            return new SpawnPhysicsEntityPacketOut(this);
        }

        public void ForceNetwork()
        {
            TheRegion.SendToAll(new PhysicsEntityUpdatePacketOut(this));
        }

        /// <summary>
        /// Builds and spawns the body into the world.
        /// </summary>
        public virtual void SpawnBody()
        {
            if (Body != null)
            {
                DestroyBody();
            }
            if (Shape is ConvexShape)
            {
                ConvexEntityShape = (ConvexShape)Shape;
            }
            else
            {
                if (Shape is MobileMeshShape)
                {
                    MobileMeshShape mms = (MobileMeshShape)Shape;
                    RigidTransform rt = new RigidTransform(Vector3.Zero, Quaternion.Identity);
                    BoundingBox bb;
                    mms.GetBoundingBox(ref rt, out bb);
                    Vector3 size = bb.Max - bb.Min;
                    ConvexEntityShape = new BoxShape(size.X, size.Y, size.Z);
                }
            }
            Body = new BEPUphysics.Entities.Entity(Shape, Mass);<commit_msg>Fix packet 3 error spam<commit_after>﻿using System.Collections.Generic;
using System;
using Voxalia.Shared;
using BEPUutilities;
using Voxalia.ServerGame.JointSystem;
using BEPUphysics.CollisionShapes;
using BEPUphysics.CollisionRuleManagement;
using BEPUphysics.BroadPhaseEntries;
using BEPUphysics.CollisionShapes.ConvexShapes;
using Voxalia.ServerGame.WorldSystem;
using Voxalia.Shared.Collision;
using BEPUphysics;
using Voxalia.ServerGame.NetworkSystem.PacketsOut;
using Voxalia.ServerGame.NetworkSystem;

namespace Voxalia.ServerGame.EntitySystem
{
    /// <summary>
    /// Represents a standard serverside entity that interacts with the physics world.
    /// </summary>
    public abstract class PhysicsEntity: Entity
    {
        public bool TransmitMe;

        /// <summary>
        /// Construct the physics entity.
        /// Sets its gravity to the world default and collisiongroup to Solid.
        /// </summary>
        /// <param name="tregion">The region the entity will be spawned in.</param>
        public PhysicsEntity(Region tregion)
            : base(tregion, true)
        {
            Gravity = new Location(TheRegion.PhysicsWorld.ForceUpdater.Gravity);
            CGroup = CollisionUtil.Solid;
        }

        /// <summary>
        /// The widest this entity gets at its furthest corner. Can be used to generate a bounding sphere.
        /// </summary>
        public float Widest = 1;

        /// <summary>
        /// All information on the physical version of this entity as it exists within the physics world.
        /// </summary>
        public BEPUphysics.Entities.Entity Body = null;

        /// <summary>
        /// The mass of the entity.
        /// </summary>
        internal float Mass = 0f;

        /// <summary>
        /// The friction value of the entity.
        /// </summary>
        internal float Friction = 0.5f;

        /// <summary>
        /// The bounciness (restitution coefficient) of the entity.
        /// </summary>
        internal float Bounciness = 0f;

        /// <summary>
        /// The gravity power of this entity.
        /// </summary>
        internal Location Gravity;

        /// <summary>
        /// Whether this entity can rotate. Only updated at SpawnBody().
        /// </summary>
        public bool CanRotate = true;

        /// <summary>
        /// The position, rotation, etc. of this entity.
        /// </summary>
        internal Matrix WorldTransform = Matrix.Identity;

        /// <summary>
        /// The linear velocity of this entity.
        /// </summary>
        internal Location LVel = Location.Zero;

        /// <summary>
        /// The angular velocity of this entity.
        /// </summary>
        internal Location AVel = Location.Zero;

        /// <summary>
        /// The shape of the entity.
        /// </summary>
        public EntityShape Shape = null;

        /// <summary>
        /// The best encompassing convex shape for the entity, for tracing.
        /// </summary>
        public ConvexShape ConvexEntityShape = null;
        
        public Location InternalOffset;

        /// <summary>
        /// What collision group this entity belongs to.
        /// </summary>
        public CollisionGroup CGroup;
        
        public bool netpActive = false;

        public double netdeltat = 0;

        public Location lPos = Location.NaN;
        
        /// <summary>
        /// Ticks the physics entity, currently only causing water float and transmitting to the network.
        /// </summary>
        public override void Tick()
        {
            if (NetworkMe)
            {
                bool sme = needNetworking;
                needNetworking = false;
                // TODO: Timer of some form, to prevent packet flood on a speedy server?
                if (Body.ActivityInformation.IsActive || (netpActive && !Body.ActivityInformation.IsActive))
                {
                    netpActive = Body.ActivityInformation.IsActive;
                    sme = true;
                }
                if (!netpActive && GetMass() > 0)
                {
                    netdeltat += TheRegion.Delta;
                    if (netdeltat > 2.0)
                    {
                        sme = true;
                    }
                }
                Location pos = GetPosition();
                if (!TransmitMe)
                {
                    sme = false;
                }
                PhysicsEntityUpdatePacketOut physupd = sme ? new PhysicsEntityUpdatePacketOut(this): null;
                foreach (PlayerEntity player in TheRegion.Players)
                {
                    bool shouldseec = player.ShouldSeePosition(pos);
                    bool shouldseel = player.ShouldSeePositionPreviously(lPos);
                    if (shouldseec && !shouldseel)
                    {
                        player.Network.SendPacket(GetSpawnPacket());
                    }
                    if (shouldseel && !shouldseec)
                    {
                        player.Network.SendPacket(new DespawnEntityPacketOut(EID));
                    }
                    if (sme && shouldseec)
                    {
                        player.Network.SendPacket(physupd);
                    }
                }
            }
        }

        public void EndTick()
        {
            lPos = GetPosition();
        }

        public override AbstractPacketOut GetSpawnPacket()
        {
            return new SpawnPhysicsEntityPacketOut(this);
        }

        bool needNetworking = false;

        public void ForceNetwork()
        {
            needNetworking = true;
        }

        /// <summary>
        /// Builds and spawns the body into the world.
        /// </summary>
        public virtual void SpawnBody()
        {
            if (Body != null)
            {
                DestroyBody();
            }
            if (Shape is ConvexShape)
            {
                ConvexEntityShape = (ConvexShape)Shape;
            }
            else
            {
                if (Shape is MobileMeshShape)
                {
                    MobileMeshShape mms = (MobileMeshShape)Shape;
                    RigidTransform rt = new RigidTransform(Vector3.Zero, Quaternion.Identity);
                    BoundingBox bb;
                    mms.GetBoundingBox(ref rt, out bb);
                    Vector3 size = bb.Max - bb.Min;
                    ConvexEntityShape = new BoxShape(size.X, size.Y, size.Z);
                }
            }
            Body = new BEPUphysics.Entities.Entity(Shape, Mass);
{'fraction_non_alphanumeric': 0.09094359675092993, 'fraction_numerical': 0.0017459955970545813, 'mean_word_length': 1.3887579329102449, 'pattern_counts': {'":': 0, '<': 75, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2972611', 'n_tokens_mistral': 3375, 'n_tokens_neox': 3159, 'n_words': 912}