Browse Source

Fixes, added SimBody class

tags/v1.1.0
NorbiPeti 4 years ago
parent
commit
dca6fe4c1b
15 changed files with 242 additions and 127 deletions
  1. +16
    -22
      GamecraftModdingAPI/Block.cs
  2. +7
    -14
      GamecraftModdingAPI/Blocks/ConsoleBlock.cs
  3. +3
    -10
      GamecraftModdingAPI/Blocks/Motor.cs
  4. +3
    -10
      GamecraftModdingAPI/Blocks/Piston.cs
  5. +4
    -11
      GamecraftModdingAPI/Blocks/Servo.cs
  6. +3
    -10
      GamecraftModdingAPI/Blocks/SignalingBlock.cs
  7. +3
    -10
      GamecraftModdingAPI/Blocks/SpawnPoint.cs
  8. +3
    -10
      GamecraftModdingAPI/Blocks/TextBlock.cs
  9. +3
    -11
      GamecraftModdingAPI/Blocks/Timer.cs
  10. +19
    -4
      GamecraftModdingAPI/Player.cs
  11. +17
    -2
      GamecraftModdingAPI/Players/PlayerEngine.cs
  12. +88
    -0
      GamecraftModdingAPI/SimBody.cs
  13. +69
    -9
      GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
  14. +2
    -2
      GamecraftModdingAPI/Utility/DebugInterfaceEngine.cs
  15. +2
    -2
      GamecraftModdingAPI/Utility/Logging.cs

+ 16
- 22
GamecraftModdingAPI/Block.cs View File

@@ -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>
@@ -48,15 +47,8 @@ namespace GamecraftModdingAPI
{
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 new Block(PlacementEngine.PlaceBlock(block, color, darkness,
position, uscale, scale, player, rotation));
}

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}";


+ 7
- 14
GamecraftModdingAPI/Blocks/ConsoleBlock.cs View File

@@ -15,21 +15,14 @@ namespace GamecraftModdingAPI.Blocks
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
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);
}
}
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
{
EGID id = PlacementEngine.PlaceBlock(BlockIDs.ConsoleBlock, color, darkness,
position, uscale, scale, player, rotation);
return new ConsoleBlock(id);
}

return null;
return null;
}

public ConsoleBlock(EGID id): base(id)


+ 3
- 10
GamecraftModdingAPI/Blocks/Motor.cs View File

@@ -25,16 +25,9 @@ namespace GamecraftModdingAPI.Blocks
}
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);
}
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
position, uscale, scale, player, rotation);
return new Motor(id);
}

return null;


+ 3
- 10
GamecraftModdingAPI/Blocks/Piston.cs View File

@@ -25,16 +25,9 @@ namespace GamecraftModdingAPI.Blocks
}
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);
}
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
position, uscale, scale, player, rotation);
return new Piston(id);
}

return null;


+ 4
- 11
GamecraftModdingAPI/Blocks/Servo.cs View File

@@ -21,20 +21,13 @@ 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);
}
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
position, uscale, scale, player, rotation);
return new Servo(id);
}

return null;


+ 3
- 10
GamecraftModdingAPI/Blocks/SignalingBlock.cs View File

@@ -25,16 +25,9 @@ namespace GamecraftModdingAPI.Blocks
{
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);
}
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
position, uscale, scale, player, rotation);
return new SignalingBlock(id);
}

return null;


+ 3
- 10
GamecraftModdingAPI/Blocks/SpawnPoint.cs View File

@@ -23,20 +23,13 @@ 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);
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
position, uscale, scale, player, rotation);
return new SpawnPoint(id);
}
catch (Exception e)
{
Logging.MetaDebugLog(e);
}
}

return null;


+ 3
- 10
GamecraftModdingAPI/Blocks/TextBlock.cs View File

@@ -18,16 +18,9 @@ namespace GamecraftModdingAPI.Blocks
{
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);
}
EGID id = PlacementEngine.PlaceBlock(BlockIDs.TextBlock, color, darkness,
position, uscale, scale, player, rotation);
return new TextBlock(id);
}

return null;


+ 3
- 11
GamecraftModdingAPI/Blocks/Timer.cs View File

@@ -21,17 +21,9 @@ namespace GamecraftModdingAPI.Blocks
{
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);
}
EGID id = PlacementEngine.PlaceBlock(BlockIDs.Timer, color, darkness,
position, uscale, scale, player, rotation);
return new Timer(id);
}

return null;


+ 19
- 4
GamecraftModdingAPI/Player.cs View File

@@ -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


+ 17
- 2
GamecraftModdingAPI/Players/PlayerEngine.cs View File

@@ -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
- 0
GamecraftModdingAPI/SimBody.cs View 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);
}
}
}

+ 69
- 9
GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs View File

@@ -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,10 +272,35 @@ namespace GamecraftModdingAPI.Tests
private string LookedAt()
{
if (player == null)
player = new Player(Players.PlayerType.Local);
Block block = player.GetBlockLookedAt();
if (block == null) return "Block: none";
return "Block: " + block.Type + "\nColor: " + block.Color + "\n" + "At: " + block.Position;
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() { }


+ 2
- 2
GamecraftModdingAPI/Utility/DebugInterfaceEngine.cs View File

@@ -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);
}
}
}


+ 2
- 2
GamecraftModdingAPI/Utility/Logging.cs View File

@@ -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…
Cancel
Save