|
|
@@ -0,0 +1,238 @@ |
|
|
|
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<PlayerIDStruct>(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<PlayerIDStruct>(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<PlayerIDStruct>(PlayersExclusiveGroups.LocalPlayers).ToFastAccess(out uint count); |
|
|
|
for (int i = 0; i < count; i++) |
|
|
|
{ |
|
|
|
if (players[i].ID.entityID == playerId) |
|
|
|
{ |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
players = entitiesDB.QueryEntities<PlayerIDStruct>(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<RigidBodyEntityStruct>(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<RigidBodyEntityStruct>(egid)) |
|
|
|
{ |
|
|
|
ref RigidBodyEntityStruct rbes = ref entitiesDB.QueryEntity<RigidBodyEntityStruct>(egid); |
|
|
|
if (characterGroups[i] == CharacterExclusiveGroups.InPilotSeatGroup && exitSeat) |
|
|
|
{ |
|
|
|
entitiesDB.QueryEntity<CharacterPilotSeatEntityStruct>(egid).instantExit = true; |
|
|
|
entitiesDB.PublishEntityChange<CharacterPilotSeatEntityStruct>(egid); |
|
|
|
} |
|
|
|
rbes.position = location; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
public quaternion GetRotation(uint playerId) |
|
|
|
{ |
|
|
|
if (GetCharacterStruct<RigidBodyEntityStruct>(playerId, out RigidBodyEntityStruct rbes)) |
|
|
|
{ |
|
|
|
return rbes.rotation; |
|
|
|
} |
|
|
|
return quaternion.identity; |
|
|
|
} |
|
|
|
|
|
|
|
public bool SetRotation(uint playerId, quaternion value) |
|
|
|
{ |
|
|
|
if (GetCharacterStruct<RigidBodyEntityStruct>(playerId, out RigidBodyEntityStruct rbes)) |
|
|
|
{ |
|
|
|
rbes.rotation = value; |
|
|
|
return true; |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
public float3 GetLinearVelocity(uint playerId) |
|
|
|
{ |
|
|
|
if (GetCharacterStruct<RigidBodyEntityStruct>(playerId, out RigidBodyEntityStruct rbes)) |
|
|
|
{ |
|
|
|
return rbes.velocity; |
|
|
|
} |
|
|
|
return float3.zero; |
|
|
|
} |
|
|
|
|
|
|
|
public bool SetLinearVelocity(uint playerId, float3 value) |
|
|
|
{ |
|
|
|
if (GetCharacterStruct<RigidBodyEntityStruct>(playerId, out RigidBodyEntityStruct rbes)) |
|
|
|
{ |
|
|
|
rbes.velocity = value; |
|
|
|
return true; |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
public float3 GetAngularVelocity(uint playerId) |
|
|
|
{ |
|
|
|
if (GetCharacterStruct<RigidBodyEntityStruct>(playerId, out RigidBodyEntityStruct rbes)) |
|
|
|
{ |
|
|
|
return rbes.angularVelocity; |
|
|
|
} |
|
|
|
return float3.zero; |
|
|
|
} |
|
|
|
|
|
|
|
public bool SetAngularVelocity(uint playerId, float3 value) |
|
|
|
{ |
|
|
|
if (GetCharacterStruct<RigidBodyEntityStruct>(playerId, out RigidBodyEntityStruct rbes)) |
|
|
|
{ |
|
|
|
rbes.angularVelocity = value; |
|
|
|
return true; |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
public PhysicsMass GetMass(uint playerId) |
|
|
|
{ |
|
|
|
if (GetCharacterStruct<RigidBodyEntityStruct>(playerId, out RigidBodyEntityStruct rbes)) |
|
|
|
{ |
|
|
|
return rbes.physicsMass; |
|
|
|
} |
|
|
|
return default; |
|
|
|
} |
|
|
|
|
|
|
|
public bool SetInverseMass(uint playerId, float inverseMass) |
|
|
|
{ |
|
|
|
if (GetCharacterStruct<RigidBodyEntityStruct>(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<PlayerNetworkStatsEntityStruct>(egid)) |
|
|
|
{ |
|
|
|
return entitiesDB.QueryEntity<PlayerNetworkStatsEntityStruct>(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<T>(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<T>(egid)) |
|
|
|
{ |
|
|
|
s = entitiesDB.QueryEntity<T>(egid); |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
s = default; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
|
public bool GetPlayerStruct<T>(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<T>(egid)) |
|
|
|
{ |
|
|
|
s = entitiesDB.QueryEntity<T>(egid); |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
s = default; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |