DI
This commit is contained in:
@@ -15,8 +15,6 @@ namespace RebootKit.Engine {
|
||||
public ServiceAsset<GameService> GameService;
|
||||
|
||||
[Space]
|
||||
public ServiceAsset[] Services;
|
||||
|
||||
public GameModeAsset StartingGameMode;
|
||||
}
|
||||
}
|
||||
117
Runtime/Engine/Code/Foundation/DIContext.cs
Normal file
117
Runtime/Engine/Code/Foundation/DIContext.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace RebootKit.Engine.Foundation {
|
||||
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Method)]
|
||||
public class InjectAttribute : Attribute {
|
||||
}
|
||||
|
||||
public class DIContext {
|
||||
private const BindingFlags k_fieldsBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
private const BindingFlags k_methodsBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||
|
||||
public interface IFieldInjector {
|
||||
bool Inject(FieldInfo field, object target, DIContext context);
|
||||
}
|
||||
|
||||
private static readonly Logger Logger = new(nameof(DIContext));
|
||||
|
||||
private readonly Dictionary<Type, object> _bindingsMaps = new();
|
||||
private readonly List<IFieldInjector> _fieldInjectors = new();
|
||||
|
||||
public DIContext() {
|
||||
Bind(this);
|
||||
|
||||
AddInjector(new InjectAttributeFieldInjector());
|
||||
}
|
||||
|
||||
public void AddInjector(IFieldInjector injector) {
|
||||
_fieldInjectors.Add(injector);
|
||||
}
|
||||
|
||||
public void Bind(Type type, object obj) {
|
||||
if (!_bindingsMaps.TryAdd(type, obj)) {
|
||||
Logger.Error($"Cannot bind to '{type}', slot is already occupied");
|
||||
}
|
||||
}
|
||||
|
||||
public void Bind<TBind>(TBind obj) {
|
||||
Bind(typeof(TBind), obj);
|
||||
}
|
||||
|
||||
public object Resolve(Type type) {
|
||||
if (_bindingsMaps.TryGetValue(type, out object obj)) {
|
||||
return obj;
|
||||
}
|
||||
|
||||
Logger.Error($"Couldn't resolve `{type}`");
|
||||
return null;
|
||||
}
|
||||
|
||||
public T Resolve<T>() {
|
||||
return (T) Resolve(typeof(T));
|
||||
}
|
||||
|
||||
public void Inject<T>(T target) {
|
||||
Type type = typeof(T);
|
||||
|
||||
foreach (FieldInfo field in type.GetFields(k_fieldsBindingFlags)) {
|
||||
if (!InjectField(field, target)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (MethodInfo method in type.GetMethods(k_methodsBindingFlags)) {
|
||||
if (!Attribute.IsDefined(method, typeof(InjectAttribute))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Type[] paramsTypes = method.GetParameters()
|
||||
.Select(t => t.ParameterType)
|
||||
.ToArray();
|
||||
|
||||
object[] instances = new object[paramsTypes.Length];
|
||||
|
||||
for (int i = 0; i < paramsTypes.Length; ++i) {
|
||||
instances[i] = Resolve(paramsTypes[i]);
|
||||
|
||||
if (instances[i] == null) {
|
||||
Logger.Error($"Failed to resolve method parameter of type `{paramsTypes[i]}`");
|
||||
}
|
||||
}
|
||||
|
||||
method.Invoke(target, instances);
|
||||
}
|
||||
}
|
||||
|
||||
private bool InjectField(FieldInfo field, object target) {
|
||||
for (int i = _fieldInjectors.Count - 1; i >= 0; i--) {
|
||||
if (_fieldInjectors[i].Inject(field, target, this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private class InjectAttributeFieldInjector : IFieldInjector {
|
||||
public bool Inject(FieldInfo field, object target, DIContext context) {
|
||||
if (!Attribute.IsDefined(field, typeof(InjectAttribute))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
object instance = context.Resolve(field.FieldType);
|
||||
|
||||
if (instance == null) {
|
||||
Logger.Error($"Cannot resolve `{field.FieldType}`");
|
||||
return false;
|
||||
}
|
||||
|
||||
field.SetValue(target, instance);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Engine/Code/Foundation/DIContext.cs.meta
Normal file
3
Runtime/Engine/Code/Foundation/DIContext.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cee4133e4a594126868703cc035663cd
|
||||
timeCreated: 1742001112
|
||||
@@ -16,7 +16,6 @@ namespace RebootKit.Engine.Foundation {
|
||||
}
|
||||
|
||||
RR.Shared = null;
|
||||
ServicesLocator.Shared.UnRegisterAll();
|
||||
|
||||
_cancellationTokenSource = new CancellationTokenSource();
|
||||
SceneManager.LoadScene(0, LoadSceneMode.Single);
|
||||
|
||||
22
Runtime/Engine/Code/Foundation/IService.cs
Normal file
22
Runtime/Engine/Code/Foundation/IService.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Foundation {
|
||||
public interface IService : IDisposable {
|
||||
UniTask OnInit(CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public abstract class ServiceMonoBehaviour : MonoBehaviour, IService {
|
||||
public abstract UniTask OnInit(CancellationToken cancellationToken);
|
||||
public abstract void Dispose();
|
||||
}
|
||||
|
||||
public abstract class ServiceAsset<T> : ScriptableObject where T : IService {
|
||||
public abstract T Create();
|
||||
}
|
||||
|
||||
public abstract class ServiceAsset : ServiceAsset<IService> {
|
||||
}
|
||||
}
|
||||
22
Runtime/Engine/Code/Foundation/SceneDI.cs
Normal file
22
Runtime/Engine/Code/Foundation/SceneDI.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Foundation {
|
||||
public interface IDependencyInstaller {
|
||||
void Install(DIContext context);
|
||||
}
|
||||
|
||||
public abstract class SceneDependencyInstaller : MonoBehaviour, IDependencyInstaller {
|
||||
public abstract void Install(DIContext context);
|
||||
}
|
||||
|
||||
public class SceneDI : MonoBehaviour, IDependencyInstaller {
|
||||
[SerializeField]
|
||||
private SceneDependencyInstaller[] _sceneInstallers;
|
||||
|
||||
public void Install(DIContext context) {
|
||||
foreach (SceneDependencyInstaller installer in _sceneInstallers) {
|
||||
installer.Install(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Engine/Code/Foundation/SceneDI.cs.meta
Normal file
3
Runtime/Engine/Code/Foundation/SceneDI.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8dd28652b58c4d689ab3f2f9354d7589
|
||||
timeCreated: 1742006992
|
||||
@@ -1,94 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine.Foundation {
|
||||
public interface IService : IDisposable {
|
||||
UniTask OnInit(CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public abstract class ServiceMonoBehaviour : MonoBehaviour, IService {
|
||||
public abstract UniTask OnInit(CancellationToken cancellationToken);
|
||||
public abstract void Dispose();
|
||||
}
|
||||
|
||||
public abstract class ServiceAsset<T> : ScriptableObject where T : IService {
|
||||
public abstract T Create();
|
||||
}
|
||||
|
||||
public abstract class ServiceAsset : ServiceAsset<IService> {
|
||||
}
|
||||
|
||||
public class ServicesLocator {
|
||||
private static readonly Logger _logger = new(nameof(ServicesLocator));
|
||||
|
||||
private static ServicesLocator _shared;
|
||||
|
||||
public static ServicesLocator Shared {
|
||||
get {
|
||||
if (_shared == null) {
|
||||
_shared = new ServicesLocator();
|
||||
}
|
||||
|
||||
return _shared;
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Dictionary<Type, IService> _servicesMap = new();
|
||||
|
||||
public void Register(IService service, Type type) {
|
||||
if (!_servicesMap.TryAdd(type, service)) {
|
||||
_logger.Error($"There is already game service of type `{type}`");
|
||||
return;
|
||||
}
|
||||
|
||||
service.OnInit(default);
|
||||
|
||||
_logger.Info($"Registered service of type {type.Name}");
|
||||
}
|
||||
|
||||
public void Register<T>(T service) where T : IService {
|
||||
Register(service, service.GetType());
|
||||
}
|
||||
|
||||
public async UniTask RegisterAsync<T>(T service, CancellationToken cancellationToken = default) where T : IService {
|
||||
if (!_servicesMap.TryAdd(typeof(T), service)) {
|
||||
_logger.Error($"There is already game service of type `{typeof(T).Name}`");
|
||||
return;
|
||||
}
|
||||
|
||||
await service.OnInit(cancellationToken);
|
||||
_logger.Info($"Registered service of type {typeof(T).Name}");
|
||||
}
|
||||
|
||||
public void UnRegister(Type type) {
|
||||
if (_servicesMap.TryGetValue(type, out IService service)) {
|
||||
service.Dispose();
|
||||
_servicesMap.Remove(type);
|
||||
_logger.Info($"Unregistered service of type {type.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
public void UnRegisterAll() {
|
||||
foreach (IService service in _servicesMap.Values) {
|
||||
service.Dispose();
|
||||
}
|
||||
_servicesMap.Clear();
|
||||
}
|
||||
|
||||
public IService Get(Type type) {
|
||||
if (_servicesMap.TryGetValue(type, out IService service)) {
|
||||
return service;
|
||||
}
|
||||
|
||||
Debug.LogAssertionFormat($"Couldn't find service of type `{type}`");
|
||||
return null;
|
||||
}
|
||||
|
||||
public T Get<T>() where T : IService {
|
||||
return (T) Get(typeof(T));
|
||||
}
|
||||
}
|
||||
}
|
||||
14
Runtime/Engine/Code/MainSceneInstaller.cs
Normal file
14
Runtime/Engine/Code/MainSceneInstaller.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Graphics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace RebootKit.Engine {
|
||||
public class MainSceneInstaller : SceneDependencyInstaller {
|
||||
[SerializeField]
|
||||
private MainCameraService _mainCameraService;
|
||||
|
||||
public override void Install(DIContext context) {
|
||||
context.Bind(_mainCameraService);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Engine/Code/MainSceneInstaller.cs.meta
Normal file
3
Runtime/Engine/Code/MainSceneInstaller.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4238ea1a17e342e583cdd929103a22c6
|
||||
timeCreated: 1742007242
|
||||
@@ -11,15 +11,13 @@ using UnityEngine.SceneManagement;
|
||||
using Logger = RebootKit.Engine.Foundation.Logger;
|
||||
|
||||
namespace RebootKit.Engine {
|
||||
|
||||
public abstract class RAsset : ScriptableObject {
|
||||
|
||||
}
|
||||
|
||||
public class RR : IDisposable {
|
||||
public static RR Shared { get; set; }
|
||||
|
||||
private static readonly Logger _logger = new Logger("RR");
|
||||
private static readonly Logger Logger = new("RR");
|
||||
|
||||
private EngineConfigAsset _engineConfigAsset;
|
||||
|
||||
@@ -28,40 +26,46 @@ namespace RebootKit.Engine {
|
||||
private WorldService _worldService;
|
||||
private GameService _gameService;
|
||||
|
||||
private DIContext _diContext;
|
||||
|
||||
public void Dispose() {
|
||||
}
|
||||
|
||||
public async UniTask Init(CancellationToken cancellationToken) {
|
||||
_logger.Info("Waking up");
|
||||
Logger.Info("Waking up");
|
||||
|
||||
_logger.Info("Loading engine config");
|
||||
Logger.Info("Loading engine config");
|
||||
_engineConfigAsset = Resources.Load<EngineConfigAsset>(RConsts.EngineConfigResourcesPath);
|
||||
if (_engineConfigAsset == null) {
|
||||
_logger.Error($"Couldn't load engine config from resources: {RConsts.EngineConfigResourcesPath}");
|
||||
Logger.Error($"Couldn't load engine config from resources: {RConsts.EngineConfigResourcesPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.Info("Loading engine found");
|
||||
Logger.Info("Loading engine found");
|
||||
|
||||
_diContext = new DIContext();
|
||||
_diContext.AddInjector(new CVarFieldInjector());
|
||||
|
||||
await CreateCoreServices(cancellationToken);
|
||||
await RegisterServiceAssetsFromConfig(cancellationToken);
|
||||
await RegisterServicesFromMainSceneAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async UniTask Run(CancellationToken cancellationToken) {
|
||||
_logger.Info($"Starting initial game mode");
|
||||
Logger.Info($"Starting initial game mode");
|
||||
await _gameService.Start(_engineConfigAsset.StartingGameMode, cancellationToken);
|
||||
}
|
||||
|
||||
private async UniTask<TService> CreateServiceAsync<TService>(ServiceAsset<TService> asset, CancellationToken cancellationToken = default) where TService : IService {
|
||||
TService service = asset.Create();
|
||||
await ServicesLocator.Shared.RegisterAsync(service, cancellationToken);
|
||||
_diContext.Bind<TService>(service);
|
||||
_diContext.Inject(service);
|
||||
|
||||
await service.OnInit(cancellationToken);
|
||||
return service;
|
||||
}
|
||||
|
||||
private async UniTask CreateCoreServices(CancellationToken cancellationToken) {
|
||||
_logger.Debug("Registering core services");
|
||||
Logger.Debug("Registering core services");
|
||||
|
||||
_consoleService = await CreateServiceAsync(_engineConfigAsset.ConsoleService, cancellationToken);
|
||||
_inputService = await CreateServiceAsync(_engineConfigAsset.InputService, cancellationToken);
|
||||
@@ -69,38 +73,23 @@ namespace RebootKit.Engine {
|
||||
_gameService = await CreateServiceAsync(_engineConfigAsset.GameService, cancellationToken);
|
||||
}
|
||||
|
||||
private async UniTask RegisterServiceAssetsFromConfig(CancellationToken cancellationToken = default) {
|
||||
if (_engineConfigAsset.Services.Length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.Info($"Registering {_engineConfigAsset.Services.Length} services");
|
||||
foreach (ServiceAsset service in _engineConfigAsset.Services) {
|
||||
await ServicesLocator.Shared.RegisterAsync(service.Create(), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
private async UniTask RegisterServicesFromMainSceneAsync(CancellationToken cancellationToken = default) {
|
||||
_logger.Info("Looking for services in mainscene");
|
||||
int foundCount = 0;
|
||||
|
||||
GameObject[] gameObjects = SceneManager.GetSceneByBuildIndex(RConsts.MainSceneBuildIndex).GetRootGameObjects();
|
||||
|
||||
if (gameObjects.Length == 0) {
|
||||
_logger.Info("No services found in main scene");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (GameObject root in gameObjects) {
|
||||
ServiceMonoBehaviour[] services = root.GetComponentsInChildren<ServiceMonoBehaviour>();
|
||||
SceneDI di = root.GetComponent<SceneDI>();
|
||||
|
||||
foreach (ServiceMonoBehaviour service in services) {
|
||||
await ServicesLocator.Shared.RegisterAsync(service, cancellationToken);
|
||||
foundCount += 1;
|
||||
}
|
||||
if (di == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_logger.Info($"Found and registered {foundCount} services from active scene");
|
||||
di.Install(_diContext);
|
||||
}
|
||||
|
||||
await UniTask.Yield();
|
||||
}
|
||||
|
||||
//
|
||||
@@ -108,10 +97,6 @@ namespace RebootKit.Engine {
|
||||
//
|
||||
|
||||
/// Services
|
||||
public static T Service<T>() where T : IService {
|
||||
return ServicesLocator.Shared.Get<T>();
|
||||
}
|
||||
|
||||
public static ConsoleService Console() => Shared._consoleService;
|
||||
public static InputService Input() => Shared._inputService;
|
||||
public static WorldService World() => Shared._worldService;
|
||||
|
||||
59
Runtime/Engine/Code/Services/Console/CVarFieldInjector.cs
Normal file
59
Runtime/Engine/Code/Services/Console/CVarFieldInjector.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using RebootKit.Engine.Foundation;
|
||||
|
||||
namespace RebootKit.Engine.Services.Console {
|
||||
[AttributeUsage(AttributeTargets.Field)]
|
||||
public class CVarAttribute : Attribute {
|
||||
public string Name { get; }
|
||||
public CVarValue Value { get; }
|
||||
|
||||
public CVarAttribute(string name, float defaultValue) {
|
||||
Name = name;
|
||||
Value = new CVarValue(defaultValue);
|
||||
}
|
||||
|
||||
public CVarAttribute(string name, double defaultValue) {
|
||||
Name = name;
|
||||
Value = new CVarValue(defaultValue);
|
||||
}
|
||||
|
||||
public CVarAttribute(string name, string defaultValue) {
|
||||
Name = name;
|
||||
Value = new CVarValue(defaultValue);
|
||||
}
|
||||
|
||||
public CVarAttribute(string name, int defaultValue) {
|
||||
Name = name;
|
||||
Value = new CVarValue(defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
public class CVarFieldInjector : DIContext.IFieldInjector {
|
||||
private static readonly Logger Logger = new(nameof(CVarFieldInjector));
|
||||
|
||||
public bool Inject(FieldInfo field, object target, DIContext context) {
|
||||
if (!Attribute.IsDefined(field, typeof(CVarAttribute))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ConsoleService console = context.Resolve<ConsoleService>();
|
||||
if (console == null) {
|
||||
Logger.Error($"Cannot inject field because cannot resolve `{nameof(ConsoleService)}`");
|
||||
return false;
|
||||
}
|
||||
|
||||
CVarAttribute cvarAttribute = field.GetCustomAttribute<CVarAttribute>();
|
||||
CVar cvar = console.GetCVar(cvarAttribute.Name);
|
||||
|
||||
if (cvar == null) {
|
||||
cvar = new CVar(cvarAttribute.Name, cvarAttribute.Value);
|
||||
console.Replace(cvar);
|
||||
}
|
||||
|
||||
field.SetValue(target, cvar);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ce6213dda8c4f8d9eafe4afd1614a86
|
||||
timeCreated: 1742005021
|
||||
@@ -72,6 +72,16 @@ namespace RebootKit.Engine.Services.Console {
|
||||
_config.ToggleAction.Action.performed -= OnToggleAction;
|
||||
}
|
||||
|
||||
public bool CVarExists(string name) {
|
||||
foreach (CVar cvar in _cvars) {
|
||||
if (cvar.Name.Equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public CVar GetCVar(string name) {
|
||||
foreach (CVar cvar in _cvars) {
|
||||
if (cvar.Name.Equals(name)) {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using RebootKit.Engine.Foundation;
|
||||
using RebootKit.Engine.Services.Console;
|
||||
|
||||
namespace RebootKit.Engine.Services.Game {
|
||||
public class GameService : IService {
|
||||
private static readonly Logger _logger = new(nameof(GameService));
|
||||
private static readonly Logger Logger = new(nameof(GameService));
|
||||
|
||||
private GameModeAsset _gameModeAsset;
|
||||
private GameMode _gameMode;
|
||||
@@ -28,7 +29,7 @@ namespace RebootKit.Engine.Services.Game {
|
||||
|
||||
private async UniTask Run(CancellationToken cancellationToken) {
|
||||
if (_gameMode == null) {
|
||||
_logger.Error("Trying to run game without game mode");
|
||||
Logger.Error("Trying to run game without game mode");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "com.szafastudio.szafakit",
|
||||
"name": "RebootKit.Engine",
|
||||
"rootNamespace": "RebootKit",
|
||||
"references": [
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f",
|
||||
@@ -22,13 +22,18 @@ namespace RebootKit.FPPKit {
|
||||
public InputActionReference SecondaryActionReference;
|
||||
}
|
||||
|
||||
private Config _config;
|
||||
|
||||
private FPPActor _player;
|
||||
|
||||
[CVar("fpp_cam_look_sens", 0.25f)]
|
||||
private CVar _sensitivityCVar;
|
||||
|
||||
[CVar("p_move_speed", 4.0f)]
|
||||
private CVar _movementSpeedCVar;
|
||||
|
||||
[Inject]
|
||||
private InputService _inputService;
|
||||
|
||||
private Config _config;
|
||||
private FPPActor _player;
|
||||
|
||||
public PlayerController(Config config) {
|
||||
_config = config;
|
||||
}
|
||||
@@ -37,8 +42,8 @@ namespace RebootKit.FPPKit {
|
||||
}
|
||||
|
||||
public async UniTask OnStart(CancellationToken cancellationToken) {
|
||||
RR.Service<InputService>().LockCursor();
|
||||
RR.Service<InputService>().EnableControls();
|
||||
_inputService.LockCursor();
|
||||
_inputService.EnableControls();
|
||||
|
||||
_sensitivityCVar = RR.CVarNumber("fpp_cam_look_sens", 0.25f);
|
||||
_movementSpeedCVar = RR.CVarNumber("p_move_speed", 4.0f);
|
||||
@@ -49,8 +54,8 @@ namespace RebootKit.FPPKit {
|
||||
}
|
||||
|
||||
public void OnStop() {
|
||||
RR.Service<InputService>().DisableControls();
|
||||
RR.Service<InputService>().UnlockCursor();
|
||||
_inputService.DisableControls();
|
||||
_inputService.UnlockCursor();
|
||||
Object.Destroy(_player);
|
||||
|
||||
RR.World().KillActor(_player);
|
||||
|
||||
20
Runtime/FPPKit/RebootKit.FPPKit.asmdef
Normal file
20
Runtime/FPPKit/RebootKit.FPPKit.asmdef
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "RebootKit.FPPKit",
|
||||
"rootNamespace": "RebootKit.FPPKit",
|
||||
"references": [
|
||||
"GUID:284059c7949783646b281a1b815580e6",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||
"GUID:4307f53044263cf4b835bd812fc161a4",
|
||||
"GUID:9e24947de15b9834991c9d8411ea37cf"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Runtime/FPPKit/RebootKit.FPPKit.asmdef.meta
Normal file
7
Runtime/FPPKit/RebootKit.FPPKit.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4d76b28af993d614f825cb34f438930f
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Tests.meta
Normal file
3
Tests.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac0e7d4df8ce40909e9802720077c57e
|
||||
timeCreated: 1742002062
|
||||
3
Tests/Runtime.meta
Normal file
3
Tests/Runtime.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38d2e5d9c5d2492fb523c373872899e0
|
||||
timeCreated: 1742002103
|
||||
8
Tests/Runtime/Engine.meta
Normal file
8
Tests/Runtime/Engine.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4abcb79b93f19b448aa8369c5894eabc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
78
Tests/Runtime/Engine/DIContextTests.cs
Normal file
78
Tests/Runtime/Engine/DIContextTests.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using NUnit.Framework;
|
||||
using NUnit.Framework.Interfaces;
|
||||
using NUnit.Framework.Internal;
|
||||
using RebootKit.Engine.Foundation;
|
||||
|
||||
namespace Tests.Runtime.Engine {
|
||||
internal interface ITestService {
|
||||
int Value();
|
||||
}
|
||||
|
||||
internal class TestServiceA : ITestService {
|
||||
public const int k_ReturnValue = 1;
|
||||
|
||||
public int Value() {
|
||||
return k_ReturnValue;
|
||||
}
|
||||
}
|
||||
|
||||
internal class TestServiceB : ITestService {
|
||||
public const int k_ReturnValue = 2;
|
||||
|
||||
public int Value() {
|
||||
return k_ReturnValue;
|
||||
}
|
||||
}
|
||||
|
||||
public class DIContextTests {
|
||||
[Test]
|
||||
public void Single_Bind_And_Resolve() {
|
||||
DIContext context = new();
|
||||
context.Bind<ITestService>(new TestServiceA());
|
||||
|
||||
ITestService testService = context.Resolve<ITestService>();
|
||||
Assert.IsNotNull(testService, "Resolved service is null!");
|
||||
|
||||
Assert.IsTrue(testService.Value() == TestServiceA.k_ReturnValue, "Invalid return value of resolved service");
|
||||
}
|
||||
|
||||
private class TestObject {
|
||||
[Inject]
|
||||
public ITestService Service;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Single_Bind_And_Field_Inject() {
|
||||
DIContext context = new();
|
||||
context.Bind<ITestService>(new TestServiceB());
|
||||
|
||||
TestObject obj = new();
|
||||
context.Inject(obj);
|
||||
|
||||
Assert.IsNotNull(obj.Service, "obj.Service != null");
|
||||
Assert.IsTrue(obj.Service.Value() == TestServiceB.k_ReturnValue);
|
||||
}
|
||||
|
||||
|
||||
private class TestObjectMethod {
|
||||
public ITestService Service;
|
||||
|
||||
[Inject]
|
||||
public void Setup(ITestService service) {
|
||||
Service = service;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Single_Bind_And_Method_Inject() {
|
||||
DIContext context = new();
|
||||
context.Bind<ITestService>(new TestServiceA());
|
||||
|
||||
TestObjectMethod obj = new();
|
||||
context.Inject(obj);
|
||||
|
||||
Assert.IsNotNull(obj.Service, "obj.Service != null");
|
||||
Assert.IsTrue(obj.Service.Value() == TestServiceA.k_ReturnValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Tests/Runtime/Engine/DIContextTests.cs.meta
Normal file
3
Tests/Runtime/Engine/DIContextTests.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb99eda81d534ddcb15cff09441d98bc
|
||||
timeCreated: 1742002479
|
||||
20
Tests/Runtime/Engine/RebootKit.Engine.Tests.asmdef
Normal file
20
Tests/Runtime/Engine/RebootKit.Engine.Tests.asmdef
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "RebootKit.Engine.Tests",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:284059c7949783646b281a1b815580e6",
|
||||
"GUID:0acc523941302664db1f4e527237feb3",
|
||||
"GUID:27619889b8ba8c24980f49ee34dbb44a"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Tests/Runtime/Engine/RebootKit.Engine.Tests.asmdef.meta
Normal file
7
Tests/Runtime/Engine/RebootKit.Engine.Tests.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 863a7983695eedb40a4fb34e2a16b5ba
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user