@@ -1,5 +1,6 @@ | |||
using System; | |||
using System.Reflection; | |||
using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using Svelto.ECS.EntityStructs; | |||
@@ -29,6 +30,8 @@ namespace GamecraftModdingAPI | |||
/// 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> | |||
@@ -59,6 +62,44 @@ namespace GamecraftModdingAPI | |||
return null; | |||
} | |||
/// <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 waits for the block to be constructed in the game.</para> | |||
/// </summary> | |||
/// <param name="block">The block's type</param> | |||
/// <param name="color">The block's color</param> | |||
/// <param name="darkness">The block color's darkness (0-9) - 0 is default color</param> | |||
/// <param name="position">The block's position in the grid - default block size is 0.2</param> | |||
/// <param name="rotation">The block's rotation in degrees</param> | |||
/// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param> | |||
/// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param> | |||
/// <param name="player">The player who placed the block</param> | |||
/// <returns>The placed block or null if failed</returns> | |||
public static async Task<Block> PlaceNewAsync(BlockIDs block, float3 position, | |||
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 | |||
{ | |||
var ret = new Block(PlacementEngine.PlaceBlock(block, color, darkness, | |||
position, uscale, scale, player, rotation)); | |||
await AsyncUtils.WaitForSubmission(); | |||
return ret; | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.MetaDebugLog(e); | |||
} | |||
} | |||
return null; | |||
} | |||
/// <summary> | |||
/// Returns the most recently placed block. | |||
/// </summary> | |||
@@ -10,6 +10,9 @@ using GamecraftModdingAPI.Engines; | |||
namespace GamecraftModdingAPI.Blocks | |||
{ | |||
/// <summary> | |||
/// Engine for executing general block actions | |||
/// </summary> | |||
public class BlockEngine : IApiEngine | |||
{ | |||
public string Name { get; } = "GamecraftModdingAPIBlockGameEngine"; | |||
@@ -28,6 +28,8 @@ namespace GamecraftModdingAPI.Events | |||
{ | |||
// register custom game engines | |||
GameEngineManager.RegisterEngines(enginesRoot); | |||
// initialize AsyncUtils | |||
AsyncUtils.Setup(enginesRoot); | |||
// A new EnginesRoot is always created when ActivateGame is called | |||
// so all event emitters and handlers must be re-registered. | |||
EventManager.RegisterEngines(enginesRoot); | |||
@@ -71,6 +71,7 @@ namespace GamecraftModdingAPI | |||
Player.Init(); | |||
Block.Init(); | |||
GameClient.Init(); | |||
AsyncUtils.Init(); | |||
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} initialized"); | |||
} | |||
@@ -143,7 +143,11 @@ namespace GamecraftModdingAPI.Tests | |||
CommandBuilder.Builder() | |||
.Name("PlaceAluminium") | |||
.Description("Place a block of aluminium at the given coordinates") | |||
.Action((float x, float y, float z) => { Block.PlaceNew(Blocks.BlockIDs.AluminiumCube, new Unity.Mathematics.float3(x, y, z)); }) | |||
.Action(async (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); | |||
}) | |||
.Build(); | |||
CommandBuilder.Builder("getBlock") | |||
@@ -170,7 +174,7 @@ namespace GamecraftModdingAPI.Tests | |||
Logging.CommandLog("Colored block to " + color); | |||
}).Build(); | |||
GameClient.SetDebugInfo("lookedAt", LookedAt); | |||
/* | |||
@@ -0,0 +1,29 @@ | |||
using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
namespace GamecraftModdingAPI.Utility | |||
{ | |||
public static class AsyncUtils | |||
{ | |||
private static AsyncUtilsEngine gameEngine = new AsyncUtilsEngine(); | |||
/// <summary> | |||
/// Waits for entity submission asynchronously. | |||
/// </summary> | |||
public static async Task WaitForSubmission() | |||
{ | |||
await gameEngine.WaitForSubmission(); | |||
} | |||
public static void Setup(EnginesRoot enginesRoot) | |||
{ | |||
gameEngine.Setup(enginesRoot.GenerateEntityFunctions(), enginesRoot.GenerateEntityFactory()); | |||
} | |||
public static void Init() | |||
{ | |||
GameEngineManager.AddGameEngine(gameEngine); | |||
} | |||
} | |||
} |
@@ -0,0 +1,50 @@ | |||
using System.Collections; | |||
using System.Threading.Tasks; | |||
using RobocraftX.Schedulers; | |||
using Svelto.ECS; | |||
using Svelto.Tasks.ExtraLean; | |||
using GamecraftModdingAPI.Engines; | |||
namespace GamecraftModdingAPI.Utility | |||
{ | |||
public class AsyncUtilsEngine : IApiEngine | |||
{ | |||
private IEntityFunctions _efu; | |||
private IEntityFactory _efa; | |||
private IEnumerator WaitForSubmissionInternal(IEntityFunctions efu, IEntityFactory efa, | |||
EntitiesDB entitiesDB, TaskCompletionSource<object> task) | |||
{ | |||
var waitEnumerator = new WaitForSubmissionEnumerator(efu, efa, entitiesDB); | |||
while (waitEnumerator.MoveNext()) | |||
yield return null; | |||
task.SetResult(null); | |||
} | |||
public Task WaitForSubmission() | |||
{ | |||
var task = new TaskCompletionSource<object>(); | |||
WaitForSubmissionInternal(_efu, _efa, entitiesDB, task).RunOn(ExtraLean.EveryFrameStepRunner); | |||
return task.Task; | |||
} | |||
public void Setup(IEntityFunctions efu, IEntityFactory efa) | |||
{ | |||
_efu = efu; | |||
_efa = efa; | |||
} | |||
public void Ready() | |||
{ | |||
} | |||
public EntitiesDB entitiesDB { get; set; } | |||
public void Dispose() | |||
{ | |||
} | |||
public string Name { get; } = "GamecraftModdingAPIAsyncUtilsGameEngine"; | |||
public bool isRemovable { get; } = false; | |||
} | |||
} |