예제 #1
0
        public static void Clear()
        {
            if (GlobalStatus == Status.Processing)
            {
                Dbg.Err($"Attempting to clear the environment while the world is in {GlobalStatus} state; should not be {Status.Processing} state");
                // but we'll do it anyway
            }

            ComponentDecDict.Clear();
            ComponentIndexDict.Clear();
            Entities.Clear();
            PhaseEndActions.Clear();

            Singletons = null;

            ActiveSystem = null;
            ActiveEntity = null;

            GlobalStatus = Status.Uninitialized;
        }
예제 #2
0
        public static void Process(ProcessDec process)
        {
            if (GlobalStatus != Status.Idle)
            {
                Dbg.Err($"Trying to run process while the world is in {GlobalStatus} state; should be {Status.Idle} state");
            }
            GlobalStatus = Status.Processing;

            foreach (var system in process.order)
            {
                try
                {
                    ActiveSystem = system;

                    var executeMethod    = system.type.GetMethod("Execute", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
                    var methodParameters = executeMethod.GetParameters();

                    var activeParameters = new object[methodParameters.Length];
                    for (int i = 0; i < methodParameters.Length; ++i)
                    {
                        if (methodParameters[i].ParameterType == typeof(Ghi.Entity))
                        {
                            continue;
                        }

                        ComponentDec component = ComponentDecDict[methodParameters[i].ParameterType];
                        if (component != null && component.singleton)
                        {
                            if (system.permissions)
                            {
                                if (!system.accessibleSingletonsRO[component.index])
                                {
                                    var err = $"{system}: Attempted to use singleton {component} without any permission";
                                    Dbg.Err(err);
                                    throw new PermissionException(err);
                                }

                                if (!system.accessibleSingletonsRW[component.index] && !methodParameters[i].Name.EndsWith("_ro"))
                                {
                                    Dbg.Wrn($"{system}: Using read-only singleton {component} without \"_ro\" suffix");
                                }
                            }

                            activeParameters[i] = Singletons[component.index];
                        }
                    }

                    if (system.iterate.Count == 0)
                    {
                        // No-iteration pathway
                        try
                        {
                            executeMethod.Invoke(null, activeParameters);
                        }
                        catch (Exception e)
                        {
                            Dbg.Ex(e);
                        }
                    }
                    else
                    {
                        // Entity-iteration pathway

                        // Doing this once per run is silly, it should be precalculated
                        int[] requiredIndices = system.iterate.Keys.Select(comp => comp.index).OrderBy(x => x).ToArray();
                        foreach (var entity in List)
                        {
                            ActiveEntity = entity;

                            bool valid = true;
                            for (int k = 0; k < requiredIndices.Length; ++k)
                            {
                                if (entity.components[requiredIndices[k]] == null)
                                {
                                    valid = false;
                                    break;
                                }
                            }

                            if (!valid)
                            {
                                continue;
                            }

                            for (int i = 0; i < methodParameters.Length; ++i)
                            {
                                if (methodParameters[i].ParameterType == typeof(Entity))
                                {
                                    activeParameters[i] = entity;
                                    continue;
                                }

                                ComponentDec component = ComponentDecDict[methodParameters[i].ParameterType];
                                if (component != null && !component.singleton)
                                {
                                    if (system.permissions)
                                    {
                                        var permission = system.iterate.TryGetValue(component);
                                        if (permission == SystemDec.Permissions.None)
                                        {
                                            Dbg.Err($"{system}: Attempted to use component {component} without any permission");
                                        }

                                        if (permission == SystemDec.Permissions.ReadOnly && !methodParameters[i].Name.EndsWith("_ro"))
                                        {
                                            Dbg.Wrn($"{system}: Using read-only component {component} without \"_ro\" suffix");
                                        }
                                    }

                                    activeParameters[i] = entity.components[component.index];
                                }
                            }

                            try
                            {
                                executeMethod.Invoke(null, activeParameters);
                            }
                            catch (Exception e)
                            {
                                Dbg.Ex(e);
                            }
                        }

                        ActiveEntity = null;
                    }
                }
                catch (Exception e)
                {
                    Dbg.Ex(e);
                }
            }

            // clean up everything, even the things that should have already been cleaned up, just in case
            ActiveSystem = null;
            ActiveEntity = null;

            GlobalStatus = Status.Idle;

            foreach (var action in PhaseEndActions)
            {
                action();
            }
            PhaseEndActions.Clear();
        }