Example #1
0
        private void DoModifications()
        {
            _modifiedLastFrame.Clear();

            // apply modifications
            _concurrentModifications.IterateAndClear(dataAccessor => {
                int id = dataAccessor.Id;

                // if we removed the data, then don't bother apply/dispatching modifications on it
                if (_data.ContainsKey(id))
                {
                    if (_data[id] is VersionedDataContainer)
                    {
                        VersionedDataContainer container = (VersionedDataContainer)_data[id];
                        container.Increment();
                    }

                    _data[id].ModificationActivation.Reset();
                    _modifiedLastFrame[id] = _data[id];
                }
            });
        }
Example #2
0
        public ContentEntitySerializationFormat GetSerializedFormat()
        {
            List <ContentEntity.DataInstance> data = new List <ContentEntity.DataInstance>();

            // the data instances that have been modified in the current update
            HashSet <int> modifiedThisFrame = new HashSet <int>();
            {
                List <DataAccessor> modifications = _concurrentModifications.ToList();
                foreach (DataAccessor modification in modifications)
                {
                    modifiedThisFrame.Add(modification.Id);
                }
            }

            // the data instances that have been removed in the current update
            HashSet <int> removedThisFrame = new HashSet <int>();

            {
                foreach (DataAccessor item in _toRemoveStage1)
                {
                    removedThisFrame.Add(item.Id);
                }
            }

            foreach (KeyValuePair <int, DataContainer> tuple in _data)
            {
                DataAccessor accessor = new DataAccessor(tuple.Key);

                // If the data was removed this frame, then next frame it won't exist anymore, so we
                // don't serialize it
                if (WasRemoved(accessor))
                {
                    continue;
                }

                var dataInstance = new ContentEntity.DataInstance()
                {
                    // these items are never added this frame; if WasAdded is true now, it will be
                    // false next frame
                    WasAdded = false,

                    // the data *may* have been removed this frame, though
                    WasRemoved = removedThisFrame.Contains(accessor.Id)
                };

                // if we were modified this frame, then we have to do a data swap (and set
                // WasModified to true)
                if (modifiedThisFrame.Contains(accessor.Id))
                {
                    // do a data swap so our modified data is correct
                    if (_data[accessor.Id] is VersionedDataContainer)
                    {
                        VersionedDataContainer container = (VersionedDataContainer)_data[accessor.Id];
                        dataInstance.CurrentData  = container.Modifying;
                        dataInstance.PreviousData = container.Current;
                    }
                    else
                    {
                        NonVersionedDataContainer container = (NonVersionedDataContainer)_data[accessor.Id];
                        dataInstance.CurrentData = container.Data;
                    }

                    dataInstance.WasModified = true;
                }

                // we were not modified this frame, so don't perform a data swap
                else
                {
                    // do a data swap so our modified data is correct
                    if (_data[accessor.Id] is VersionedDataContainer)
                    {
                        VersionedDataContainer container = (VersionedDataContainer)_data[accessor.Id];
                        dataInstance.CurrentData  = container.Current;
                        dataInstance.PreviousData = container.Previous;
                    }
                    else
                    {
                        NonVersionedDataContainer container = (NonVersionedDataContainer)_data[accessor.Id];
                        dataInstance.CurrentData = container.Data;
                    }

                    dataInstance.WasModified = false;
                }

                data.Add(dataInstance);
            }

            foreach (var toAdd in _toAddStage1)
            {
                data.Add(new ContentEntity.DataInstance()
                {
                    CurrentData  = toAdd,
                    PreviousData = toAdd,
                    WasAdded     = true,

                    // added data is never modified
                    WasModified = false,

                    // added data also cannot be removed in the same frame it was added in
                    WasRemoved = false
                });
            }

            return(new ContentEntitySerializationFormat()
            {
                PrettyName = PrettyName,
                UniqueId = UniqueId,
                Data = data
            });
        }
Example #3
0
        /// <summary>
        /// Applies data state changes to the entity.
        /// </summary>
        /// <remarks>
        /// This function is not thread-safe; no other API calls can be made to the Entity while
        /// this function is being executed.
        /// </remarks>
        /// <returns>If more data state change updates are needed</returns>
        public void DataStateChangeUpdate()
        {
            // do removals
            {
                for (int i = 0; i < _toRemoveStage1.Count; ++i)
                {
                    int id = _toRemoveStage1[i].Id;
                    _removedLastFrame[id] = _toRemoveStage1[i];
                    // _removedLastFrame[id] is removed in stage2

                    _eventDispatcher.Submit(RemovedDataEvent.Create(this, DataAccessorFactory.GetTypeFromId(id)));
                }

                for (int i = 0; i < _toRemoveStage2.Count; ++i)
                {
                    int id = _toRemoveStage2[i].Id;
                    _removedLastFrame.Remove(id);
                    _data.Remove(id);
                }
                _toRemoveStage2.Clear();

                Utils.Swap(ref _toRemoveStage1, ref _toRemoveStage2);
            }

            // We don't throw an exception immediately. If we are throwing an exception, that means
            // that the Entity is in an invalid state (adding a bad data instance). However, the
            // only way to recover from that invalid state is by having this method terminate.
            // Hence, we only throw an exception at the end of the method.
            Exception exceptionToThrow = null;

            // do additions
            for (int i = 0; i < _toAddStage1.Count; ++i)
            {
                Data.IData added = _toAddStage1[i];
                int        id    = DataAccessorFactory.GetId(added.GetType());

                // make sure we do not readd the same data instance twice
                if (_data.ContainsKey(id))
                {
                    exceptionToThrow = new AlreadyAddedDataException(this, new DataAccessor(added));
                    continue;
                }

                _addedLastFrame[id] = added;

                if (added is Data.IVersioned)
                {
                    Data.IVersioned versioned = (Data.IVersioned)added;

                    _data[id] = new VersionedDataContainer(versioned.Duplicate(), versioned.Duplicate(), versioned.Duplicate());
                }
                else
                {
                    Data.NonVersioned nonVersioned = (Data.NonVersioned)added;
                    _data[id] = new NonVersionedDataContainer(nonVersioned);
                }

                // visualize the initial data
                _eventDispatcher.Submit(AddedDataEvent.Create(this, added.GetType()));
            }

            for (int i = 0; i < _toAddStage2.Count; ++i)
            {
                _addedLastFrame.Remove(new DataAccessor(_toAddStage2[i]).Id);
            }
            _toAddStage2.Clear();

            Utils.Swap(ref _toAddStage1, ref _toAddStage2);

            if (exceptionToThrow != null)
            {
                throw exceptionToThrow;
            }
        }
Example #4
0
        /// <summary>
        /// Applies data state changes to the entity.
        /// </summary>
        /// <remarks>
        /// This function is not thread-safe; no other API calls can be made to the Entity while
        /// this function is being executed.
        /// </remarks>
        /// <returns>If more data state change updates are needed</returns>
        public void DataStateChangeUpdate() {
            // do removals
            {
                for (int i = 0; i < _toRemoveStage1.Count; ++i) {
                    int id = _toRemoveStage1[i].Id;
                    _removedLastFrame[id] = _toRemoveStage1[i];
                    // _removedLastFrame[id] is removed in stage2

                    _eventDispatcher.Submit(RemovedDataEvent.Create(this, DataAccessorFactory.GetTypeFromId(id)));
                }

                for (int i = 0; i < _toRemoveStage2.Count; ++i) {
                    int id = _toRemoveStage2[i].Id;
                    _removedLastFrame.Remove(id);
                    _data.Remove(id);
                }
                _toRemoveStage2.Clear();

                Utils.Swap(ref _toRemoveStage1, ref _toRemoveStage2);
            }

            // We don't throw an exception immediately. If we are throwing an exception, that means
            // that the Entity is in an invalid state (adding a bad data instance). However, the
            // only way to recover from that invalid state is by having this method terminate.
            // Hence, we only throw an exception at the end of the method.
            Exception exceptionToThrow = null;

            // do additions
            for (int i = 0; i < _toAddStage1.Count; ++i) {
                Data.IData added = _toAddStage1[i];
                int id = DataAccessorFactory.GetId(added.GetType());

                // make sure we do not readd the same data instance twice
                if (_data.ContainsKey(id)) {
                    exceptionToThrow = new AlreadyAddedDataException(this, new DataAccessor(added));
                    continue;
                }

                _addedLastFrame[id] = added;

                if (added is Data.IVersioned) {
                    Data.IVersioned versioned = (Data.IVersioned)added;

                    _data[id] = new VersionedDataContainer(versioned.Duplicate(), versioned.Duplicate(), versioned.Duplicate());
                }
                else {
                    Data.NonVersioned nonVersioned = (Data.NonVersioned)added;
                    _data[id] = new NonVersionedDataContainer(nonVersioned);
                }

                // visualize the initial data
                _eventDispatcher.Submit(AddedDataEvent.Create(this, added.GetType()));
            }

            for (int i = 0; i < _toAddStage2.Count; ++i) {
                _addedLastFrame.Remove(new DataAccessor(_toAddStage2[i]).Id);
            }
            _toAddStage2.Clear();

            Utils.Swap(ref _toAddStage1, ref _toAddStage2);

            if (exceptionToThrow != null) {
                throw exceptionToThrow;
            }
        }