Пример #1
0
        public static void CreateBlocks()
        {
#warning Change "mod.json" info

            //var harmony = HarmonyInstance.Create("examplepack.changethisname");
            //harmony.PatchAll(System.Reflection.Assembly.GetExecutingAssembly());

            new BlockPrefabBuilder(/*"GSO_Block_111", true*/) //Use a reference if you want quick functionality (explosion effects, etc)
            .SetBlockID(87532)                                //CHANGE THIS TO SOMETHING RANDOM
            .SetName("Block Name")
            .SetDescription("Description")
            .SetPrice(2000)
            .SetHP(100)
            .SetFaction(FactionSubTypes.SPE)
            .SetCategory(BlockCategories.Standard)
            .SetIcon(GameObjectJSON.SpriteFromImage(GameObjectJSON.ImageFromFile("Blocks/icon.png")))
            .SetMass(1f)
            .SetSize(IntVector3.one, BlockPrefabBuilder.AttachmentPoints.All)
            .SetModel(GameObjectJSON.MeshFromFile("Blocks/block.obj"), true, GameObjectJSON.GetObjectFromGameResources <Material>("GSO_Main"))     //"GC_Main", "HE_Main", "BF_Main", "VEN_Main"
            .RegisterLater();
        }
Пример #2
0
        public static void Load()
        {
            var harmony = new Harmony("exund.weapongroups");
            harmony.PatchAll(Assembly.GetExecutingAssembly());

            var holder = new GameObject();
            holder.AddComponent<GroupControllerEditor>();

            GameObject.DontDestroyOnLoad(holder);

            new BlockPrefabBuilder(BlockTypes.HE_StdBlock_01_111)
                .SetBlockID(7030)
                .SetName("Hawkeye Weapons Controller")
                .SetDescription("This block can control the firing of weapons (guns, drills and hammers).\n\nUsed to manage weapon groups.")
                .SetFaction(FactionSubTypes.HE)
                .SetGrade(2)
                .SetCategory(BlockCategories.Accessories)
                .SetRarity(BlockRarity.Rare)
                .SetSize(IntVector3.one)
                .SetAPsManual(new Vector3[]
                {
                    Vector3.down * 0.5f,
                    Vector3.forward * 0.5f,
                    Vector3.left * 0.5f
                })
                .SetPrice(24705)
                .SetRecipe(new Dictionary<ChunkTypes, int> {
                    { ChunkTypes.HardenedTitanic, 1 },
                    { ChunkTypes.HeatCoil, 2 },
                    { ChunkTypes.SensoryTransmitter, 1 },
                    { ChunkTypes.TitanicAlloy, 1 },
                    { ChunkTypes.SeedAI, 1 }
                })
                .SetModel(GameObjectJSON.MeshFromFile(asm_path + "Assets/weapon_group_fusebox.obj"), true, GameObjectJSON.GetObjectFromGameResources<Material>("HE_Main"))
                .SetIcon(GameObjectJSON.ImageFromFile(asm_path + "Assets/weapon_group_fusebox.png"))
                .AddComponent<ModuleWeaponGroupController>()
                .SetCustomEmissionMode(BlockPrefabBuilder.EmissionMode.Active)
                .SetDropFromCrates(true)
                .RegisterLater();
        }
Пример #3
0
        public static void Load()
        {
            ModConfig config = new ModConfig();
            int       v      = (int)KeyCode.Keypad0;

            config.TryGetConfig <int>("colorToolsKeycode", ref v);
            colorToolsKeycode = (KeyCode)v;

            OptionKey commandConsoleKey = new OptionKey("Color tools toggle", "Procedural Blocks", colorToolsKeycode);

            commandConsoleKey.onValueSaved.AddListener(() =>
            {
                colorToolsKeycode           = commandConsoleKey.SavedValue;
                config["colorToolsKeycode"] = (int)colorToolsKeycode;
            });

            v = (int)KeyCode.M;
            config.TryGetConfig <int>("img2TechKeycode", ref v);
            img2TechKeycode = (KeyCode)v;

            OptionKey img2TechKey = new OptionKey("Image to tech toggle", "Procedural Blocks", img2TechKeycode);

            img2TechKey.onValueSaved.AddListener(() =>
            {
                img2TechKeycode           = img2TechKey.SavedValue;
                config["img2TechKeycode"] = (int)img2TechKeycode;
            });

            NativeOptionsMod.onOptionsSaved.AddListener(() =>
            {
                config.WriteConfigJsonFile();
            });


            var harmony = new Harmony("exund.prodcedural.blocks");

            harmony.PatchAll(Assembly.GetExecutingAssembly());

            _holder = new GameObject();
            _holder.AddComponent <ProceduralEditor>();
            _holder.AddComponent <ImageToTech>();
            _holder.AddComponent <ColorTools>();
            UnityEngine.Object.DontDestroyOnLoad(_holder);

            var t = new Texture2D(1, 1);

            t.SetPixel(0, 0, Color.white);

            Material mat = GameObjectJSON.MaterialFromShader();

            mat.mainTexture = Texture2D.whiteTexture;
            mat.name        = "ProceduralMaterial";

            var cube1 = GameObject.CreatePrimitive(PrimitiveType.Cube);

            cube1.GetComponent <MeshRenderer>().material.color       = Color.white;
            cube1.GetComponent <MeshRenderer>().material.mainTexture = t;
            var color_block = new BlockPrefabBuilder()
                              .SetBlockID(7000, "64965b4027b723b16d1c")
                              .SetName("Color Block")
                              .SetDescription("A block that can change color (right click to edit)")
                              .SetFaction(FactionSubTypes.SPE)
                              .SetCategory(BlockCategories.Standard)
                              .SetGrade()
                              .SetHP(250)
                              .SetMass(1)
                              .SetModel(cube1.GetComponent <MeshFilter>().sharedMesh, cube1.GetComponent <MeshFilter>().sharedMesh, true, mat)
                              .SetSize(IntVector3.one, BlockPrefabBuilder.AttachmentPoints.All)
                              .SetIcon(GameObjectJSON.SpriteFromImage(GameObjectJSON.ImageFromFile(Path.Combine(AssetsFolder, "Icons/colorblock_icon.png"))))
                              .AddComponent <ModuleColor>();

            color_block.RegisterLater();
            GameObject.Destroy(cube1);

            var cube = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Block.obj"));

            cube.name = "ProceduralMesh";
            var procedural_block = new BlockPrefabBuilder()
                                   .SetBlockID(7001, "fd49964942512e91ec41")
                                   .SetName("Procedural Block")
                                   .SetDescription("A block that can change size")
                                   .SetFaction(FactionSubTypes.EXP)
                                   .SetCategory(BlockCategories.Standard)
                                   .SetGrade()
                                   .SetHP(250)
                                   .SetMass(1)
                                   .SetModel(cube, cube, true, mat)
                                   .SetSize(IntVector3.one, BlockPrefabBuilder.AttachmentPoints.All)
                                   .AddComponent <ModuleProcedural>()
                                   .AddComponent <ModuleColor>();

            procedural_block.RegisterLater();

            var cylinder = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Cylinder.obj"));

            cylinder.name = "ProceduralMesh";
            var procedural_cylinder = new BlockPrefabBuilder()
                                      .SetBlockID(7002, "8ccfce9497e1ace52d5b")
                                      .SetName("Procedural Cylinder")
                                      .SetDescription("A cylinder that can change size")
                                      .SetFaction(FactionSubTypes.EXP)
                                      .SetCategory(BlockCategories.Standard)
                                      .SetGrade()
                                      .SetHP(250)
                                      .SetMass(1)
                                      .SetModel(cylinder, cylinder, true, mat)
                                      .SetSize(IntVector3.one)
                                      .AddComponent <ModuleProceduralCylinder>()
                                      .AddComponent <ModuleColor>();

            procedural_cylinder.TankBlock.attachPoints = new Vector3[] { new Vector3(0, -0.5f, 0), new Vector3(0, 0.5f, 0) };
            procedural_cylinder.RegisterLater();

            var half = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Half Block.obj"));

            half.name = "ProceduralMesh";
            var procedural_half = new BlockPrefabBuilder()
                                  .SetBlockID(7003, "89c854222b7088b24b72")
                                  .SetName("Procedural Half Block")
                                  .SetDescription("A half block that can change size")
                                  .SetFaction(FactionSubTypes.EXP)
                                  .SetCategory(BlockCategories.Standard)
                                  .SetGrade()
                                  .SetHP(250 / 2)
                                  .SetMass(1)
                                  .SetModel(half, half, true, mat)
                                  .SetSize(IntVector3.one)
                                  .AddComponent <ModuleProceduralHalfBlock>()
                                  .AddComponent <ModuleColor>();

            procedural_half.TankBlock.attachPoints = new Vector3[] { new Vector3(0, -0.5f, 0), new Vector3(-0.5f, 0, 0), new Vector3(0, 0, -0.5f), new Vector3(0, 0, 0.5f) };
            procedural_half.RegisterLater();

            var corner2 = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Corner (2-way).obj"));

            corner2.name = "ProceduralMesh";
            var procedural_corner_2 = new BlockPrefabBuilder()
                                      .SetBlockID(7004, "3302c74153a768f81be1")
                                      .SetName("Procedural Corner (2-way)")
                                      .SetDescription("A corner that can change size")
                                      .SetFaction(FactionSubTypes.EXP)
                                      .SetCategory(BlockCategories.Standard)
                                      .SetGrade()
                                      .SetHP(250)
                                      .SetMass(1)
                                      .SetModel(corner2, corner2, true, mat)
                                      .SetSize(IntVector3.one)
                                      .AddComponent <ModuleProceduralCorner2>()
                                      .AddComponent <ModuleColor>();

            procedural_corner_2.TankBlock.attachPoints = new Vector3[] { new Vector3(0.5f, 0, 0), new Vector3(0, -0.5f, 0), new Vector3(0, 0, 0.5f) };
            procedural_corner_2.RegisterLater();

            var corner3 = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Corner (3-way).obj"));

            corner3.name = "ProceduralMesh";
            var procedural_corner_3 = new BlockPrefabBuilder()
                                      .SetBlockID(7005, "5397ca4583307f7d37fe")
                                      .SetName("Procedural Corner (3-way)")
                                      .SetDescription("A corner that can change size")
                                      .SetFaction(FactionSubTypes.EXP)
                                      .SetCategory(BlockCategories.Standard)
                                      .SetGrade()
                                      .SetHP(250 / 3)
                                      .SetMass(1)
                                      .SetModel(corner3, corner3, true, mat)
                                      .SetSize(IntVector3.one)
                                      .AddComponent <ModuleProceduralCorner3>()
                                      .AddComponent <ModuleColor>();

            procedural_corner_3.TankBlock.attachPoints = new Vector3[] { new Vector3(-0.5f, 0, 0), new Vector3(0, -0.5f, 0), new Vector3(0, 0, -0.5f) };
            procedural_corner_3.RegisterLater();

            var rounded = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Rounded Half Block.obj"));

            rounded.name = "ProceduralMesh";
            var procedural_rounded = new BlockPrefabBuilder()
                                     .SetBlockID(7006, "be4c9e7859e29073aec0")
                                     .SetName("Procedural Rounded Half Block")
                                     .SetDescription("A rounded half block that can change size")
                                     .SetFaction(FactionSubTypes.EXP)
                                     .SetCategory(BlockCategories.Standard)
                                     .SetGrade()
                                     .SetHP(250 / 2)
                                     .SetMass(1)
                                     .SetModel(rounded, rounded, true, mat)
                                     .SetSize(IntVector3.one)
                                     .AddComponent <ModuleProceduralRoundedHalfBlock>()
                                     .AddComponent <ModuleColor>();

            procedural_rounded.TankBlock.attachPoints = new Vector3[] { new Vector3(0, -0.5f, 0), new Vector3(-0.5f, 0, 0), new Vector3(0, 0, -0.5f), new Vector3(0, 0, 0.5f) };
            procedural_rounded.RegisterLater();

            var sphere = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Sphere.obj"));

            sphere.name = "ProceduralMesh";
            var procedural_sphere = new BlockPrefabBuilder()
                                    .SetBlockID(7007, "88df56b7bc96edd1e288")
                                    .SetName("Procedural Sphere")
                                    .SetDescription("A sphere that can change size")
                                    .SetFaction(FactionSubTypes.EXP)
                                    .SetCategory(BlockCategories.Standard)
                                    .SetGrade()
                                    .SetHP(250)
                                    .SetMass(1)
                                    .SetModel(sphere, sphere, true, mat)
                                    .SetSize(IntVector3.one, BlockPrefabBuilder.AttachmentPoints.All)
                                    .AddComponent <ModuleProcedural>()
                                    .AddComponent <ModuleColor>();

            procedural_sphere.RegisterLater();

            var converter = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Cylinder-Cube Converter.obj"));

            converter.name = "ProceduralMesh";
            var procedural_converter = new BlockPrefabBuilder()
                                       .SetBlockID(7008, "92f1be44b016bb6e7e50")
                                       .SetName("Procedural Converter")
                                       .SetDescription("A cylinder that can change size")
                                       .SetFaction(FactionSubTypes.EXP)
                                       .SetCategory(BlockCategories.Standard)
                                       .SetGrade()
                                       .SetHP(250)
                                       .SetMass(1)
                                       .SetModel(converter, converter, true, mat)
                                       .SetSize(IntVector3.one)
                                       .AddComponent <ModuleProceduralConverter>()
                                       .AddComponent <ModuleColor>();

            procedural_converter.TankBlock.attachPoints = new Vector3[] { new Vector3(0, -0.5f, 0), new Vector3(0, 0.5f, 0) };
            procedural_converter.RegisterLater();

            var incorner2 = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Inside Corner (2-way).obj"));

            incorner2.name = "ProceduralMesh";
            var procedural_incorner_2 = new BlockPrefabBuilder()
                                        .SetBlockID(7009, "d2976201068b86e4b7cc")
                                        .SetName("Procedural Inside Corner (2-way)")
                                        .SetDescription("A corner that can change size")
                                        .SetFaction(FactionSubTypes.EXP)
                                        .SetCategory(BlockCategories.Standard)
                                        .SetGrade()
                                        .SetHP(250)
                                        .SetMass(1)
                                        .SetModel(incorner2, incorner2, true, mat)
                                        .SetSize(IntVector3.one)
                                        .AddComponent <ModuleProceduralCorner2>(out ModuleProceduralCorner2 inverted2)
                                        .AddComponent <ModuleColor>();

            procedural_incorner_2.TankBlock.attachPoints = new Vector3[] { new Vector3(-0.5f, 0, 0), new Vector3(0, -0.5f, 0), new Vector3(0, 0, -0.5f), new Vector3(0.5f, 0, 0), new Vector3(0, 0, 0.5f) };
            inverted2.inverted = true;
            procedural_incorner_2.RegisterLater();

            var incorner3 = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Inside Corner (3-way).obj"));

            incorner3.name = "ProceduralMesh";
            var procedural_incorner_3 = new BlockPrefabBuilder()
                                        .SetBlockID(7010, "d85e864aad33b54a6028")
                                        .SetName("Procedural Inside Corner (3-way)")
                                        .SetDescription("A corner that can change size")
                                        .SetFaction(FactionSubTypes.EXP)
                                        .SetCategory(BlockCategories.Standard)
                                        .SetGrade()
                                        .SetHP(250 / 3)
                                        .SetMass(1)
                                        .SetModel(incorner3, incorner3, true, mat)
                                        .SetSize(IntVector3.one)
                                        .AddComponent <ModuleProceduralCorner3>(out ModuleProceduralCorner3 inverted3)
                                        .AddComponent <ModuleColor>();

            procedural_incorner_3.TankBlock.attachPoints = new Vector3[] { new Vector3(-0.5f, 0, 0), new Vector3(0, -0.5f, 0), new Vector3(0, 0, -0.5f), new Vector3(0.5f, 0, 0), new Vector3(0, 0.5f, 0), new Vector3(0, 0, 0.5f) };
            inverted3.inverted = true;
            procedural_incorner_3.RegisterLater();

            var rounded_corner2 = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Rounded Corner (2-way).obj"));

            rounded_corner2.name = "ProceduralMesh";
            var procedural_rounded_corner2 = new BlockPrefabBuilder()
                                             .SetBlockID(7011, "ab23c00ba9ab31d27e04")
                                             .SetName("Procedural Rounded Corner (2-way)")
                                             .SetDescription("A rounded corner that can change size")
                                             .SetFaction(FactionSubTypes.EXP)
                                             .SetCategory(BlockCategories.Standard)
                                             .SetGrade()
                                             .SetHP(250)
                                             .SetMass(1)
                                             .SetModel(rounded_corner2, rounded_corner2, true, mat)
                                             .SetSize(IntVector3.one)
                                             .AddComponent <ModuleProceduralRoundedCorner2>()
                                             .AddComponent <ModuleColor>();

            procedural_rounded_corner2.TankBlock.attachPoints = new Vector3[] { new Vector3(-0.5f, 0, 0), new Vector3(0, -0.5f, 0), new Vector3(0, 0, -0.5f) };
            procedural_rounded_corner2.RegisterLater();

            var rounded_corner3 = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Rounded Corner (3-way).obj"));

            rounded_corner3.name = "ProceduralMesh";
            var procedural_rounded_corner3 = new BlockPrefabBuilder()
                                             .SetBlockID(7012, "9630f2a69c42c30c0862")
                                             .SetName("Procedural Rounded Corner (3-way)")
                                             .SetDescription("A rounded corner that can change size")
                                             .SetFaction(FactionSubTypes.EXP)
                                             .SetCategory(BlockCategories.Standard)
                                             .SetGrade()
                                             .SetHP(250)
                                             .SetMass(1)
                                             .SetModel(rounded_corner3, rounded_corner3, true, mat)
                                             .SetSize(IntVector3.one)
                                             .AddComponent <ModuleProceduralRoundedCorner3>()
                                             .AddComponent <ModuleColor>();

            procedural_rounded_corner3.TankBlock.attachPoints = new Vector3[] { new Vector3(-0.5f, 0, 0), new Vector3(0, -0.5f, 0), new Vector3(0, 0, -0.5f) };
            procedural_rounded_corner3.RegisterLater();

            var rounded_incorner2 = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Inside Rounded Corner (2-way).obj"));

            rounded_incorner2.name = "ProceduralMesh";
            var procedural_rounded_incorner2 = new BlockPrefabBuilder()
                                               .SetBlockID(7013, "2381cf216f226ed2f537")
                                               .SetName("Procedural Inside Rounded Corner (2-way)")
                                               .SetDescription("A rounded corner that can change size")
                                               .SetFaction(FactionSubTypes.EXP)
                                               .SetCategory(BlockCategories.Standard)
                                               .SetGrade()
                                               .SetHP(250)
                                               .SetMass(1)
                                               .SetModel(rounded_incorner2, rounded_incorner2, true, mat)
                                               .SetSize(IntVector3.one)
                                               .AddComponent <ModuleProceduralRoundedCorner2>(out ModuleProceduralRoundedCorner2 invertedr2)
                                               .AddComponent <ModuleColor>();

            procedural_rounded_incorner2.TankBlock.attachPoints = new Vector3[] { new Vector3(-0.5f, 0, 0), new Vector3(0, -0.5f, 0), new Vector3(0, 0, -0.5f) };
            invertedr2.inverted = true;
            procedural_rounded_incorner2.RegisterLater();

            var rounded_incorner3 = GameObjectJSON.MeshFromFile(Path.Combine(AssetsFolder, "Models/Standalone/Procedural Inside Rounded Corner (3-way).obj"));

            rounded_incorner3.name = "ProceduralMesh";
            var procedural_rounded_incorner3 = new BlockPrefabBuilder()
                                               .SetBlockID(7014, "eadb1d61f1dc3e7f1fc9")
                                               .SetName("Procedural Inside Rounded Corner (3-way)")
                                               .SetDescription("A rounded corner that can change size")
                                               .SetFaction(FactionSubTypes.EXP)
                                               .SetCategory(BlockCategories.Standard)
                                               .SetGrade()
                                               .SetHP(250)
                                               .SetMass(1)
                                               .SetModel(rounded_incorner3, rounded_incorner3, true, mat)
                                               .SetSize(IntVector3.one)
                                               .AddComponent <ModuleProceduralRoundedCorner3>(out ModuleProceduralRoundedCorner3 invertedr3)
                                               .AddComponent <ModuleColor>();

            procedural_rounded_incorner3.TankBlock.attachPoints = new Vector3[] { new Vector3(-0.5f, 0, 0), new Vector3(0, -0.5f, 0), new Vector3(0, 0, -0.5f) };
            invertedr3.inverted = true;
            procedural_rounded_incorner3.RegisterLater();


            var cube2 = GameObject.Instantiate(cube);

            cube2.name = "ProceduralMesh";
            var procedural_mesh_block = new BlockPrefabBuilder()
                                        .SetBlockID(7015)
                                        .SetName("Procedural Mesh Block")
                                        .SetDescription("A block that can change size")
                                        .SetFaction(FactionSubTypes.EXP)
                                        .SetCategory(BlockCategories.Standard)
                                        .SetGrade()
                                        .SetHP(250)
                                        .SetMass(1)
                                        .SetModel(cube2, true, mat)
                                        //.SetModel(cube2, cube2, true, mat)
                                        .SetSize(IntVector3.one, BlockPrefabBuilder.AttachmentPoints.All)
                                        .AddComponent <ModuleProceduralSlicedMesh>()
                                        .AddComponent <ModuleColor>();

            procedural_mesh_block.RegisterLater();

            if (!Directory.Exists(TechArtFolder))
            {
                Directory.CreateDirectory(TechArtFolder);
            }

            SlicedMeshJSON.LoadSets();
        }
        public static void Load()
        {
            var harmony = HarmonyInstance.Create("exund.advancedbuilding");

            harmony.PatchAll(Assembly.GetExecutingAssembly());

            assetBundle = AssetBundle.LoadFromFile(asm_path + "Assets/advancedbuilding");

            try
            {
                _holder = new GameObject();
                _holder.AddComponent <AdvancedEditor>();
                _holder.AddComponent <BlockPicker>();

                if (Directory.Exists(PreciseSnapshotsFolder))
                {
                    _holder.AddComponent <LoadWindow>();
                }


                UnityEngine.Object.DontDestroyOnLoad(_holder);

                transformGizmo         = Singleton.cameraTrans.gameObject.AddComponent <RuntimeGizmos.TransformGizmo>();
                transformGizmo.enabled = false;

                config.TryGetConfig <float>("position_step", ref AdvancedEditor.position_step);
                config.TryGetConfig <float>("rotation_step", ref AdvancedEditor.rotation_step);
                config.TryGetConfig <float>("scale_step", ref AdvancedEditor.scale_step);

                config.TryGetConfig <bool>("open_inventory", ref BlockPicker.open_inventory);
                config.TryGetConfig <bool>("global_filters", ref BlockPicker.global_filters);
                var key = (int)BlockPicker.block_picker_key;
                config.TryGetConfig <int>("block_picker_key", ref key);
                BlockPicker.block_picker_key = (KeyCode)key;

                config.TryGetConfig <bool>("clearOnCollapse", ref PaletteTextFilter.clearOnCollapse);

                var key2 = (int)PhysicsInfo.centers_key;
                config.TryGetConfig <int>("centers_key", ref key2);
                PhysicsInfo.centers_key = (KeyCode)key2;


                string    modName        = "Advanced Building";
                OptionKey blockPickerKey = new OptionKey("Block Picker activation key", modName, BlockPicker.block_picker_key);
                blockPickerKey.onValueSaved.AddListener(() =>
                {
                    BlockPicker.block_picker_key = blockPickerKey.SavedValue;
                    config["block_picker_key"]   = (int)BlockPicker.block_picker_key;
                });

                OptionToggle globalFilterToggle = new OptionToggle("Block Picker - Use global filters", modName, BlockPicker.global_filters);
                globalFilterToggle.onValueSaved.AddListener(() =>
                {
                    BlockPicker.global_filters = globalFilterToggle.SavedValue;
                    config["global_filters"]   = BlockPicker.global_filters;
                });

                OptionToggle openInventoryToggle = new OptionToggle("Block Picker - Automatically open the inventory when picking a block", modName, BlockPicker.open_inventory);
                openInventoryToggle.onValueSaved.AddListener(() =>
                {
                    BlockPicker.open_inventory = openInventoryToggle.SavedValue;
                    config["open_inventory"]   = BlockPicker.open_inventory;
                });

                OptionToggle clearOnCollapse = new OptionToggle("Block Search - Clear filter when closing inventory", modName, PaletteTextFilter.clearOnCollapse);
                clearOnCollapse.onValueSaved.AddListener(() =>
                {
                    PaletteTextFilter.clearOnCollapse = clearOnCollapse.SavedValue;
                    config["clearOnCollapse"]         = PaletteTextFilter.clearOnCollapse;
                });

                OptionKey centersKey = new OptionKey("Open physics info menu (Ctrl + ?)", modName, PhysicsInfo.centers_key);
                centersKey.onValueSaved.AddListener(() =>
                {
                    PhysicsInfo.centers_key = centersKey.SavedValue;
                    config["centers_key"]   = (int)PhysicsInfo.centers_key;
                });

                NativeOptionsMod.onOptionsSaved.AddListener(() =>
                {
                    config.WriteConfigJsonFile();
                });

                new BlockPrefabBuilder(BlockTypes.GSOBlock_111, true)
                .SetBlockID(7020)
                .SetName("Reticule Research Hadamard Superposer")
                .SetDescription("This block can register quantum fluctuations applied on the tech's blocks and stabilize them during the snapshot process.\n\n<b>Warning</b>: Can cause temporary quantum jumps if it enters in contact with zero-stasis gluons.\nUsed to activate Advanced Building.")
                .SetFaction(FactionSubTypes.EXP)
                .SetCategory(BlockCategories.Accessories)
                .SetRarity(BlockRarity.Rare)
                .SetPrice(58860)
                .SetRecipe(new Dictionary <ChunkTypes, int> {
                    { ChunkTypes.SeedAI, 5 }
                })
                .SetModel(GameObjectJSON.MeshFromFile(asm_path + "Assets/hadamard_superposer.obj"), true, GameObjectJSON.GetObjectFromGameResources <Material>("RR_Main"))
                .SetIcon(GameObjectJSON.ImageFromFile(asm_path + "Assets/hadamard_superposer.png"))
                .AddComponent <ModuleOffgridStore>()
                .RegisterLater();

                {
                    var ontop = new Material(assetBundle.LoadAsset <Shader>("OnTop"));
                    var go    = new GameObject();
                    var mr    = go.AddComponent <MeshRenderer>();
                    mr.material                        = ontop;
                    mr.material.mainTexture            = GameObjectJSON.ImageFromFile(asm_path + "Assets/CO.png");
                    mr.material.mainTexture.filterMode = FilterMode.Point;
                    var mf = go.AddComponent <MeshFilter>();
                    mf.sharedMesh = mf.mesh = GameObjectJSON.MeshFromFile(asm_path + "Assets/CO.obj");

                    var line = new GameObject();
                    var lr   = line.AddComponent <LineRenderer>();
                    lr.startWidth = 0.5f;
                    lr.endWidth   = 0;
                    lr.SetPositions(new Vector3[] { Vector3.zero, Vector3.zero });
                    lr.useWorldSpace  = true;
                    lr.material       = ontop;
                    lr.material.color = lr.material.color.SetAlpha(1);
                    line.transform.SetParent(go.transform, false);

                    go.SetActive(false);
                    go.transform.SetParent(_holder.transform, false);

                    PhysicsInfo.COM = GameObject.Instantiate(go);
                    var commat = PhysicsInfo.COM.GetComponent <MeshRenderer>().material;
                    commat.color       = Color.yellow;
                    commat.renderQueue = 1;
                    PhysicsInfo.COM.GetComponentInChildren <LineRenderer>().enabled = false;

                    PhysicsInfo.COT = GameObject.Instantiate(go);
                    PhysicsInfo.COT.transform.localScale *= 0.8f;
                    var cotmat = PhysicsInfo.COT.GetComponent <MeshRenderer>().material;
                    cotmat.color       = Color.magenta;
                    cotmat.renderQueue = 3;
                    var COTlr = PhysicsInfo.COT.GetComponentInChildren <LineRenderer>();
                    COTlr.material.renderQueue = 2;
                    COTlr.startColor           = COTlr.endColor = Color.magenta;

                    PhysicsInfo.COL = GameObject.Instantiate(go);
                    PhysicsInfo.COL.transform.localScale *= 0.64f;
                    var colmat = PhysicsInfo.COL.GetComponent <MeshRenderer>().material;
                    colmat.color       = Color.cyan;
                    colmat.renderQueue = 5;
                    var COLlr = PhysicsInfo.COL.GetComponentInChildren <LineRenderer>();
                    COLlr.startColor           = COLlr.endColor = Color.cyan;
                    COLlr.material.renderQueue = 4;
                }

                _holder.AddComponent <PhysicsInfo>();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }