diff --git a/Ringway/Data/Scripts/TeleportGateway/TeleportCore.cs b/Ringway/Data/Scripts/TeleportGateway/TeleportCore.cs index 516a21a..0b0db43 100644 --- a/Ringway/Data/Scripts/TeleportGateway/TeleportCore.cs +++ b/Ringway/Data/Scripts/TeleportGateway/TeleportCore.cs @@ -176,9 +176,8 @@ public static void ServerProcessTeleportRequest(TeleportRequestMessage message) } } - public static void TeleportEntity(IMyEntity entity, IMyCollector sourceGateway, IMyCollector destGateway) { - MyLogger.Log($"TPCore: TeleportEntity: Teleporting entity {entity.EntityId}"); - + public static void TeleportEntity(IMyEntity entity, IMyCollector sourceGateway, IMyCollector destGateway) + { var relativePosition = entity.GetPosition() - sourceGateway.GetPosition(); var localPosition = Vector3D.TransformNormal(relativePosition, MatrixD.Invert(sourceGateway.WorldMatrix)); var newPosition = Vector3D.TransformNormal(localPosition, destGateway.WorldMatrix) + destGateway.GetPosition(); @@ -188,13 +187,16 @@ public static void TeleportEntity(IMyEntity entity, IMyCollector sourceGateway, var newOrientation = relativeOrientation * destGateway.WorldMatrix; var character = entity as IMyCharacter; - if (character != null) { + if (character != null) + { character.Teleport(newOrientation); character.SetWorldMatrix(newOrientation); } - else { + else + { var grid = entity as IMyCubeGrid; - if (grid != null) { + if (grid != null) + { TeleportGrid(grid, newOrientation, sourceGateway.WorldMatrix, destGateway.WorldMatrix); } } @@ -202,77 +204,99 @@ public static void TeleportEntity(IMyEntity entity, IMyCollector sourceGateway, MyLogger.Log($"TPCore: TeleportEntity: Entity {entity.EntityId} teleported to {newPosition}"); } - private static void TeleportGrid(IMyCubeGrid mainGrid, MatrixD newOrientation, MatrixD sourceGatewayMatrix, MatrixD destinationGatewayMatrix) { - var allGrids = new List(); - MyAPIGateway.GridGroups.GetGroup(mainGrid, GridLinkTypeEnum.Physical, allGrids); + private static void TeleportGrid(IMyCubeGrid mainGrid, MatrixD newOrientation, MatrixD sourceGatewayMatrix, MatrixD destinationGatewayMatrix) + { + MyLogger.Log($"TPGate: TeleportGrid: Starting teleport for main grid {mainGrid.DisplayName} (EntityId: {mainGrid.EntityId})"); + + // Get all physically connected grids (including mechanical connections like landing gear) + var allConnectedGrids = new HashSet(); + var physicalGroup = MyAPIGateway.GridGroups.GetGridGroup(GridLinkTypeEnum.Physical, mainGrid); + var mechanicalGroup = MyAPIGateway.GridGroups.GetGridGroup(GridLinkTypeEnum.Mechanical, mainGrid); - // Create a new list for subgrids, excluding the main grid - var subgrids = allGrids.Where(grid => grid != mainGrid).ToList(); + if (physicalGroup != null) + { + MyAPIGateway.GridGroups.GetGroup(mainGrid, GridLinkTypeEnum.Physical, allConnectedGrids); + MyLogger.Log($"TPGate: TeleportGrid: Found {allConnectedGrids.Count} physically connected grids"); + } - // Dictionary to store the local matrices of each subgrid relative to the main grid - Dictionary relativeLocalMatrices = new Dictionary(); + if (mechanicalGroup != null) + { + MyAPIGateway.GridGroups.GetGroup(mainGrid, GridLinkTypeEnum.Mechanical, allConnectedGrids); + MyLogger.Log($"TPGate: TeleportGrid: Added mechanical connections, total grids: {allConnectedGrids.Count}"); + } - // Calculate and store the relative local matrix for each subgrid - foreach (var subgrid in subgrids) { - MatrixD relativeMatrix = subgrid.WorldMatrix * MatrixD.Invert(mainGrid.WorldMatrix); - relativeLocalMatrices[subgrid] = relativeMatrix; - MyLogger.Log($"TPCore: TeleportGrid: Calculated relative matrix for subgrid {subgrid.DisplayName} (EntityId: {subgrid.EntityId}), Relative Matrix: {relativeMatrix}"); + // Calculate relative positions before any teleporting + var relativeMatrices = new Dictionary(); + foreach (var grid in allConnectedGrids) + { + if (grid != mainGrid) + { + MatrixD relativeMatrix = grid.WorldMatrix * MatrixD.Invert(mainGrid.WorldMatrix); + relativeMatrices[grid] = relativeMatrix; + MyLogger.Log($"TPGate: TeleportGrid: Calculated relative matrix for grid {grid.DisplayName} (EntityId: {grid.EntityId})"); + } } - // Teleport the main grid using both Teleport and WorldMatrix setting - MyLogger.Log($"TPCore: TeleportGrid: Teleporting main grid {mainGrid.DisplayName} (EntityId: {mainGrid.EntityId}), New Orientation: {newOrientation}"); + // First teleport the main grid + MyLogger.Log($"TPGate: TeleportGrid: Teleporting main grid to new position"); mainGrid.Teleport(newOrientation); - mainGrid.WorldMatrix = newOrientation; //double prevents most wiggle + mainGrid.WorldMatrix = newOrientation; - // Update physics for the main grid + // Update main grid physics var mainPhysics = mainGrid.Physics; - if (mainPhysics != null) { + if (mainPhysics != null) + { mainPhysics.LinearVelocity = Vector3D.Zero; mainPhysics.AngularVelocity = Vector3D.Zero; - float naturalGravityInterference; var naturalGravity = MyAPIGateway.Physics.CalculateNaturalGravityAt(mainGrid.PositionComp.WorldAABB.Center, out naturalGravityInterference); mainPhysics.Gravity = naturalGravity; - MyLogger.Log($"TPCore: TeleportGrid: Updated physics for main grid {mainGrid.DisplayName} (EntityId: {mainGrid.EntityId}), Linear Velocity: {mainPhysics.LinearVelocity}, Angular Velocity: {mainPhysics.AngularVelocity}, Gravity: {mainPhysics.Gravity}"); + MyLogger.Log($"TPGate: TeleportGrid: Updated main grid physics - Gravity: {naturalGravity}"); } - // HashSet to track processed subgrids - HashSet processedSubgrids = new HashSet(); - - // Transform and update all subgrids - foreach (var subgrid in subgrids) { - if (processedSubgrids.Contains(subgrid.EntityId)) { - MyLogger.Log($"TPCore: TeleportGrid: Skipping already processed subgrid {subgrid.DisplayName} (EntityId: {subgrid.EntityId})"); + // Now teleport all connected grids + foreach (var grid in allConnectedGrids) + { + if (grid == mainGrid) continue; - } - try { - MatrixD newGridWorldMatrix = relativeLocalMatrices[subgrid] * mainGrid.WorldMatrix; - MyLogger.Log($"TPCore: TeleportGrid: Calculating new WorldMatrix for subgrid {subgrid.DisplayName} (EntityId: {subgrid.EntityId}), New World Matrix: {newGridWorldMatrix}"); - subgrid.WorldMatrix = newGridWorldMatrix; - MyLogger.Log($"TPCore: TeleportGrid: Updated WorldMatrix for subgrid {subgrid.DisplayName} (EntityId: {subgrid.EntityId}), New World Matrix: {newGridWorldMatrix}"); + try + { + MatrixD newGridMatrix = relativeMatrices[grid] * mainGrid.WorldMatrix; + grid.WorldMatrix = newGridMatrix; - var physics = subgrid.Physics; - if (physics != null) { + var physics = grid.Physics; + if (physics != null) + { physics.LinearVelocity = Vector3D.Zero; physics.AngularVelocity = Vector3D.Zero; physics.Gravity = mainPhysics?.Gravity ?? Vector3.Zero; - MyLogger.Log($"TPCore: TeleportGrid: Updated physics for subgrid {subgrid.DisplayName} (EntityId: {subgrid.EntityId}), Linear Velocity: {physics.LinearVelocity}, Angular Velocity: {physics.AngularVelocity}, Gravity: {physics.Gravity}"); } - // Mark this subgrid as processed - processedSubgrids.Add(subgrid.EntityId); + MyLogger.Log($"TPGate: TeleportGrid: Teleported connected grid {grid.DisplayName} (EntityId: {grid.EntityId})"); } - catch (Exception ex) { - MyLogger.Log($"TPCore: TeleportGrid: Exception occurred while handling subgrid {subgrid.DisplayName} (EntityId: {subgrid.EntityId}): {ex.Message}"); + catch (Exception ex) + { + MyLogger.Log($"TPGate: TeleportGrid: Error teleporting grid {grid.DisplayName}: {ex.Message}"); } } - // These last two get rid of connector based wiggle - mainGrid.Teleport(newOrientation); - mainGrid.WorldMatrix = newOrientation; + // Verify connections are maintained + var finalPhysicalGroup = MyAPIGateway.GridGroups.GetGridGroup(GridLinkTypeEnum.Physical, mainGrid); + var finalMechanicalGroup = MyAPIGateway.GridGroups.GetGridGroup(GridLinkTypeEnum.Mechanical, mainGrid); + + if (finalPhysicalGroup != null && finalMechanicalGroup != null) + { + var finalConnectedGrids = new HashSet(); + MyAPIGateway.GridGroups.GetGroup(mainGrid, GridLinkTypeEnum.Physical, finalConnectedGrids); + MyAPIGateway.GridGroups.GetGroup(mainGrid, GridLinkTypeEnum.Mechanical, finalConnectedGrids); - MyLogger.Log($"TPCore: TeleportGrid: Teleportation complete for main grid {mainGrid.DisplayName} (EntityId: {mainGrid.EntityId}) and its {subgrids.Count} subgrids"); + MyLogger.Log($"TPGate: TeleportGrid: Final connected grids count: {finalConnectedGrids.Count}"); + if (finalConnectedGrids.Count != allConnectedGrids.Count) + { + MyLogger.Log($"TPGate: TeleportGrid: Warning - Grid connections may have been affected during teleport"); + } + } } public static void ClientApplyTeleportResponse(TeleportResponseMessage message) { diff --git a/Ringway/Data/Scripts/TeleportGateway/TeleportGateway.cs b/Ringway/Data/Scripts/TeleportGateway/TeleportGateway.cs index 05e4ad3..e886fce 100644 --- a/Ringway/Data/Scripts/TeleportGateway/TeleportGateway.cs +++ b/Ringway/Data/Scripts/TeleportGateway/TeleportGateway.cs @@ -21,6 +21,7 @@ using VRage.Game.ObjectBuilders.Definitions; using IMyTerminalBlock = Sandbox.ModAPI.IMyTerminalBlock; using VRage.Noise.Patterns; +using System.Linq; namespace TeleportMechanisms { [MyEntityComponentDescriptor(typeof(MyObjectBuilder_Collector), false, @@ -887,7 +888,6 @@ public static void ProcessJumpRequest(long gatewayId, string link) return; } - // If already teleporting, don't start another jump if (sourceGatewayLogic._isTeleporting) { MyLogger.Log("TPCore: ProcessJumpRequest: Gateway is already teleporting"); @@ -906,91 +906,133 @@ public static void ProcessJumpRequest(long gatewayId, string link) List gatewayGridGroup = new List(); MyAPIGateway.GridGroups.GetGroup(sourceGateway.CubeGrid, GridLinkTypeEnum.Physical, gatewayGridGroup); - // Schedule the actual teleport MyAPIGateway.Utilities.InvokeOnGameThread(() => { - float sphereRadius = sourceGatewayLogic.Settings.SphereDiameter / 2.0f; - Vector3D sphereCenter = sourceGateway.GetPosition() + sourceGateway.WorldMatrix.Forward * sphereRadius; - BoundingSphereD sphere = new BoundingSphereD(sphereCenter, sphereRadius); - - List entitiesInSphere = MyAPIGateway.Entities.GetEntitiesInSphere(ref sphere); - int teleportedCount = 0; - - foreach (var entity in entitiesInSphere) + try { - bool shouldTeleport = false; - var character = entity as IMyCharacter; - var grid = entity as IMyCubeGrid; - - if (character != null && sourceGatewayLogic.Settings.AllowPlayers) - { - shouldTeleport = true; - } - else if (grid != null && sourceGatewayLogic.Settings.AllowShips) + float sphereRadius = sourceGatewayLogic.Settings.SphereDiameter / 2.0f; + Vector3D sphereCenter = sourceGateway.GetPosition() + sourceGateway.WorldMatrix.Forward * sphereRadius; + BoundingSphereD sphere = new BoundingSphereD(sphereCenter, sphereRadius); + + List entitiesInSphere = MyAPIGateway.Entities.GetEntitiesInSphere(ref sphere); + Dictionary> gridGroups = new Dictionary>(); + HashSet processedGrids = new HashSet(); + List charactersToTeleport = new List(); + int teleportedCount = 0; + + // First pass - identify all entities to teleport + foreach (var entity in entitiesInSphere) { - // Check 1: Skip if grid is static - if (grid.IsStatic) + // Handle characters + var character = entity as IMyCharacter; + if (character != null) { - MyLogger.Log($"TPGate: ProcessJumpRequest: Skipping static grid {grid.DisplayName}"); + if (sourceGatewayLogic.Settings.AllowPlayers) + { + charactersToTeleport.Add(character); + MyLogger.Log($"TPGate: ProcessJumpRequest: Found character to teleport"); + } continue; } - // Check 2: Skip if grid is part of the gateway's GridGroup - if (gatewayGridGroup.Contains(grid)) + // Handle grids + var grid = entity as IMyCubeGrid; + if (grid == null || grid.IsStatic || processedGrids.Contains(grid) || gatewayGridGroup.Contains(grid)) { - MyLogger.Log($"TPGate: ProcessJumpRequest: Skipping grid {grid.DisplayName} as it's part of the gateway's GridGroup"); + if (grid != null) + { + MyLogger.Log($"TPGate: ProcessJumpRequest: Skipping grid {grid.DisplayName} - Static: {grid.IsStatic}, Already Processed: {processedGrids.Contains(grid)}, Gateway Grid: {gatewayGridGroup.Contains(grid)}"); + } continue; } - // Additional existing checks - List landingGears = new List(); - grid.GetBlocks(landingGears, b => b.FatBlock is SpaceEngineers.Game.ModAPI.Ingame.IMyLandingGear); - bool hasLockedGear = false; + if (!sourceGatewayLogic.Settings.AllowShips) + { + MyLogger.Log($"TPGate: ProcessJumpRequest: Ships not allowed, skipping grid {grid.DisplayName}"); + continue; + } + + // Get connected grids + HashSet connectedGrids = new HashSet(); + MyAPIGateway.GridGroups.GetGroup(grid, GridLinkTypeEnum.Physical, connectedGrids); + MyAPIGateway.GridGroups.GetGroup(grid, GridLinkTypeEnum.Mechanical, connectedGrids); - foreach (var gear in landingGears) + MyLogger.Log($"TPGate: ProcessJumpRequest: Found grid group with {connectedGrids.Count} connected grids"); + + // Check for locked landing gear in the group + bool hasLockedLandingGear = false; + foreach (var connectedGrid in connectedGrids) { - var landingGear = gear.FatBlock as SpaceEngineers.Game.ModAPI.Ingame.IMyLandingGear; - if (landingGear != null && landingGear.IsLocked) + List landingGears = new List(); + connectedGrid.GetBlocks(landingGears, b => b.FatBlock is SpaceEngineers.Game.ModAPI.Ingame.IMyLandingGear); + + foreach (var gear in landingGears) { - hasLockedGear = true; - break; + var landingGear = gear.FatBlock as SpaceEngineers.Game.ModAPI.Ingame.IMyLandingGear; + if (landingGear != null && landingGear.IsLocked) + { + hasLockedLandingGear = true; + MyLogger.Log($"TPGate: ProcessJumpRequest: Found locked landing gear on grid {connectedGrid.DisplayName}"); + break; + } } + if (hasLockedLandingGear) break; + } + + if (hasLockedLandingGear) + { + MyLogger.Log($"TPGate: ProcessJumpRequest: Skipping grid group due to locked landing gear"); + continue; } - if (!hasLockedGear) + // Find the main grid + var mainGrid = connectedGrids + .Select(g => g.GetTopMostParent() as IMyCubeGrid) + .FirstOrDefault(g => g != null); + + if (mainGrid != null && !gridGroups.ContainsKey(mainGrid.EntityId)) { - shouldTeleport = true; + gridGroups[mainGrid.EntityId] = connectedGrids; + MyLogger.Log($"TPGate: ProcessJumpRequest: Added grid group with main grid {mainGrid.DisplayName} (EntityId: {mainGrid.EntityId})"); } + + processedGrids.UnionWith(connectedGrids); } - if (shouldTeleport) + // Teleport characters + foreach (var character in charactersToTeleport) { - TeleportCore.TeleportEntity(entity, sourceGateway, destGateway); + TeleportCore.TeleportEntity(character, sourceGateway, destGateway); teleportedCount++; + MyVisualScriptLogicProvider.CreateParticleEffectAtPosition("InvalidCustomBlinkParticleEnter", character.GetPosition()); + MyVisualScriptLogicProvider.PlaySingleSoundAtPosition("ShipPrototechJumpDriveJumpIn", character.GetPosition()); + MyLogger.Log($"TPGate: ProcessJumpRequest: Teleported character"); + } - MyVisualScriptLogicProvider.CreateParticleEffectAtPosition( - "InvalidCustomBlinkParticleEnter", - entity.GetPosition() - ); - MyVisualScriptLogicProvider.PlaySingleSoundAtPosition( - "ShipPrototechJumpDriveJumpIn", - entity.GetPosition() - ); + // Teleport grid groups + foreach (var group in gridGroups) + { + var mainGrid = MyAPIGateway.Entities.GetEntityById(group.Key) as IMyCubeGrid; + if (mainGrid == null) continue; + + TeleportCore.TeleportEntity(mainGrid, sourceGateway, destGateway); + teleportedCount += group.Value.Count; + MyVisualScriptLogicProvider.CreateParticleEffectAtPosition("InvalidCustomBlinkParticleEnter", mainGrid.GetPosition()); + MyVisualScriptLogicProvider.PlaySingleSoundAtPosition("ShipPrototechJumpDriveJumpIn", mainGrid.GetPosition()); + MyLogger.Log($"TPGate: ProcessJumpRequest: Teleported grid group with main grid {mainGrid.DisplayName}"); } - } - if (teleportedCount > 0) + if (teleportedCount > 0) + { + MyLogger.Log($"TPGate: ProcessJumpRequest: Teleported {teleportedCount} entities ({charactersToTeleport.Count} characters and {gridGroups.Count} grid groups)"); + NotifyPlayersInRange($"Teleported {teleportedCount} entities", sourceGateway.GetPosition(), 100, "White"); + } + } + catch (Exception ex) { - MyLogger.Log($"TPGate: ProcessJumpRequest: Teleported {teleportedCount} entities"); - NotifyPlayersInRange( - $"Teleported {teleportedCount} entities", - sourceGateway.GetPosition(), - 100, - "White" - ); + MyLogger.Log($"TPGate: ProcessJumpRequest: Exception during teleport: {ex}"); } - // Reset teleporting state sourceGatewayLogic._isTeleporting = false; sourceGatewayLogic._showSphereDuringCountdown = false; @@ -998,5 +1040,11 @@ public static void ProcessJumpRequest(long gatewayId, string link) MyLogger.Log($"TPGate: ProcessJumpRequest: Scheduled teleport after {sourceGatewayLogic._teleportCountdown / 60f}s"); } + + private static void CreateTeleportEffects(Vector3D position) + { + MyVisualScriptLogicProvider.CreateParticleEffectAtPosition("InvalidCustomBlinkParticleEnter", position); + MyVisualScriptLogicProvider.PlaySingleSoundAtPosition("ShipPrototechJumpDriveJumpIn", position); + } } }