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 istags/v2.0.0
@@ -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); | |||
} | |||
} | |||
} |
@@ -71,7 +71,6 @@ namespace TechbloxModdingAPI | |||
Input.FakeInput.Init(); | |||
// init object-oriented classes | |||
Player.Init(); | |||
FlyCam.Init(); | |||
Block.Init(); | |||
BlockGroup.Init(); | |||
Wire.Init(); | |||
@@ -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; | |||
} | |||
} | |||
} |
@@ -1,17 +1,23 @@ | |||
using System; | |||
using RobocraftX.Character; | |||
using Unity.Mathematics; | |||
using RobocraftX.Common; | |||
using RobocraftX.Common.Players; | |||
using RobocraftX.Physics; | |||
using Svelto.ECS; | |||
using Techblox.Camera; | |||
using Techblox.FlyCam; | |||
using TechbloxModdingAPI.Blocks; | |||
using TechbloxModdingAPI.Players; | |||
using TechbloxModdingAPI.Utility; | |||
using UnityEngine; | |||
namespace TechbloxModdingAPI | |||
{ | |||
/// <summary> | |||
/// An in-game player character. Any Leo you see is a player. | |||
/// </summary> | |||
public class Player : IEquatable<Player>, IEquatable<EGID> | |||
public partial class Player : IEquatable<Player>, IEquatable<EGID> | |||
{ | |||
// static functionality | |||
private static PlayerEngine playerEngine = new PlayerEngine(); | |||
@@ -123,50 +129,33 @@ namespace TechbloxModdingAPI | |||
/// <value>The position.</value> | |||
public float3 Position | |||
{ | |||
get | |||
{ | |||
return playerEngine.GetLocation(Id); | |||
} | |||
set | |||
{ | |||
playerEngine.SetLocation(Id, value, false); | |||
} | |||
} | |||
get => playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().position; | |||
set => playerEngine.SetLocation(Id, value, false); | |||
} | |||
/// <summary> | |||
/// The player's current rotation. | |||
/// </summary> | |||
/// <value>The rotation.</value> | |||
public float3 Rotation | |||
{ | |||
get | |||
{ | |||
return playerEngine.GetRotation(Id); | |||
} | |||
set | |||
{ | |||
playerEngine.SetRotation(Id, value); | |||
} | |||
} | |||
{ | |||
get => ((Quaternion) (GameState.IsBuildMode() | |||
? playerEngine.GetCameraStruct<CharacterCameraEntityStruct>(Id).Get().rotation | |||
: playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().rotation)).eulerAngles; | |||
set => _ = GameState.IsBuildMode() | |||
? playerEngine.GetCameraStruct<CharacterCameraEntityStruct>(Id).Get().rotation = quaternion.Euler(value) | |||
: playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().rotation = quaternion.Euler(value); | |||
} | |||
/// <summary> | |||
/// The player's current velocity. | |||
/// </summary> | |||
/// <value>The velocity.</value> | |||
public float3 Velocity | |||
{ | |||
get | |||
{ | |||
return playerEngine.GetLinearVelocity(Id); | |||
} | |||
set | |||
{ | |||
playerEngine.SetLinearVelocity(Id, value); | |||
} | |||
} | |||
{ | |||
get => playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().velocity; | |||
set => playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().velocity = value; | |||
} | |||
/// <summary> | |||
/// The player's current angular velocity. | |||
@@ -174,36 +163,18 @@ namespace TechbloxModdingAPI | |||
/// <value>The angular velocity.</value> | |||
public float3 AngularVelocity | |||
{ | |||
get | |||
{ | |||
return playerEngine.GetAngularVelocity(Id); | |||
} | |||
set | |||
{ | |||
playerEngine.SetAngularVelocity(Id, value); | |||
} | |||
get => playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().angularVelocity; | |||
set => playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().angularVelocity = value; | |||
} | |||
/// <summary> | |||
/// The player's mass. | |||
/// </summary> | |||
/// <value>The mass.</value> | |||
public float Mass | |||
{ | |||
get | |||
{ | |||
return 1f / playerEngine.GetMass(Id).InverseMass; | |||
} | |||
// FIXME: Setting mass doesn't do anything | |||
/*set | |||
{ | |||
playerEngine.SetInverseMass(Id, 1f / value); | |||
}*/ | |||
} | |||
public float Mass => | |||
1f / playerEngine.GetCharacterStruct<RigidBodyEntityStruct>(Id).Get().physicsMass.InverseMass; | |||
private float _ping = -1f; | |||
private float _ping = -1f; | |||
/// <summary> | |||
/// The player's latest network ping time. | |||
@@ -213,10 +184,10 @@ namespace TechbloxModdingAPI | |||
{ | |||
get | |||
{ | |||
float? temp = playerEngine.GetLastPingTime(Id, Type); | |||
if (temp.HasValue) | |||
var opt = playerEngine.GetPlayerStruct<PlayerNetworkStatsEntityStruct>(Id, Type); | |||
if (opt) | |||
{ | |||
_ping = temp.Value; | |||
_ping = opt.Get().lastPingTimeSinceLevelLoad ?? _ping; | |||
} | |||
return _ping; | |||
} | |||
@@ -227,14 +198,15 @@ namespace TechbloxModdingAPI | |||
/// </summary> | |||
/// <value>The initial health.</value> | |||
public float InitialHealth | |||
{ | |||
get => playerEngine.GetInitialHealth(Id); | |||
{ | |||
get | |||
{ | |||
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id); | |||
return opt ? opt.Get().initialHealth : -1f; | |||
} | |||
set | |||
{ | |||
playerEngine.SetInitialHealth(Id, value); | |||
} | |||
} | |||
set => playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id).Get().initialHealth = value; | |||
} | |||
/// <summary> | |||
/// The player's current health in Simulation (aka Time Running) mode. | |||
@@ -242,12 +214,13 @@ namespace TechbloxModdingAPI | |||
/// <value>The current health.</value> | |||
public float CurrentHealth | |||
{ | |||
get => playerEngine.GetCurrentHealth(Id); | |||
get | |||
{ | |||
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id); | |||
return opt ? opt.Get().currentHealth : -1f; | |||
} | |||
set | |||
{ | |||
playerEngine.DamagePlayer(Id, CurrentHealth - value); | |||
} | |||
set => playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id).Get().currentHealth = value; | |||
} | |||
/// <summary> | |||
@@ -255,14 +228,20 @@ namespace TechbloxModdingAPI | |||
/// </summary> | |||
/// <value><c>true</c> if damageable; otherwise, <c>false</c>.</value> | |||
public bool Damageable | |||
{ | |||
get => playerEngine.GetDamageable(Id); | |||
{ | |||
get | |||
{ | |||
var opt = playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id); | |||
return opt.Get().canTakeDamageStat; | |||
} | |||
set | |||
{ | |||
playerEngine.SetDamageable(Id, value); | |||
} | |||
} | |||
set | |||
{ | |||
ref var healthStruct = ref playerEngine.GetCharacterStruct<CharacterHealthEntityStruct>(Id).Get(); | |||
healthStruct.canTakeDamage = value; | |||
healthStruct.canTakeDamageStat = value; | |||
} | |||
} | |||
/// <summary> | |||
/// The player's lives when initially entering Simulation (aka Time Running) mode. | |||
@@ -270,9 +249,13 @@ namespace TechbloxModdingAPI | |||
/// <value>The initial lives.</value> | |||
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> | |||
@@ -281,19 +264,23 @@ namespace TechbloxModdingAPI | |||
/// <value>The current lives.</value> | |||
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. | |||
/// </summary> | |||
/// <value><c>true</c> if game over; otherwise, <c>false</c>.</value> | |||
public bool GameOver | |||
{ | |||
get => playerEngine.GetGameOverScreen(Id); | |||
} | |||
}*/ | |||
/// <summary> | |||
/// Whether the player is dead. | |||
@@ -313,7 +300,8 @@ namespace TechbloxModdingAPI | |||
{ | |||
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 | |||
{ | |||
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 | |||
{ | |||
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> | |||
public Blueprint SelectedBlueprint | |||
{ | |||
get => playerEngine.GetPlayerStruct(Id, out LocalBlueprintInputStruct lbis) | |||
? new Blueprint(lbis.selectedBlueprintId) | |||
: null; | |||
get | |||
{ | |||
var lbiso = playerEngine.GetPlayerStruct<LocalBlueprintInputStruct>(Id, Type); | |||
return lbiso ? new Blueprint(lbiso.Get().selectedBlueprintId) : null; | |||
} | |||
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. | |||
/// </summary> | |||
public PlayerBuildingMode BuildingMode => (PlayerBuildingMode) playerEngine | |||
.GetCharacterStruct<PlayerInputTimeStoppedContextStruct>(Id, out _).timeStoppedContext; | |||
.GetCharacterStruct<PlayerInputTimeStoppedContextStruct>(Id).Get().timeStoppedContext; | |||
// object methods | |||
@@ -373,7 +365,7 @@ namespace TechbloxModdingAPI | |||
float3 location = new float3(x, y, z); | |||
if (relative) | |||
{ | |||
location += playerEngine.GetLocation(Id); | |||
location += Position; | |||
} | |||
playerEngine.SetLocation(Id, location, exitSeat: exitSeat); | |||
} | |||
@@ -395,7 +387,7 @@ namespace TechbloxModdingAPI | |||
/// Returns the rigid body the player is currently looking at during simulation. | |||
/// </summary> | |||
/// <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) | |||
{ | |||
var egid = playerEngine.GetThingLookedAt(Id, maxDistance); | |||
@@ -413,11 +405,6 @@ namespace TechbloxModdingAPI | |||
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) | |||
{ | |||
if (ReferenceEquals(null, other)) return false; | |||
@@ -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; | |||
} | |||
} | |||
} |
@@ -5,6 +5,7 @@ | |||
BlockMode, | |||
ColourMode, | |||
ConfigMode, | |||
BlueprintMode | |||
BlueprintMode, | |||
MaterialMode | |||
} | |||
} |
@@ -21,6 +21,7 @@ using HarmonyLib; | |||
using RobocraftX.Common; | |||
using Svelto.ECS.DataStructures; | |||
using TechbloxModdingAPI.Engines; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Players | |||
{ | |||
@@ -98,17 +99,6 @@ namespace TechbloxModdingAPI.Players | |||
|| 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) | |||
{ | |||
if (entitiesDB == null) return false; | |||
@@ -131,233 +121,6 @@ namespace TechbloxModdingAPI.Players | |||
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) | |||
{ | |||
if (entitiesDB == null) return false; | |||
@@ -372,78 +135,44 @@ namespace TechbloxModdingAPI.Players | |||
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 | |||
[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)] | |||
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; | |||
for (int i = 0; i < characterGroups.count; i++) | |||
{ | |||
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 | |||
var playerGroup = type == PlayerType.Local ? PlayersExclusiveGroups.LocalPlayers : PlayersExclusiveGroups.RemotePlayers; | |||
EGID egid = new EGID(playerId, playerGroup); | |||
return entitiesDB.QueryEntityOptional<T>(egid); | |||
} | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
public bool GetPlayerStruct<T>(uint playerId, out T s) where T : unmanaged, IEntityComponent | |||
public OptionalRef<T> GetCameraStruct<T>(uint playerId) where T : unmanaged, IEntityComponent | |||
{ | |||
var playerGroups = PlayersExclusiveGroups.AllPlayers; | |||
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; | |||
return entitiesDB.QueryEntityOptional<T>(new EGID(playerId, CameraExclusiveGroups.CameraGroup)); | |||
} | |||
public EGID GetThingLookedAt(uint playerId, float maxDistance = -1f) | |||
{ | |||
if (!entitiesDB.TryQueryMappedEntities<CharacterCameraRayCastEntityStruct>( | |||
CameraExclusiveGroups.CameraGroup, out var mapper)) | |||
return EGID.Empty; | |||
mapper.TryGetEntity(playerId, out CharacterCameraRayCastEntityStruct rayCast); | |||
var opt = GetCameraStruct<CharacterCameraRayCastEntityStruct>(playerId); | |||
if (!opt) return EGID.Empty; | |||
CharacterCameraRayCastEntityStruct rayCast = opt; | |||
float distance = maxDistance < 0 | |||
? GhostBlockUtils.GetBuildInteractionDistance(entitiesDB, rayCast, | |||
GhostBlockUtils.GhostCastMethod.GhostCastProportionalToBlockSize) | |||
@@ -8,6 +8,7 @@ | |||
<PackageProjectUrl>https://git.exmods.org/modtainers/GamecraftModdingAPI</PackageProjectUrl> | |||
<NeutralLanguage>en-CA</NeutralLanguage> | |||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |||
<LangVersion>8</LangVersion> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
</PropertyGroup> | |||