Automatically invoke the correct block constructor
And store delegates of dynamic methods invoking constructors Tested with the automated tests
This commit is contained in:
parent
ea8a9184bc
commit
89d32956d9
11 changed files with 114 additions and 195 deletions
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Linq;
|
||||||
|
using System.Reflection.Emit;
|
||||||
|
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
using Svelto.ECS.EntityStructs;
|
using Svelto.ECS.EntityStructs;
|
||||||
|
@ -67,10 +68,6 @@ 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 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.
|
/// 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.
|
/// 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 which may take a significant amount of time.
|
|
||||||
/// Only use this to place a single block.
|
|
||||||
/// For placing multiple blocks, use PlaceNew() then AsyncUtils.WaitForSubmission() when done with placing blocks.</para>
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="block">The block's type</param>
|
/// <param name="block">The block's type</param>
|
||||||
/// <param name="color">The block's color</param>
|
/// <param name="color">The block's color</param>
|
||||||
|
@ -81,23 +78,15 @@ namespace GamecraftModdingAPI
|
||||||
/// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</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>
|
/// <param name="player">The player who placed the block</param>
|
||||||
/// <returns>The placed block or null if failed</returns>
|
/// <returns>The placed block or null if failed</returns>
|
||||||
public static async Task<Block> PlaceNewAsync(BlockIDs block, float3 position,
|
public static T PlaceNew<T>(BlockIDs block, float3 position,
|
||||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
||||||
int uscale = 1, float3 scale = default, Player player = null)
|
int uscale = 1, float3 scale = default, Player player = null) where T : Block
|
||||||
{
|
{
|
||||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
||||||
{
|
{
|
||||||
try
|
var egid = PlacementEngine.PlaceBlock(block, color, darkness,
|
||||||
{
|
position, uscale, scale, player, rotation);
|
||||||
var ret = new Block(PlacementEngine.PlaceBlock(block, color, darkness,
|
return New<T>(egid.entityID, egid.groupID);
|
||||||
position, uscale, scale, player, rotation));
|
|
||||||
await AsyncUtils.WaitForSubmission();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Logging.MetaDebugLog(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -109,7 +98,7 @@ namespace GamecraftModdingAPI
|
||||||
/// <returns>The block object</returns>
|
/// <returns>The block object</returns>
|
||||||
public static Block GetLastPlacedBlock()
|
public static Block GetLastPlacedBlock()
|
||||||
{
|
{
|
||||||
return new Block(BlockIdentifiers.LatestBlockID);
|
return New<Block>(BlockIdentifiers.LatestBlockID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -130,6 +119,75 @@ namespace GamecraftModdingAPI
|
||||||
remove => BlockEventsEngine.Removed -= value;
|
remove => BlockEventsEngine.Removed -= value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Dictionary<Type, Func<EGID, Block>> initializers = new Dictionary<Type, Func<EGID, Block>>();
|
||||||
|
|
||||||
|
private static Dictionary<Type, ExclusiveGroupStruct[]> typeToGroup =
|
||||||
|
new Dictionary<Type, ExclusiveGroupStruct[]>
|
||||||
|
{
|
||||||
|
{typeof(ConsoleBlock), new[] {CommonExclusiveGroups.BUILD_CONSOLE_BLOCK_GROUP}},
|
||||||
|
{typeof(Motor), new[] {CommonExclusiveGroups.BUILD_MOTOR_BLOCK_GROUP}},
|
||||||
|
{typeof(Piston), new[] {CommonExclusiveGroups.BUILD_PISTON_BLOCK_GROUP}},
|
||||||
|
{typeof(Servo), new[] {CommonExclusiveGroups.BUILD_SERVO_BLOCK_GROUP}},
|
||||||
|
{
|
||||||
|
typeof(SpawnPoint),
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
CommonExclusiveGroups.BUILD_SPAWNPOINT_BLOCK_GROUP,
|
||||||
|
CommonExclusiveGroups.BUILD_BUILDINGSPAWN_BLOCK_GROUP
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{typeof(TextBlock), new[] {CommonExclusiveGroups.BUILD_TEXT_BLOCK_GROUP}},
|
||||||
|
{typeof(Timer), new[] {CommonExclusiveGroups.BUILD_TIMER_BLOCK_GROUP}}
|
||||||
|
};
|
||||||
|
|
||||||
|
private static T New<T>(uint id, ExclusiveGroupStruct? group = null) where T : Block
|
||||||
|
{
|
||||||
|
var type = typeof(T);
|
||||||
|
EGID egid;
|
||||||
|
if (!group.HasValue)
|
||||||
|
{
|
||||||
|
if (typeToGroup.TryGetValue(type, out var gr) && gr.Length == 1)
|
||||||
|
egid = new EGID(id, gr[0]);
|
||||||
|
else
|
||||||
|
egid = BlockEngine.FindBlockEGID(id) ?? throw new BlockTypeException("Could not find block group!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
egid = new EGID(id, group.Value);
|
||||||
|
if (typeToGroup.TryGetValue(type, out var gr)
|
||||||
|
&& gr.All(egs => egs != group.Value)) //If this subclass has a specific group, then use that - so Block should still work
|
||||||
|
throw new BlockTypeException($"Incompatible block type! Type {type.Name} belongs to group {gr.Select(g => g.ToString()).Aggregate((a, b) => a + ", " + b)} instead of {group.Value}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initializers.TryGetValue(type, out var func))
|
||||||
|
{
|
||||||
|
var bl = (T) func(egid);
|
||||||
|
return bl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//https://stackoverflow.com/a/10593806/2703239
|
||||||
|
var ctor = type.GetConstructor(new[] {typeof(EGID)});
|
||||||
|
if (ctor == null)
|
||||||
|
throw new MissingMethodException("There is no constructor with an EGID parameter for this object");
|
||||||
|
DynamicMethod dynamic = new DynamicMethod(string.Empty,
|
||||||
|
type,
|
||||||
|
new[] {typeof(EGID)},
|
||||||
|
type);
|
||||||
|
ILGenerator il = dynamic.GetILGenerator();
|
||||||
|
|
||||||
|
il.DeclareLocal(type);
|
||||||
|
il.Emit(OpCodes.Ldarg_0); //Load EGID and pass to constructor
|
||||||
|
il.Emit(OpCodes.Newobj, ctor); //Call constructor
|
||||||
|
il.Emit(OpCodes.Stloc_0);
|
||||||
|
il.Emit(OpCodes.Ldloc_0);
|
||||||
|
il.Emit(OpCodes.Ret);
|
||||||
|
|
||||||
|
func = (Func<EGID, T>) dynamic.CreateDelegate(typeof(Func<EGID, T>));
|
||||||
|
initializers.Add(type, func);
|
||||||
|
var block = (T) func(egid);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
public Block(EGID id)
|
public Block(EGID id)
|
||||||
{
|
{
|
||||||
Id = id;
|
Id = id;
|
||||||
|
@ -344,12 +402,9 @@ namespace GamecraftModdingAPI
|
||||||
// C# can't cast to a child of Block unless the object was originally that child type
|
// C# can't cast to a child of Block unless the object was originally that child type
|
||||||
// And C# doesn't let me make implicit cast operators for child types
|
// And C# doesn't let me make implicit cast operators for child types
|
||||||
// So thanks to Microsoft, we've got this horrible implementation using reflection
|
// So thanks to Microsoft, we've got this horrible implementation using reflection
|
||||||
ConstructorInfo ctor = typeof(T).GetConstructor(types: new System.Type[] { typeof(EGID) });
|
|
||||||
if (ctor == null)
|
//Lets improve that using delegates
|
||||||
{
|
return New<T>(Id.entityID, Id.groupID);
|
||||||
throw new BlockSpecializationException("Specialized block constructor does not accept an EGID");
|
|
||||||
}
|
|
||||||
return (T)ctor.Invoke(new object[] { Id });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
|
|
|
@ -32,9 +32,8 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
[APITestCase(TestType.EditMode)]
|
[APITestCase(TestType.EditMode)]
|
||||||
public static void TestTextBlock()
|
public static void TestTextBlock()
|
||||||
{
|
{
|
||||||
Block newBlock = Block.PlaceNew(BlockIDs.TextBlock, Unity.Mathematics.float3.zero + 1);
|
|
||||||
TextBlock textBlock = null; // Note: the assignment operation is a lambda, which slightly confuses the compiler
|
TextBlock textBlock = null; // Note: the assignment operation is a lambda, which slightly confuses the compiler
|
||||||
Assert.Errorless(() => { textBlock = newBlock.Specialise<TextBlock>(); }, "Block.Specialize<TextBlock>() raised an exception: ", "Block.Specialize<TextBlock>() completed without issue.");
|
Assert.Errorless(() => { textBlock = Block.PlaceNew<TextBlock>(BlockIDs.TextBlock, Unity.Mathematics.float3.zero + 1); }, "Block.PlaceNew<TextBlock>() raised an exception: ", "Block.PlaceNew<TextBlock>() completed without issue.");
|
||||||
if (!Assert.NotNull(textBlock, "Block.Specialize<TextBlock>() returned null, possibly because it failed silently.", "Specialized TextBlock is not null.")) return;
|
if (!Assert.NotNull(textBlock, "Block.Specialize<TextBlock>() returned null, possibly because it failed silently.", "Specialized TextBlock is not null.")) return;
|
||||||
if (!Assert.NotNull(textBlock.Text, "TextBlock.Text is null, possibly because it failed silently.", "TextBlock.Text is not null.")) return;
|
if (!Assert.NotNull(textBlock.Text, "TextBlock.Text is null, possibly because it failed silently.", "TextBlock.Text is not null.")) return;
|
||||||
if (!Assert.NotNull(textBlock.TextBlockId, "TextBlock.TextBlockId is null, possibly because it failed silently.", "TextBlock.TextBlockId is not null.")) return;
|
if (!Assert.NotNull(textBlock.TextBlockId, "TextBlock.TextBlockId is null, possibly because it failed silently.", "TextBlock.TextBlockId is not null.")) return;
|
||||||
|
|
|
@ -12,33 +12,19 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
public class ConsoleBlock : Block
|
public class ConsoleBlock : Block
|
||||||
{
|
{
|
||||||
public static ConsoleBlock PlaceNew(float3 position,
|
public ConsoleBlock(EGID id): base(id)
|
||||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
|
||||||
int uscale = 1, float3 scale = default, Player player = null)
|
|
||||||
{
|
{
|
||||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
if (!BlockEngine.GetBlockInfoExists<ConsoleBlockEntityStruct>(this.Id))
|
||||||
{
|
{
|
||||||
EGID id = PlacementEngine.PlaceBlock(BlockIDs.ConsoleBlock, color, darkness,
|
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||||
position, uscale, scale, player, rotation);
|
}
|
||||||
return new ConsoleBlock(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConsoleBlock(EGID id): base(id)
|
public ConsoleBlock(uint id): base(new EGID(id, CommonExclusiveGroups.BUILD_CONSOLE_BLOCK_GROUP))
|
||||||
{
|
{
|
||||||
if (!BlockEngine.GetBlockInfoExists<ConsoleBlockEntityStruct>(this.Id))
|
if (!BlockEngine.GetBlockInfoExists<ConsoleBlockEntityStruct>(this.Id))
|
||||||
{
|
|
||||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConsoleBlock(uint id): base(new EGID(id, CommonExclusiveGroups.BUILD_CONSOLE_BLOCK_GROUP))
|
|
||||||
{
|
|
||||||
if (!BlockEngine.GetBlockInfoExists<ConsoleBlockEntityStruct>(this.Id))
|
|
||||||
{
|
{
|
||||||
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,29 +11,6 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
public class Motor : Block
|
public class Motor : Block
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Places a new motor.
|
|
||||||
/// Any valid motor type is accepted.
|
|
||||||
/// This re-implements Block.PlaceNew(...)
|
|
||||||
/// </summary>
|
|
||||||
public static new Motor PlaceNew(BlockIDs block, float3 position,
|
|
||||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
|
||||||
int uscale = 1, float3 scale = default, Player player = null)
|
|
||||||
{
|
|
||||||
if (!(block == BlockIDs.MotorS || block == BlockIDs.MotorM))
|
|
||||||
{
|
|
||||||
throw new BlockTypeException($"Block is not a {typeof(Motor).Name} block");
|
|
||||||
}
|
|
||||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
|
||||||
{
|
|
||||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
|
||||||
position, uscale, scale, player, rotation);
|
|
||||||
return new Motor(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Motor(EGID id) : base(id)
|
public Motor(EGID id) : base(id)
|
||||||
{
|
{
|
||||||
if (!BlockEngine.GetBlockInfoExists<MotorReadOnlyStruct>(this.Id))
|
if (!BlockEngine.GetBlockInfoExists<MotorReadOnlyStruct>(this.Id))
|
||||||
|
|
|
@ -11,30 +11,7 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
public class Piston : Block
|
public class Piston : Block
|
||||||
{
|
{
|
||||||
/// <summary>
|
public Piston(EGID id) : base(id)
|
||||||
/// Places a new piston.
|
|
||||||
/// Any valid piston type is accepted.
|
|
||||||
/// This re-implements Block.PlaceNew(...)
|
|
||||||
/// </summary>
|
|
||||||
public static new Piston PlaceNew(BlockIDs block, float3 position,
|
|
||||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
|
||||||
int uscale = 1, float3 scale = default, Player player = null)
|
|
||||||
{
|
|
||||||
if (!(block == BlockIDs.ServoPiston || block == BlockIDs.StepperPiston || block == BlockIDs.PneumaticPiston))
|
|
||||||
{
|
|
||||||
throw new BlockTypeException($"Block is not a {typeof(Piston).Name} block");
|
|
||||||
}
|
|
||||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
|
||||||
{
|
|
||||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
|
||||||
position, uscale, scale, player, rotation);
|
|
||||||
return new Piston(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Piston(EGID id) : base(id)
|
|
||||||
{
|
{
|
||||||
if (!BlockEngine.GetBlockInfoExists<PistonReadOnlyStruct>(this.Id))
|
if (!BlockEngine.GetBlockInfoExists<PistonReadOnlyStruct>(this.Id))
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,29 +11,6 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
public class Servo : Block
|
public class Servo : Block
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Places a new servo.
|
|
||||||
/// Any valid servo type is accepted.
|
|
||||||
/// This re-implements Block.PlaceNew(...)
|
|
||||||
/// </summary>
|
|
||||||
public static new Servo PlaceNew(BlockIDs block, float3 position,
|
|
||||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
|
||||||
int uscale = 1, float3 scale = default, Player player = null)
|
|
||||||
{
|
|
||||||
if (!(block == BlockIDs.ServoAxle || block == BlockIDs.ServoHinge || block == BlockIDs.ServoPiston))
|
|
||||||
{
|
|
||||||
throw new BlockTypeException($"Block is not a {nameof(Servo)} block");
|
|
||||||
}
|
|
||||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
|
||||||
{
|
|
||||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
|
||||||
position, uscale, scale, player, rotation);
|
|
||||||
return new Servo(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Servo(EGID id) : base(id)
|
public Servo(EGID id) : base(id)
|
||||||
{
|
{
|
||||||
if (!BlockEngine.GetBlockInfoExists<ServoReadOnlyStruct>(this.Id))
|
if (!BlockEngine.GetBlockInfoExists<ServoReadOnlyStruct>(this.Id))
|
||||||
|
|
|
@ -14,25 +14,6 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SignalingBlock : Block
|
public class SignalingBlock : Block
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Places a new signaling block.
|
|
||||||
/// Any valid functional block type with IO ports will work.
|
|
||||||
/// This re-implements Block.PlaceNew(...)
|
|
||||||
/// </summary>
|
|
||||||
public static new SignalingBlock PlaceNew(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())
|
|
||||||
{
|
|
||||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
|
||||||
position, uscale, scale, player, rotation);
|
|
||||||
return new SignalingBlock(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SignalingBlock(EGID id) : base(id)
|
public SignalingBlock(EGID id) : base(id)
|
||||||
{
|
{
|
||||||
if (!BlockEngine.GetBlockInfoExists<BlockPortsStruct>(this.Id))
|
if (!BlockEngine.GetBlockInfoExists<BlockPortsStruct>(this.Id))
|
||||||
|
|
|
@ -13,30 +13,7 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
public class SpawnPoint : Block
|
public class SpawnPoint : Block
|
||||||
{
|
{
|
||||||
/// <summary>
|
public SpawnPoint(EGID id) : base(id)
|
||||||
/// Places a new spawn point.
|
|
||||||
/// Any valid spawn block type is accepted.
|
|
||||||
/// This re-implements Block.PlaceNew(...)
|
|
||||||
/// </summary>
|
|
||||||
public static new SpawnPoint PlaceNew(BlockIDs block, float3 position,
|
|
||||||
float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
|
|
||||||
int uscale = 1, float3 scale = default, Player player = null)
|
|
||||||
{
|
|
||||||
if (!(block == BlockIDs.LargeSpawn || block == BlockIDs.SmallSpawn || block == BlockIDs.MediumSpawn || block == BlockIDs.PlayerSpawn))
|
|
||||||
{
|
|
||||||
throw new BlockTypeException($"Block is not a {nameof(SpawnPoint)} block");
|
|
||||||
}
|
|
||||||
if (PlacementEngine.IsInGame && GameState.IsBuildMode())
|
|
||||||
{
|
|
||||||
EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
|
|
||||||
position, uscale, scale, player, rotation);
|
|
||||||
return new SpawnPoint(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpawnPoint(EGID id) : base(id)
|
|
||||||
{
|
{
|
||||||
if (!BlockEngine.GetBlockInfoExists<SpawnPointStatsEntityStruct>(this.Id))
|
if (!BlockEngine.GetBlockInfoExists<SpawnPointStatsEntityStruct>(this.Id))
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,21 +12,6 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
public class TextBlock : Block
|
public class TextBlock : Block
|
||||||
{
|
{
|
||||||
|
|
||||||
public static TextBlock PlaceNew(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())
|
|
||||||
{
|
|
||||||
EGID id = PlacementEngine.PlaceBlock(BlockIDs.TextBlock, color, darkness,
|
|
||||||
position, uscale, scale, player, rotation);
|
|
||||||
return new TextBlock(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextBlock(EGID id) : base(id)
|
public TextBlock(EGID id) : base(id)
|
||||||
{
|
{
|
||||||
if (!BlockEngine.GetBlockInfoExists<TextBlockDataStruct>(this.Id))
|
if (!BlockEngine.GetBlockInfoExists<TextBlockDataStruct>(this.Id))
|
||||||
|
|
|
@ -13,23 +13,6 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
public class Timer : Block
|
public class Timer : Block
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Places a new timer block.
|
|
||||||
/// </summary>
|
|
||||||
public static Timer PlaceNew(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())
|
|
||||||
{
|
|
||||||
EGID id = PlacementEngine.PlaceBlock(BlockIDs.Timer, color, darkness,
|
|
||||||
position, uscale, scale, player, rotation);
|
|
||||||
return new Timer(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Timer(EGID id) : base(id)
|
public Timer(EGID id) : base(id)
|
||||||
{
|
{
|
||||||
if (!BlockEngine.GetBlockInfoExists<TimerBlockDataStruct>(this.Id))
|
if (!BlockEngine.GetBlockInfoExists<TimerBlockDataStruct>(this.Id))
|
||||||
|
|
|
@ -232,6 +232,28 @@ namespace GamecraftModdingAPI.Tests
|
||||||
}
|
}
|
||||||
}).Build();
|
}).Build();
|
||||||
|
|
||||||
|
CommandBuilder.Builder()
|
||||||
|
.Name("PlaceConsole")
|
||||||
|
.Description("Place a bunch of console block with a given text")
|
||||||
|
.Action((float x, float y, float z) =>
|
||||||
|
{
|
||||||
|
Stopwatch sw = new Stopwatch();
|
||||||
|
sw.Start();
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < 100; j++)
|
||||||
|
{
|
||||||
|
var block = Block.PlaceNew<ConsoleBlock>(BlockIDs.ConsoleBlock,
|
||||||
|
new float3(x + i, y, z + j));
|
||||||
|
block.Command = "test_command";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.Stop();
|
||||||
|
Logging.CommandLog($"Blocks placed in {sw.ElapsedMilliseconds} ms");
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
GameClient.SetDebugInfo("InstalledMods", InstalledMods);
|
GameClient.SetDebugInfo("InstalledMods", InstalledMods);
|
||||||
Block.Placed += (sender, args) =>
|
Block.Placed += (sender, args) =>
|
||||||
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID);
|
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID);
|
||||||
|
|
Loading…
Reference in a new issue