private void Remove(ModSessionComponent component) { var myType = component.GetType(); List <RuntimeSessionComponent> list; if (m_componentDictionary.TryGetValue(myType, out list)) { for (var i = 0; i < list.Count; i++) { if (list[i].Component != component) { continue; } if (list[i].Dependents.Count > 0) { FallbackLogger.Log(MyLogSeverity.Critical, "Unable to remove {0} because it still has {1} dependents", component.GetType(), list[i].Dependents.Count); using (FallbackLogger.IndentUsing()) foreach (var dep in list[i].Dependents) { FallbackLogger.Log(MyLogSeverity.Critical, "Dependent: {0}", dep.Component.GetType()); } throw new ArgumentException("Can't remove " + component.GetType() + " because it still has dependents"); } foreach (var dep in list[i].Dependencies) { dep.Dependents.Remove(list[i]); } list.RemoveAtFast(i); break; } if (list.Count == 0) { m_componentDictionary.Remove(myType); } } foreach (var dep in component.SuppliedComponents) { m_dependencySatisfyingComponents.Remove(dep); } for (var i = 0; i < m_orderedComponentList.Count; i++) { if (m_orderedComponentList[i].Component == component) { m_orderedComponentList.RemoveAt(i); break; } } component.Detached(); ComponentDetached?.Invoke(component); }
public void AppendConfiguration(Ob_SessionManager config) { if (config.SessionComponents == null) { return; } TolerableLag = config.TolerableLag; foreach (var x in config.SessionComponents) { var desc = ModSessionComponentRegistry.Get(x); var module = desc.Activator(); FallbackLogger.Log(MyLogSeverity.Debug, "Registering module {0} from configuration", module.GetType()); Register(module, x); } }
private void SortComponents() { ApplyComponentChanges(); // Fill using factories var prevCount = 0; while (true) { var entries = m_componentDictionary.Values.SelectMany(x => x).ToList(); if (entries.Count == prevCount) { break; } foreach (var sat in entries) { foreach (var dep in sat.Component.Dependencies) { if (m_dependencySatisfyingComponents.ContainsKey(dep)) { continue; } ModSessionComponentRegistry.CreateComponent factory; if (!_factories.TryGetValue(dep, out factory)) { throw new ArgumentException("Unable to resolve " + dep + " for " + sat.Component.GetType()); } Register(factory()); } } prevCount = entries.Count; } // Fill dependency information. foreach (var c in m_componentDictionary.Values.SelectMany(x => x)) { c.Dependencies.Clear(); c.Dependents.Clear(); } foreach (var c in m_componentDictionary.Values.SelectMany(x => x)) { foreach (var dependency in c.Component.Dependencies) { RuntimeSessionComponent resolved; if (m_dependencySatisfyingComponents.TryGetValue(dependency, out resolved)) { resolved.Dependents.Add(c); c.Dependencies.Add(resolved); c.Component.SatisfyDependency(resolved.Component); c.UnsolvedDependencies = c.Dependencies.Count; } else { throw new ArgumentException("Unable to resolve " + dependency + " for " + c.Component.GetType()); } } } m_orderedComponentList.Clear(); m_dagQueue.AddRange(m_componentDictionary.Values.SelectMany(x => x)); while (m_dagQueue.Count > 0) { foreach (var x in m_componentDictionary.Values.SelectMany(y => y)) { x.UnsolvedDependenciesNext = x.UnsolvedDependencies; } m_tmpQueue.Clear(); for (var i = 0; i < m_dagQueue.Count; i++) { var c = m_dagQueue[i]; if (c.UnsolvedDependencies == 0) { m_tmpQueue.Add(c); foreach (var d in c.Dependents) { d.UnsolvedDependenciesNext--; } } else if (m_tmpQueue.Count > 0) { m_dagQueue[i - m_tmpQueue.Count] = c; } } foreach (var x in m_componentDictionary.Values.SelectMany(y => y)) { x.UnsolvedDependencies = x.UnsolvedDependenciesNext; } if (m_tmpQueue.Count == 0) { FallbackLogger.Log(MyLogSeverity.Critical, "Dependency loop detected when solving session DAG"); using (FallbackLogger.IndentUsing()) foreach (var k in m_dagQueue) { FallbackLogger.Log(MyLogSeverity.Critical, "{0}x{1} has {2} unsolved dependencies. Dependencies are {3}, Dependents are {4}", k.Component.GetType().Name, k.Component.GetType().GetHashCode(), k.UnsolvedDependencies, string.Join(", ", k.Dependencies.Select(x => x.Component.GetType() + "x" + x.Component.GetHashCode())), string.Join(", ", k.Dependents.Select(x => x.Component.GetType() + "x" + x.Component.GetHashCode()))); } throw new ArgumentException("Dependency loop inside " + string.Join(", ", m_dagQueue.Select(x => x.Component.GetType() + "x" + x.Component.GetHashCode()))); } m_dagQueue.RemoveRange(m_dagQueue.Count - m_tmpQueue.Count, m_tmpQueue.Count); // Sort temp queue, add to sorted list. m_tmpQueue.Sort((a, b) => a.Component.Priority.CompareTo(b.Component.Priority)); foreach (var k in m_tmpQueue) { m_orderedComponentList.Add(k); } m_tmpQueue.Clear(); } }