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* EntityHasComponentIcall; internal static unsafe delegate* EntityAddComponentIcall; internal static unsafe delegate* EntityHasManagedInstanceIcall; internal static unsafe delegate* EntityGetEntityIcall; internal static unsafe delegate* EntityGetNameIcall; internal static unsafe delegate* EntitySetNameIcall; internal static unsafe delegate* EntityIsValidIcall; internal static unsafe delegate*> EntityGetTargetsIcall; internal static unsafe delegate* 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 Targets { get { unsafe { var targetIds = EntityGetTargetsIcall(Target); List targets = new List(); foreach(var target in targetIds) { bool hasInstance = EntityHasManagedInstanceIcall(target); Entity entityInstance; if (hasInstance) { entityInstance = Scene.GetEntity(target); } else { entityInstance = new Entity(ECSHandle); } targets.Add(entityInstance); } return targets; } } } protected TransformComponent internalTransform; public TransformComponent Transform { get { if(internalTransform == null) { internalTransform = GetComponent()!; } 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); } else { entityInstance = new Entity(ECSHandle); } } OnCollision(entityInstance); } protected static Dictionary MappingTypeEnum = new Dictionary() { { 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() { if (MappingTypeEnum.ContainsKey(typeof(T))) { unsafe { return EntityHasComponentIcall(ECSHandle, (int)MappingTypeEnum[typeof(T)]); }; } return false; } public T? AddComponent() where T : IComponent { if(HasComponent()) { return (T?)Activator.CreateInstance(typeof(T), ECSHandle); } unsafe { EntityAddComponentIcall(ECSHandle, (int)MappingTypeEnum[typeof(T)]); return (T?)Activator.CreateInstance(typeof(T), ECSHandle); }; } public T? GetComponent() where T : IComponent { if (HasComponent()) { return (T?)Activator.CreateInstance(typeof(T), ECSHandle); } throw new Exception("Component not found: " + typeof(T).GetType().Name); } public T? GetEntity(string path) where T : Entity { Entity entityInstance; unsafe { int entityHandle = EntityGetEntityIcall(ECSHandle, path ); bool hasInstance = EntityHasManagedInstanceIcall(entityHandle); if (hasInstance) { entityInstance = Scene.GetEntity(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* 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(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(handle); instance.OnInit(); return instance; } public static implicit operator bool(Prefab prefab) { if (object.ReferenceEquals(prefab, null)) { return false; } return prefab.Path != string.Empty; } } }