Files
Nuake/NuakeNet/Source/Entity.cs
2025-01-31 18:04:43 -05:00

331 lines
9.8 KiB
C#

using Coral.Managed.Interop;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Nuake.Net
{
public struct CollisionData
{
Entity Entity1;
Entity Entity2;
Vector3 Normal;
Vector3 Position;
}
[StructLayout(LayoutKind.Sequential)]
public class Entity
{
internal static unsafe delegate*<int, int, bool> EntityHasComponentIcall;
internal static unsafe delegate*<int, int, void> EntityAddComponentIcall;
internal static unsafe delegate*<int, bool> EntityHasManagedInstanceIcall;
internal static unsafe delegate*<int, NativeString, int> EntityGetEntityIcall;
internal static unsafe delegate*<int, NativeString> EntityGetNameIcall;
internal static unsafe delegate*<int, NativeString, void> EntitySetNameIcall;
internal static unsafe delegate*<int, bool> EntityIsValidIcall;
internal static unsafe delegate*<NativeString, NativeArray<int>> EntityGetTargetsIcall;
internal static unsafe delegate*<int, NativeString> EntityGetTargetIcall;
public enum ComponentTypes
{
Unknown = -1,
PARENT = 0,
NAME,
PREFAB,
TRANSFORM,
LIGHT,
CAMERA,
AUDIO_EMITTER,
MODEL,
SKINNED_MODEL,
BONE,
RIGIDBODY,
BOX_COLLIDER,
SPHERE_COLLIDER,
CAPSULE_COLLIDER,
CYLINDER_COLLIDER,
MESH_COLLIDER,
CHARACTER_CONTROLLER,
PARTICLE_EMITTER,
QUAKE_MAP,
BSP_BRUSH,
SPRITE,
NAVMESH
}
public List<Entity> Targets
{
get
{
unsafe
{
var targetIds = EntityGetTargetsIcall(Target);
List<Entity> targets = new List<Entity>();
foreach(var target in targetIds)
{
bool hasInstance = EntityHasManagedInstanceIcall(target);
Entity entityInstance;
if (hasInstance)
{
entityInstance = Scene.GetEntity<Entity>(target);
}
else
{
entityInstance = new Entity(ECSHandle);
}
targets.Add(entityInstance);
}
return targets;
}
}
}
protected TransformComponent internalTransform;
public TransformComponent Transform
{
get
{
if(internalTransform == null)
{
internalTransform = GetComponent<TransformComponent>()!;
}
return internalTransform;
}
}
public string Target { get { unsafe { return EntityGetTargetIcall(ECSHandle); } }}
public int ID { get; set; }
public int ECSHandle { get; set; } = -1;
public string Name
{
get
{
unsafe
{
NativeString name = EntityGetNameIcall(ECSHandle);
return name;
}
}
set
{
if(String.IsNullOrEmpty(value))
{
Engine.Log("Invalid entity name: cannot be empty.");
return;
}
unsafe
{
EntitySetNameIcall(ECSHandle, value);
}
}
}
public Entity() { }
public Entity(int handle)
{
ECSHandle = handle;
}
public virtual void OnInit() { }
public virtual void OnUpdate(float dt) { }
public virtual void OnFixedUpdate(float dt) { }
public virtual void OnDestroy() { }
public virtual void OnCollision(Entity entity)
{
}
public virtual void Activate(Entity triggeredFrom)
{
}
// Physics
public void OnCollisionInternal(int entity)
{
Entity entityInstance;
unsafe
{
bool hasInstance = EntityHasManagedInstanceIcall(entity);
if (hasInstance)
{
entityInstance = Scene.GetEntity<Entity>(entity);
}
else
{
entityInstance = new Entity(ECSHandle);
}
}
OnCollision(entityInstance);
}
protected static Dictionary<Type, ComponentTypes> MappingTypeEnum = new Dictionary<Type, ComponentTypes>()
{
{ typeof(ParentComponent), ComponentTypes.PARENT },
{ typeof(NameComponent), ComponentTypes.NAME },
{ typeof(PrefabComponent), ComponentTypes.PREFAB },
{ typeof(TransformComponent), ComponentTypes.TRANSFORM},
{ typeof(LightComponent), ComponentTypes.LIGHT },
{ typeof(CameraComponent), ComponentTypes.CAMERA },
{ typeof(AudioEmitterComponent), ComponentTypes.AUDIO_EMITTER },
{ typeof(ModelComponent), ComponentTypes.MODEL },
{ typeof(SkinnedModelComponent), ComponentTypes.SKINNED_MODEL },
{ typeof(BoneComponent), ComponentTypes.BONE },
{ typeof(BoxCollider), ComponentTypes.BOX_COLLIDER },
{ typeof(SphereCollider), ComponentTypes.SPHERE_COLLIDER },
{ typeof(CapsuleColliderComponent), ComponentTypes.CAPSULE_COLLIDER },
{ typeof(CylinderColliderComponent), ComponentTypes.CYLINDER_COLLIDER },
{ typeof(MeshColliderComponent), ComponentTypes.MESH_COLLIDER },
{ typeof(CharacterControllerComponent), ComponentTypes.CHARACTER_CONTROLLER },
{ typeof(ParticleEmitterComponent), ComponentTypes.PARTICLE_EMITTER },
{ typeof(QuakeMapComponent), ComponentTypes.QUAKE_MAP },
{ typeof(BSPBrushComponent), ComponentTypes.BSP_BRUSH },
{ typeof(SpriteComponent), ComponentTypes.SPRITE },
{ typeof(NavMeshVolumeComponent), ComponentTypes.NAVMESH }
};
public bool HasComponent<T>()
{
if (MappingTypeEnum.ContainsKey(typeof(T)))
{
unsafe { return EntityHasComponentIcall(ECSHandle, (int)MappingTypeEnum[typeof(T)]); };
}
return false;
}
public T? AddComponent<T>() where T : IComponent
{
if(HasComponent<T>())
{
return (T?)Activator.CreateInstance(typeof(T), ECSHandle);
}
unsafe
{
EntityAddComponentIcall(ECSHandle, (int)MappingTypeEnum[typeof(T)]);
return (T?)Activator.CreateInstance(typeof(T), ECSHandle);
};
}
public T? GetComponent<T>() where T : IComponent
{
if (HasComponent<T>())
{
return (T?)Activator.CreateInstance(typeof(T), ECSHandle);
}
throw new Exception("Component not found: " + typeof(T).GetType().Name);
}
public T? GetEntity<T>(string path) where T : Entity
{
Entity entityInstance;
unsafe
{
int entityHandle = EntityGetEntityIcall(ECSHandle, path );
bool hasInstance = EntityHasManagedInstanceIcall(entityHandle);
if (hasInstance)
{
entityInstance = Scene.GetEntity<Entity>(entityHandle);
}
else
{
entityInstance = new Entity(entityHandle);
}
}
return entityInstance as T;
}
public static implicit operator bool(Entity entity)
{
if (object.ReferenceEquals(entity, null))
{
return false;
}
bool isValid;
unsafe
{
isValid = EntityIsValidIcall(entity.ECSHandle);
}
return isValid;
}
}
public class Prefab
{
internal static unsafe delegate*<NativeString, Vector3, float, float, float, float, int> PrefabInstanceIcall;
string Path { get; set; }
public Prefab()
{
}
public Prefab(string path)
{
Path = path;
Engine.Log("Prefab instance created with path: " + path);
}
public Entity? Instance(Vector3 position = default, Quaternion quat = default)
{
int handle;
unsafe { handle = PrefabInstanceIcall(Path, position, quat.X, quat.Y, quat.Z, quat.W); }
if (handle == -1)
{
return null;
}
Entity entity = new Entity(handle);
return entity;
}
public T? Instance<T>(Vector3 position = default, Quaternion quat = default) where T : Entity
{
int handle;
unsafe { handle = PrefabInstanceIcall(Path, position, quat.X, quat.Y, quat.Z, quat.W); }
if (handle == -1)
{
return null;
}
T? instance = Scene.GetEntity<T>(handle);
instance.OnInit();
return instance;
}
public static implicit operator bool(Prefab prefab)
{
if (object.ReferenceEquals(prefab, null))
{
return false;
}
return prefab.Path != string.Empty;
}
}
}