Architecture Overview
Relevant source files
The following files were used as context for generating this wiki page:Skid-Inc is an idle game packaged as a desktop application using the Electron framework. The architecture is centered around a standard Electron model, which separates the application into a Main process for backend operations and a Renderer process for the user interface. This structure allows the original web-based game to run within a native window while leveraging Node.js capabilities for features like a robust local file-based save system and automated builds.
The system is composed of three primary architectural domains: the core Electron application, a sophisticated save management system, and an automated build and deployment pipeline. The core application manages the window and application lifecycle. The save system provides features like auto-saving, backups, and data validation. The build pipeline automates the process of creating distributable packages for Windows, macOS, and Linux.
Core Application Architecture
The application's foundation is built on Electron, which divides responsibilities between a Main process and a Renderer process. Communication between these isolated processes is handled securely via a preload script and Inter-Process Communication (IPC) channels.
Sources: src/main.js, ELECTRON-SETUP.md
This diagram shows the high-level relationship between the Electron Main and Renderer processes, the role of the preload script, and access to system resources.
Main Process
The Main process, defined in src/main.js, serves as the application's entry point and backend. It is responsible for creating and managing the BrowserWindow, handling the application lifecycle, and managing native functionalities.
Key Responsibilities:
- Window Management: Creates the main browser window, setting its dimensions and web preferences.
- Application Lifecycle: Handles
appevents likeready,window-all-closed, andactivate. - IPC Handling: Listens for and responds to messages from the Renderer process for operations like saving/loading files and checking for updates.
- System Integration: Manages native menus and integrates with backend modules like
AutoSaveManagerandFileSystemManager. - Security: Configures the
BrowserWindowwithcontextIsolationenabled andnodeIntegrationdisabled to secure the renderer environment.
Sources: src/main.js:15-39, src/main.js:41-63
Renderer Process
The Renderer process is responsible for rendering the user interface. It loads the game's UI from index.html and executes the frontend JavaScript logic. This process runs in a sandboxed environment with no direct access to Node.js APIs for security reasons.
Key Components:
index.html: The main HTML file that defines the structure of the game UI, including the terminal, stat tabs, and various modals for options, achievements, and save management.- Game Logic Scripts: A collection of JavaScript files (e.g.,
core.js,player.js,console.js) loaded byindex.htmlthat implement the game's mechanics. SaveStateManager: A class insrc/renderer/save-manager.jsthat orchestrates communication with the Main process for all save-related operations. It acts as the bridge between the game's state and the backend file system.
Sources: index.html, src/renderer/save-manager.js
Preload Script & IPC
A preload script (src/preload.js) is used to bridge the gap between the Renderer and Main processes. It runs in the Renderer process but has access to Node.js APIs. It securely exposes a limited set of functions to the Renderer via Electron's contextBridge. This prevents the game's frontend code from having full access to the system while still allowing it to request backend operations.
The main.js file sets up ipcMain handlers to listen for requests from the renderer on specific channels.
| Channel Name | Direction | Description |
|---|---|---|
save-game-state | Renderer -> Main | Sends the current game state to be saved to a file. |
load-game-state | Renderer -> Main | Requests the latest game state from the file system. |
get-save-list | Renderer -> Main | Requests a list of all available save files. |
delete-save | Renderer -> Main | Requests the deletion of a specific save file. |
load-specific-save | Renderer -> Main | Requests a specific save file to be loaded. |
create-manual-backup | Renderer -> Main | Triggers the creation of a manual backup file. |
save-status | Main -> Renderer | Notifies the renderer of the result of a save operation. |
auto-save-event | Main -> Renderer | Forwards events from the AutoSaveManager (e.g., save-success, save-failed). |
Sources: src/main.js:258-554, src/renderer/save-manager.js:28-60
Save System Architecture
The save system is a critical feature of the Electron port, providing robust, file-based persistence. It is split between the renderer and main processes to maintain security and separation of concerns.
Sources: src/auto-save-manager.js, src/renderer/save-manager.js, src/main.js
This sequence diagram illustrates the flow of data during an auto-save operation, from state change detection in the renderer to file writing in the main process.
Renderer-Side: SaveStateManager
The SaveStateManager class (src/renderer/save-manager.js) is the frontend component of the save system. It runs in the renderer process and is responsible for:
- Gathering the current game state from the
skidincorgamewindow objects. - Monitoring the game state for changes to trigger auto-saves.
- Sending save/load requests to the main process via IPC.
- Receiving status updates and notifications from the main process.
- Applying loaded game state back to the game objects.
- Managing the UI for save-related notifications and modals.
Sources: src/renderer/save-manager.js:126-239, src/renderer/save-manager.js:264-301
Main-Process: AutoSaveManager
The AutoSaveManager class (src/auto-save-manager.js) is the backend core of the save system. It runs in the main process and handles all file I/O and save logic.
Key Features:
- Periodic Saving: Saves the game at a regular interval (default 30 seconds).
- Quick Saving: Saves the game shortly after a significant state change is detected (default 5 seconds).
- Retry Logic: Implements exponential backoff for failed save attempts.
- Data Validation: Uses a
DataValidatorto check game state integrity before writing to disk. - Backup Management: Creates timestamped backups and cleans up old files based on a retention policy (default 30 days).
- Error Handling: Utilizes a
SaveErrorHandlerto manage I/O errors, including attempting to recover from backups. - Performance Management: Integrates a
PerformanceManagerto use adaptive save intervals based on system load.
Sources: src/auto-save-manager.js:46-88, src/auto-save-manager.js:215-300
Build and Deployment Pipeline
The project includes a set of Node.js scripts to automate the building and deployment of the application for multiple platforms. These scripts are defined in the scripts section of package.json and located in the scripts/ directory.
Sources: package.json:15-46, scripts/build-all.js, scripts/deploy.js, scripts/README.md
This flowchart outlines the automated release process, from running the initial command to generating the final distributable artifacts.
Build Automation (build-all.js)
The build-all.js script orchestrates the multi-platform build process using electron-builder.
Key Features:
- Environment Validation: Checks for Node.js,
electron-builder, and required source files before starting. - Multi-Platform Builds: Can build for Windows, macOS, and Linux. It intelligently skips macOS builds if not run on a macOS host.
- Error Handling & Retries: Automatically retries a failed build up to a configured number of times (
maxRetries). - Reporting: Generates a
build-report.jsonfile in the output directory with metrics on build duration, successes, and failures.
Sources: scripts/build-all.js:70-89, scripts/build-all.js:122-171
Deployment (deploy.js)
The deploy.js script takes the artifacts generated by the build process and prepares them for distribution.
Key Features:
- Artifact Collection: Gathers distributable files (e.g.,
.exe,.dmg,.AppImage) from thedistdirectory. - Checksum Generation: Calculates SHA256 checksums for all artifacts to ensure file integrity.
- Manifest Creation: Creates a
manifest.jsonfile containing metadata about the release, including version, build date, and artifact details. - Documentation: Auto-generates
RELEASE_NOTES.md. - Archiving: Packages all release files into a single
.ziparchive.
Sources: scripts/deploy.js:68-115, scripts/deploy.js:137-160