Fixes, added SimBody class
This commit is contained in:
parent
084cbb40c4
commit
dca6fe4c1b
15 changed files with 242 additions and 127 deletions
|
@ -23,15 +23,14 @@ namespace GamecraftModdingAPI
|
|||
protected static readonly MovementEngine MovementEngine = new MovementEngine();
|
||||
protected static readonly RotationEngine RotationEngine = new RotationEngine();
|
||||
protected static readonly RemovalEngine RemovalEngine = new RemovalEngine();
|
||||
protected static readonly BlockEngine BlockEngine = new BlockEngine();
|
||||
protected static readonly SignalEngine SignalEngine = new SignalEngine();
|
||||
|
||||
protected internal static readonly BlockEngine BlockEngine = new BlockEngine();
|
||||
|
||||
/// <summary>
|
||||
/// Place a new block at the given position. If scaled, position means the center of the block. The default block size is 0.2 in terms of position.
|
||||
/// Place blocks next to each other to connect them.
|
||||
/// The placed block will be a complete block with a placement grid and collision which will be saved along with the game.
|
||||
/// <para></para>
|
||||
/// <para>This method causes a sync which may have a performance impact. Use the async version if possible.</para>
|
||||
/// </summary>
|
||||
/// <param name="block">The block's type</param>
|
||||
/// <param name="color">The block's color</param>
|
||||
|
@ -47,17 +46,10 @@ namespace GamecraftModdingAPI
|
|||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
try
|
||||
{
|
||||
return new Block(PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.MetaDebugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -122,17 +114,8 @@ namespace GamecraftModdingAPI
|
|||
}
|
||||
}
|
||||
|
||||
public Block(uint id)
|
||||
public Block(uint id) : this(new EGID(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP))
|
||||
{
|
||||
Id = new EGID(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
|
||||
if (!BlockEngine.BlockExists(Id))
|
||||
{
|
||||
Sync();
|
||||
if (!BlockEngine.BlockExists(Id))
|
||||
{
|
||||
throw new BlockDoesNotExistException($"Block {Id.entityID} must be placed using PlaceNew(...) since it does not exist yet");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -264,6 +247,17 @@ namespace GamecraftModdingAPI
|
|||
/// <returns>True if the block exists and could be removed.</returns>
|
||||
public bool Remove() => RemovalEngine.RemoveBlock(Id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the rigid body of the cluster of blocks this one belongs to during simulation.
|
||||
/// Can be used to apply forces or move the block around while the simulation is running.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public SimBody ToSimBody()
|
||||
{
|
||||
uint id = BlockEngine.GetBlockInfo<GridConnectionsEntityStruct>(Id).machineRigidBodyId;
|
||||
return new SimBody(id);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Rotation)}: {Rotation}";
|
||||
|
|
|
@ -16,18 +16,11 @@ namespace GamecraftModdingAPI.Blocks
|
|||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
try
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(BlockIDs.ConsoleBlock, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new ConsoleBlock(id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.MetaDebugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -24,18 +24,11 @@ namespace GamecraftModdingAPI.Blocks
|
|||
throw new BlockTypeException($"Block is not a {typeof(Motor).Name} block");
|
||||
}
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
try
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new Motor(id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.MetaDebugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -24,18 +24,11 @@ namespace GamecraftModdingAPI.Blocks
|
|||
throw new BlockTypeException($"Block is not a {typeof(Piston).Name} block");
|
||||
}
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
try
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new Piston(id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.MetaDebugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -21,21 +21,14 @@ namespace GamecraftModdingAPI.Blocks
|
|||
{
|
||||
if (!(block == BlockIDs.ServoAxle || block == BlockIDs.ServoHinge || block == BlockIDs.ServoPiston))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {typeof(Servo).Name} block");
|
||||
throw new BlockTypeException($"Block is not a {nameof(Servo)} block");
|
||||
}
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
try
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new Servo(id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.MetaDebugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -24,18 +24,11 @@ namespace GamecraftModdingAPI.Blocks
|
|||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
try
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new SignalingBlock(id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.MetaDebugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -23,21 +23,14 @@ namespace GamecraftModdingAPI.Blocks
|
|||
{
|
||||
if (!(block == BlockIDs.LargeSpawn || block == BlockIDs.SmallSpawn || block == BlockIDs.MediumSpawn || block == BlockIDs.PlayerSpawn))
|
||||
{
|
||||
throw new BlockTypeException($"Block is not a {typeof(SpawnPoint).Name} block");
|
||||
throw new BlockTypeException($"Block is not a {nameof(SpawnPoint)} block");
|
||||
}
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
try
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new SpawnPoint(id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.MetaDebugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -17,18 +17,11 @@ namespace GamecraftModdingAPI.Blocks
|
|||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
try
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(BlockIDs.TextBlock, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new TextBlock(id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.MetaDebugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -20,19 +20,11 @@ namespace GamecraftModdingAPI.Blocks
|
|||
int uscale = 1, float3 scale = default, Player player = null)
|
||||
{
|
||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
EGID id = PlacementEngine.PlaceBlock(BlockIDs.Timer, color, darkness,
|
||||
position, uscale, scale, player, rotation);
|
||||
return new Timer(id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.MetaDebugLog(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
|
||||
using Unity.Mathematics;
|
||||
using RobocraftX.Common;
|
||||
|
||||
using GamecraftModdingAPI.Players;
|
||||
|
||||
|
@ -221,13 +222,27 @@ namespace GamecraftModdingAPI
|
|||
/// <summary>
|
||||
/// Returns the block the player is currently looking at.
|
||||
/// </summary>
|
||||
/// <param name="playerId">The player's ID</param>
|
||||
/// <param name="entitiesDB">The entities DB</param>
|
||||
/// <param name="maxDistance">The maximum distance from the player (default is the player's building reach)</param>
|
||||
/// <returns>The block's EGID or null if not found</returns>
|
||||
/// <returns>The block or null if not found</returns>
|
||||
public Block GetBlockLookedAt(float maxDistance = -1f)
|
||||
{
|
||||
return playerEngine.GetBlockLookedAt(Id, maxDistance);
|
||||
var egid = playerEngine.GetThingLookedAt(Id, maxDistance);
|
||||
return egid.HasValue && egid.Value.groupID == CommonExclusiveGroups.OWNED_BLOCKS_GROUP
|
||||
? new Block(egid.Value)
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
public SimBody GetSimBodyLookedAt(float maxDistance = -1f)
|
||||
{
|
||||
var egid = playerEngine.GetThingLookedAt(Id, maxDistance);
|
||||
return egid.HasValue && egid.Value.groupID == CommonExclusiveGroups.SIMULATION_BODIES_GROUP
|
||||
? new SimBody(egid.Value)
|
||||
: null;
|
||||
}
|
||||
|
||||
// internal methods
|
||||
|
|
|
@ -238,7 +238,7 @@ namespace GamecraftModdingAPI.Players
|
|||
return false;
|
||||
}
|
||||
|
||||
public Block GetBlockLookedAt(uint playerId, float maxDistance = -1f)
|
||||
public EGID? GetThingLookedAt(uint playerId, float maxDistance = -1f)
|
||||
{
|
||||
if (!entitiesDB.TryQueryMappedEntities<CharacterCameraRayCastEntityStruct>(
|
||||
CameraExclusiveGroups.CameraGroup, out var mapper))
|
||||
|
@ -248,7 +248,22 @@ namespace GamecraftModdingAPI.Players
|
|||
? GhostBlockUtils.GetBuildInteractionDistance(entitiesDB, rayCast)
|
||||
: maxDistance;
|
||||
if (rayCast.hit && rayCast.distance <= distance)
|
||||
return new Block(rayCast.hitEgid);
|
||||
return rayCast.hitEgid;
|
||||
/*if (rayCast.hit)
|
||||
{
|
||||
*Logging.MetaDebugLog("RayCast EGID: " + rayCast.hitEgid);
|
||||
var d = AccessTools.Field(typeof(ExclusiveGroup), "_knownGroups").GetValue(null) as
|
||||
Dictionary<string, ExclusiveGroupStruct>;
|
||||
foreach (var groupStruct in d)
|
||||
{
|
||||
if (groupStruct.Value == rayCast.hitEgid.groupID)
|
||||
{
|
||||
Logging.MetaDebugLog("Group name: " + groupStruct.Key);
|
||||
break; //SIMULATION_BODIES_GROUP
|
||||
}
|
||||
}*
|
||||
//Logging.MetaDebugLog("Position: " + Block.GetBlockPositionTest(rayCast.hitEgid));
|
||||
}*/
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
88
GamecraftModdingAPI/SimBody.cs
Normal file
88
GamecraftModdingAPI/SimBody.cs
Normal file
|
@ -0,0 +1,88 @@
|
|||
using RobocraftX.Common;
|
||||
using RobocraftX.Physics;
|
||||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Physics;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GamecraftModdingAPI
|
||||
{
|
||||
/// <summary>
|
||||
/// A rigid body (like a cluster of connected blocks) during simulation.
|
||||
/// </summary>
|
||||
public class SimBody
|
||||
{
|
||||
public EGID Id { get; }
|
||||
|
||||
public SimBody(EGID id)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public SimBody(uint id) : this(new EGID(id, CommonExclusiveGroups.SIMULATION_BODIES_GROUP))
|
||||
{
|
||||
}
|
||||
|
||||
public float3 Position
|
||||
{
|
||||
get => GetStruct().position;
|
||||
set => GetStruct().position = value;
|
||||
}
|
||||
|
||||
public float3 Velocity
|
||||
{
|
||||
get => GetStruct().velocity;
|
||||
set => GetStruct().velocity = value;
|
||||
}
|
||||
|
||||
public float3 AngularVelocity
|
||||
{
|
||||
get => GetStruct().angularVelocity;
|
||||
set => GetStruct().angularVelocity = value;
|
||||
}
|
||||
|
||||
public float3 DeltaVelocity
|
||||
{
|
||||
get => GetStruct().deltaVelocity;
|
||||
set => GetStruct().deltaVelocity = value;
|
||||
}
|
||||
|
||||
public float3 DeltaAngularVelocity
|
||||
{
|
||||
get => GetStruct().deltaAngularVelocity;
|
||||
set => GetStruct().deltaAngularVelocity = value;
|
||||
}
|
||||
|
||||
public float3 Rotation
|
||||
{
|
||||
get => ((Quaternion) GetStruct().rotation).eulerAngles;
|
||||
set
|
||||
{
|
||||
ref var str = ref GetStruct();
|
||||
Quaternion quaternion = str.rotation;
|
||||
quaternion.eulerAngles = value;
|
||||
str.rotation = quaternion;
|
||||
}
|
||||
}
|
||||
|
||||
public float Mass
|
||||
{
|
||||
get => math.rcp(GetStruct().physicsMass.InverseMass);
|
||||
set => GetStruct().physicsMass.InverseMass = math.rcp(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the body can be moved or static
|
||||
/// </summary>
|
||||
public bool Static
|
||||
{
|
||||
get => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(Id).isStatic;
|
||||
set => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(Id).isStatic = value;
|
||||
}
|
||||
|
||||
private ref RigidBodyEntityStruct GetStruct()
|
||||
{
|
||||
return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(Id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,11 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
using HarmonyLib;
|
||||
using IllusionInjector;
|
||||
// test
|
||||
using Svelto.ECS;
|
||||
using RobocraftX.Blocks;
|
||||
|
@ -143,15 +146,46 @@ namespace GamecraftModdingAPI.Tests
|
|||
CommandBuilder.Builder()
|
||||
.Name("PlaceAluminium")
|
||||
.Description("Place a block of aluminium at the given coordinates")
|
||||
.Action(async (float x, float y, float z) =>
|
||||
.Action((float x, float y, float z) =>
|
||||
{
|
||||
var block = await Block.PlaceNewAsync(BlockIDs.AluminiumCube, new float3(x, y, z));
|
||||
Logging.MetaDebugLog("Block placed with type: " + block.Type);
|
||||
var block = Block.PlaceNew(BlockIDs.AluminiumCube, new float3(x, y, z));
|
||||
Logging.CommandLog("Block placed with type: " + block.Type);
|
||||
})
|
||||
.Build();
|
||||
|
||||
CommandBuilder.Builder("getBlock")
|
||||
.Action(() => uREPL.Log.Output(new Player(Players.PlayerType.Local).GetBlockLookedAt()+"")).Build();
|
||||
CommandBuilder.Builder()
|
||||
.Name("PlaceAluminiumLots")
|
||||
.Description("Place a lot of blocks of aluminium at the given coordinates")
|
||||
.Action((float x, float y, float z) =>
|
||||
{
|
||||
Logging.CommandLog("Starting...");
|
||||
var sw = Stopwatch.StartNew();
|
||||
for (int i = 0; i < 100; i++)
|
||||
for (int j = 0; j < 100; j++)
|
||||
Block.PlaceNew(BlockIDs.AluminiumCube, new float3(x + i, y, z + j));
|
||||
//Block.Sync();
|
||||
sw.Stop();
|
||||
Logging.CommandLog("Finished in " + sw.ElapsedMilliseconds + "ms");
|
||||
})
|
||||
.Build();
|
||||
//With Sync(): 1135ms
|
||||
//Without Sync(): 134ms
|
||||
//Async: 348 794ms, doesn't freeze game
|
||||
//Without Sync() but wait for submission: 530ms
|
||||
//With Sync() at the end: 380ms
|
||||
|
||||
Block b = null;
|
||||
CommandBuilder.Builder("moveBlockInSim", "Run in build mode first, then in sim while looking at a block to move it up")
|
||||
.Action(() =>
|
||||
{
|
||||
if (b == null)
|
||||
{
|
||||
b = new Player(PlayerType.Local).GetBlockLookedAt();
|
||||
Logging.CommandLog("Block saved: " + b);
|
||||
}
|
||||
else
|
||||
Logging.CommandLog("Block moved to: " + (b.ToSimBody().Position += new float3(0, 2, 0)));
|
||||
}).Build();
|
||||
|
||||
CommandBuilder.Builder("Error", "Throw an error to make sure SimpleCustomCommandEngine's wrapper catches it.")
|
||||
.Action(() => { throw new Exception("Error Command always throws an error"); })
|
||||
|
@ -176,6 +210,7 @@ namespace GamecraftModdingAPI.Tests
|
|||
}).Build();
|
||||
|
||||
GameClient.SetDebugInfo("lookedAt", LookedAt);
|
||||
GameClient.SetDebugInfo("InstalledMods", InstalledMods);
|
||||
|
||||
/*
|
||||
CommandManager.AddCommand(new SimpleCustomCommandEngine<float>((float d) => { UnityEngine.Camera.main.fieldOfView = d; },
|
||||
|
@ -237,11 +272,36 @@ namespace GamecraftModdingAPI.Tests
|
|||
private string LookedAt()
|
||||
{
|
||||
if (player == null)
|
||||
player = new Player(Players.PlayerType.Local);
|
||||
player = new Player(PlayerType.Local);
|
||||
if (GameState.IsBuildMode())
|
||||
{
|
||||
Block block = player.GetBlockLookedAt();
|
||||
if (block == null) return "Block: none";
|
||||
return "Block: " + block.Type + "\nColor: " + block.Color + "\n" + "At: " + block.Position;
|
||||
}
|
||||
if (GameState.IsSimulationMode())
|
||||
{
|
||||
SimBody body = player.GetSimBodyLookedAt();
|
||||
if (body == null) return "Body: none";
|
||||
return "Body: " + (body.Static ? "static" : "non-static")
|
||||
+ "\nAt: " + body.Position + " - rotated: " + body.Rotation
|
||||
+ "\nWith mass: " + body.Mass
|
||||
+ "\nVelocity: " + body.Velocity + " - angular: " + body.AngularVelocity
|
||||
+ "\nDelta velocity: " + body.DeltaVelocity + " - angular: " + body.DeltaAngularVelocity;
|
||||
}
|
||||
|
||||
return "Switching modes...";
|
||||
}
|
||||
|
||||
private string modsString;
|
||||
private string InstalledMods()
|
||||
{
|
||||
if (modsString != null) return modsString;
|
||||
StringBuilder sb = new StringBuilder("Installed mods:");
|
||||
foreach (var plugin in PluginManager.Plugins)
|
||||
sb.Append("\n" + plugin);
|
||||
return modsString = sb.ToString();
|
||||
}
|
||||
|
||||
public void OnFixedUpdate() { }
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace GamecraftModdingAPI.Utility
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.LogException(e, "Failed to inject AddInfo method for the debug display!");
|
||||
Logging.LogWarning("Failed to inject AddInfo method for the debug display!\n" + e);
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -68,7 +68,7 @@ namespace GamecraftModdingAPI.Utility
|
|||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.LogException(e, "Unable to get info for " + info.Key);
|
||||
Logging.LogWarning("Unable to get info for " + info.Key + "\n" + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ namespace GamecraftModdingAPI.Utility
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an exception to Gamecraft's log
|
||||
/// Write an exception to Gamecraft's log and to the screen and exit game
|
||||
/// </summary>
|
||||
/// <param name="e">The exception to log</param>
|
||||
/// <param name="extraData">The extra data to pass to the ILogger.
|
||||
|
@ -95,7 +95,7 @@ namespace GamecraftModdingAPI.Utility
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write an exception message to Gamecraft's log
|
||||
/// Write an exception message to Gamecraft's log and to the screen and exit game
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to log</param>
|
||||
/// <param name="e">The exception to log</param>
|
||||
|
|
Loading…
Reference in a new issue