diff --git a/ChickenGameTest.csproj b/ChickenGameTest.csproj
index ecfe2fb..59fe145 100644
--- a/ChickenGameTest.csproj
+++ b/ChickenGameTest.csproj
@@ -39,7 +39,7 @@
-
+
@@ -47,21 +47,23 @@
-
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
@@ -70,9 +72,9 @@
-
+
-
+
diff --git a/RTSCamera.cs b/RTSCamera.cs
index 3d56e4e..5215b4d 100755
--- a/RTSCamera.cs
+++ b/RTSCamera.cs
@@ -1,8 +1,20 @@
using Godot;
using System;
using SJK.Math;
+using Chickensoft.SaveFileBuilder;
+using Chickensoft.Introspection;
+using Chickensoft.Serialization;
-public partial class RTSCamera : Node3D
+
+[Meta, Id("save_data")]
+public partial class SaveData
+{
+ [Save("player_transform")]
+ public Transform3D Transform3D {get;set;}
+ [Save("player_camera")]
+ public Transform3D CameraTransform {get;set;}
+}
+public partial class RTSCamera : Node3D, ISaveable
{
[Export]
public Camera3D camera;
@@ -53,7 +65,7 @@ public partial class RTSCamera : Node3D
{
CancelUpdateFunc();
}
- GD.PrintS(positionStartPos,positionOffsetPos,lastTransalation,LastMouseGroundPlanePositon,LastMousePostition,cameraTargetOffset,scrollAmount);
+ // GD.PrintS(positionStartPos,positionOffsetPos,lastTransalation,LastMouseGroundPlanePositon,LastMousePostition,cameraTargetOffset,scrollAmount);
Update_CurrentFunc();
Update_CameraScroll((float)delta);
LastMousePostition = GetViewport().GetMousePosition();
@@ -113,7 +125,7 @@ public partial class RTSCamera : Node3D
{
cameraTargetOffset += dir * scrollAmount;
}
- DebugDraw3D.DrawArrow(Vector3.Zero,cameraTargetOffset);
+ // DebugDraw3D.DrawArrow(Vector3.Zero,cameraTargetOffset);
Vector3 lastCameraPosition = camera.Position;
camera.Position = camera.Position.Lerp(camera.Position + cameraTargetOffset, delta);
cameraTargetOffset -= camera.Position - lastCameraPosition;
@@ -153,6 +165,13 @@ public partial class RTSCamera : Node3D
);
LastMousePostition = hitpos = GetViewport().GetMousePosition();
}
+
+ public SaveData Save() => new(){Transform3D = Transform, CameraTransform = camera.Transform};
+ public void Load(in SaveData data)
+ {
+ Transform = data.Transform3D;
+ camera.Transform = data.CameraTransform;
+ }
}
public static partial class SJKMath
diff --git a/addons.jsonc b/addons.jsonc
index 2925576..0545c5b 100644
--- a/addons.jsonc
+++ b/addons.jsonc
@@ -20,7 +20,19 @@
"url": "https://github.com/DmitriySalnikov/godot_debug_draw_3d/releases/download/1.7.3/debug-draw-3d_1.7.3.zip/",
"source": "zip", // optional — this is the default
// "checkout": "master", // optional — this is the default
- // "subfolder": "addons/debug_draw_3d" // optional — defaults to "/"
+ // "subfolder": "" // optional — defaults to "/"
},
+ "controller_icons": {
+ "url": "https://github.com/jembawls/controller_icons_csharp/releases/download/v3.1.6/controller_icons_csharp-3.1.6.zip",
+ "source": "zip", // optional — this is the default
+ // "checkout": "master", // optional — this is the default
+ "subfolder": "controller_icons_csharp-3.1.6/addons/controller_icons/" // optional — defaults to "/"
+ },
+ // "editor_theme_explorer": {
+ // "url": "https://github.com/YuriSizov/godot-editor-theme-explorer/releases/godot-editor-theme-explorer-2.1.1.zip",
+ // "source": "zip", // optional — this is the default
+ // // "checkout": "master", // optional — this is the default
+ // // "subfolder": "controller_icons_csharp-3.1.6/addons/controller_icons/" // optional — defaults to "/"
+ // },
}
}
diff --git a/mods/modA/mod.json b/mods/modA/mod.json
new file mode 100644
index 0000000..4b849db
--- /dev/null
+++ b/mods/modA/mod.json
@@ -0,0 +1 @@
+"Hello"
diff --git a/mods/modB/mod.json b/mods/modB/mod.json
new file mode 100644
index 0000000..1cf718a
--- /dev/null
+++ b/mods/modB/mod.json
@@ -0,0 +1 @@
+"World"
diff --git a/project.godot b/project.godot
index a44370a..daec0ed 100644
--- a/project.godot
+++ b/project.godot
@@ -19,6 +19,10 @@ run/main_scene="res://src/Main.tscn"
config/features=PackedStringArray("4.6", "C#", "Mobile")
config/icon="res://icon.png"
+[autoload]
+
+ControllerIcons="*uid://cvqaxgmq6by3f"
+
[debug_draw_3d]
settings/addon_root_folder="res://addons/debug_draw_3d"
@@ -41,7 +45,7 @@ naming/scene_name_casing=1
[editor_plugins]
-enabled=PackedStringArray("res://addons/imrp/plugin.cfg")
+enabled=PackedStringArray("res://addons/controller_icons/plugin.cfg", "res://addons/explore-editor-theme/plugin.cfg", "res://addons/imrp/plugin.cfg")
[gui]
@@ -54,6 +58,7 @@ theme/default_theme_scale=2.0
move_forward={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"location":0,"echo":false,"script":null)
+, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":-1,"axis":1,"axis_value":-1.0,"script":null)
]
}
move_back={
diff --git a/src/App/App.cs b/src/App/App.cs
new file mode 100644
index 0000000..7b6ada9
--- /dev/null
+++ b/src/App/App.cs
@@ -0,0 +1,474 @@
+namespace FoodFactory;
+
+using Godot;
+using Chickensoft.AutoInject;
+using Chickensoft.Introspection;
+using Chickensoft.GodotNodeInterfaces;
+using Chickensoft.LogicBlocks.Auto;
+using Chickensoft.LogicBlocks;
+using System;
+using System.Threading.Tasks;
+using Chickensoft.UMLGenerator;
+using System.Collections.Generic;
+using System.Linq;
+using FoodFactory.Modding;
+using System.IO.Abstractions;
+using Chickensoft.Sync.Primitives;
+using Chickensoft.SaveFileBuilder;
+using System.IO;
+using System.Text.Json;
+using Chickensoft.Serialization;
+using Chickensoft.Collections;
+using Chickensoft.Serialization.Godot;
+using SJK.Functional;
+
+// using Shouldly;
+
+public interface IApp : ICanvasLayer, IProvide, IProvide, IProvide;
+[Meta(typeof(IAutoNode))]
+[ClassDiagram(UseVSCodePaths = true)]
+public partial class App : CanvasLayer, IApp
+{
+ public const string GAME_PATH = "res://src/Game/Game.tscn";
+ public override void _Notification(int what) => this.Notify(what);
+
+ [Node] public ISubViewport GameViewPort { get; private set; } = default!;
+ [Node] public Menu.IMainMenu MainMenu {get;set;} = default!;
+ [Node] public ICreateGameMenu CreateGameMenu {get;set;} = default!;
+ [Node] public ILoadingGameMenu LoadingGameMenu {get;set;} = default!;
+ [Node] public IOptionsMenu OptionsMenu {get;set;} = default!;
+ [Node] public IModMenu ModsMenu {get;set;} = default!;
+
+ public IGame Game { get; set; } = default!;
+
+ public IAppRepo AppRepo { get; set; } = default!;
+ public IOptionConfig OptionConfig { get; set; } = default!;
+ public IAppLogic AppLogic { get; set; } = default!;
+ public LogicBlock.Binding AppBinding { get; set; } = default!;
+ IAppRepo IProvide.Value() => AppRepo;
+ IOptionConfig IProvide.Value() => OptionConfig;
+ private AutoChannel.Binding _binding;
+ private static JsonSerializerOptions _serializerOptions = new JsonSerializerOptions()
+ {
+ Converters = {
+ new SerializableTypeConverter(new Blackboard())
+ },
+ TypeInfoResolver = new SerializableTypeResolver(),
+ WriteIndented = true
+ };
+ public ISaveService SaveService { get; set; } = new SaveService(){
+ FilePath =Path.Join(OS.GetUserDataDir(), "saves", "game.json.gz"),
+ CurrentSave =
+ Chickensoft.SaveFileBuilder.SaveFile.CreateGZipJsonFile(
+ Path.Join(OS.GetUserDataDir(), "saves", "game.json.gz"),
+ // Create a standard JsonSerializerOptions with our introspective type
+ // resolver and the logic blocks converter.
+ _serializerOptions
+ )
+ };
+ private Dictionary> _settingsBind = [];
+ public void BindSetting<[MustBeVariant] T>(IOptionKey option, Action action) => _settingsBind.Add(option, variant => action(variant.As()));
+
+ public void Initialize()
+ {
+ GodotSerialization.Setup();
+ var fileSystem =new FileSystem();
+ AppRepo = new AppRepo()
+ {
+ ModManger = new ModManger()
+ {
+ AllMods = new AllMods("/home/ronnie/Documents/Godot/Projects/ChickenGameTest/mods", fileSystem),
+ Profiles = new ModProfiles()
+ }
+ };
+ AppRepo.ModManger.Profiles.Add(("base", [.. AppRepo.ModManger.AllMods.GetMods()]));
+ AppRepo.ModManger.Profiles.Add(("test", []));
+ // GD.Print(string.Join(',', AppRepo.ModManger.AllMods.GetMods()));
+ AppLogic = new AppLogic();
+ AppLogic.Set(AppRepo);
+
+ OptionConfig = new TestConfig();
+ ((TestConfig)OptionConfig).OnSettingChanged += AppRepo.OnSettingChanged;
+ BindSetting(OptionConfig.SettingKeys.Video.RenderQuality, value => GameViewPort.Scaling3DScale = value);
+ BindSetting(OptionConfig.SettingKeys.Video.FullScreen, value => DisplayServer.WindowSetMode(value ? DisplayServer.WindowMode.Fullscreen : DisplayServer.WindowMode.Windowed));
+ _binding = AppRepo.AutoChannel.Bind();
+ _binding.On((in setting) =>
+ {
+ GD.Print(setting);
+ if (_settingsBind.GetValue(setting.Setting).HasValue(out var action)){
+ action(setting.Value);
+ }
+ return;
+ if (setting.Setting is OptionKey key && key.Key == "FullScreen")
+ {
+ DisplayServer.WindowSetMode(setting.Value.As() ? DisplayServer.WindowMode.Fullscreen : DisplayServer.WindowMode.Windowed );
+ }
+ if (setting.Setting is OptionKey key2 && key2.Key == "RenderQuality")
+ {
+ GameViewPort.Scaling3DScale = setting.Value.As() / 100f;
+ }
+ });
+ _binding.On((in IAppRepo.GameExiting exiting) =>
+ {
+ AppLogic.Input(new AppLogicState.Input.EndGame(ExitGameReason.QuitToMenu));
+ });
+ MainMenu.NewGame += OnNewGame;
+ MainMenu.LastGame += () =>
+ {
+ var path = fileSystem.File.ReadAllText(Path.Combine(OS.GetUserDataDir(), "lastGame.txt"));
+ AppLogic.Input(new AppLogicState.Input.LoadGame());
+ OnLoadSaveGame(path);
+ };
+ MainMenu.LoadGame += OnLoadGame;
+ MainMenu.Options += OnOptions;
+ MainMenu.Exit += () => GetTree().Quit();
+
+ MainMenu.Mods += OnMods;
+
+ // =>
+ // {
+ // var vbox = new VBoxContainer();
+ // vbox.SetAnchorsPreset(Control.LayoutPreset.Center);
+ // foreach (var item in AppRepo.ModManger.AllMods.GetMods())
+ // {
+ // var b = new Button(){Text = item.ModName};
+ // b.Pressed += () =>
+ // {
+ // var p = AppRepo.ModManger.Profiles;
+ // if (p.Current.Contains(item))
+ // {
+ // p.Current.Remove(item);
+ // }
+ // else
+ // {
+ // p.Current.Add(item);
+ // }
+ // b.Text += "a";
+ // };
+ // vbox.AddChild(b);
+ // }
+ // MainMenu.AddChild(vbox);
+ // };
+ OptionsMenu.OnMenuExit += OnMenuExit;
+ CreateGameMenu.Exit += OnMenuExit;
+ CreateGameMenu.NewGame += OnNewGame;
+ CreateGameMenu.LevelSelected += (index) => GD.Print("selected ",index);
+
+ LoadingGameMenu.Exit += OnMenuExit;
+ LoadingGameMenu.LoadGame += index => OnLoadSaveGame(GetSaves()[index]);
+
+ MainMenu.SetLastGameVisible(fileSystem.File.Exists(Path.Combine(OS.GetUserDataDir(), "lastGame.txt")));
+
+ this.Provide();
+ }
+
+ private void OnLastGame()
+ {
+ AppLogic.Input(new AppLogicState.Input.LoadGame());
+
+ AppLogic.Input(new AppLogicState.Input.LoadSave());
+ }
+
+ private void OnMenuExit() => AppLogic.Input(new AppLogicState.Input.ExitMenu());
+ private void OnNewGame() => AppLogic.Input(new AppLogicState.Input.NewGame());
+ private void OnLoadGame() => AppLogic.Input(new AppLogicState.Input.LoadGame());
+ private void OnLoadSaveGame(string path)
+ {
+ SaveService.FilePath = path;
+ SaveService.CurrentSave = Chickensoft.SaveFileBuilder.SaveFile.CreateGZipJsonFile(
+ path,
+ _serializerOptions);
+ // Game.LoadExistingGame(GetSaves()[arg]);
+ GD.Print("save ", path, " loaded.");
+ AppLogic.Input(new AppLogicState.Input.LoadSave());
+ }
+
+ private void OnOptions() => AppLogic.Input(new AppLogicState.Input.Options());
+ private void OnMods() => AppLogic.Input(new AppLogicState.Input.Mods());
+
+ public void OnReady()
+ {
+ AppBinding = AppLogic.Bind();
+ AppBinding
+ .OnOutput((in AppLogicState.Output.ShowMainMenu _) =>
+ {
+ HideMenus();
+ MainMenu.Show();
+ //Fade In from black
+ })
+ .OnOutput((in AppLogicState.Output.StartLoadingSaveFile save) =>
+ {
+ Game.SaveFileLoaded += OnSaveFileLoaded;
+ Game.LoadGame();
+ })
+ .OnOutput((in AppLogicState.Output.RemoveExistingGame _) =>
+ {
+ GameViewPort.RemoveChildEx(Game);
+ Game.QueueFree();
+ Game = default!;
+ })
+ .OnOutput((in AppLogicState.Output.SetUpGameScene _) =>
+ {
+ Game = GD.Load(GAME_PATH).Instantiate();
+ Game.Visible = false;
+ GameViewPort.AddChildEx(Game);
+ })
+ .OnOutput((in AppLogicState.Output.ShowGameCreationWindow _) =>
+ {
+ HideMenus();
+ CreateGameMenu.Initialize([.. GetLevels()]);
+ CreateGameMenu.Show();
+ })
+ .OnOutput((in AppLogicState.Output.ShowGameLoadingWindow _) =>
+ {
+ HideMenus();
+ LoadingGameMenu.Initialize(GetSaves());
+ LoadingGameMenu.Show();
+ })
+ .OnOutput((in AppLogicState.Output.ShowGame _) =>
+ {
+ HideMenus();
+ Game.Show();
+ })
+ .OnOutput((in AppLogicState.Output.QuitGame _) =>
+ {
+ GetTree().CallDeferred(SceneTree.MethodName.Quit);
+ })
+ .OnOutput((in AppLogicState.Output.ShowOptionMenu _) =>
+ {
+ HideMenus();
+ OptionsMenu.Show();
+ })
+ .OnOutput((in AppLogicState.Output.ShowModsMenu _) =>
+ {
+ HideMenus();
+ ModsMenu.Show();
+ })
+
+ ;
+ AppLogic.Start();
+ }
+
+ private IReadOnlyList GetSaves()
+ {
+ var fileSystem = new FileSystem();
+ var saves = fileSystem.Directory.EnumerateFiles(Path.Join(OS.GetUserDataDir(), "saves"));
+ return [.. saves];
+
+ }
+
+ private void OnSaveFileLoaded()
+ {
+ Game.SaveFileLoaded -= OnSaveFileLoaded;
+ AppLogic.Input(new AppLogicState.Input.SaveFileLoaded());
+ }
+
+ public void Setup()
+ {
+
+ }
+ public void OnExitTree()
+ {
+ AppLogic.Stop();
+ AppLogic.Dispose();
+ AppRepo.Dispose();
+ MainMenu.NewGame -= OnNewGame;
+ MainMenu.LoadGame -= OnLoadGame;
+ MainMenu.Options -= OnOptions;
+ MainMenu.Mods -= OnMods;
+ OptionsMenu.OnMenuExit -= OnMenuExit;
+ }
+
+
+ public void OnResolved()
+ {
+
+ }
+
+ public void HideMenus()
+ {
+ // Splash.Hide();
+ MainMenu.Hide();
+ CreateGameMenu.Hide();
+ LoadingGameMenu.Hide();
+ OptionsMenu.Hide();
+ ModsMenu.Hide();
+ }
+
+
+ public IEnumerable GetLevels()
+ {
+yield return new LevelEntry("Level1", "res://assets/kenney_conveyor-kit/Sample.png");
+yield return new LevelEntry("Level2", "res://assets/KayKit_Restaurant_Bits_1.0_FREE/sample.png");
+yield return new LevelEntry("Level3", "res://assets/KayKit_Restaurant_Bits_1.0_FREE/contents.png");
+ }
+
+ public ISaveService Value() => SaveService;
+
+
+
+
+
+
+
+ // public override void _Ready()//=> new Test().TestECS();
+ // {
+ // // TestButton = GetNode