From e5f6e7ccae6223b6dcf95b53bd3436bb4de7268f Mon Sep 17 00:00:00 2001 From: harrison Date: Thu, 23 Oct 2025 13:53:29 +0000 Subject: [PATCH] added ARCHITECTURE.md --- ARCHITECTURE.md | 806 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 806 insertions(+) create mode 100644 ARCHITECTURE.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 0000000..b0a9fc5 --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,806 @@ +# Godot C# Library Management System + +## Overview + +This document describes a comprehensive system for managing reusable C# libraries across multiple Godot game projects using Git submodules. This approach enables clean separation of concerns, version control for individual libraries, and easy code reuse across multiple game projects. + +## System Architecture + +### Core Principles + +1. **Separation of Concerns**: Libraries and game projects exist in separate Git repositories +2. **Modular Design**: Each library serves a specific purpose and can be developed independently +3. **Version Control**: Libraries can be versioned and updated independently of game projects +4. **Code Reuse**: Multiple projects can share the same libraries without code duplication +5. **Clean Dependencies**: C# project references ensure proper compilation and IntelliSense support + +### Directory Structure + +``` +~/GameDev/ +├── Godot/ # Godot engine installation +├── libraries/ # Local development copies of libraries +│ ├── utilities/ # Example: utilities library repository +│ ├── audio-manager/ # Example: audio management library +│ └── ui-framework/ # Example: UI framework library +└── projects/ # Game project repositories + ├── test-game/ # Example: test game project + │ └── Libraries/ # Git submodules directory + │ ├── utilities/ # Submodule → library/utilities + │ └── audio-manager/# Submodule → library/audio-manager + └── puzzle-game/ # Example: another game project + └── Libraries/ # Git submodules directory + └── utilities/ # Submodule → library/utilities +``` + +### Git Repository Organization + +**Gitea Organizations:** +- `library/` - Contains all reusable library repositories +- `project/` - Contains all game project repositories + +**Repository Examples:** +- `https://git.ein-softworks.com/library/utilities.git` +- `https://git.ein-softworks.com/library/audio-manager.git` +- `https://git.ein-softworks.com/project/test-game.git` +- `https://git.ein-softworks.com/project/puzzle-game.git` + +## How Git Submodules Work + +Git submodules allow you to include one Git repository inside another as a subdirectory. In our case: + +1. **Library repositories** contain reusable C# code and Godot scenes +2. **Game project repositories** include libraries as submodules in their `Libraries/` directory +3. **Submodules point to specific commits** in the library repositories, ensuring reproducible builds +4. **Updates are explicit** - you control when to pull in library changes + +### Benefits of This Approach + +- **Independent Development**: Work on libraries without affecting game projects +- **Version Stability**: Games use specific library versions until explicitly updated +- **Selective Updates**: Choose which libraries to update in each project +- **Clean History**: Each repository maintains its own commit history +- **Collaborative Friendly**: Multiple developers can work on different libraries simultaneously + +## Initial Setup Process + +### Prerequisites + +- macOS with Godot v4.5.1 stable installed at `~/GameDev/Godot/` +- .NET 8.0.121 installed +- Git configured with access to your Gitea instance +- Gitea instance with `library` and `project` organizations created + +### Step 1: Create Directory Structure + +```bash +cd ~/GameDev +mkdir -p libraries projects +``` + +### Step 2: Create Your First Library + +#### Initialize the Library Repository + +```bash +cd ~/GameDev/libraries +git init utilities +cd utilities +mkdir -p Scripts +``` + +#### Create Library Project Configuration + +Create `project.godot`: +```ini +; Engine configuration file. + +[application] + +config/name="Utilities Library" +config/features=PackedStringArray("4.3", "C#", "Forward Plus") + +[dotnet] + +project/assembly_name="EinSoftworks.Utilities" +``` + +Create `Utilities.csproj`: +```xml + + + net6.0 + net7.0 + net8.0 + true + EinSoftworks.Utilities + EinSoftworks.Utilities + + +``` + +#### Create Example Library Code + +Create `Scripts/MathUtils.cs`: +```csharp +using Godot; + +namespace EinSoftworks.Utilities +{ + public static class MathUtils + { + /// + /// Clamps a value between 0 and 1. + /// + public static float Clamp01(float value) + { + return Mathf.Clamp(value, 0f, 1f); + } + + /// + /// Checks if a number is approximately equal to another number. + /// + public static bool Approximately(float a, float b, float threshold = 0.001f) + { + return Mathf.Abs(a - b) < threshold; + } + + /// + /// Converts degrees to radians. + /// + public static float DegreesToRadians(float degrees) + { + return degrees * Mathf.Pi / 180f; + } + + /// + /// Converts radians to degrees. + /// + public static float RadiansToDegrees(float radians) + { + return radians * 180f / Mathf.Pi; + } + } +} +``` + +#### Create .gitignore + +```gitignore +# Godot 4+ specific ignores +.godot/ + +# Godot-specific ignores +.import/ +export.cfg +export_presets.cfg + +# Imported translations (automatically generated from CSV files) +*.translation + +# Mono-specific ignores +.mono/ +data_*/ +mono_crash.*.json + +# .NET specific ignores +bin/ +obj/ +*.tmp +``` + +#### Commit and Push Library + +```bash +git add . +git commit -m "Initial utilities library setup with MathUtils" +git remote add origin https://git.ein-softworks.com/library/utilities.git +git branch -M main +git push -u origin main +``` + +### Step 3: Create Your First Game Project + +#### Initialize the Game Repository + +```bash +cd ~/GameDev/projects +git init test-game +cd test-game +mkdir -p Scripts Scenes Libraries +``` + +#### Create Game Project Configuration + +Create `project.godot`: +```ini +; Engine configuration file. + +[application] + +config/name="Test Game" +config/features=PackedStringArray("4.3", "C#", "Forward Plus") +run/main_scene="res://Scenes/Main.tscn" + +[dotnet] + +project/assembly_name="TestGame" +``` + +Create `TestGame.csproj`: +```xml + + + net6.0 + net7.0 + net8.0 + true + TestGame + + + + + + +``` + +#### Add Library as Submodule + +```bash +git submodule add https://git.ein-softworks.com/library/utilities.git Libraries/utilities +git submodule update --init --recursive +``` + +#### Create Game Code + +Create `Scripts/Main.cs`: +```csharp +using Godot; +using EinSoftworks.Utilities; + +namespace TestGame +{ + public partial class Main : Node2D + { + public override void _Ready() + { + GD.Print("Test Game Started!"); + + // Test the utilities library + TestMathUtils(); + } + + private void TestMathUtils() + { + // Test degree/radian conversion + float testAngle = 90f; + float radians = MathUtils.DegreesToRadians(testAngle); + float backToDegrees = MathUtils.RadiansToDegrees(radians); + GD.Print($"90° → {radians} rad → {backToDegrees}°"); + + // Test clamping + float clampedValue = MathUtils.Clamp01(1.5f); + GD.Print($"Clamped 1.5 to 0-1 range: {clampedValue}"); + + // Test approximation + bool isApprox = MathUtils.Approximately(0.1f, 0.100001f); + GD.Print($"0.1 ≈ 0.100001: {isApprox}"); + } + } +} +``` + +Create `Scenes/Main.tscn`: +``` +[gd_scene load_steps=2 format=3 uid="uid://b8y1qxqxqxqxq"] + +[ext_resource type="Script" path="res://Scripts/Main.cs" id="1"] + +[node name="Main" type="Node2D"] +script = ExtResource("1") + +[node name="Label" type="Label" parent="."] +offset_right = 400.0 +offset_bottom = 100.0 +text = "Test Game - Check console for utilities library output" +horizontal_alignment = 1 +vertical_alignment = 1 +``` + +#### Create .gitignore + +```gitignore +# Godot 4+ specific ignores +.godot/ + +# Godot-specific ignores +.import/ +export.cfg +export_presets.cfg + +# Imported translations (automatically generated from CSV files) +*.translation + +# Mono-specific ignores +.mono/ +data_*/ +mono_crash.*.json + +# .NET specific ignores +bin/ +obj/ +*.tmp +``` + +#### Commit and Push Game Project + +```bash +git add . +git commit -m "Initial test game setup with utilities library submodule" +git remote add origin https://git.ein-softworks.com/project/test-game.git +git branch -M main +git push -u origin main +``` + +### Step 4: Open and Build in Godot + +1. Launch Godot: `~/GameDev/Godot/Godot.app/Contents/MacOS/Godot` +2. In Project Manager, click **"Import"** +3. Navigate to `~/GameDev/projects/test-game/` and select `project.godot` +4. Click **"Import & Edit"** +5. In the Godot editor, go to **Project → Tools → C# → Create C# solution** +6. Click the **"Build"** button in the toolbar (or **Project → Tools → C# → Build Solution**) +7. Run the game with the **Play** button + +Expected console output: +``` +Test Game Started! +90° → 1.5708 rad → 90° +Clamped 1.5 to 0-1 range: 1 +0.1 ≈ 0.100001: True +``` + +## Usage Workflows + +### Working on Libraries + +#### Developing New Features + +When you want to add functionality to an existing library: + +```bash +# Navigate to library +cd ~/GameDev/libraries/utilities + +# Create a new branch for your feature +git checkout -b feature/string-utilities + +# Add your new code (example) +cat >> Scripts/StringUtils.cs << 'EOF' +using Godot; + +namespace EinSoftworks.Utilities +{ + public static class StringUtils + { + public static string ToPascalCase(string input) + { + if (string.IsNullOrEmpty(input)) return input; + return char.ToUpper(input[0]) + input.Substring(1).ToLower(); + } + + public static bool IsValidEmail(string email) + { + return email.Contains("@") && email.Contains("."); + } + } +} +EOF + +# Test your changes in Godot +# Open ~/GameDev/libraries/utilities in Godot +# Build and test the library + +# Commit your changes +git add . +git commit -m "Add StringUtils with PascalCase and email validation" + +# Push the feature branch +git push origin feature/string-utilities + +# Create a pull request in Gitea +# After review and merge, switch back to main +git checkout main +git pull origin main + +# Clean up feature branch +git branch -d feature/string-utilities +``` + +#### Creating a New Library + +```bash +# Create new library repository +cd ~/GameDev/libraries +git init audio-manager +cd audio-manager + +# Set up library structure +mkdir -p Scripts Resources +cat > project.godot << 'EOF' +; Engine configuration file. + +[application] + +config/name="Audio Manager Library" +config/features=PackedStringArray("4.3", "C#", "Forward Plus") + +[dotnet] + +project/assembly_name="EinSoftworks.AudioManager" +EOF + +cat > AudioManager.csproj << 'EOF' + + + net6.0 + net7.0 + net8.0 + true + EinSoftworks.AudioManager + EinSoftworks.AudioManager + + +EOF + +# Create basic audio manager +cat > Scripts/AudioManager.cs << 'EOF' +using Godot; + +namespace EinSoftworks.AudioManager +{ + public partial class AudioManager : Node + { + private AudioStreamPlayer _musicPlayer; + private AudioStreamPlayer _sfxPlayer; + + public override void _Ready() + { + _musicPlayer = new AudioStreamPlayer(); + _sfxPlayer = new AudioStreamPlayer(); + + AddChild(_musicPlayer); + AddChild(_sfxPlayer); + } + + public void PlayMusic(AudioStream music, float volume = 1.0f) + { + _musicPlayer.Stream = music; + _musicPlayer.VolumeDb = Mathf.LinearToDb(volume); + _musicPlayer.Play(); + } + + public void PlaySFX(AudioStream sfx, float volume = 1.0f) + { + _sfxPlayer.Stream = sfx; + _sfxPlayer.VolumeDb = Mathf.LinearToDb(volume); + _sfxPlayer.Play(); + } + } +} +EOF + +# Copy standard .gitignore +cp ../utilities/.gitignore . + +# Commit and push +git add . +git commit -m "Initial audio manager library" +git remote add origin https://git.ein-softworks.com/library/audio-manager.git +git branch -M main +git push -u origin main +``` + +### Working with Game Projects + +#### Adding Libraries to Existing Projects + +To add a new library to an existing game project: + +```bash +# Navigate to your game project +cd ~/GameDev/projects/test-game + +# Add the new library as a submodule +git submodule add https://git.ein-softworks.com/library/audio-manager.git Libraries/audio-manager + +# Update the .csproj file to reference the new library +# Edit TestGame.csproj and add to ItemGroup: +# + +# Example of the updated .csproj: +cat > TestGame.csproj << 'EOF' + + + net6.0 + net7.0 + net8.0 + true + TestGame + + + + + + + +EOF + +# Commit the changes +git add . +git commit -m "Add audio-manager library dependency" +git push origin main + +# In Godot: Project → Reload Current Project +# Then build the solution +``` + +#### Updating Libraries in Projects + +To update a library to the latest version: + +```bash +# Navigate to your game project +cd ~/GameDev/projects/test-game + +# Update specific library to latest +git submodule update --remote Libraries/utilities + +# Or update all submodules +git submodule update --remote + +# Commit the library updates +git add . +git commit -m "Update utilities library to latest version" +git push origin main + +# In Godot: Project → Reload Current Project +# Then rebuild the solution +``` + +To update to a specific version/commit: + +```bash +# Navigate to the submodule +cd ~/GameDev/projects/test-game/Libraries/utilities + +# Check available tags/versions +git tag -l + +# Checkout specific version +git checkout v1.2.0 + +# Go back to project root +cd ~/GameDev/projects/test-game + +# Commit the specific version +git add Libraries/utilities +git commit -m "Update utilities library to v1.2.0" +git push origin main +``` + +#### Creating New Game Projects + +To create a new game project with existing libraries: + +```bash +# Create new project +cd ~/GameDev/projects +git init puzzle-game +cd puzzle-game + +# Set up basic structure +mkdir -p Scripts Scenes Libraries + +# Create project.godot +cat > project.godot << 'EOF' +; Engine configuration file. + +[application] + +config/name="Puzzle Game" +config/features=PackedStringArray("4.3", "C#", "Forward Plus") +run/main_scene="res://Scenes/Main.tscn" + +[dotnet] + +project/assembly_name="PuzzleGame" +EOF + +# Add required libraries +git submodule add https://git.ein-softworks.com/library/utilities.git Libraries/utilities +git submodule add https://git.ein-softworks.com/library/audio-manager.git Libraries/audio-manager + +# Create .csproj with all dependencies +cat > PuzzleGame.csproj << 'EOF' + + + net6.0 + net7.0 + net8.0 + true + PuzzleGame + + + + + + + +EOF + +# Copy .gitignore from another project +cp ../test-game/.gitignore . + +# Initialize submodules +git submodule update --init --recursive + +# Create basic game code +cat > Scripts/Main.cs << 'EOF' +using Godot; +using EinSoftworks.Utilities; +using EinSoftworks.AudioManager; + +namespace PuzzleGame +{ + public partial class Main : Node2D + { + private AudioManager _audioManager; + + public override void _Ready() + { + GD.Print("Puzzle Game Started!"); + + // Set up audio manager + _audioManager = new AudioManager(); + AddChild(_audioManager); + + // Test utilities + float angle = MathUtils.DegreesToRadians(45f); + GD.Print($"45 degrees = {angle} radians"); + } + } +} +EOF + +# Commit and push +git add . +git commit -m "Initial puzzle game setup with utilities and audio-manager libraries" +git remote add origin https://git.ein-softworks.com/project/puzzle-game.git +git branch -M main +git push -u origin main +``` + +### Advanced Workflows + +#### Working with Library Dependencies + +If one library depends on another: + +```csharp +// In Libraries/ui-framework/UIFramework.csproj + + + net6.0 + true + EinSoftworks.UIFramework + EinSoftworks.UIFramework + + + + + + +``` + +#### Creating Library Releases + +For important library milestones: + +```bash +# In your library repository +cd ~/GameDev/libraries/utilities + +# Create and push a tag +git tag -a v1.0.0 -m "Release version 1.0.0 - Initial stable release" +git push origin v1.0.0 + +# Create release notes in Gitea +# Navigate to your Gitea repository → Releases → New Release +``` + +#### Cloning Projects on New Machines + +When setting up on a new development machine: + +```bash +# Clone project with submodules +git clone --recursive https://git.ein-softworks.com/project/test-game.git + +# Or if already cloned without --recursive +cd test-game +git submodule update --init --recursive +``` + +## Best Practices + +### Library Design + +1. **Keep libraries focused**: Each library should have a single, well-defined purpose +2. **Use proper namespacing**: Follow the pattern `CompanyName.LibraryName` +3. **Document your code**: Use XML documentation comments for public APIs +4. **Version your releases**: Use semantic versioning (major.minor.patch) +5. **Test thoroughly**: Create test projects for each library + +### Project Organization + +1. **Consistent naming**: Use kebab-case for repository names, PascalCase for namespaces +2. **Clear dependencies**: Only include libraries you actually use +3. **Regular updates**: Keep libraries updated, but test thoroughly after updates +4. **Backup strategy**: Ensure all repositories are backed up on your Gitea instance + +### Git Workflow + +1. **Feature branches**: Use feature branches for library development +2. **Descriptive commits**: Write clear commit messages +3. **Regular pushes**: Push changes regularly to avoid data loss +4. **Clean history**: Squash commits when merging features + +### Development Environment + +1. **Consistent paths**: Always use the `~/GameDev/` structure +2. **IDE setup**: Configure your IDE to recognize the library references +3. **Build automation**: Consider setting up CI/CD for library testing +4. **Documentation**: Keep this document updated as your system evolves + +## Troubleshooting + +### Common Issues + +#### Submodule Not Found +```bash +# If Libraries/utilities is empty +cd ~/GameDev/projects/test-game +git submodule update --init --recursive +``` + +#### Build Errors +```bash +# In Godot editor +# Project → Reload Current Project +# Project → Tools → C# → Create C# solution +# Build +``` + +#### Missing References +Check that your `.csproj` file includes all required `` entries for your submodules. + +#### Submodule Update Conflicts +```bash +# If you have uncommitted changes in a submodule +cd Libraries/utilities +git stash +git pull origin main +git stash pop +``` + +### Getting Help + +1. Check Godot's C# documentation +2. Review Git submodule documentation +3. Examine this document for reference patterns +4. Test changes in isolation before applying to important projects + +--- + +*This documentation should be updated as your library system evolves and new patterns emerge.* \ No newline at end of file