Skip to content

Commit 6f140d1

Browse files
committed
**New**:
- Added *AGENTS.md* document to help guide AI coding assistants to understand and work with this package library - Added an entire test suit of unit/integration/performance/smoke tests to cover all the code for all services in this package **Changed**: - Changed *VersionServices* namespace from *GameLovers* to *GameLovers.Services* to maintain consistency with other services in the package. - Made *CallOnSpawned*, *CallOnSpawned\<TData\>*, and *CallOnDespawned* methods virtual in *ObjectPoolBase\<T\>* to allow derived pool classes to customize lifecycle callback behavior. **Fixed**: - Fixed the *README.md* file to now follow best practices in OSS standards for Unity's package library projects - Fixed linter warnings in *VersionServices.cs* (redundant field initialization, unused lambda parameter, member shadowing) - Fixed *GameObjectPool* not invoking *IPoolEntitySpawn.OnSpawn()* and *IPoolEntityDespawn.OnDespawn()* on components attached to spawned GameObjects.
1 parent 3f363fe commit 6f140d1

File tree

71 files changed

+1865
-664
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1865
-664
lines changed

AGENTS.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# GameLovers.Services - AI Agent Guide
2+
3+
## 1. Package Overview
4+
- **Package**: `com.gamelovers.services`
5+
- **Unity**: 6000.0+
6+
- **Dependencies** (see `package.json`)
7+
- `com.gamelovers.dataextensions` (**0.6.2**) (contains `floatP`, used by `RngService`)
8+
9+
This package provides a set of small, modular “foundation services” for Unity projects (service locator/DI-lite, messaging, ticking, coroutines, pooling, persistence, RNG, time, and build version helpers).
10+
11+
For user-facing docs, treat `README.md` as the primary entry point. This file is for contributors/agents working on the package itself.
12+
13+
## 2. Runtime Architecture (high level)
14+
- **Service locator / bindings**: `Runtime/Installer.cs`, `Runtime/MainInstaller.cs`
15+
- `Installer` stores a `Dictionary<Type, object>` of interface type → instance.
16+
- `MainInstaller` is a **static** wrapper over a single `Installer` instance (global scope).
17+
- Binding is **instance-based** (`Bind<T>(T instance)`), not “type-to-type” or lifetime-managed DI.
18+
- Only **interfaces** can be bound (binding a non-interface throws).
19+
- **Messaging**: `Runtime/MessageBrokerService.cs`
20+
- Message contract: `IMessage`
21+
- Pub/sub via `IMessageBrokerService` (`Publish`, `PublishSafe`, `Subscribe`, `Unsubscribe`, `UnsubscribeAll`)
22+
- Stores subscribers keyed by `action.Target` (so **static method subscriptions are not supported**).
23+
- **Tick / update fan-out**: `Runtime/TickService.cs`
24+
- Creates a `DontDestroyOnLoad` GameObject with `TickServiceMonoBehaviour` to drive Update/LateUpdate/FixedUpdate callbacks.
25+
- Supports “buffered” ticking (`deltaTime`) and optional overflow carry (`timeOverflowToNextTick`) to reduce drift.
26+
- Uses scaled (`Time.time`) or unscaled (`Time.realtimeSinceStartup`) time depending on `realTime`.
27+
- **Coroutine host**: `Runtime/CoroutineService.cs`
28+
- Creates a `DontDestroyOnLoad` GameObject with `CoroutineServiceMonoBehaviour` to run coroutines from pure C# code.
29+
- `IAsyncCoroutine` / `IAsyncCoroutine<T>` wraps a Unity `Coroutine` and offers completion callbacks + state flags.
30+
- **Pooling**:
31+
- Pool registry: `Runtime/PoolService.cs` (`PoolService : IPoolService`)
32+
- Pool implementations: `Runtime/ObjectPool.cs`
33+
- Generic `ObjectPool<T>`
34+
- Unity-specific: `GameObjectPool`, `GameObjectPool<TBehaviour>`
35+
- Lifecycle hooks: `IPoolEntitySpawn`, `IPoolEntitySpawn<TData>`, `IPoolEntityDespawn`, `IPoolEntityObject<T>`
36+
- **Persistence**: `Runtime/DataService.cs`
37+
- In-memory store keyed by `Type`
38+
- Disk persistence via `PlayerPrefs` + `Newtonsoft.Json` serialization
39+
- **Time + manipulation**: `Runtime/TimeService.cs`
40+
- `ITimeService` + `ITimeManipulator` for querying time (Unity / Unix / DateTime UTC) and applying offsets.
41+
- **Deterministic RNG**: `Runtime/RngService.cs`
42+
- Deterministic RNG state stored in `RngData` and exposed via `IRngData`.
43+
- Float API uses `floatP` (from `com.gamelovers.dataextensions`) for deterministic float math.
44+
- **Build/version info**: `Runtime/VersionServices.cs`
45+
- Runtime access to version strings and git/build metadata loaded from a Resources TextAsset.
46+
47+
## 3. Key Directories / Files
48+
- **Runtime**: `Runtime/`
49+
- Entry points: `MainInstaller.cs`, `Installer.cs`
50+
- Services: `MessageBrokerService.cs`, `TickService.cs`, `CoroutineService.cs`, `PoolService.cs`, `DataService.cs`, `TimeService.cs`, `RngService.cs`, `VersionServices.cs`
51+
- Pooling: `ObjectPool.cs`
52+
- **Editor**: `Editor/`
53+
- Version data generation: `VersionEditorUtils.cs`, `GitEditorProcess.cs`
54+
- Must remain editor-only (relies on `UnityEditor` + starting git processes)
55+
- **Tests**: `Tests/`
56+
- EditMode/PlayMode tests validating service behavior
57+
58+
## 4. Important Behaviors / Gotchas
59+
- **`MainInstaller` API vs README snippets**
60+
- `MainInstaller` is a static class exposing `Bind/Resolve/TryResolve/Clean`.
61+
- If you see docs/examples referring to `MainInstaller.Instance` or fluent bindings, verify against runtime code—those snippets may be stale.
62+
- **Message broker mutation safety**
63+
- `Publish<T>` iterates subscribers directly; subscribing/unsubscribing during publish is blocked and throws.
64+
- Use `PublishSafe<T>` if you have chain subscriptions/unsubscriptions during message handling (it copies delegates first, at extra allocation cost).
65+
- `Subscribe` uses `action.Target` as the subscriber key, so **static methods cannot subscribe**.
66+
- **Tick/coroutine services allocate a global GameObject**
67+
- `TickService` and `CoroutineService` each create a `DontDestroyOnLoad` GameObject. Call `Dispose()` when you want to tear them down (tests, game reset, domain reload edge cases).
68+
- These services do **not** enforce a singleton at runtime; constructing multiple instances will create multiple host GameObjects.
69+
- **`IAsyncCoroutine.StopCoroutine(triggerOnComplete)`**
70+
- The current implementation triggers completion callbacks even when `triggerOnComplete` is `false` (parameter is not respected). Keep this in mind if you rely on cancellation semantics.
71+
- **DataService persistence details**
72+
- Keys are `typeof(T).Name` in `PlayerPrefs` (name collisions are possible across assemblies/types with same name).
73+
- `LoadData<T>` requires `T` to have a parameterless constructor (via `Activator.CreateInstance<T>()`) if no data exists.
74+
- **Pool lifecycle**
75+
- `PoolService` keeps **one pool per type**; it does not guard against duplicate `AddPool<T>()` calls (duplicate adds throw from `Dictionary.Add`).
76+
- `GameObjectPool.Dispose(bool)` destroys the `SampleEntity` GameObject; `GameObjectPool.Dispose()` destroys pooled instances but does not necessarily destroy the sample reference—be explicit about disposal expectations when changing pool behavior.
77+
- `GameObjectPool` and `GameObjectPool<T>` override `CallOnSpawned`/`CallOnDespawned` (virtual methods) to use `GetComponent<IPoolEntitySpawn>()` / `GetComponent<IPoolEntityDespawn>()` for lifecycle hooks on **components**. This differs from `ObjectPool<T>` which casts the entity directly.
78+
- **Version data pipeline**
79+
- Runtime expects a Resources TextAsset named `version-data` (`VersionServices.VersionDataFilename`).
80+
- `VersionEditorUtils` writes `Assets/Configs/Resources/version-data.txt` on editor load and can be invoked before builds. It uses git CLI; failures should be handled gracefully.
81+
- Accessors like `VersionServices.VersionInternal` will throw if version data hasn’t been loaded yet—call `VersionServices.LoadVersionDataAsync()` early (and decide how you want to handle load failures).
82+
83+
## 5. Coding Standards (Unity 6 / C# 9.0)
84+
- **C#**: C# 9.0 syntax; explicit namespaces; no global usings.
85+
- **Assemblies**
86+
- Runtime must not reference `UnityEditor`.
87+
- Editor tooling must live under `Editor/` (or be guarded with `#if UNITY_EDITOR` if absolutely necessary).
88+
- **Performance**
89+
- Be mindful of allocations in hot paths (e.g., `PublishSafe` allocates; tick lists mutate; avoid per-frame allocations).
90+
91+
## 6. External Package Sources (for API lookups)
92+
Prefer local UPM cache / local packages when needed:
93+
- DataExtensions: `Packages/com.gamelovers.dataextensions/` (e.g., `floatP`)
94+
- Unity Newtonsoft JSON (Unity package): check `Library/PackageCache/` if you need source details
95+
96+
## 7. Dev Workflows (common changes)
97+
- **Add a new service**
98+
- Add runtime interface + implementation under `Runtime/` (keep UnityEngine usage minimal if possible).
99+
- Add/adjust tests under `Tests/`.
100+
- If the service needs Unity callbacks, follow the `TickService`/`CoroutineService` pattern (single `DontDestroyOnLoad` host object + `Dispose()`).
101+
- **Bind/resolve services**
102+
- Bind instances via `MainInstaller.Bind<IMyService>(myServiceInstance)`.
103+
- Resolve via `MainInstaller.Resolve<IMyService>()` or `TryResolve`.
104+
- Clear bindings on reset via `MainInstaller.Clean()` (or `Clean<T>()` / `CleanDispose<T>()`).
105+
- **Update versioning**
106+
- Ensure `version-data.txt` exists/updates correctly in `Assets/Configs/Resources/`.
107+
- If changing `VersionServices.VersionData`, update both runtime parsing and `VersionEditorUtils` writing logic.
108+
109+
## 8. Update Policy
110+
Update this file when:
111+
- The binding/service-locator API changes (`Installer`, `MainInstaller`)
112+
- Core service behavior changes (publish safety rules, tick timing, coroutine completion/cancellation semantics, pooling lifecycle)
113+
- Versioning pipeline changes (resource filename, editor generator behavior, runtime parsing)
114+
- Dependencies change (`package.json`, new external types like `floatP`)
115+

AGENTS.md.meta

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@ All notable changes to this package will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7+
## [1.0.0] - 2026-01-11
8+
9+
**New**:
10+
- Added *AGENTS.md* document to help guide AI coding assistants to understand and work with this package library
11+
- Added an entire test suit of unit/integration/performance/smoke tests to cover all the code for all services in this package
12+
13+
**Changed**:
14+
- Changed *VersionServices* namespace from *GameLovers* to *GameLovers.Services* to maintain consistency with other services in the package.
15+
- Made *CallOnSpawned*, *CallOnSpawned\<TData\>*, and *CallOnDespawned* methods virtual in *ObjectPoolBase\<T\>* to allow derived pool classes to customize lifecycle callback behavior.
16+
17+
**Fixed**:
18+
- Fixed the *README.md* file to now follow best practices in OSS standards for Unity's package library projects
19+
- Fixed linter warnings in *VersionServices.cs* (redundant field initialization, unused lambda parameter, member shadowing)
20+
- Fixed *GameObjectPool* not invoking *IPoolEntitySpawn.OnSpawn()* and *IPoolEntityDespawn.OnDespawn()* on components attached to spawned GameObjects.
21+
722
## [0.15.1] - 2025-09-24
823

924
**New**:

Editor/VersionEditorUtils.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.IO;
33
using UnityEditor;
44
using UnityEngine;
5+
using GameLovers.Services;
56

67
namespace GameLovers.Services.Editor
78
{
@@ -89,7 +90,7 @@ private static VersionServices.VersionData GenerateInternalVersionSuffix(bool is
8990
}
9091
else
9192
{
92-
data.Commit = commitHash.Substring(0, ShortenedCommitLength);
93+
data.CommitHash = commitHash.Substring(0, ShortenedCommitLength);
9394
}
9495
}
9596
}

0 commit comments

Comments
 (0)