Added AsyncUtils and Block.PlaceNewAsync()

This commit is contained in:
Norbi Peti 2020-05-22 03:00:33 +02:00
parent 4e08acf44c
commit 084cbb40c4
7 changed files with 132 additions and 2 deletions

View file

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

View file

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

View file

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

View file

@ -71,6 +71,7 @@ namespace GamecraftModdingAPI
Player.Init();
Block.Init();
GameClient.Init();
AsyncUtils.Init();
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} initialized");
}

View file

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

View file

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

View file

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