using System; using System.Runtime.CompilerServices; using RobocraftX.Character; using RobocraftX.Character.Movement; using RobocraftX.Common.Players; using RobocraftX.Common.Input; using RobocraftX.Physics; using Svelto.ECS; using Unity.Mathematics; using Unity.Physics; using GamecraftModdingAPI.Engines; namespace GamecraftModdingAPI.Players { internal class PlayerEngine : IApiEngine { public string Name { get; } = "GamecraftModdingAPIPlayerGameEngine"; public EntitiesDB entitiesDB { set; private get; } public bool isRemovable => false; private bool isReady = false; public void Dispose() { isReady = false; } public void Ready() { isReady = true; } public uint GetLocalPlayer() { if (!isReady) return uint.MaxValue; PlayerIDStruct[] localPlayers = entitiesDB.QueryEntities(PlayersExclusiveGroups.LocalPlayers).ToFastAccess(out uint count); if (count > 0) { return localPlayers[0].ID.entityID; } return uint.MaxValue; } public uint GetRemotePlayer() { if (!isReady) return uint.MaxValue; PlayerIDStruct[] localPlayers = entitiesDB.QueryEntities(PlayersExclusiveGroups.RemotePlayers).ToFastAccess(out uint count); if (count > 0) { return localPlayers[0].ID.entityID; } return uint.MaxValue; } public bool ExistsById(uint playerId) { PlayerIDStruct[] players = entitiesDB.QueryEntities(PlayersExclusiveGroups.LocalPlayers).ToFastAccess(out uint count); for (int i = 0; i < count; i++) { if (players[i].ID.entityID == playerId) { return true; } } players = entitiesDB.QueryEntities(PlayersExclusiveGroups.RemotePlayers).ToFastAccess(out count); for (int i = 0; i < count; i++) { if (players[i].ID.entityID == playerId) { return true; } } return false; } public float3 GetLocation(uint playerId) { if (GetCharacterStruct(playerId, out RigidBodyEntityStruct rbes)) { return rbes.position; } return float3.zero; } public bool SetLocation(uint playerId, float3 location, bool exitSeat = true) { ExclusiveGroup[] characterGroups = CharacterExclusiveGroups.AllCharacters; for (int i = 0; i < characterGroups.Length; i++) { EGID egid = new EGID(playerId, characterGroups[i]); if (entitiesDB.Exists(egid)) { ref RigidBodyEntityStruct rbes = ref entitiesDB.QueryEntity(egid); if (characterGroups[i] == CharacterExclusiveGroups.InPilotSeatGroup && exitSeat) { entitiesDB.QueryEntity(egid).instantExit = true; entitiesDB.PublishEntityChange(egid); } rbes.position = location; return true; } } return false; } public quaternion GetRotation(uint playerId) { if (GetCharacterStruct(playerId, out RigidBodyEntityStruct rbes)) { return rbes.rotation; } return quaternion.identity; } public bool SetRotation(uint playerId, quaternion value) { if (GetCharacterStruct(playerId, out RigidBodyEntityStruct rbes)) { rbes.rotation = value; return true; } return false; } public float3 GetLinearVelocity(uint playerId) { if (GetCharacterStruct(playerId, out RigidBodyEntityStruct rbes)) { return rbes.velocity; } return float3.zero; } public bool SetLinearVelocity(uint playerId, float3 value) { if (GetCharacterStruct(playerId, out RigidBodyEntityStruct rbes)) { rbes.velocity = value; return true; } return false; } public float3 GetAngularVelocity(uint playerId) { if (GetCharacterStruct(playerId, out RigidBodyEntityStruct rbes)) { return rbes.angularVelocity; } return float3.zero; } public bool SetAngularVelocity(uint playerId, float3 value) { if (GetCharacterStruct(playerId, out RigidBodyEntityStruct rbes)) { rbes.angularVelocity = value; return true; } return false; } public PhysicsMass GetMass(uint playerId) { if (GetCharacterStruct(playerId, out RigidBodyEntityStruct rbes)) { return rbes.physicsMass; } return default; } public bool SetInverseMass(uint playerId, float inverseMass) { if (GetCharacterStruct(playerId, out RigidBodyEntityStruct rbes)) { rbes.physicsMass.InverseInertia = inverseMass; return true; } return false; } public float? GetLastPingTime(uint playerId, PlayerType type) { EGID egid = new EGID(playerId, GroupFromEnum(type)); if (entitiesDB.Exists(egid)) { return entitiesDB.QueryEntity(egid).lastPingTimeSinceLevelLoad; } return null; } // reusable methods [MethodImpl(MethodImplOptions.AggressiveInlining)] private ExclusiveGroup GroupFromEnum(PlayerType type) { return type == PlayerType.Local ? PlayersExclusiveGroups.LocalPlayers : PlayersExclusiveGroups.RemotePlayers; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool GetCharacterStruct(uint playerId, out T s) where T : unmanaged, IEntityComponent { ExclusiveGroup[] characterGroups = CharacterExclusiveGroups.AllCharacters; for (int i = 0; i < characterGroups.Length; i++) { EGID egid = new EGID(playerId, characterGroups[i]); if (entitiesDB.Exists(egid)) { s = entitiesDB.QueryEntity(egid); return true; } } s = default; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool GetPlayerStruct(uint playerId, out T s) where T : unmanaged, IEntityComponent { ExclusiveGroup[] playerGroups = PlayersExclusiveGroups.AllPlayers; for (int i = 0; i < playerGroups.Length; i++) { EGID egid = new EGID(playerId, playerGroups[i]); if (entitiesDB.Exists(egid)) { s = entitiesDB.QueryEntity(egid); return true; } } s = default; return false; } } }