Removing blocks from groups when they are removed from the game Attempted to update graphics when changing blocks Disallowing changing the block group after creation, now that we can copy blockstags/v1.7.0
@@ -244,6 +244,7 @@ namespace GamecraftModdingAPI | |||
MovementEngine.MoveBlock(Id, InitData, value); | |||
if (blockGroup != null) | |||
blockGroup.PosAndRotCalculated = false; | |||
BlockEngine.UpdateDisplayedBlock(Id); | |||
} | |||
} | |||
@@ -258,6 +259,7 @@ namespace GamecraftModdingAPI | |||
RotationEngine.RotateBlock(Id, InitData, value); | |||
if (blockGroup != null) | |||
blockGroup.PosAndRotCalculated = false; | |||
BlockEngine.UpdateDisplayedBlock(Id); | |||
} | |||
} | |||
@@ -273,6 +275,7 @@ namespace GamecraftModdingAPI | |||
BlockEngine.SetBlockInfo(this, (ref ScalingEntityStruct st, float3 val) => st.scale = val, value); | |||
if (!Exists) return; //UpdateCollision needs the block to exist | |||
ScalingEngine.UpdateCollision(Id); | |||
BlockEngine.UpdateDisplayedBlock(Id); | |||
} | |||
} | |||
@@ -364,8 +367,10 @@ namespace GamecraftModdingAPI | |||
/// <summary> | |||
/// Returns the block group this block is a part of. Block groups can be placed using blueprints. | |||
/// Returns null if not part of a group.<br /> | |||
/// Setting the group after the block has been initialized will not update everything properly. | |||
/// You should only set this property on blocks newly placed by your code. | |||
/// Setting the group after the block has been initialized will not update everything properly, | |||
/// so you can only set this property on blocks newly placed by your code.<br /> | |||
/// To set it for existing blocks, you can use the Copy() method and set the property on the resulting block | |||
/// (and remove this block). | |||
/// </summary> | |||
public BlockGroup BlockGroup | |||
{ | |||
@@ -378,6 +383,15 @@ namespace GamecraftModdingAPI | |||
} | |||
set | |||
{ | |||
if (Exists) | |||
{ | |||
/*var copy = Copy<Block>(); | |||
copy.BlockGroup = value; //It won't run this on the new instance as it won't 'exist' yet | |||
Remove();*/ | |||
Logging.LogWarning("Attempted to set group of existing block. This is not supported." | |||
+ " Copy the block and set the group of the resulting block."); | |||
return; | |||
} | |||
blockGroup?.RemoveInternal(this); | |||
BlockEngine.SetBlockInfo(this, | |||
(ref BlockGroupEntityComponent bgec, BlockGroup val) => bgec.currentBlockGroup = val?.Id ?? -1, | |||
@@ -418,7 +432,7 @@ namespace GamecraftModdingAPI | |||
} | |||
/// <summary> | |||
/// Creates a copy of the block in the game with the same basic properties and tweakable stats. | |||
/// Creates a copy of the block in the game with the same properties, stats and wires. | |||
/// </summary> | |||
/// <returns></returns> | |||
public T Copy<T>() where T : Block | |||
@@ -12,9 +12,9 @@ using GamecraftModdingAPI.Utility; | |||
namespace GamecraftModdingAPI | |||
{ | |||
/// <summary> | |||
/// A group of blocks that can be selected together. The placed version of blueprints. | |||
/// A group of blocks that can be selected together. The placed version of blueprints. Dispose after usage. | |||
/// </summary> | |||
public class BlockGroup : ICollection<Block> | |||
public class BlockGroup : ICollection<Block>, IDisposable | |||
{ | |||
internal static BlueprintEngine _engine = new BlueprintEngine(); | |||
public int Id { get; } | |||
@@ -30,8 +30,30 @@ namespace GamecraftModdingAPI | |||
Id = id; | |||
sourceBlock = block; | |||
blocks = new List<Block>(GetBlocks()); | |||
Block.Removed += OnBlockRemoved; | |||
} | |||
private void OnBlockRemoved(object sender, BlockPlacedRemovedEventArgs e) | |||
{ | |||
//blocks.RemoveAll(block => block.Id == e.ID); - Allocation heavy | |||
int index = -1; | |||
for (int i = 0; i < blocks.Count; i++) | |||
{ | |||
if (blocks[i].Id == e.ID) | |||
{ | |||
index = i; | |||
break; | |||
} | |||
} | |||
if (index != -1) blocks.RemoveAt(index); | |||
} | |||
public void Dispose() | |||
{ | |||
Block.Removed -= OnBlockRemoved; | |||
} | |||
/// <summary> | |||
/// The position of the block group (center). Recalculated if blocks have been added/removed since the last query. | |||
/// </summary> | |||
@@ -1,5 +1,7 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Reflection; | |||
using Gamecraft.Wires; | |||
using GamecraftModdingAPI.Engines; | |||
using HarmonyLib; | |||
using RobocraftX.Blocks; | |||
@@ -15,9 +17,15 @@ namespace GamecraftModdingAPI.Blocks | |||
{ | |||
private static Type copyEngineType = | |||
AccessTools.TypeByName("Gamecraft.GUI.Tweaks.Engines.CopyTweaksOnPickEngine"); | |||
private static Type copyWireEngineType = | |||
AccessTools.TypeByName("Gamecraft.Wires.WireConnectionCopyOnPickEngine"); | |||
private static Type createWireEngineType = | |||
AccessTools.TypeByName("RobocraftX.GUI.Wires.WireConnectionCreateOnPlaceEngine"); | |||
private MethodBase copyFromBlock = AccessTools.Method(copyEngineType, "CopyTweaksFromBlock"); | |||
private MethodBase copyToBlock = AccessTools.Method(copyEngineType, "ApplyTweaksToPlacedBlock"); | |||
private MethodBase copyWireFromBlock = AccessTools.Method(copyWireEngineType, "CopyWireInputsAndOutputs"); | |||
private MethodBase copyWireToBlock = AccessTools.Method(createWireEngineType, "PlaceWiresOnPlaceNewCube"); | |||
public void Ready() | |||
{ | |||
@@ -45,13 +53,23 @@ namespace GamecraftModdingAPI.Blocks | |||
if (entitiesDB.Exists<DBEntityStruct>(pickedBlock.pickedBlockEntityID) | |||
&& entitiesDB.Exists<DBEntityStruct>(pickedBlock.placedBlockEntityID)) | |||
{ | |||
copyFromBlock.Invoke(Patch.instance, new object[] {pickedBlock.ID, pickedBlock}); | |||
copyToBlock.Invoke(Patch.instance, new object[] {pickedBlock.ID, pickedBlock}); | |||
copyFromBlock.Invoke(Patch.copyEngine, new object[] {pickedBlock.ID, pickedBlock}); | |||
uint playerID = Player.LocalPlayer.Id; | |||
var parameters = new object[] {playerID, pickedBlock}; | |||
copyWireFromBlock.Invoke(Patch.copyWireEngine, parameters); | |||
pickedBlock = (PickedBlockExtraDataStruct) parameters[1]; //ref arg | |||
copyToBlock.Invoke(Patch.copyEngine, new object[] {pickedBlock.ID, pickedBlock}); | |||
ExclusiveGroupStruct group = WiresExclusiveGroups.WIRES_COPY_GROUP + playerID; | |||
copyWireToBlock.Invoke(Patch.createWireEngine, new object[] {group, pickedBlock.ID}); | |||
pickedBlock.placedBlockTweaksMustCopy = false; | |||
pickedBlock.placedBlockTweaksCopied = false; | |||
} | |||
pickedBlock = oldStruct; //Make sure to not interfere with the game | |||
pickedBlock = oldStruct; //Make sure to not interfere with the game - Although that might not be the case with the wire copying | |||
} | |||
} | |||
} | |||
@@ -59,16 +77,28 @@ namespace GamecraftModdingAPI.Blocks | |||
[HarmonyPatch] | |||
private static class Patch | |||
{ | |||
public static object instance; | |||
public static object copyEngine; | |||
public static object copyWireEngine; | |||
public static object createWireEngine; | |||
public static void Postfix(object __instance) | |||
{ | |||
instance = __instance; | |||
if (__instance.GetType() == copyEngineType) | |||
copyEngine = __instance; | |||
else if (__instance.GetType() == copyWireEngineType) | |||
copyWireEngine = __instance; | |||
else if (__instance.GetType() == createWireEngineType) | |||
createWireEngine = __instance; | |||
} | |||
public static MethodBase TargetMethod() | |||
public static IEnumerable<MethodBase> TargetMethods() | |||
{ | |||
return AccessTools.GetDeclaredConstructors(copyEngineType)[0]; | |||
return new[] | |||
{ | |||
AccessTools.GetDeclaredConstructors(copyEngineType)[0], | |||
AccessTools.GetDeclaredConstructors(copyWireEngineType)[0], | |||
AccessTools.GetDeclaredConstructors(createWireEngineType)[0] | |||
}; | |||
} | |||
} | |||
@@ -8,6 +8,8 @@ using Gamecraft.Wires; | |||
using RobocraftX.Blocks; | |||
using RobocraftX.Common; | |||
using RobocraftX.Physics; | |||
using RobocraftX.Rendering; | |||
using Svelto.ECS.EntityStructs; | |||
using Svelto.DataStructures; | |||
using Svelto.ECS; | |||
@@ -149,6 +151,15 @@ namespace GamecraftModdingAPI.Blocks | |||
} | |||
} | |||
public void UpdateDisplayedBlock(EGID id) | |||
{ | |||
if (!BlockExists(id)) return; | |||
var pos = entitiesDB.QueryEntity<PositionEntityStruct>(id); | |||
var rot = entitiesDB.QueryEntity<RotationEntityStruct>(id); | |||
var scale = entitiesDB.QueryEntity<ScalingEntityStruct>(id); | |||
entitiesDB.QueryEntity<RenderingDataStruct>(id).matrix = float4x4.TRS(pos.position, rot.rotation, scale.scale); | |||
} | |||
public bool BlockExists(EGID blockID) | |||
{ | |||
return entitiesDB.Exists<DBEntityStruct>(blockID); | |||
@@ -101,6 +101,13 @@ namespace GamecraftModdingAPI.Blocks | |||
loadedFromDisk = false, | |||
placedBy = playerId | |||
}); | |||
/*structInitializer.Init(new CollisionFilterOverride | |||
{ | |||
belongsTo = 32U, | |||
collidesWith = 239532U | |||
});*/ | |||
PrimaryRotationUtility.InitialisePrimaryDirection(rotation.rotation, ref structInitializer); | |||
EGID playerEGID = new EGID(playerId, CharacterExclusiveGroups.OnFootGroup); | |||
ref PickedBlockExtraDataStruct pickedBlock = ref entitiesDB.QueryEntity<PickedBlockExtraDataStruct>(playerEGID); | |||