예제 #1
0
        /// <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);
                        }
                    }
                }
            }
        }
예제 #2
0
        /// <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);
        }
예제 #3
0
        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;
    }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        /// <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;
            }
        }
예제 #8
0
        /// <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;
                }
            }
        }
예제 #9
0
        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
                }
            }
        }
예제 #10
0
        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]++;
                    }
                }
            }
        }
예제 #11
0
 private IEnumerable <Type> GetReferences(Type type)
 {
     return(_comFac.GetRegistration(type).References);
 }
예제 #12
0
        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}");
                }
            }
        }
예제 #13
0
        /// <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;
            }
        }
    }