/// <summary> /// Filling the dependencies of newComp by iterating over entity's components /// </summary> /// <param name="entity"></param> /// <param name="newComp"></param> public void InjectIntoComponent(IEntity entity, IComponent newComp) { var queries = GetPointerQueries(newComp); if (queries.Length == 0) { return; } //get all present components in entity foreach (var entityComp in entity.GetAllComponents()) { var entityCompReg = _componentFactory.GetRegistration(entityComp); foreach (var reference in entityCompReg.References) { foreach (var entry in queries) { if (entry.Query == reference) { SetField(newComp, entry.FieldMemoryOffset, entityComp); entry.OnAddMethod?.Invoke(newComp); } } } } }
/// <summary> /// Adds a component to the component list. /// </summary> /// <param name="component"></param> public void AddComponent(IComponent component) { var reg = ComponentFactory.GetRegistration(component); foreach (Type type in reg.References) { if (!components.ContainsKey(type)) { components[type] = new List <IComponent>(); } components[type].Add(component); } allComponents.Add(component); }
public bool TryAddStatusEffect(EntityUid uid, string key, TimeSpan time, bool refresh, string component, StatusEffectsComponent?status = null) { if (!Resolve(uid, ref status, false)) { return(false); } if (TryAddStatusEffect(uid, key, time, refresh, status)) { // If they already have the comp, we just won't bother updating anything. if (!EntityManager.HasComponent(uid, _componentFactory.GetRegistration(component).Type)) { // F**k this shit I hate it var newComponent = (Component)_componentFactory.GetComponent(component); newComponent.Owner = uid; EntityManager.AddComponent(uid, newComponent); status.ActiveEffects[key].RelevantComponent = component; } return(true); } return(false); }
private void OnGotEquipped(EntityUid uid, AddAccentClothingComponent component, GotEquippedEvent args) { if (!TryComp(uid, out ClothingComponent? clothing)) { return; } // check if entity was actually used as clothing // not just taken in pockets or something var isCorrectSlot = clothing.SlotFlags.HasFlag(args.SlotFlags); if (!isCorrectSlot) { return; } // does the user already has this accent? var componentType = _componentFactory.GetRegistration(component.Accent).Type; if (EntityManager.HasComponent(args.Equipee, componentType)) { return; } // add accent to the user var accentComponent = (Component)_componentFactory.GetComponent(componentType); accentComponent.Owner = args.Equipee; EntityManager.AddComponent(args.Equipee, accentComponent); // snowflake case for replacement accent if (accentComponent is ReplacementAccentComponent rep) { rep.Accent = component.ReplacementPrototype !; } component.IsActive = true; }
public async Task <bool> Condition(IEntity entity) { if (string.IsNullOrEmpty(Component)) { return(false); } var type = _componentFactory.GetRegistration(Component).Type; var indices = entity.Transform.Coordinates.ToVector2i(entity.EntityManager, _mapManager); var entities = indices.GetEntitiesInTile(entity.Transform.GridID, LookupFlags.Approximate | LookupFlags.IncludeAnchored, IoCManager.Resolve <IEntityLookup>()); foreach (var ent in entities) { if (ent.HasComponent(type)) { return(HasEntity); } } return(!HasEntity); }
public async Task <bool> Condition(IEntity entity) { if (string.IsNullOrEmpty(Component)) { return(false); } var type = _componentFactory.GetRegistration(Component).Type; var indices = entity.Transform.Coordinates.ToVector2i(entity.EntityManager, _mapManager); var entities = indices.GetEntitiesInTile(entity.Transform.GridID, true, entity.EntityManager); foreach (var ent in entities) { if (ent.HasComponent(type)) { return(HasEntity); } } return(!HasEntity); }
/// <inheritdoc /> public void AddComponent <T>(IEntity entity, T component, bool overwrite = false) where T : Component { 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."); } var uid = entity.Uid; // 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(uid, type, out var duplicate)) { continue; } if (!overwrite) { throw new InvalidOperationException( $"Component reference type {type} already occupied by {duplicate}"); } // these two components are required on all entities and cannot be overwritten. if (duplicate is ITransformComponent || duplicate is IMetaDataComponent) { throw new InvalidOperationException("Tried to overwrite a protected component."); } RemoveComponentImmediate((Component)duplicate); } // add the component to the grid foreach (var type in reg.References) { _entTraitDict[type].Add(uid, component); _entCompIndex.Add(uid, component); } // add the component to the netId grid if (component.NetID != null) { // the main comp grid keeps this in sync var netId = component.NetID.Value; _entNetIdDict[netId].Add(uid, component); // mark the component as dirty for networking component.Dirty(); ComponentAdded?.Invoke(this, new AddedComponentEventArgs(component)); } component.ExposeData(DefaultValueSerializer.Reader()); component.OnAdd(); if (!entity.Initialized && !entity.Initializing) { return; } component.Initialize(); DebugTools.Assert(component.Initialized, "Component is not initialized after calling Initialize(). " + "Did you forget to call base.Initialize() in an override?"); if (entity.Initialized) { component.Running = true; } }
/// <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}"); } // these two components are required on all entities and cannot be overwritten. if (duplicate is ITransformComponent || duplicate is IMetaDataComponent) { throw new InvalidOperationException("Tried to overwrite a protected component."); } RemoveComponentImmediate((Component)duplicate); } // add the component to the grid foreach (var type in reg.References) { _dictComponents[type].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 || entity.Initializing) { component.Initialize(); if (entity.Initialized) { component.Running = true; } } }
private void HandleEntityState(IComponentManager compMan, IEntity entity, EntityState curState, EntityState nextState) { var compStateWork = new Dictionary <uint, (ComponentState curState, ComponentState nextState)>(); var entityUid = entity.Uid; if (curState?.ComponentChanges != null) { foreach (var compChange in curState.ComponentChanges) { if (compChange.Deleted) { if (compMan.TryGetComponent(entityUid, compChange.NetID, out var comp)) { compMan.RemoveComponent(entityUid, comp); } } else { if (compMan.HasComponent(entityUid, compChange.NetID)) { continue; } var newComp = (Component)_compFactory.GetComponent(compChange.ComponentName); newComp.Owner = entity; compMan.AddComponent(entity, newComp, true); } } } if (curState?.ComponentStates != null) { foreach (var compState in curState.ComponentStates) { compStateWork[compState.NetID] = (compState, null); } } if (nextState?.ComponentStates != null) { foreach (var compState in nextState.ComponentStates) { if (compStateWork.TryGetValue(compState.NetID, out var state)) { compStateWork[compState.NetID] = (state.curState, compState); } else { compStateWork[compState.NetID] = (null, compState); } } } foreach (var kvStates in compStateWork) { if (!compMan.TryGetComponent(entityUid, kvStates.Key, out var component)) { var eUid = entityUid; var eExpectedNetUid = kvStates.Key; var eRegisteredNetUidName = _compFactory.GetRegistration(eExpectedNetUid).Name; DebugTools.Assert($"Component does not exist for state: entUid={eUid}, expectedNetId={eExpectedNetUid}, expectedName={eRegisteredNetUidName}"); continue; } try { component.HandleComponentState(kvStates.Value.curState, kvStates.Value.nextState); } catch (Exception e) { var wrapper = new ComponentStateApplyException( $"Failed to apply comp state: entity={component.Owner}, comp={component.Name}", e); #if EXCEPTION_TOLERANCE _runtimeLog.LogException(wrapper, "Component state apply"); #else throw wrapper; #endif } } }
public void RegenerateProgress() { AppearanceComponent appearance; if (!HasBoard) { if (Owner.TryGetComponent(out appearance)) { appearance.SetData(MachineFrameVisuals.State, 1); } Requirements = null; MaterialRequirements = null; ComponentRequirements = null; _progress = null; _materialProgress = null; _componentProgress = null; return; } var board = _boardContainer.ContainedEntities[0]; if (!board.TryGetComponent <MachineBoardComponent>(out var machineBoard)) { return; } if (Owner.TryGetComponent(out appearance)) { appearance.SetData(MachineFrameVisuals.State, 2); } ResetProgressAndRequirements(machineBoard); foreach (var part in _partContainer.ContainedEntities) { if (part.TryGetComponent <MachinePartComponent>(out var machinePart)) { // Check this is part of the requirements... if (!Requirements.ContainsKey(machinePart.PartType)) { continue; } if (!_progress.ContainsKey(machinePart.PartType)) { _progress[machinePart.PartType] = 1; } else { _progress[machinePart.PartType]++; } } if (part.TryGetComponent <StackComponent>(out var stack)) { var type = stack.StackTypeId; // Check this is part of the requirements... if (!MaterialRequirements.ContainsKey(type)) { continue; } if (!_materialProgress.ContainsKey(type)) { _materialProgress[type] = 1; } else { _materialProgress[type]++; } } // I have many regrets. foreach (var(compName, amount) in ComponentRequirements) { var registration = _componentFactory.GetRegistration(compName); if (!part.HasComponent(registration.Type)) { continue; } if (!_componentProgress.ContainsKey(compName)) { _componentProgress[compName] = 1; } else { _componentProgress[compName]++; } } } }
private IEnumerable <Type> GetReferences(Type type) { return(_comFac.GetRegistration(type).References); }
private void HandleEntityState(IComponentManager compMan, IEntity entity, EntityState?curState, EntityState?nextState) { var compStateWork = new Dictionary <uint, (ComponentState?curState, ComponentState?nextState)>(); var entityUid = entity.Uid; if (curState?.ComponentChanges != null) { foreach (var compChange in curState.ComponentChanges) { if (compChange.Deleted) { if (compMan.TryGetComponent(entityUid, compChange.NetID, out var comp)) { compMan.RemoveComponent(entityUid, comp); } } else { if (compMan.HasComponent(entityUid, compChange.NetID)) { continue; } var newComp = (Component)_compFactory.GetComponent(compChange.ComponentName !); newComp.Owner = entity; compMan.AddComponent(entity, newComp, true); } } } if (curState?.ComponentStates != null) { foreach (var compState in curState.ComponentStates) { compStateWork[compState.NetID] = (compState, null); } } if (nextState?.ComponentStates != null) { foreach (var compState in nextState.ComponentStates) { if (compStateWork.TryGetValue(compState.NetID, out var state)) { compStateWork[compState.NetID] = (state.curState, compState); } else { compStateWork[compState.NetID] = (null, compState); } } } foreach (var(netId, (cur, next)) in compStateWork) { if (compMan.TryGetComponent(entityUid, netId, out var component)) { try { component.HandleComponentState(cur, next); } catch (Exception e) { var wrapper = new ComponentStateApplyException( $"Failed to apply comp state: entity={component.Owner}, comp={component.Name}", e); #if EXCEPTION_TOLERANCE _runtimeLog.LogException(wrapper, "Component state apply"); #else throw wrapper; #endif } } else { // The component can be null here due to interp. // Because the NEXT state will have a new component, but this one doesn't yet. // That's fine though. if (cur == null) { continue; } var eUid = entityUid; var eRegisteredNetUidName = _compFactory.GetRegistration(netId).Name; DebugTools.Assert( $"Component does not exist for state: entUid={eUid}, expectedNetId={netId}, expectedName={eRegisteredNetUidName}"); } } }
/// <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(); } component.OnAdd(); if (entity.Initialized) { component.Initialize(); component.Startup(); } }
private void OnInteractUsing(EntityUid uid, MachineFrameComponent component, InteractUsingEvent args) { if (!component.HasBoard && TryComp <MachineBoardComponent?>(args.Used, out var machineBoard)) { if (args.Used.TryRemoveFromContainer()) { // Valid board! component.BoardContainer.Insert(args.Used); // Setup requirements and progress... ResetProgressAndRequirements(component, machineBoard); if (TryComp <AppearanceComponent?>(uid, out var appearance)) { appearance.SetData(MachineFrameVisuals.State, 2); } if (TryComp(uid, out ConstructionComponent? construction)) { // So prying the components off works correctly. _construction.ResetEdge(uid, construction); } } } else if (component.HasBoard) { if (TryComp <MachinePartComponent>(args.Used, out var machinePart)) { if (!component.Requirements.ContainsKey(machinePart.PartType)) { return; } if (component.Progress[machinePart.PartType] != component.Requirements[machinePart.PartType] && args.Used.TryRemoveFromContainer() && component.PartContainer.Insert(args.Used)) { component.Progress[machinePart.PartType]++; args.Handled = true; return; } } if (TryComp <StackComponent?>(args.Used, out var stack)) { var type = stack.StackTypeId; if (!component.MaterialRequirements.ContainsKey(type)) { return; } if (component.MaterialProgress[type] == component.MaterialRequirements[type]) { return; } var needed = component.MaterialRequirements[type] - component.MaterialProgress[type]; var count = stack.Count; if (count < needed) { if (!component.PartContainer.Insert(stack.Owner)) { return; } component.MaterialProgress[type] += count; args.Handled = true; return; } var splitStack = _stack.Split(args.Used, needed, Comp <TransformComponent>(uid).Coordinates, stack); if (splitStack == null) { return; } if (!component.PartContainer.Insert(splitStack.Value)) { return; } component.MaterialProgress[type] += needed; args.Handled = true; return; } foreach (var(compName, info) in component.ComponentRequirements) { if (component.ComponentProgress[compName] >= info.Amount) { continue; } var registration = _factory.GetRegistration(compName); if (!HasComp(args.Used, registration.Type)) { continue; } if (!args.Used.TryRemoveFromContainer() || !component.PartContainer.Insert(args.Used)) { continue; } component.ComponentProgress[compName]++; args.Handled = true; return; } foreach (var(tagName, info) in component.TagRequirements) { if (component.TagProgress[tagName] >= info.Amount) { continue; } if (!_tag.HasTag(args.Used, tagName)) { continue; } if (!args.Used.TryRemoveFromContainer() || !component.PartContainer.Insert(args.Used)) { continue; } component.TagProgress[tagName]++; args.Handled = true; return; } } }