/// <inheritdoc /> public void AddComponent(IEntity entity, Component component, bool overwrite = false) { if (entity == null || !entity.IsValid()) { throw new ArgumentException("Entity is not valid.", nameof(entity)); } if (component == null) { throw new ArgumentNullException(nameof(component)); } if (component.Owner != entity) { throw new InvalidOperationException("Component is not owned by entity."); } // get interface aliases for mapping var reg = _componentFactory.GetRegistration(component); // Check that there are no overlapping references. foreach (var type in reg.References) { if (!TryGetComponent(entity.Uid, type, out var duplicate)) { continue; } if (!overwrite) { throw new InvalidOperationException($"Component reference type {type} already occupied by {duplicate}"); } RemoveComponentImmediate((Component)duplicate); } // add the component to the grid foreach (var type in reg.References) { // new types can be added at any time if (!_dictComponents.TryGetValue(type, out var typeDict)) { typeDict = new Dictionary <EntityUid, Component>(EntityCapacity); _dictComponents.Add(type, typeDict); } typeDict.Add(entity.Uid, component); } // add the component to the netId grid if (component.NetID != null) { // the main comp grid keeps this in sync if (!_netComponents.TryGetValue(entity.Uid, out var netDict)) { netDict = new Dictionary <uint, Component>(CompTypeCapacity); _netComponents.Add(entity.Uid, netDict); } netDict.Add(component.NetID.Value, component); // mark the component as dirty for networking component.Dirty(); ComponentAdded?.Invoke(this, new ComponentEventArgs(component)); } component.OnAdd(); if (entity.Initialized) { component.Initialize(); component.Startup(); } }