using System.Collections.Generic; using Gamecraft.Wires; using RobocraftX.Blocks; using RobocraftX.Common; using RobocraftX.GUI.Hotbar.Colours; using RobocraftX.Physics; using RobocraftX.Scene.Simulation; using Svelto.DataStructures; using Svelto.ECS; using GamecraftModdingAPI.Engines; using GamecraftModdingAPI.Utility; namespace GamecraftModdingAPI.Blocks { /// /// Engine for executing general block actions /// public class BlockEngine : IApiEngine { public string Name { get; } = "GamecraftModdingAPIBlockGameEngine"; public EntitiesDB entitiesDB { set; private get; } public bool isRemovable => false; internal bool Synced = true; public void Dispose() { } public void Ready() { } public Block[] GetConnectedBlocks(EGID blockID) { if (!BlockExists(blockID)) return new Block[0]; Stack cubeStack = new Stack(); FasterList cubesToProcess = new FasterList(); ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID.entityID, cubeStack, cubesToProcess, (in GridConnectionsEntityStruct g) => { return false; }); var ret = new Block[cubesToProcess.count]; for (int i = 0; i < cubesToProcess.count; i++) ret[i] = new Block(cubesToProcess[i]); return ret; } public void SetBlockColorFromPalette(ref ColourParameterEntityStruct color) { ref var paletteEntry = ref entitiesDB.QueryEntity(color.indexInPalette, CommonExclusiveGroups.COLOUR_PALETTE_GROUP); color.paletteColour = paletteEntry.Colour; } /// /// Get a struct of a block. Can be used to set properties. /// Returns a default value if not found. /// /// The block's ID /// The struct to query /// An editable reference to the struct public ref T GetBlockInfo(EGID blockID) where T : struct, IEntityComponent { if (!Synced) { Sync(); Synced = true; } if (entitiesDB.Exists(blockID)) return ref entitiesDB.QueryEntity(blockID); T[] structHolder = new T[1]; //Create something that can be referenced return ref structHolder[0]; //Gets a default value automatically } /// /// Get a struct of a block. Can be used to set properties. /// Returns a default value if not found. /// /// The block's ID /// Whether the specified struct exists for the block /// The struct to query /// An editable reference to the struct public ref T GetBlockInfo(EGID blockID, out bool exists) where T : struct, IEntityComponent { if (!Synced) { Sync(); Synced = true; } exists = entitiesDB.Exists(blockID); if (exists) return ref entitiesDB.QueryEntity(blockID); T[] structHolder = new T[1]; return ref structHolder[0]; } public bool BlockExists(EGID id) { return entitiesDB.Exists(id); } public bool GetBlockInfoExists(EGID blockID) where T : struct, IEntityComponent { return entitiesDB.Exists(blockID); } public SimBody[] GetSimBodiesFromID(byte id) { var ret = new FasterList(4); if (!entitiesDB.HasAny(CommonExclusiveGroups.OWNED_BLOCKS_GROUP)) return new SimBody[0]; var oids = entitiesDB.QueryEntities(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); var connections = entitiesDB.QueryMappedEntities(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); foreach (ref ObjectIdEntityStruct oid in oids) { if (oid.objectId != id) continue; var rid = connections.Entity(oid.ID.entityID).machineRigidBodyId; foreach (var rb in ret) { if (rb.Id.entityID == rid) goto DUPLICATE; //Multiple Object Identifiers on one rigid body } ret.Add(new SimBody(rid)); DUPLICATE: ; } return ret.ToArray(); } public ObjectIdentifier[] GetObjectIDsFromID(byte id) { var ret = new FasterList(4); if (!entitiesDB.HasAny(CommonExclusiveGroups.OWNED_BLOCKS_GROUP)) return new ObjectIdentifier[0]; var oids = entitiesDB.QueryEntities(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); foreach (ref ObjectIdEntityStruct oid in oids) if (oid.objectId == id) ret.Add(new ObjectIdentifier(oid.ID)); return ret.ToArray(); } public SimBody[] GetConnectedSimBodies(uint id) { var joints = entitiesDB.QueryEntities(MachineSimulationGroups.JOINTS_GROUP); var list = new FasterList(4); foreach (var joint in joints) { if (joint.jointState == JointState.Broken) continue; if (joint.connectedEntityA == id) list.Add(new SimBody(joint.connectedEntityB)); else if (joint.connectedEntityB == id) list.Add(new SimBody(joint.connectedEntityA)); } return list.ToArray(); } /// /// Synchronize newly created entity components with entities DB. /// This forces a partial game tick, so it may be slow. /// This also has the potential to make Gamecraft unstable. /// Use this sparingly. /// private static void Sync() { DeterministicStepCompositionRootPatch.SubmitEntitiesNow(); } #if DEBUG public EntitiesDB GetEntitiesDB() { return entitiesDB; } #endif } }