diff --git a/Layman's SafeZone/Data/CubeBlocks_Communications.sbc b/Layman's SafeZone/Data/CubeBlocks_Communications.sbc index 7fb4df99..189086a8 100644 --- a/Layman's SafeZone/Data/CubeBlocks_Communications.sbc +++ b/Layman's SafeZone/Data/CubeBlocks_Communications.sbc @@ -26,7 +26,7 @@ - + diff --git a/Ringway/Data/Scripts/minified_output.txt b/Ringway/Data/Scripts/minified_output.txt deleted file mode 100644 index ba9bbb25..00000000 --- a/Ringway/Data/Scripts/minified_output.txt +++ /dev/null @@ -1 +0,0 @@ -using System;using System.Text;using Sandbox.ModAPI;using VRage.Utils;using VRage.Game.ModAPI;using System.IO;using VRage.Game;using VRage.Game.ModAPI.Ingame.Utilities;namespace TeleportMechanisms{public static class MyLogger{private const string LogFileName="TPGatewayMod.log";private const string ConfigFileName="TPGateway.ini";private static System.IO.TextWriter _writer=null;private static StringBuilder _cache=new StringBuilder();private static MyIni _config=new MyIni();private static bool _writeToCustomLog;private static bool _writeToIngameLog;private const int CurrentConfigVersion=1;private static object _lock=new object();private static bool _isInitialized=false;public static void LoadConfig(){lock(_lock){if(_isInitialized)return;if(!MyAPIGateway.Utilities.FileExistsInWorldStorage(ConfigFileName,typeof(MyLogger))){CreateDefaultConfig();}else{using(var reader=MyAPIGateway.Utilities.ReadFileInWorldStorage(ConfigFileName,typeof(MyLogger))){string configContent=reader.ReadToEnd();MyIniParseResult result;if(!_config.TryParse(configContent,out result)){throw new Exception($"Failed to parse config file: {result.ToString()}");}}if(!_config.ContainsSection("Version")||_config.Get("Version","ConfigVersion").ToInt32()(data);TeleportGateway instance;if(TeleportCore._instances.TryGetValue(message.EntityId,out instance)){instance.ApplySettings(message.Settings);MyLogger.Log($"NetworkHandler: HandleSyncSettings: Applied settings to EntityId: {message.EntityId}");}else{MyLogger.Log($"NetworkHandler: HandleSyncSettings: No instance found for EntityId: {message.EntityId}");}if(MyAPIGateway.Multiplayer.IsServer){MyAPIGateway.Multiplayer.SendMessageToOthers(SyncSettingsId,data);}}private static void HandleTeleportRequest(byte[]data){MyLogger.Log("NetworkHandler: HandleTeleportRequest: called");if(!MyAPIGateway.Multiplayer.IsServer){MyLogger.Log("NetworkHandler: HandleTeleportRequest: Not server, ignoring TeleportRequest");return;}var message=MyAPIGateway.Utilities.SerializeFromBinary(data);TeleportCore.ServerProcessTeleportRequest(message);}private static void HandleTeleportResponse(byte[]data){MyLogger.Log("NetworkHandler: HandleTeleportResponse: called");if(MyAPIGateway.Multiplayer.IsServer){MyLogger.Log("NetworkHandler: HandleTeleportResponse: Server received TeleportResponse, ignoring");return;}var message=MyAPIGateway.Utilities.SerializeFromBinary(data);TeleportCore.ClientApplyTeleportResponse(message);}private static void HandleJumpRequest(byte[]data){if(!MyAPIGateway.Multiplayer.IsServer)return;var message=MyAPIGateway.Utilities.SerializeFromBinary(data);TeleportGateway.ProcessJumpRequest(message.GatewayId,message.Link);}}}using Sandbox.ModAPI;using VRage.Game.Components;namespace TeleportMechanisms{[MySessionComponentDescriptor(MyUpdateOrder.BeforeSimulation|MyUpdateOrder.AfterSimulation)]public class Session:MySessionComponentBase{private static bool _isInitialized=false;public override void LoadData(){if(!_isInitialized&&MyAPIGateway.Session.IsServer){MyLogger.LoadConfig();_isInitialized=true;}MyLogger.Log("Session: LoadData called");NetworkHandler.Register();}protected override void UnloadData(){MyLogger.Log("Session: UnloadData called");NetworkHandler.Unregister();if(_isInitialized&&MyAPIGateway.Session.IsServer){MyLogger.Close();_isInitialized=false;}}}}using System;using System.Collections.Generic;using Sandbox.ModAPI;using VRage.Game;using VRage.Game.ModAPI;using VRage.Utils;using VRageMath;namespace TeleportMechanisms{public static class TeleportBubbleManager{private static readonly Dictionary_bubblePositions=new Dictionary();private static readonly object _lock=new object();private static readonly Color _bubbleColor=new Color(0,0,255,64);public static void CreateOrUpdateBubble(IMyTerminalBlock gateway){var gatewayLogic=gateway.GameLogic.GetAs();if(gatewayLogic==null||!gatewayLogic.Settings.ShowSphere){RemoveBubble(gateway);return;}lock(_lock){float sphereRadius=gatewayLogic.Settings.SphereDiameter/2.0f;Vector3D position=gateway.GetPosition()+gateway.WorldMatrix.Forward*sphereRadius;_bubblePositions[gateway.EntityId]=position;}}public static void DrawBubble(IMyTerminalBlock gateway){try{if(MyAPIGateway.Utilities.IsDedicated){return;}if(MyAPIGateway.Session==null){return;}var gatewayLogic=gateway.GameLogic.GetAs();if(gatewayLogic==null||!gatewayLogic.Settings.ShowSphere){return;}Vector3D position;lock(_lock){if(!_bubblePositions.TryGetValue(gateway.EntityId,out position)){return;}}float radius=gatewayLogic.Settings.SphereDiameter/2.0f;MatrixD worldMatrix=gateway.WorldMatrix;MatrixD adjustedMatrix=MatrixD.CreateWorld(position,worldMatrix.Forward,worldMatrix.Up);Color bubbleColor=_bubbleColor;MySimpleObjectDraw.DrawTransparentSphere(ref adjustedMatrix,radius,ref bubbleColor,MySimpleObjectRasterizer.Solid,20,null,MyStringId.GetOrCompute("Square"));}catch(Exception exc){MyLog.Default.WriteLineAndConsole($"TeleportBubbleManager: Error drawing bubble: {exc.Message}\n{exc.StackTrace}");}}public static void RemoveBubble(IMyTerminalBlock gateway){lock(_lock){_bubblePositions.Remove(gateway.EntityId);}}}}using Sandbox.Game.EntityComponents;using Sandbox.ModAPI;using VRage.Game.Components;using VRage.Game.ModAPI;using VRageMath;using System.Collections.Generic;using VRage.Utils;using VRage.ModAPI;using System.Linq;using Sandbox.Common.ObjectBuilders;using VRage.Game.ObjectBuilders;using VRage.ObjectBuilders;using VRage.Game;using System;using System.Security.Cryptography;using Sandbox.Game.Entities.Cube;using SpaceEngineers.Game.ModAPI.Ingame;using Sandbox.Game.Entities;using System.Reflection.Emit;namespace TeleportMechanisms{public static class TeleportCore{internal static Dictionary>_TeleportLinks=new Dictionary>();internal static Dictionary_instances=new Dictionary();internal static readonly object _lock=new object();public static void UpdateTeleportLinks(){lock(_lock){_TeleportLinks.Clear();MyLogger.Log($"TPCore: UpdateTeleportLinks: Updating Teleport links. Total instances: {_instances.Count}");var gateways=new HashSet();foreach(var instance in _instances.Values){if(instance.Block!=null&&(instance.Block.BlockDefinition.SubtypeName=="LargeTeleportGateway"||instance.Block.BlockDefinition.SubtypeName=="SmallTeleportGateway")){MyLogger.Log($"TPCore: UpdateTeleportLinks: Found instance gateway: {instance.Block.CustomName}, EntityId: {instance.Block.EntityId}, IsWorking: {instance.Block.IsWorking}");gateways.Add(instance.Block);}else{MyLogger.Log($"TPCore: UpdateTeleportLinks: Instance has null or invalid gateway");}}MyLogger.Log($"TPCore: UpdateTeleportLinks: Total gateways found: {gateways.Count}");foreach(var gateway in gateways){var gatewayLogic=gateway.GameLogic.GetAs();var link=GetTeleportLink(gateway);if(!string.IsNullOrEmpty(link)){if(!_TeleportLinks.ContainsKey(link)){_TeleportLinks[link]=new List();}_TeleportLinks[link].Add(gateway.EntityId);MyLogger.Log($"TPCore: UpdateTeleportLinks: Added gateway {gateway.CustomName} (EntityId: {gateway.EntityId}) to link {link}. AllowPlayers: {gatewayLogic.Settings.AllowPlayers}, AllowShips: {gatewayLogic.Settings.AllowShips}");}else{MyLogger.Log($"TPCore: UpdateTeleportLinks: Gateway {gateway.CustomName} (EntityId: {gateway.EntityId}) does not have a valid teleport link");}}MyLogger.Log($"TPCore: UpdateTeleportLinks: Total Teleport links: {_TeleportLinks.Count}");foreach(var kvp in _TeleportLinks){MyLogger.Log($"TPCore: UpdateTeleportLinks: Link {kvp.Key}: {string.Join(", ",kvp.Value)}");}}}public static string GetTeleportLink(IMyTerminalBlock gateway){var gatewayLogic=gateway.GameLogic.GetAs();if(gatewayLogic!=null){MyLogger.Log($"TPCore: GetTeleportLink: GatewayName: {gatewayLogic.Settings.GatewayName}, AllowPlayers: {gatewayLogic.Settings.AllowPlayers}, AllowShips: {gatewayLogic.Settings.AllowShips}");return gatewayLogic.Settings.GatewayName;}return null;}public static void RequestTeleport(long playerId,long sourceGatewayId,string link){MyLogger.Log($"TPCore: RequestTeleport: Player {playerId}, Gateway {sourceGatewayId}, Link {link}");var message=new TeleportRequestMessage{PlayerId=(ulong)playerId,SourceGatewayId=sourceGatewayId,TeleportLink=link};var data=MyAPIGateway.Utilities.SerializeToBinary(message);MyLogger.Log($"TPCore: RequestTeleport: Sending teleport request to server for player {playerId}");MyAPIGateway.Multiplayer.SendMessageToServer(NetworkHandler.TeleportRequestId,data);}public static void ServerProcessTeleportRequest(TeleportRequestMessage message){MyLogger.Log($"TPCore: ProcessTeleportRequest: Player {message.PlayerId}, Link {message.TeleportLink}");MyLogger.Log($"TPCore: ProcessTeleportRequest: Current Teleport links: {string.Join(", ",_TeleportLinks.Keys)}");ListlinkedGateways;lock(_lock){if(!_TeleportLinks.TryGetValue(message.TeleportLink,out linkedGateways)){MyLogger.Log($"TPCore: ProcessTeleportRequest: No linked gateways found for link {message.TeleportLink}");return;}}MyLogger.Log($"TPCore: ProcessTeleportRequest: Found {linkedGateways.Count} linked gateways for link {message.TeleportLink}");if(linkedGateways.Count<2){MyLogger.Log("TPCore: ProcessTeleportRequest: At least two linked gateways are required for teleportation. Aborting.");return;}var sourceIndex=linkedGateways.IndexOf(message.SourceGatewayId);if(sourceIndex==-1){MyLogger.Log($"TPCore: ProcessTeleportRequest: Source gateway {message.SourceGatewayId} not found in linked gateways");return;}var destIndex=(sourceIndex+1)%linkedGateways.Count;var destGatewayId=linkedGateways[destIndex];var destGateway=MyAPIGateway.Entities.GetEntityById(destGatewayId)as IMyTerminalBlock;if(destGateway==null){MyLogger.Log($"TPCore: ProcessTeleportRequest: Destination gateway {destGatewayId} not found");return;}var player=GetPlayerById((long)message.PlayerId);if(player==null||player.Character==null){MyLogger.Log($"TPCore: ProcessTeleportRequest: Player {message.PlayerId} or their character not found");return;}var sourceGateway=MyAPIGateway.Entities.GetEntityById(message.SourceGatewayId)as IMyTerminalBlock;if(sourceGateway==null){MyLogger.Log($"TPCore: ProcessTeleportRequest: Source gateway {message.SourceGatewayId} not found");return;}var sourceGatewayLogic=sourceGateway.GameLogic.GetAs();if(sourceGatewayLogic==null){MyLogger.Log($"TPCore: ProcessTeleportRequest: Could not retrieve TeleportGateway for source gateway {sourceGateway.EntityId}");return;}var sourceGatewaySettings=sourceGatewayLogic.Settings;MyLogger.Log($"TPCore: ProcessTeleportRequest: Source gateway settings - AllowPlayers: {sourceGatewaySettings.AllowPlayers}, AllowShips: {sourceGatewaySettings.AllowShips}");if(!sourceGatewaySettings.AllowPlayers){MyLogger.Log($"TPCore: ProcessTeleportRequest: Player teleportation is not allowed for source gateway {sourceGateway.EntityId}");return;}var isShip=player.Controller.ControlledEntity is IMyCubeBlock;if(isShip&&!sourceGatewaySettings.AllowShips){MyLogger.Log($"TPCore: ProcessTeleportRequest: Ship teleportation is not allowed for source gateway {sourceGateway.EntityId}");return;}TeleportEntity(player.Character,sourceGateway,destGateway);var grid=player.Controller.ControlledEntity?.Entity.GetTopMostParent()as IMyCubeGrid;if(grid!=null){if(grid.IsStatic){MyLogger.Log($"TPCore: ProcessTeleportRequest: Grid {grid.DisplayName} is static, teleportation aborted");return;}if(HasLockedLandingGear(grid)){MyLogger.Log($"TPCore: ProcessTeleportRequest: Grid {grid.DisplayName} has locked landing gear, teleportation aborted");return;}TeleportEntity(grid,sourceGateway,destGateway);}}private static void TeleportEntity(IMyEntity entity,IMyTerminalBlock sourceGateway,IMyTerminalBlock destGateway){MyLogger.Log($"TPCore: TeleportEntity: Teleporting entity {entity.EntityId}");var relativePosition=entity.GetPosition()-sourceGateway.GetPosition();var localPosition=Vector3D.TransformNormal(relativePosition,MatrixD.Invert(sourceGateway.WorldMatrix));var newPosition=Vector3D.TransformNormal(localPosition,destGateway.WorldMatrix)+destGateway.GetPosition();var entityOrientation=entity.WorldMatrix;var relativeOrientation=entityOrientation*MatrixD.Invert(sourceGateway.WorldMatrix);var newOrientation=relativeOrientation*destGateway.WorldMatrix;var character=entity as IMyCharacter;if(character!=null){character.Teleport(newOrientation);character.SetWorldMatrix(newOrientation);}else{var grid=entity as IMyCubeGrid;if(grid!=null){TeleportGrid(grid,newOrientation,sourceGateway.WorldMatrix,destGateway.WorldMatrix);}}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);var subgrids=allGrids.Where(grid=>grid!=mainGrid).ToList();DictionaryrelativeLocalMatrices=new Dictionary();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}");}MyLogger.Log($"TPCore: TeleportGrid: Teleporting main grid {mainGrid.DisplayName} (EntityId: {mainGrid.EntityId}), New Orientation: {newOrientation}");mainGrid.Teleport(newOrientation);mainGrid.WorldMatrix=newOrientation;var mainPhysics=mainGrid.Physics;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}");}HashSetprocessedSubgrids=new HashSet();foreach(var subgrid in subgrids){if(processedSubgrids.Contains(subgrid.EntityId)){MyLogger.Log($"TPCore: TeleportGrid: Skipping already processed subgrid {subgrid.DisplayName} (EntityId: {subgrid.EntityId})");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}");var physics=subgrid.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}");}processedSubgrids.Add(subgrid.EntityId);}catch(Exception ex){MyLogger.Log($"TPCore: TeleportGrid: Exception occurred while handling subgrid {subgrid.DisplayName} (EntityId: {subgrid.EntityId}): {ex.Message}");}}mainGrid.Teleport(newOrientation);mainGrid.WorldMatrix=newOrientation;MyLogger.Log($"TPCore: TeleportGrid: Teleportation complete for main grid {mainGrid.DisplayName} (EntityId: {mainGrid.EntityId}) and its {subgrids.Count} subgrids");}public static void ClientApplyTeleportResponse(TeleportResponseMessage message){MyLogger.Log($"TPCore: ApplyTeleport: Player {message.PlayerId}, Success {message.Success}");if(!message.Success){MyLogger.Log($"TPCore: ApplyTeleport: Teleport unsuccessful for player {message.PlayerId}");return;}var player=GetPlayerById((long)message.PlayerId);if(player==null||player.Character==null){MyLogger.Log($"TPCore: ApplyTeleport: Player {message.PlayerId} or their character not found during teleport");return;}var controlledEntity=player.Controller.ControlledEntity;if(controlledEntity!=null){var topMostParent=controlledEntity.Entity.GetTopMostParent();var grid=topMostParent as IMyCubeGrid;if(grid!=null){MyLogger.Log($"TPCore: ApplyTeleport: Attempting to teleport ship: {grid.DisplayName}");var shipRelativeOrientation=grid.WorldMatrix*MatrixD.Invert(player.Character.WorldMatrix);var newShipOrientation=shipRelativeOrientation*message.NewOrientation;TeleportGrid(grid,newShipOrientation,message.SourceGatewayMatrix,message.DestinationGatewayMatrix);MyLogger.Log($"TPCore: ApplyTeleport: Ship {grid.DisplayName} teleported");}}else{player.Character.Teleport(message.NewOrientation);player.Character.SetWorldMatrix(message.NewOrientation);MyLogger.Log($"TPCore: ApplyTeleport: Player {message.PlayerId} teleported to {message.NewPosition}");}}public static long GetDestinationGatewayId(string link,long sourceGatewayId){ListlinkedGateways;lock(_lock){if(!_TeleportLinks.TryGetValue(link,out linkedGateways)){MyLogger.Log($"TPCore: GetDestinationGatewayId: No linked gateways found for link {link}");return 0;}}MyLogger.Log($"TPCore: GetDestinationGatewayId: Found {linkedGateways.Count} linked gateways for link {link}");if(linkedGateways.Count<2){MyLogger.Log("TPCore: GetDestinationGatewayId: At least two linked gateways are required for teleportation. Aborting.");return 0;}var sourceIndex=linkedGateways.IndexOf(sourceGatewayId);if(sourceIndex==-1){MyLogger.Log($"TPCore: GetDestinationGatewayId: Source gateway {sourceGatewayId} not found in linked gateways");return 0;}var destIndex=(sourceIndex+1)%linkedGateways.Count;return linkedGateways[destIndex];}public static int TeleportNearbyShips(IMyTerminalBlock sourceGateway,IMyTerminalBlock destGateway){var teleportGatewayLogic=sourceGateway.GameLogic.GetAs();if(teleportGatewayLogic==null){MyLogger.Log($"TPCore: TeleportNearbyShips: TeleportGateway logic not found for source gateway {sourceGateway.EntityId}");return 0;}float sphereDiameter=teleportGatewayLogic.Settings.SphereDiameter;float sphereRadius=sphereDiameter/2.0f;Vector3D sphereCenter=sourceGateway.GetPosition()+sourceGateway.WorldMatrix.Forward*sphereRadius;MyLogger.Log($"TPCore: TeleportNearbyShips: Sphere Center: {sphereCenter}, Sphere Diameter: {sphereDiameter}, Sphere Radius: {sphereRadius}");BoundingSphereD sphere=new BoundingSphereD(sphereCenter,sphereRadius);ListpotentialEntities=MyAPIGateway.Entities.GetEntitiesInSphere(ref sphere);MyLogger.Log($"TPCore: TeleportNearbyShips: Potential entities found: {potentialEntities.Count}");int teleportedShipsCount=0;foreach(var entity in potentialEntities){var grid=entity as IMyCubeGrid;if(grid==null||grid.IsStatic||grid.EntityId==sourceGateway.CubeGrid.EntityId){continue;}double distanceToSphereCenter=Vector3D.Distance(grid.WorldVolume.Center,sphereCenter);MyLogger.Log($"TPCore: TeleportNearbyShips: Grid {grid.DisplayName} (EntityId: {grid.EntityId}):");MyLogger.Log($" Distance to sphere center: {distanceToSphereCenter}");MyLogger.Log($" Sphere radius: {sphereRadius}");if(distanceToSphereCenter>sphereRadius){MyLogger.Log($" Grid is outside the teleport sphere, skipping");continue;}if(IsControlledByPlayer(grid)){MyLogger.Log($" Grid is controlled by a player, skipping");continue;}if(IsSubgridOrConnectedToLargerGrid(grid)){MyLogger.Log($" Grid is a subgrid or connected to a larger grid, skipping");continue;}if(HasLockedLandingGear(grid)){MyLogger.Log($" Grid has locked landing gear, skipping");continue;}if(!teleportGatewayLogic.Settings.AllowShips){MyLogger.Log($" Ship teleportation is not allowed for this gateway, skipping");continue;}TeleportEntity(grid,sourceGateway,destGateway);MyLogger.Log($" Teleported grid {grid.DisplayName}");teleportedShipsCount++;}MyLogger.Log($"TPCore: TeleportNearbyShips: Total teleported ships: {teleportedShipsCount}");return teleportedShipsCount;}private static bool IsControlledByPlayer(IMyCubeGrid grid){var blocks=new List();grid.GetBlocks(blocks);foreach(var block in blocks){var controller=block.FatBlock as IMyShipController;if(controller!=null&&controller.Pilot!=null){return true;}}return false;}private static bool IsSubgridOrConnectedToLargerGrid(IMyCubeGrid grid){var group=MyAPIGateway.GridGroups.GetGroup(grid,GridLinkTypeEnum.Physical);IMyCubeGrid largestGrid=null;int largestBlockCount=0;foreach(var g in group){var myGrid=g as MyCubeGrid;if(myGrid!=null&&myGrid.BlocksCount>largestBlockCount){largestGrid=myGrid;largestBlockCount=myGrid.BlocksCount;}}return largestGrid!=null&&largestGrid.EntityId!=grid.EntityId;}private static bool HasLockedLandingGear(IMyCubeGrid grid){ListlandingGears=new List();grid.GetBlocks(landingGears,b=>b.FatBlock is SpaceEngineers.Game.ModAPI.Ingame.IMyLandingGear);foreach(var gear in landingGears){var landingGear=gear.FatBlock as SpaceEngineers.Game.ModAPI.Ingame.IMyLandingGear;if(landingGear!=null&&landingGear.IsLocked){return true;}}return false;}private static IMyPlayer GetPlayerById(long playerId){var playerList=new List();MyAPIGateway.Players.GetPlayers(playerList);return playerList.Find(p=>p.IdentityId==playerId);}}}using Sandbox.Common.ObjectBuilders;using Sandbox.ModAPI;using Sandbox.ModAPI.Interfaces.Terminal;using VRage.Game.Components;using VRage.ObjectBuilders;using VRage.Utils;using VRageMath;using System.Collections.Generic;using System.Text;using ProtoBuf;using VRage.Game.ModAPI;using VRage.Game;using System;using Sandbox.Game.EntityComponents;using VRage.ModAPI;namespace TeleportMechanisms{[MyEntityComponentDescriptor(typeof(MyObjectBuilder_TerminalBlock),false,"LargeTeleportGateway","SmallTeleportGateway")]public class TeleportGateway:MyGameLogicComponent{public IMyTerminalBlock Block{get;private set;}public TeleportGatewaySettings Settings{get;private set;}=new TeleportGatewaySettings();private static bool _controlsCreated=false;private static readonly Guid StorageGuid=new Guid("7F995845-BCEF-4E37-9B47-A035AC2A8E0B");private const int SAVE_INTERVAL_FRAMES=100;private int _frameCounter=0;static TeleportGateway(){CreateControls();}public override void Init(MyObjectBuilder_EntityBase objectBuilder){base.Init(objectBuilder);Block=Entity as IMyTerminalBlock;if(Block==null){MyLogger.Log($"TPGate: Init: Entity is not a terminal block. EntityId: {Entity?.EntityId}");return;}Settings=Load(Block);MyLogger.Log($"TPGate: Init: Initialized for EntityId: {Block.EntityId}, GatewayName: {Settings.GatewayName}");CreateControls();lock(TeleportCore._lock){TeleportCore._instances[Block.EntityId]=this;MyLogger.Log($"TPGate: Init: Added instance for EntityId {Entity.EntityId}. Total instances: {TeleportCore._instances.Count}");}NeedsUpdate=MyEntityUpdateEnum.EACH_FRAME;}public override void UpdateAfterSimulation(){base.UpdateAfterSimulation();if(++_frameCounter>=SAVE_INTERVAL_FRAMES){_frameCounter=0;TrySave();}if(!MyAPIGateway.Utilities.IsDedicated&&MyAPIGateway.Session!=null){TeleportBubbleManager.CreateOrUpdateBubble(Block);TeleportBubbleManager.DrawBubble(Block);}}private void TrySave(){if(!Settings.Changed)return;Save();MyLogger.Log($"TPGate: TrySave: Settings saved for EntityId: {Block.EntityId}");}private void Save(){if(Block.Storage==null){Block.Storage=new MyModStorageComponent();}string serializedData=MyAPIGateway.Utilities.SerializeToXML(Settings);Block.Storage.SetValue(StorageGuid,serializedData);var message=new SyncSettingsMessage{EntityId=Block.EntityId,Settings=this.Settings};var data=MyAPIGateway.Utilities.SerializeToBinary(message);MyAPIGateway.Multiplayer.SendMessageToServer(NetworkHandler.SyncSettingsId,data);Settings.Changed=false;Settings.LastSaved=MyAPIGateway.Session.ElapsedPlayTime;MyLogger.Log($"TPGate: Save: Settings saved for EntityId: {Block.EntityId}");}public void ApplySettings(TeleportGatewaySettings settings){this.Settings=settings;MyLogger.Log($"TPGate: ApplySettings: Applied settings for EntityId: {Block.EntityId}, GatewayName: {Settings.GatewayName}");}private static TeleportGatewaySettings Load(IMyTerminalBlock block){MyLogger.Log($"TPGate: Load: Called. Attempting to load with StorageGuid: {StorageGuid}");if(block==null){MyLogger.Log($"TPGate: Load: Block is null.");return new TeleportGatewaySettings();}if(block.Storage==null){MyLogger.Log($"TPGate: Load: Block Storage is null. Creating new Storage.");block.Storage=new MyModStorageComponent();}MyLogger.Log($"TPGate: Load: Block and Storage not null.");string data;if(block.Storage.TryGetValue(StorageGuid,out data)){MyLogger.Log($"TPGate: Load: blockid:{block.EntityId} Storage had data: {data}");try{var settings=MyAPIGateway.Utilities.SerializeFromXML(data);if(settings!=null){settings.Changed=false;settings.LastSaved=MyAPIGateway.Session.ElapsedPlayTime;MyLogger.Log($"TPGate: Load: Successfully loaded settings.");return settings;}else{MyLogger.Log($"TPGate: Load: Deserialized settings were null.");}}catch(Exception ex){MyLogger.Log($"TPGate: Load - Exception loading settings: {ex}");}}else{MyLogger.Log($"TPGate: Load: No data found for StorageGuid.");}MyLogger.Log($"TPGate: Load: Creating and returning new TeleportGatewaySettings.");var newSettings=new TeleportGatewaySettings();newSettings.Changed=true;return newSettings;}public override void Close(){Save();lock(TeleportCore._lock){TeleportCore._instances.Remove(Block.EntityId);MyLogger.Log($"TPGate: Close: Removed instance for EntityId {Entity.EntityId}. Remaining instances: {TeleportCore._instances.Count}");}TeleportBubbleManager.RemoveBubble(Block);base.Close();}public override bool IsSerialized(){Save();return base.IsSerialized();}private static void CreateControls(){if(_controlsCreated)return;MyLogger.Log("TPGate: CreateControl: Creating custom controls and actions");var controls=new List{CreateGatewayNameControl(),CreateJumpButton(),CreateAllowPlayersCheckbox(),CreateAllowShipsCheckbox(),CreateShowSphereCheckbox(),CreateSphereDiameterSlider()};var actions=new List{CreateJumpAction(),CreateToggleShowSphereAction(),CreateShowSphereOnAction(),CreateShowSphereOffAction()};MyAPIGateway.TerminalControls.CustomControlGetter+=(block,blockControls)=>{if(block is IMyTerminalBlock&&(block.BlockDefinition.SubtypeName=="LargeTeleportGateway"||block.BlockDefinition.SubtypeName=="SmallTeleportGateway")){blockControls.AddRange(controls);}};MyAPIGateway.TerminalControls.CustomActionGetter+=(block,blockActions)=>{if(block is IMyTerminalBlock&&(block.BlockDefinition.SubtypeName=="LargeTeleportGateway"||block.BlockDefinition.SubtypeName=="SmallTeleportGateway")){blockActions.AddRange(actions);}};_controlsCreated=true;MyLogger.Log("TPGate: CreateControl: Custom controls and actions created");}private static IMyTerminalControl CreateGatewayNameControl(){var control=MyAPIGateway.TerminalControls.CreateControl("GatewayName");control.Title=MyStringId.GetOrCompute("Gateway Name");control.Getter=(block)=>{var gateway=block.GameLogic.GetAs();return gateway!=null?new StringBuilder(gateway.Settings.GatewayName):new StringBuilder();};control.Setter=(block,value)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null){gateway.Settings.GatewayName=value.ToString();gateway.Settings.Changed=true;gateway.TrySave();}};control.SupportsMultipleBlocks=false;return control;}private static IMyTerminalControl CreateAllowPlayersCheckbox(){var control=MyAPIGateway.TerminalControls.CreateControl("AllowPlayers");control.Title=MyStringId.GetOrCompute("Allow Players");control.Getter=(block)=>{var gateway=block.GameLogic.GetAs();return gateway!=null?gateway.Settings.AllowPlayers:false;};control.Setter=(block,value)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null){gateway.Settings.AllowPlayers=value;gateway.Settings.Changed=true;gateway.TrySave();MyLogger.Log($"TPGate: AllowPlayers set to {value} for EntityId: {block.EntityId}");}};control.SupportsMultipleBlocks=true;return control;}private static IMyTerminalControl CreateAllowShipsCheckbox(){var control=MyAPIGateway.TerminalControls.CreateControl("AllowShips");control.Title=MyStringId.GetOrCompute("Allow Ships");control.Getter=(block)=>{var gateway=block.GameLogic.GetAs();return gateway!=null?gateway.Settings.AllowShips:false;};control.Setter=(block,value)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null){gateway.Settings.AllowShips=value;gateway.Settings.Changed=true;gateway.TrySave();MyLogger.Log($"TPGate: AllowShips set to {value} for EntityId: {block.EntityId}");}};control.SupportsMultipleBlocks=true;return control;}private static IMyTerminalControl CreateJumpButton(){var control=MyAPIGateway.TerminalControls.CreateControl("JumpButton");control.Title=MyStringId.GetOrCompute("Jump");control.Visible=(block)=>true;control.Action=(block)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null)gateway.JumpAction(block);};return control;}private static IMyTerminalAction CreateJumpAction(){var action=MyAPIGateway.TerminalControls.CreateAction("Jump");action.Name=new StringBuilder("Jump");action.Icon=@"Textures\GUI\Icons\Actions\Jump.dds";action.Action=(block)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null)gateway.JumpAction(block);};action.Writer=(b,sb)=>sb.Append("Initiate Jump");return action;}private static IMyTerminalControl CreateShowSphereCheckbox(){var control=MyAPIGateway.TerminalControls.CreateControl("ShowSphere");control.Title=MyStringId.GetOrCompute("Show Sphere");control.Getter=(block)=>{var gateway=block.GameLogic.GetAs();return gateway!=null?gateway.Settings.ShowSphere:false;};control.Setter=(block,value)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null){gateway.Settings.ShowSphere=value;gateway.Settings.Changed=true;gateway.TrySave();MyLogger.Log($"TPGate: ShowSphere set to {value} for EntityId: {block.EntityId}");}};control.SupportsMultipleBlocks=true;return control;}private static IMyTerminalControl CreateSphereDiameterSlider(){var control=MyAPIGateway.TerminalControls.CreateControl("SphereDiameter");control.Title=MyStringId.GetOrCompute("Sphere Diameter");control.SetLimits(1,300);control.Getter=(block)=>{var gateway=block.GameLogic.GetAs();return gateway!=null?gateway.Settings.SphereDiameter:50.0f;};control.Setter=(block,value)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null){gateway.Settings.SphereDiameter=value;gateway.Settings.Changed=true;gateway.TrySave();}};control.Writer=(block,sb)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null){sb.Append($"{gateway.Settings.SphereDiameter} meters");}};control.SupportsMultipleBlocks=true;return control;}private static IMyTerminalAction CreateToggleShowSphereAction(){var action=MyAPIGateway.TerminalControls.CreateAction("ToggleShowSphere");action.Name=new StringBuilder("Toggle Show Sphere");action.Icon=@"Textures\GUI\Icons\Actions\SwitchOn.dds";action.Action=(block)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null){gateway.Settings.ShowSphere=!gateway.Settings.ShowSphere;gateway.Settings.Changed=true;gateway.TrySave();MyLogger.Log($"TPGate: ShowSphere toggled to {gateway.Settings.ShowSphere} for EntityId: {block.EntityId}");}};action.Writer=(b,sb)=>sb.Append(b.GameLogic.GetAs()?.Settings.ShowSphere==true?"Hide Sphere":"Show Sphere");return action;}private static IMyTerminalAction CreateShowSphereOnAction(){var action=MyAPIGateway.TerminalControls.CreateAction("ShowSphereOn");action.Name=new StringBuilder("Show Sphere On");action.Icon=@"Textures\GUI\Icons\Actions\SwitchOn.dds";action.Action=(block)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null){gateway.Settings.ShowSphere=true;gateway.Settings.Changed=true;gateway.TrySave();MyLogger.Log($"TPGate: ShowSphere set to true for EntityId: {block.EntityId}");}};action.Writer=(b,sb)=>sb.Append("Show Sphere On");return action;}private static IMyTerminalAction CreateShowSphereOffAction(){var action=MyAPIGateway.TerminalControls.CreateAction("ShowSphereOff");action.Name=new StringBuilder("Show Sphere Off");action.Icon=@"Textures\GUI\Icons\Actions\SwitchOff.dds";action.Action=(block)=>{var gateway=block.GameLogic.GetAs();if(gateway!=null){gateway.Settings.ShowSphere=false;gateway.Settings.Changed=true;gateway.TrySave();MyLogger.Log($"TPGate: ShowSphere set to false for EntityId: {block.EntityId}");}};action.Writer=(b,sb)=>sb.Append("Show Sphere Off");return action;}private void JumpAction(IMyTerminalBlock block){MyLogger.Log($"TPGate: JumpAction: Jump action triggered for EntityId: {block.EntityId}");var link=Settings.GatewayName;if(string.IsNullOrEmpty(link))return;if(!MyAPIGateway.Multiplayer.IsServer){MyLogger.Log($"TPGate: JumpAction: Sending jump request to server");var message=new JumpRequestMessage{GatewayId=block.EntityId,Link=link};MyAPIGateway.Multiplayer.SendMessageToServer(NetworkHandler.JumpRequestId,MyAPIGateway.Utilities.SerializeToBinary(message));}else{ProcessJumpRequest(block.EntityId,link);}}public static void ProcessJumpRequest(long gatewayId,string link){MyLogger.Log($"TPGate: ProcessJumpRequest: Processing jump request for gateway {gatewayId}, link {link}");var block=MyAPIGateway.Entities.GetEntityById(gatewayId)as IMyTerminalBlock;if(block==null)return;TeleportCore.UpdateTeleportLinks();var playerList=new List();MyAPIGateway.Players.GetPlayers(playerList);bool teleportAttempted=false;int playersToTeleport=0;int shipsToTeleport=0;foreach(var player in playerList){float sphereRadius=block.GameLogic.GetAs()?.Settings.SphereDiameter/2.0f??25.0f;var distance=Vector3D.Distance(player.GetPosition(),block.GetPosition()+block.WorldMatrix.Forward*sphereRadius);if(distance<=sphereRadius){TeleportCore.RequestTeleport(player.IdentityId,block.EntityId,link);teleportAttempted=true;playersToTeleport++;if(player.Controller.ControlledEntity is IMyShipController){shipsToTeleport++;}}}var destGatewayId=TeleportCore.GetDestinationGatewayId(link,block.EntityId);var destGateway=MyAPIGateway.Entities.GetEntityById(destGatewayId)as IMyTerminalBlock;if(destGateway!=null){var unpilotedShipsCount=TeleportCore.TeleportNearbyShips(block,destGateway);shipsToTeleport+=unpilotedShipsCount;if(unpilotedShipsCount>0){teleportAttempted=true;}}if(teleportAttempted){MyLogger.Log($"TPGate: ProcessJumpRequest: Teleport attempted");MyAPIGateway.Utilities.ShowNotification($"TPGate: Teleporting {playersToTeleport} player(s) and {shipsToTeleport} ship(s)",5000,"White");}}}}using System;using ProtoBuf;namespace TeleportMechanisms{[ProtoContract]public class TeleportGatewaySettings{[ProtoMember(1)]public string GatewayName{get;set;}="";[ProtoMember(2)]public bool AllowPlayers{get;set;}=true;[ProtoMember(3)]public bool AllowShips{get;set;}=true;[ProtoMember(4)]public bool ShowSphere{get;set;}=false;[ProtoMember(5)]public float SphereDiameter{get;set;}=50.0f;[ProtoIgnore]public bool Changed{get;set;}=false;[ProtoIgnore]public TimeSpan LastSaved{get;set;}public TeleportGatewaySettings(){Changed=true;LastSaved=TimeSpan.Zero;}}} diff --git a/Ringway/Data/TeleportGateway.sbc b/Ringway/Data/TeleportGateway.sbc index 2274375b..e2e59746 100644 --- a/Ringway/Data/TeleportGateway.sbc +++ b/Ringway/Data/TeleportGateway.sbc @@ -23,7 +23,7 @@ - + @@ -70,66 +70,6 @@ - - - - TerminalBlock - SmallTeleportGateway - - Small Teleport Gateway - Textures\GUI\Icons\Cubes\TeleportGatewayIcon.dds - A gateway for teleportation - Small - TriangleMesh - - Models\Cubes\Small\FlightMovementBlock.mwm - - - - - - - - - - - - - - - - - - - - - - - TeleportGateway - Y - Z - Light - 10 - Damage_Electrical_Damaged - ParticleElectrical - Utility - 0.001 - Extended - 25 - false - true - true - - - Jump - Jump - - - ToggleShowSphere - Toggle Show Sphere - - -