Integrate FlyCam class into Player

Using QueryEntityOptional directly with the player properties
Character structs are camera structs in build mode
The FlyCam rotation is not updated in build mode, only the camera is
This commit is contained in:
Norbi Peti 2021-05-28 02:12:54 +02:00
parent 220eb02a19
commit 5bfd0b7f10
8 changed files with 163 additions and 566 deletions

View file

@ -1,132 +0,0 @@
using RobocraftX.Physics;
using Svelto.ECS;
using Svelto.ECS.EntityStructs;
using Techblox.FlyCam;
using TechbloxModdingAPI.Blocks;
using TechbloxModdingAPI.Players;
using TechbloxModdingAPI.Utility;
using Unity.Mathematics;
using UnityEngine;
namespace TechbloxModdingAPI
{
public class FlyCam : EcsObjectBase
{
private static FlyCamEngine Engine = new FlyCamEngine();
public override EGID Id { get; }
public FlyCam(uint id) => Id = new EGID(id, Techblox.FlyCam.FlyCam.Group);
/// <summary>
/// The local player's camera.
/// </summary>
public static FlyCam LocalCamera => new FlyCam(Player.LocalPlayer.Id);
/// <summary>
/// The current position of the camera.
/// </summary>
public float3 Position
{
get => Engine.GetComponent<PositionEntityStruct>(this).position;
set
{
Engine.GetComponent<PositionEntityStruct>(this).position = value;
Engine.GetComponent<RigidBodyEntityStruct>(this).position = value;
}
}
/// <summary>
/// The current rotation of the camera.
/// </summary>
public float3 Rotation
{
get => ((Quaternion) Engine.GetComponent<RotationEntityStruct>(this).rotation).eulerAngles;
set
{
Engine.GetComponent<RotationEntityStruct>(this).rotation = Quaternion.Euler(value);
Engine.GetComponent<RigidBodyEntityStruct>(this).rotation = Quaternion.Euler(value);
}
}
/// <summary>
/// The current direction the camera is moving.
/// </summary>
public float3 MovementDirection
{
get => Engine.GetComponent<FlyCamMovementComponent>(this).movementDirection;
set => Engine.GetComponent<FlyCamMovementComponent>(this).movementDirection = value;
}
/// <summary>
/// Whether the camera (player) is sprinting.
/// </summary>
public bool Sprinting
{
get => Engine.GetComponent<FlyCamMovementComponent>(this).sprinting;
set => Engine.GetComponent<FlyCamMovementComponent>(this).sprinting = value;
}
/// <summary>
/// The speed setting of the camera.
/// </summary>
public float Speed
{
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speed;
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speed = value;
}
/// <summary>
/// The multiplier setting to use when sprinting.
/// </summary>
public float SpeedSprintMultiplier
{
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speedSprintMultiplier;
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).speedSprintMultiplier = value;
}
/// <summary>
/// The acceleration setting of the camera.
/// </summary>
public float Acceleration
{
get => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).acceleration;
set => Engine.GetComponent<FlyCamMovementSettingsComponent>(this).acceleration = value;
}
/// <summary>
/// The current velocity of the camera.
/// </summary>
public float3 Velocity
{
get => Engine.GetComponent<RigidBodyEntityStruct>(this).velocity;
set => Engine.GetComponent<RigidBodyEntityStruct>(this).velocity = value;
}
/// <summary>
/// The current angular velocity of the camera.
/// </summary>
public float3 AngularVelocity
{
get => Engine.GetComponent<RigidBodyEntityStruct>(this).angularVelocity;
set => Engine.GetComponent<RigidBodyEntityStruct>(this).angularVelocity = value;
}
/// <summary>
/// The player's selected block ID in their hand.
/// </summary>
/// <value>The selected block.</value>
public BlockIDs SelectedBlock => (BlockIDs)Engine.GetSelectedBlock(this);
/// <summary>
/// The player's selected block color in their hand.
/// </summary>
/// <value>The selected block's color.</value>
public BlockColor SelectedColor => new BlockColor(Engine.GetSelectedColor(this));
public static void Init()
{
GameEngineManager.AddGameEngine(Engine);
}
}
}

View file

@ -71,7 +71,6 @@ namespace TechbloxModdingAPI
Input.FakeInput.Init(); Input.FakeInput.Init();
// init object-oriented classes // init object-oriented classes
Player.Init(); Player.Init();
FlyCam.Init();
Block.Init(); Block.Init();
BlockGroup.Init(); BlockGroup.Init();
Wire.Init(); Wire.Init();

View file

@ -0,0 +1,51 @@
using RobocraftX.Physics;
using Svelto.ECS;
using Svelto.ECS.EntityStructs;
using Techblox.FlyCam;
using TechbloxModdingAPI.Blocks;
using TechbloxModdingAPI.Players;
using TechbloxModdingAPI.Utility;
using Unity.Mathematics;
using UnityEngine;
namespace TechbloxModdingAPI
{
public partial class Player
{
/// <summary>
/// Whether the camera (player) is sprinting.
/// </summary>
public bool Sprinting
{
get => playerEngine.GetCharacterStruct<FlyCamMovementComponent>(Id).Get().sprinting;
set => playerEngine.GetCharacterStruct<FlyCamMovementComponent>(Id).Get().sprinting = value;
}
/// <summary>
/// The speed setting of the camera.
/// </summary>
public float Speed
{
get => playerEngine.GetCharacterStruct<FlyCamMovementSettingsComponent>(Id).Get().speed;
set => playerEngine.GetCharacterStruct<FlyCamMovementSettingsComponent>(Id).Get().speed = value;
}
/// <summary>
/// The multiplier setting to use when sprinting.
/// </summary>
public float SpeedSprintMultiplier
{
get => playerEngine.GetCharacterStruct<FlyCamMovementSettingsComponent>(Id).Get().speedSprintMultiplier;
set => playerEngine.GetCharacterStruct<FlyCamMovementSettingsComponent>(Id).Get().speedSprintMultiplier = value;
}
/// <summary>
/// The acceleration setting of the camera.
/// </summary>
public float Acceleration
{
get => playerEngine.GetCharacterStruct<FlyCamMovementSettingsComponent>(Id).Get().acceleration;
set => playerEngine.GetCharacterStruct<FlyCamMovementSettingsComponent>(Id).Get().acceleration = value;
}
}
}

View file

@ -1,17 +1,23 @@
using System; using System;
using RobocraftX.Character;
using Unity.Mathematics; using Unity.Mathematics;
using RobocraftX.Common; using RobocraftX.Common;
using RobocraftX.Common.Players; using RobocraftX.Common.Players;
using RobocraftX.Physics;
using Svelto.ECS; using Svelto.ECS;
using Techblox.Camera;
using Techblox.FlyCam;
using TechbloxModdingAPI.Blocks; using TechbloxModdingAPI.Blocks;
using TechbloxModdingAPI.Players; using TechbloxModdingAPI.Players;
using TechbloxModdingAPI.Utility;
using UnityEngine;
namespace TechbloxModdingAPI namespace TechbloxModdingAPI
{ {
/// <summary> /// <summary>
/// An in-game player character. Any Leo you see is a player. /// An in-game player character. Any Leo you see is a player.
/// </summary> /// </summary>
public class Player : IEquatable<Player>, IEquatable<EGID> public partial class Player : IEquatable<Player>, IEquatable<EGID>
{ {
// static functionality // static functionality
private static PlayerEngine playerEngine = new PlayerEngine(); private static PlayerEngine playerEngine = new PlayerEngine();
@ -123,50 +129,33 @@ namespace TechbloxModdingAPI
/// <value>The position.</value> /// <value>The position.</value>
public float3 Position public float3 Position
{ {
get get => playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().position;
{ set => playerEngine.SetLocation(Id, value, false);
return playerEngine.GetLocation(Id); }
}
set
{
playerEngine.SetLocation(Id, value, false);
}
}
/// <summary> /// <summary>
/// The player's current rotation. /// The player's current rotation.
/// </summary> /// </summary>
/// <value>The rotation.</value> /// <value>The rotation.</value>
public float3 Rotation public float3 Rotation
{ {
get get => ((Quaternion) (GameState.IsBuildMode()
{ ? playerEngine.GetCameraStruct<CharacterCameraEntityStruct>(Id).Get().rotation
return playerEngine.GetRotation(Id); : playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().rotation)).eulerAngles;
} set => _ = GameState.IsBuildMode()
? playerEngine.GetCameraStruct<CharacterCameraEntityStruct>(Id).Get().rotation = quaternion.Euler(value)
set : playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().rotation = quaternion.Euler(value);
{ }
playerEngine.SetRotation(Id, value);
}
}
/// <summary> /// <summary>
/// The player's current velocity. /// The player's current velocity.
/// </summary> /// </summary>
/// <value>The velocity.</value> /// <value>The velocity.</value>
public float3 Velocity public float3 Velocity
{ {
get get => playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().velocity;
{ set => playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().velocity = value;
return playerEngine.GetLinearVelocity(Id); }
}
set
{
playerEngine.SetLinearVelocity(Id, value);
}
}
/// <summary> /// <summary>
/// The player's current angular velocity. /// The player's current angular velocity.
@ -174,36 +163,18 @@ namespace TechbloxModdingAPI
/// <value>The angular velocity.</value> /// <value>The angular velocity.</value>
public float3 AngularVelocity public float3 AngularVelocity
{ {
get get => playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().angularVelocity;
{ set => playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().angularVelocity = value;
return playerEngine.GetAngularVelocity(Id);
}
set
{
playerEngine.SetAngularVelocity(Id, value);
}
} }
/// <summary> /// <summary>
/// The player's mass. /// The player's mass.
/// </summary> /// </summary>
/// <value>The mass.</value> /// <value>The mass.</value>
public float Mass public float Mass =>
{ 1f / playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().physicsMass.InverseMass;
get
{
return 1f / playerEngine.GetMass(Id).InverseMass;
}
// FIXME: Setting mass doesn't do anything private float _ping = -1f;
/*set
{
playerEngine.SetInverseMass(Id, 1f / value);
}*/
}
private float _ping = -1f;
/// <summary> /// <summary>
/// The player's latest network ping time. /// The player's latest network ping time.
@ -213,10 +184,10 @@ namespace TechbloxModdingAPI
{ {
get get
{ {
float? temp = playerEngine.GetLastPingTime(Id, Type); var opt = playerEngine.GetPlayerStruct<PlayerNetworkStatsEntityStruct>(Id, Type);
if (temp.HasValue) if (opt)
{ {
_ping = temp.Value; _ping = opt.Get().lastPingTimeSinceLevelLoad ?? _ping;
} }
return _ping; return _ping;
} }
@ -227,14 +198,15 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
/// <value>The initial health.</value> /// <value>The initial health.</value>
public float InitialHealth public float InitialHealth
{ {
get => playerEngine.GetInitialHealth(Id); get
{
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id);
return opt ? opt.Get().initialHealth : -1f;
}
set set => playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id).Get().initialHealth = value;
{ }
playerEngine.SetInitialHealth(Id, value);
}
}
/// <summary> /// <summary>
/// The player's current health in Simulation (aka Time Running) mode. /// The player's current health in Simulation (aka Time Running) mode.
@ -242,12 +214,13 @@ namespace TechbloxModdingAPI
/// <value>The current health.</value> /// <value>The current health.</value>
public float CurrentHealth public float CurrentHealth
{ {
get => playerEngine.GetCurrentHealth(Id); get
{
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id);
return opt ? opt.Get().currentHealth : -1f;
}
set set => playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id).Get().currentHealth = value;
{
playerEngine.DamagePlayer(Id, CurrentHealth - value);
}
} }
/// <summary> /// <summary>
@ -255,14 +228,20 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
/// <value><c>true</c> if damageable; otherwise, <c>false</c>.</value> /// <value><c>true</c> if damageable; otherwise, <c>false</c>.</value>
public bool Damageable public bool Damageable
{ {
get => playerEngine.GetDamageable(Id); get
{
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id);
return opt.Get().canTakeDamageStat;
}
set set
{ {
playerEngine.SetDamageable(Id, value); ref var healthStruct = ref playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id).Get();
} healthStruct.canTakeDamage = value;
} healthStruct.canTakeDamageStat = value;
}
}
/// <summary> /// <summary>
/// The player's lives when initially entering Simulation (aka Time Running) mode. /// The player's lives when initially entering Simulation (aka Time Running) mode.
@ -270,9 +249,13 @@ namespace TechbloxModdingAPI
/// <value>The initial lives.</value> /// <value>The initial lives.</value>
public uint InitialLives public uint InitialLives
{ {
get => playerEngine.GetInitialLives(Id); get
{
var opt = playerEngine.GetCharacterStruct<CharacterLivesEntityComponent>(Id);
return opt ? opt.Get().initialLives : uint.MaxValue;
}
set => playerEngine.SetInitialLives(Id, value); set => playerEngine.GetCharacterStruct<CharacterLivesEntityComponent>(Id).Get().initialLives = value;
} }
/// <summary> /// <summary>
@ -281,19 +264,23 @@ namespace TechbloxModdingAPI
/// <value>The current lives.</value> /// <value>The current lives.</value>
public uint CurrentLives public uint CurrentLives
{ {
get => playerEngine.GetCurrentLives(Id); get
{
var opt = playerEngine.GetCharacterStruct<CharacterLivesEntityComponent>(Id);
return opt ? opt.Get().currentLives : uint.MaxValue;
}
set => playerEngine.SetCurrentLives(Id, value); set => playerEngine.GetCharacterStruct<CharacterLivesEntityComponent>(Id).Get().currentLives = value;
} }
/// <summary> /*/// <summary>
/// Whether the Game Over screen is displayed for the player. /// Whether the Game Over screen is displayed for the player.
/// </summary> /// </summary>
/// <value><c>true</c> if game over; otherwise, <c>false</c>.</value> /// <value><c>true</c> if game over; otherwise, <c>false</c>.</value>
public bool GameOver public bool GameOver
{ {
get => playerEngine.GetGameOverScreen(Id); get => playerEngine.GetGameOverScreen(Id);
} }*/
/// <summary> /// <summary>
/// Whether the player is dead. /// Whether the player is dead.
@ -313,7 +300,8 @@ namespace TechbloxModdingAPI
{ {
get get
{ {
return BuildCamera.SelectedBlock; var optstruct = playerEngine.GetCharacterStruct<EquippedPartStruct>(Id);
return optstruct ? (BlockIDs) optstruct.Get().SelectedDBPartID : BlockIDs.Invalid;
} }
} }
@ -325,7 +313,8 @@ namespace TechbloxModdingAPI
{ {
get get
{ {
return BuildCamera.SelectedColor; var optstruct = playerEngine.GetCharacterStruct<EquippedColourStruct>(Id);
return optstruct ? new BlockColor(optstruct.Get().indexInPalette) : BlockColors.Default;
} }
} }
@ -337,7 +326,8 @@ namespace TechbloxModdingAPI
{ {
get get
{ {
return new BlockColor(playerEngine.GetSelectedColor(Id)); var optstruct = playerEngine.GetCharacterStruct<EquippedColourStruct>(Id);
return optstruct ? new BlockColor(optstruct.Get().indexInPalette) : BlockColors.Default;
} }
} }
@ -346,9 +336,11 @@ namespace TechbloxModdingAPI
/// </summary> /// </summary>
public Blueprint SelectedBlueprint public Blueprint SelectedBlueprint
{ {
get => playerEngine.GetPlayerStruct(Id, out LocalBlueprintInputStruct lbis) get
? new Blueprint(lbis.selectedBlueprintId) {
: null; var lbiso = playerEngine.GetPlayerStruct<LocalBlueprintInputStruct>(Id, Type);
return lbiso ? new Blueprint(lbiso.Get().selectedBlueprintId) : null;
}
set => BlockGroup._engine.SelectBlueprint(value?.Id ?? uint.MaxValue); set => BlockGroup._engine.SelectBlueprint(value?.Id ?? uint.MaxValue);
} }
@ -356,7 +348,7 @@ namespace TechbloxModdingAPI
/// The player's mode in time stopped mode, determining what they place. /// The player's mode in time stopped mode, determining what they place.
/// </summary> /// </summary>
public PlayerBuildingMode BuildingMode => (PlayerBuildingMode) playerEngine public PlayerBuildingMode BuildingMode => (PlayerBuildingMode) playerEngine
.GetCharacterStruct<PlayerInputTimeStoppedContextStruct>(Id, out _).timeStoppedContext; .GetCharacterStruct<PlayerInputTimeStoppedContextStruct>(Id).Get().timeStoppedContext;
// object methods // object methods
@ -373,7 +365,7 @@ namespace TechbloxModdingAPI
float3 location = new float3(x, y, z); float3 location = new float3(x, y, z);
if (relative) if (relative)
{ {
location += playerEngine.GetLocation(Id); location += Position;
} }
playerEngine.SetLocation(Id, location, exitSeat: exitSeat); playerEngine.SetLocation(Id, location, exitSeat: exitSeat);
} }
@ -395,7 +387,7 @@ namespace TechbloxModdingAPI
/// Returns the rigid body the player is currently looking at during simulation. /// Returns the rigid body the player is currently looking at during simulation.
/// </summary> /// </summary>
/// <param name="maxDistance">The maximum distance from the player (default is the player's building reach)</param> /// <param name="maxDistance">The maximum distance from the player (default is the player's building reach)</param>
/// <returns>The block or null if not found</returns> /// <returns>The body or null if not found</returns>
public SimBody GetSimBodyLookedAt(float maxDistance = -1f) public SimBody GetSimBodyLookedAt(float maxDistance = -1f)
{ {
var egid = playerEngine.GetThingLookedAt(Id, maxDistance); var egid = playerEngine.GetThingLookedAt(Id, maxDistance);
@ -413,11 +405,6 @@ namespace TechbloxModdingAPI
return playerEngine.GetSelectedBlocks(Id); return playerEngine.GetSelectedBlocks(Id);
} }
/// <summary>
/// The camera of this player used when building.
/// </summary>
public FlyCam BuildCamera => new FlyCam(Id);
public bool Equals(Player other) public bool Equals(Player other)
{ {
if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(null, other)) return false;

View file

@ -1,39 +0,0 @@
using Svelto.ECS;
using Techblox.FlyCam;
using TechbloxModdingAPI.Engines;
using TechbloxModdingAPI.Utility;
namespace TechbloxModdingAPI.Players
{
public class FlyCamEngine : IApiEngine
{
public void Ready()
{
}
public EntitiesDB entitiesDB { get; set; }
public void Dispose()
{
}
public string Name => "TechbloxModdingAPIFlyCamEngine";
public bool isRemovable => false;
public ref T GetComponent<T>(FlyCam cam) where T : unmanaged, IEntityComponent
{
return ref entitiesDB.QueryEntityOrDefault<T>(cam);
}
public ushort GetSelectedBlock(FlyCam cam)
{
var oc = entitiesDB.QueryEntityOptional<EquippedPartStruct>(cam);
return oc ? (ushort) oc.Get().SelectedDBPartID : ushort.MaxValue;
}
public byte GetSelectedColor(FlyCam cam)
{
var oc = entitiesDB.QueryEntityOptional<EquippedColourStruct>(cam);
return oc ? oc.Get().indexInPalette : (byte) 255;
}
}
}

View file

@ -5,6 +5,7 @@
BlockMode, BlockMode,
ColourMode, ColourMode,
ConfigMode, ConfigMode,
BlueprintMode BlueprintMode,
MaterialMode
} }
} }

View file

@ -21,6 +21,7 @@ using HarmonyLib;
using RobocraftX.Common; using RobocraftX.Common;
using Svelto.ECS.DataStructures; using Svelto.ECS.DataStructures;
using TechbloxModdingAPI.Engines; using TechbloxModdingAPI.Engines;
using TechbloxModdingAPI.Utility;
namespace TechbloxModdingAPI.Players namespace TechbloxModdingAPI.Players
{ {
@ -98,17 +99,6 @@ namespace TechbloxModdingAPI.Players
|| entitiesDB.Exists<PlayerIDStruct>(playerId, PlayersExclusiveGroups.RemotePlayers); || entitiesDB.Exists<PlayerIDStruct>(playerId, PlayersExclusiveGroups.RemotePlayers);
} }
public float3 GetLocation(uint playerId)
{
if (entitiesDB == null) return float3.zero;
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
if (exists)
{
return rbes.position;
}
return float3.zero;
}
public bool SetLocation(uint playerId, float3 location, bool exitSeat = true) public bool SetLocation(uint playerId, float3 location, bool exitSeat = true)
{ {
if (entitiesDB == null) return false; if (entitiesDB == null) return false;
@ -131,233 +121,6 @@ namespace TechbloxModdingAPI.Players
return false; return false;
} }
public float3 GetRotation(uint playerId)
{
if (entitiesDB == null) return float3.zero;
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
if (exists)
{
return ((Quaternion) rbes.rotation).eulerAngles;
}
return default(float3);
}
public bool SetRotation(uint playerId, float3 value)
{
if (entitiesDB == null) return false;
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
if (exists)
{
Quaternion q = rbes.rotation;
q.eulerAngles = value;
rbes.rotation = q;
return true;
}
return false;
}
public float3 GetLinearVelocity(uint playerId)
{
if (entitiesDB == null) return float3.zero;
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
if (exists)
{
return rbes.velocity;
}
return float3.zero;
}
public bool SetLinearVelocity(uint playerId, float3 value)
{
if (entitiesDB == null) return false;
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
if (exists)
{
rbes.velocity = value;
return true;
}
return false;
}
public float3 GetAngularVelocity(uint playerId)
{
if (entitiesDB == null) return float3.zero;
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
if (exists)
{
return rbes.angularVelocity;
}
return float3.zero;
}
public bool SetAngularVelocity(uint playerId, float3 value)
{
if (entitiesDB == null) return false;
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
if (exists)
{
rbes.angularVelocity = value;
return true;
}
return false;
}
public PhysicsMass GetMass(uint playerId)
{
if (entitiesDB == null) return default(PhysicsMass);
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
if (exists)
{
return rbes.physicsMass;
}
return default(PhysicsMass);
}
public bool SetInverseMass(uint playerId, float inverseMass)
{
if (entitiesDB == null) return false;
ref var rbes = ref GetCharacterStruct<RigidBodyEntityStruct>(playerId, out bool exists);
if (exists)
{
rbes.physicsMass.InverseInertia = inverseMass;
return true;
}
return false;
}
public float? GetLastPingTime(uint playerId, PlayerType type)
{
if (entitiesDB == null) return null;
EGID egid = new EGID(playerId, PlayerGroupFromEnum(type));
if (entitiesDB.Exists<PlayerNetworkStatsEntityStruct>(egid))
{
//return entitiesDB.QueryEntity<PlayerNetworkStatsEntityStruct>(egid).lastPingTimeSinceLevelLoad; - TODO
}
return null;
}
public float GetInitialHealth(uint playerId)
{
if (entitiesDB == null) return 0;
ref var c = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
if (exists)
{
return c.initialHealth;
}
return -1f;
}
public bool SetInitialHealth(uint playerId, float val)
{
if (entitiesDB == null) return false;
ref var c = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
if (exists)
{
c.initialHealth = val;
return true;
}
return false;
}
public float GetCurrentHealth(uint playerId)
{
if (entitiesDB == null) return 0;
ref var c = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
if (exists)
{
return c.currentHealth;
}
return -1f;
}
public bool SetCurrentHealth(uint playerId, float val)
{
if (entitiesDB == null) return false;
ref var c = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
if (exists)
{
c.currentHealth = val;
return true;
}
return false;
}
public bool DamagePlayer(uint playerId, float amount)
{
if (entitiesDB == null) return false;
return SetCurrentHealth(playerId, GetCurrentHealth(playerId) - amount);
}
public bool GetDamageable(uint playerId)
{
if (entitiesDB == null) return false;
ref var c = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
if (exists)
{
return c.canTakeDamageStat;
}
return false;
}
public bool SetDamageable(uint playerId, bool val)
{
if (entitiesDB == null) return false;
ref var ches = ref GetCharacterStruct<CharacterHealthEntityStruct>(playerId, out bool exists);
if (exists)
{
ches.canTakeDamage = val;
ches.canTakeDamage = val;
return true;
}
return false;
}
public uint GetInitialLives(uint playerId)
{
if (entitiesDB == null) return 0;
ref var c = ref GetCharacterStruct<CharacterLivesEntityComponent>(playerId, out bool exists);
if (exists)
{
return c.initialLives;
}
return uint.MaxValue;
}
public bool SetInitialLives(uint playerId, uint val)
{
if (entitiesDB == null) return false;
ref var c = ref GetCharacterStruct<CharacterLivesEntityComponent>(playerId, out bool exists);
if (exists)
{
c.initialLives = val;
return true;
}
return false;
}
public uint GetCurrentLives(uint playerId)
{
if (entitiesDB == null) return 0;
ref var c = ref GetCharacterStruct<CharacterLivesEntityComponent>(playerId, out bool exists);
if (exists)
{
return c.currentLives;
}
return uint.MaxValue;
}
public bool SetCurrentLives(uint playerId, uint val)
{
if (entitiesDB == null) return false;
ref var c = ref GetCharacterStruct<CharacterLivesEntityComponent>(playerId, out bool exists);
if (exists)
{
c.currentLives = val;
return true;
}
return false;
}
public bool GetGameOverScreen(uint playerId) public bool GetGameOverScreen(uint playerId)
{ {
if (entitiesDB == null) return false; if (entitiesDB == null) return false;
@ -372,78 +135,44 @@ namespace TechbloxModdingAPI.Players
return entitiesDB.Exists<RigidBodyEntityStruct>(playerId, CharacterExclusiveGroups.DeadCharacters); return entitiesDB.Exists<RigidBodyEntityStruct>(playerId, CharacterExclusiveGroups.DeadCharacters);
} }
public int GetSelectedBlock(uint playerId)
{
if (entitiesDB == null) return 0;
ref var c = ref GetCharacterStruct<EquippedPartStruct>(playerId, out bool exists);
if (exists)
{
return c.SelectedDBPartID;
}
return ushort.MaxValue;
}
public byte GetSelectedColor(uint playerId)
{
if (entitiesDB == null) return 0;
ref var c = ref GetCharacterStruct<EquippedColourStruct>(playerId, out bool exists);
if (exists)
{
return c.indexInPalette;
}
return 255;
}
// reusable methods // reusable methods
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private ExclusiveGroup PlayerGroupFromEnum(PlayerType type) public OptionalRef<T> GetCharacterStruct<T>(uint playerId) where T : unmanaged, IEntityComponent
{ {
return type == PlayerType.Local ? PlayersExclusiveGroups.LocalPlayers : PlayersExclusiveGroups.RemotePlayers; if (GameState.IsBuildMode())
return entitiesDB.QueryEntityOptional<T>(new EGID(playerId, Techblox.FlyCam.FlyCam.Group));
var characterGroups = CharacterExclusiveGroups.AllCharacters;
for (int i = 0; i < characterGroups.count; i++)
{
EGID egid = new EGID(playerId, characterGroups[i]);
var opt = entitiesDB.QueryEntityOptional<T>(egid);
if (opt.Exists)
return opt;
}
return new OptionalRef<T>();
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T GetCharacterStruct<T>(uint playerId, out bool exists) where T : unmanaged, IEntityComponent public OptionalRef<T> GetPlayerStruct<T>(uint playerId, PlayerType type) where T : unmanaged, IEntityComponent
{ {
var characterGroups = CharacterExclusiveGroups.AllCharacters; var playerGroup = type == PlayerType.Local ? PlayersExclusiveGroups.LocalPlayers : PlayersExclusiveGroups.RemotePlayers;
for (int i = 0; i < characterGroups.count; i++) EGID egid = new EGID(playerId, playerGroup);
{ return entitiesDB.QueryEntityOptional<T>(egid);
EGID egid = new EGID(playerId, characterGroups[i]);
if (entitiesDB.Exists<T>(egid))
{
exists = true;
return ref entitiesDB.QueryEntity<T>(egid);
}
}
exists = false;
T[] arr = new T[1];
return ref arr[0]; //Return default value
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] public OptionalRef<T> GetCameraStruct<T>(uint playerId) where T : unmanaged, IEntityComponent
public bool GetPlayerStruct<T>(uint playerId, out T s) where T : unmanaged, IEntityComponent
{ {
var playerGroups = PlayersExclusiveGroups.AllPlayers; return entitiesDB.QueryEntityOptional<T>(new EGID(playerId, CameraExclusiveGroups.CameraGroup));
for (int i = 0; i < playerGroups.count; i++)
{
EGID egid = new EGID(playerId, playerGroups[i]);
if (entitiesDB.Exists<T>(egid))
{
s = entitiesDB.QueryEntity<T>(egid);
return true;
}
}
s = default;
return false;
} }
public EGID GetThingLookedAt(uint playerId, float maxDistance = -1f) public EGID GetThingLookedAt(uint playerId, float maxDistance = -1f)
{ {
if (!entitiesDB.TryQueryMappedEntities<CharacterCameraRayCastEntityStruct>( var opt = GetCameraStruct<CharacterCameraRayCastEntityStruct>(playerId);
CameraExclusiveGroups.CameraGroup, out var mapper)) if (!opt) return EGID.Empty;
return EGID.Empty; CharacterCameraRayCastEntityStruct rayCast = opt;
mapper.TryGetEntity(playerId, out CharacterCameraRayCastEntityStruct rayCast);
float distance = maxDistance < 0 float distance = maxDistance < 0
? GhostBlockUtils.GetBuildInteractionDistance(entitiesDB, rayCast, ? GhostBlockUtils.GetBuildInteractionDistance(entitiesDB, rayCast,
GhostBlockUtils.GhostCastMethod.GhostCastProportionalToBlockSize) GhostBlockUtils.GhostCastMethod.GhostCastProportionalToBlockSize)

View file

@ -8,6 +8,7 @@
<PackageProjectUrl>https://git.exmods.org/modtainers/GamecraftModdingAPI</PackageProjectUrl> <PackageProjectUrl>https://git.exmods.org/modtainers/GamecraftModdingAPI</PackageProjectUrl>
<NeutralLanguage>en-CA</NeutralLanguage> <NeutralLanguage>en-CA</NeutralLanguage>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>8</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
</PropertyGroup> </PropertyGroup>