<commit_before>﻿using LunaClient.Systems.SettingsSys;
using LunaClient.Utilities;
using LunaClient.VesselUtilities;
using LunaCommon;
using System;
using System.Collections.Generic;
using UniLinq;

namespace LunaClient.VesselStore
{
    public class VesselProtoUpdate
    {
        #region Fields & properties

        public Guid VesselId { get; set; }
        public bool VesselHasUpdate { get; set; }

        private ProtoVessel _protoVessel;
        public ProtoVessel ProtoVessel
        {
            get
            {
                if (VesselHasUpdate || _protoVessel == null)
                {
                    DeserializeVesselBytes();
                }
                return _protoVessel;
            }
            set => _protoVessel = value;
        }

        public Vessel Vessel => FlightGlobals.FindVessel(VesselId);
        public bool VesselExist => Vessel != null;
        public bool ShouldBeLoaded => SettingsSystem.ServerSettings.ShowVesselsInThePast || !VesselCommon.VesselIsControlledAndInPastSubspace(VesselId);

        private List<uint> _vesselPartIds = new List<uint>();
        public List<uint> VesselPartIds
        {
            get
            {
                if (VesselHasUpdate || _protoVessel == null)
                {
                    DeserializeVesselBytes();
                }
                return _vesselPartIds;
            }
            set => _vesselPartIds = value;
        }

        #region Private

        private byte[] _vesselData = new byte[1000];
        private int _numBytes;
        private ConfigNode _vesselNode;
        private string _vesselHash;

        #endregion

        #endregion

        public VesselProtoUpdate(byte[] vesselData, int numBytes, Guid vesselId)
        {
            VesselId = vesselId;
            CopyVesselBytes(vesselData, numBytes);
        }

        /// <summary>
        /// Update this class with the new data received
        /// </summary>
        public void Update(byte[] vesselData, int numBytes, Guid vesselId, int situation)
        {
            if (VesselId != vesselId)
            {
                LunaLog.LogError("Cannot update a VesselProtoUpdate with a differente vesselId");
                return;
            }
            var newHash = Common.CalculateSha256Hash(vesselData);
            if (_vesselHash == newHash) return; //Skip Updating as the hash is the same

            CopyVesselBytes(vesselData, numBytes);

            _vesselHash = newHash;
            VesselHasUpdate = true;
        }

        /// <summary>
        /// Copies the received vessel bytes to this class
        /// </summary>
        private void CopyVesselBytes(byte[] vesselData, int numBytes)
        {
            if (_vesselData.Length < numBytes)
                Array.Resize(ref _vesselData, numBytes);
            Array.Copy(vesselData, _vesselData, numBytes);
            _numBytes = numBytes;
        }

        /// <summary>
        /// This method uses a lot of memory so try to call it as less as possible and only when needed
        /// </summary>
        public void DeserializeVesselBytes()
        {
            _vesselNode = ConfigNodeSerializer.Deserialize(_vesselData, _numBytes);
            ProtoVessel = VesselCommon.CreateSafeProtoVesselFromConfigNode(_vesselNode, VesselId);

            VesselPartIds.Clear();
            VesselPartIds.AddRange(ProtoVessel.protoPartSnapshots.Select(p => p.flightID).ToList());
        }
    }
}
<commit_msg>Switched list to concurrent dictionary for better thread safety<commit_after>﻿using LunaClient.Systems.SettingsSys;
using LunaClient.Utilities;
using LunaClient.VesselUtilities;
using LunaCommon;
using System;
using System.Collections.Concurrent;

namespace LunaClient.VesselStore
{
    public class VesselProtoUpdate
    {
        #region Fields & properties

        public Guid VesselId { get; set; }
        public bool VesselHasUpdate { get; set; }

        private ProtoVessel _protoVessel;
        public ProtoVessel ProtoVessel
        {
            get
            {
                if (VesselHasUpdate || _protoVessel == null)
                {
                    DeserializeVesselBytes();
                }
                return _protoVessel;
            }
            set => _protoVessel = value;
        }

        public Vessel Vessel => FlightGlobals.FindVessel(VesselId);
        public bool VesselExist => Vessel != null;
        public bool ShouldBeLoaded => SettingsSystem.ServerSettings.ShowVesselsInThePast || !VesselCommon.VesselIsControlledAndInPastSubspace(VesselId);

        public readonly ConcurrentDictionary<uint, ProtoPartSnapshot> VesselParts = new ConcurrentDictionary<uint, ProtoPartSnapshot>();

        #region Private

        private byte[] _vesselData = new byte[1000];
        private int _numBytes;
        private ConfigNode _vesselNode;
        private string _vesselHash;

        #endregion

        #endregion

        public VesselProtoUpdate(byte[] vesselData, int numBytes, Guid vesselId)
        {
            VesselId = vesselId;
            CopyVesselBytes(vesselData, numBytes);
        }

        /// <summary>
        /// Update this class with the new data received
        /// </summary>
        public void Update(byte[] vesselData, int numBytes, Guid vesselId, int situation)
        {
            if (VesselId != vesselId)
            {
                LunaLog.LogError("Cannot update a VesselProtoUpdate with a differente vesselId");
                return;
            }
            var newHash = Common.CalculateSha256Hash(vesselData);
            if (_vesselHash == newHash) return; //Skip Updating as the hash is the same

            CopyVesselBytes(vesselData, numBytes);

            _vesselHash = newHash;
            VesselHasUpdate = true;
        }

        /// <summary>
        /// Copies the received vessel bytes to this class
        /// </summary>
        private void CopyVesselBytes(byte[] vesselData, int numBytes)
        {
            if (_vesselData.Length < numBytes)
                Array.Resize(ref _vesselData, numBytes);
            Array.Copy(vesselData, _vesselData, numBytes);
            _numBytes = numBytes;
        }

        /// <summary>
        /// This method uses a lot of memory so try to call it as less as possible and only when needed
        /// </summary>
        public void DeserializeVesselBytes()
        {
            _vesselNode = ConfigNodeSerializer.Deserialize(_vesselData, _numBytes);
            ProtoVessel = VesselCommon.CreateSafeProtoVesselFromConfigNode(_vesselNode, VesselId);

            VesselParts.Clear();
            foreach (var protoPart in ProtoVessel.protoPartSnapshots)
            {
                VesselParts.TryAdd(protoPart.flightID, protoPart);
            }
        }
    }
}

{'fraction_non_alphanumeric': 0.07683249926405653, 'fraction_numerical': 0.0020606417427141595, 'mean_word_length': 1.9188144329896908, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 30, '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': '7305885', 'n_tokens_mistral': 1952, 'n_tokens_neox': 1754, 'n_words': 450}