diff --git a/GamecraftModdingAPI/Block.cs b/GamecraftModdingAPI/Block.cs
index dc3fe19..5f30a64 100644
--- a/GamecraftModdingAPI/Block.cs
+++ b/GamecraftModdingAPI/Block.cs
@@ -137,6 +137,16 @@ namespace GamecraftModdingAPI
{typeof(Timer), new[] {CommonExclusiveGroups.BUILD_TIMER_BLOCK_GROUP}}
};
+ ///
+ /// Constructs a new instance of T with the given ID and group using dynamically created delegates.
+ /// It's equivalent to new T(EGID) with a minimal overhead thanks to caching the created delegates.
+ ///
+ /// The block ID
+ /// The block group
+ /// The block's type or Block itself
+ /// An instance of the provided type
+ /// The block group doesn't match or cannot be found
+ /// The block class doesn't have the needed constructor
private static T New(uint id, ExclusiveGroupStruct? group = null) where T : Block
{
var type = typeof(T);
@@ -175,8 +185,8 @@ namespace GamecraftModdingAPI
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.Stloc_0); - doesn't seem like we need these
+ //il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ret);
func = (Func) dynamic.CreateDelegate(typeof(Func));
@@ -188,6 +198,9 @@ namespace GamecraftModdingAPI
public Block(EGID id)
{
Id = id;
+ if (typeToGroup.TryGetValue(GetType(), out var groups) && groups.All(gr => gr != id.groupID))
+ throw new BlockTypeException("The block has the wrong group! The type is " + GetType() +
+ " while the group is " + id.groupID);
}
///
@@ -328,6 +341,7 @@ namespace GamecraftModdingAPI
///
/// Whether the block exists. The other properties will return a default value if the block doesn't exist.
+ /// If the block was just placed, then this will also return false but the properties will work correctly.
///
public bool Exists => BlockEngine.BlockExists(Id);
diff --git a/GamecraftModdingAPI/Blocks/BlockEngine.cs b/GamecraftModdingAPI/Blocks/BlockEngine.cs
index 375620e..f97e405 100644
--- a/GamecraftModdingAPI/Blocks/BlockEngine.cs
+++ b/GamecraftModdingAPI/Blocks/BlockEngine.cs
@@ -85,10 +85,11 @@ namespace GamecraftModdingAPI.Blocks
{
if (entitiesDB.Exists(block.Id))
setter(ref entitiesDB.QueryEntity(block.Id), value);
- if (block.InitData.Group != null)
+ else if (block.InitData.Group != null)
{
var initializer = new EntityComponentInitializer(block.Id, block.InitData.Group);
- ref T structRef = ref (new T[1])[0]; //A reference for a default value for struct
+ T component = initializer.Has() ? initializer.Get() : default;
+ ref T structRef = ref component;
setter(ref structRef, value);
initializer.Init(structRef);
}
diff --git a/GamecraftModdingAPI/Blocks/BlockEngineInit.cs b/GamecraftModdingAPI/Blocks/BlockEngineInit.cs
index 4be9a98..70f713a 100644
--- a/GamecraftModdingAPI/Blocks/BlockEngineInit.cs
+++ b/GamecraftModdingAPI/Blocks/BlockEngineInit.cs
@@ -9,6 +9,9 @@ namespace GamecraftModdingAPI.Blocks
{
public partial class BlockEngine
{
+ ///
+ /// Holds information needed to construct a component initializer
+ ///
internal struct BlockInitData
{
public FasterDictionary, ITypeSafeDictionary> Group;
@@ -17,6 +20,9 @@ namespace GamecraftModdingAPI.Blocks
internal delegate FasterDictionary, ITypeSafeDictionary> GetInitGroup(
EntityComponentInitializer initializer);
+ ///
+ /// Accesses the group field of the initializer
+ ///
internal GetInitGroup InitGroup = CreateAccessor("_group");
//https://stackoverflow.com/questions/55878525/unit-testing-ref-structs-with-private-fields-via-reflection