summary refs log blame commit diff stats
path: root/GameState.cs
blob: 9280eb317be1766b44e6af6dee6fcdfe521f630a (plain) (tree)

































                                                                                                                                             













                                                                                                













































































                                                                                            
                                                                       





                                                                          






                                                                                     


















                                                                                                                                                                       








                                                                                               
 











                                                                                                                                                 

                                                           
                                                                        













                                                                                                                                                                 





























                                                                                                                                                                 

         
using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace ManifoldGardenArchipelago
{
    public class GameState
    {
        public static LevelSystems GetLevelSystems(Component component)
        {
            return component.gameObject.scene.GetRootGameObjects().Single((obj) => obj.name == "Level Systems").GetComponent<LevelSystems>();
        }

        public static LevelSystems GetLevelSystems(Scene scene)
        {
            return scene.GetRootGameObjects().Single((obj) => obj.name == "Level Systems").GetComponent<LevelSystems>();
        }

        public static SceneItemReference GetChainListenerSceneReference(Component component)
        {
            LevelSystems levelSystem = GetLevelSystems(component);

            for (int i = 0; i < levelSystem.chainListeners.Count(); i++)
            {
                if (levelSystem.chainListeners[i] == component)
                {
                    return new(component.gameObject.scene.name, i);
                }
            }

            throw new Exception("Shouldn't happen");
        }

        public static SceneItemReference GetGameplayComponentSceneReference(Component component)
        {
            LevelSystems levelSystem = GetLevelSystems(component);

            for (int i = 0; i < levelSystem.gameplayComponentsInLevel.Count(); i++)
            {
                if (levelSystem.gameplayComponentsInLevel[i] == component)
                {
                    return new(component.gameObject.scene.name, i);
                }
            }

            throw new Exception("Shouldn't happen");
        }

        public static SceneItemReference GetButtonSceneReference(ButtonLineActivator arg)
        {
            LevelSystems levelSystem = GetLevelSystems(arg);

            for (int i = 0; i < levelSystem.buttonLineActivators.Count(); i++)
            {
                if (levelSystem.buttonLineActivators[i] == arg)
                {
                    return new(arg.gameObject.scene.name, i);
                }
            }

            throw new Exception("Shouldn't happen");
        }

        public static SceneItemReference GetPadSceneReference(CubeLineActivator arg)
        {
            LevelSystems levelSystem = GetLevelSystems(arg);

            for (int i = 0; i < levelSystem.cubeLineActivators.Count(); i++)
            {
                if (levelSystem.cubeLineActivators[i] == arg)
                {
                    return new(arg.gameObject.scene.name, i);
                }
            }

            throw new Exception("Shouldn't happen");
        }

        public static SceneItemReference GetSocketSceneReference(CubeReceiverController arg)
        {
            LevelSystems levelSystem = GetLevelSystems(arg);

            for (int i = 0; i < levelSystem.cubeReceiverControllers.Count(); i++)
            {
                if (levelSystem.cubeReceiverControllers[i] == arg)
                {
                    return new(arg.gameObject.scene.name, i);
                }
            }

            throw new Exception("Shouldn't happen");
        }

        public static SceneItemReference GetSphereSceneReference(SphereController arg)
        {
            LevelSystems levelSystem = GetLevelSystems(arg);

            for (int i = 0; i < levelSystem.sphereControllers.Count(); i++)
            {
                if (levelSystem.sphereControllers[i] == arg)
                {
                    return new(arg.gameObject.scene.name, i);
                }
            }

            throw new Exception("Shouldn't happen");
        }

        public static SceneItemReference GetWaterwheelSceneReference(WaterDetector arg)
        {
            LevelSystems levelSystem = GetLevelSystems(arg);

            for (int i = 0; i < levelSystem.waterDetectors.Count(); i++)
            {
                if (levelSystem.waterDetectors[i] == arg)
                {
                    return new(arg.gameObject.scene.name, i);
                }
            }

            throw new Exception("Shouldn't happen");
        }

        public static void EvaluateGameStateListeners(GameStateListeners listeners)
        {
            foreach (var location in listeners.locations)
            {
                if (location.Value.Check() == Requirement.Decision.Yes)
                {
                    Plugin.archipelagoManager.CheckLocation(location.Key);
                }
            }

            foreach (var door in listeners.doors)
            {
                Requirement.Decision decision = door.Value.Check();
                if (decision == Requirement.Decision.Maybe)
                {
                    continue;
                }

                bool shouldOpen = (decision == Requirement.Decision.Yes);
                //Plugin.Logger.LogInfo($"{door.Key}: {door.Value} -> {shouldOpen}");

                if (SceneManager.GetSceneByName(door.Key.scene) is Scene doorScene && doorScene.isLoaded)
                {
                    LevelSystems levelSystems = GetLevelSystems(doorScene);
                    if (levelSystems.isActiveAndEnabled)
                    {
                        LineDoorController ldc = levelSystems.chainListeners[door.Key.index].GetComponent<LineDoorController>();
                        ldc.chains.Clear();

                        FieldInfo fieldInfo = typeof(LineDoorController).GetField("doorShouldOpenImmediatelyOnEnable", BindingFlags.Instance | BindingFlags.NonPublic);
                        fieldInfo.SetValue(ldc, shouldOpen);

                        MethodInfo methodInfo = typeof(LineDoorController).GetMethod("SetDoorOpenCloseStateAnimated", BindingFlags.NonPublic | BindingFlags.Instance);
                        methodInfo.Invoke(ldc, [shouldOpen, false]);

                        ldc.saveData.isOpen = shouldOpen;
                    }
                }
            }

            foreach (var smokeWall in listeners.smokeWalls)
            {
                Requirement.Decision decision = smokeWall.Value.Check();
                if (decision == Requirement.Decision.Maybe)
                {
                    continue;
                }

                bool shouldOpen = (decision == Requirement.Decision.Yes);
                //Plugin.Logger.LogInfo($"{smokeWall.Key}: {smokeWall.Value} -> {shouldOpen}");

                if (SceneManager.GetSceneByName(smokeWall.Key.scene) is Scene smokeScene && smokeScene.isLoaded)
                {
                    LevelSystems levelSystems = GetLevelSystems(smokeScene);
                    if (levelSystems.isActiveAndEnabled)
                    {
                        SolidStateController ldc = levelSystems.chainListeners[smokeWall.Key.index].GetComponent<SolidStateController>();
                        ldc.chains.Clear();

                        FieldInfo fieldInfo = typeof(SolidStateController).GetField("m_isSolid", BindingFlags.Instance | BindingFlags.NonPublic);
                        fieldInfo.SetValue(ldc, !shouldOpen);
                    }
                }
            }

            foreach (var worldGrow in listeners.worldGrows)
            {
                if (worldGrow.Value.Check() == Requirement.Decision.Yes)
                {
                    if (SceneManager.GetSceneByName(worldGrow.Key.scene) is Scene gardenScene && gardenScene.isLoaded)
                    {
                        LevelSystems levelSystems = GetLevelSystems(gardenScene);
                        if (levelSystems.isActiveAndEnabled)
                        {
                            DarkModeCollapsedCubeWorldGrow ldc = levelSystems.chainListeners[worldGrow.Key.index].GetComponent<DarkModeCollapsedCubeWorldGrow>();
                            ldc.chains.Clear();

                            FieldInfo fieldInfo = typeof(DarkModeCollapsedCubeWorldGrow).GetField("m_grown", BindingFlags.Instance | BindingFlags.NonPublic);
                            fieldInfo.SetValue(ldc, true);
                        }
                    }
                }
            }

            foreach (var laser in listeners.lasers)
            {
                Requirement.Decision decision = laser.Value.Check();
                if (decision == Requirement.Decision.Maybe)
                {
                    continue;
                }

                bool shouldOpen = (decision == Requirement.Decision.Yes);

                if (SceneManager.GetSceneByName(laser.Key.scene) is Scene laserScene && laserScene.isLoaded)
                {
                    LevelSystems levelSystems = GetLevelSystems(laserScene);
                    if (levelSystems.isActiveAndEnabled)
                    {
                        DarkModeCageController ldc = levelSystems.gameplayComponentsInLevel[laser.Key.index].GetComponent<DarkModeCageController>();
                        
                        if (shouldOpen)
                        {
                            MethodInfo methodInfo = typeof(DarkModeCageController).GetMethod("OpenLaserSource", BindingFlags.Instance | BindingFlags.NonPublic);
                            methodInfo.Invoke(ldc, [false]);
                        }
                        else
                        {
                            MethodInfo methodInfo = typeof(DarkModeCageController).GetMethod("CloseLaserSource", BindingFlags.Instance | BindingFlags.NonPublic);
                            methodInfo.Invoke(ldc, [false]);
                        }
                    }
                }
            }
        }
    }
}