public static byte[] SerializeAndSign(IMyCubeGrid grid, IMyPlayer player, Vector3I block) { var c = grid.GetCubeBlock(block)?.FatBlock as IMyCockpit; IMyCharacter pilot = c?.Pilot; c?.RemovePilot(); var ob = (MyObjectBuilder_CubeGrid)grid.GetObjectBuilder(); if (pilot != null) { c.AttachPilot(pilot); } IMyFaction fac = MyAPIGateway.Session.Factions.TryGetPlayerFaction(player.IdentityId); var data = new ClientData(ob, fac, block, Settings.Instance.HubIP); string obStr = MyAPIGateway.Utilities.SerializeToXML(data); string totalStr = DateTime.UtcNow.Ticks + obStr; string evalStr = totalStr + Settings.Instance.Password; var m = new MD5(); m.Value = evalStr; totalStr += m.FingerPrint; return(Encoding.UTF8.GetBytes(totalStr)); }
public void ExportGrid(IMyCubeGrid grid, string path) { var ob = grid.GetObjectBuilder(true); using (var f = File.Open(path, FileMode.CreateNew)) MyObjectBuilderSerializer.SerializeXML(f, ob); }
public grid_logic(IMyCubeGrid new_grid) { _grid = new_grid; _grid.OnBlockAdded += on_block_added; _grid.OnBlockRemoved += on_block_removed; sync_helper.register_logic_object(this, _grid.EntityId); _ID_on = ((MyObjectBuilder_CubeGrid)_grid.GetObjectBuilder()).DampenersEnabled; var block_list = new List <IMySlimBlock>(); _grid.GetBlocks(block_list, delegate(IMySlimBlock block) { return(block.FatBlock is IMyThrust || block.FatBlock is IMyGyro || block.FatBlock is IMyCockpit || block.FatBlock is IMyRemoteControl); } ); foreach (var cur_block in block_list) { on_block_added(cur_block); } /* * if (block_list.Count > 0) * { * _ECU = new engine_control_unit(_grid); * foreach (var cur_block in block_list) * { * var thruster = cur_block.FatBlock as IMyThrust; * var gyro = cur_block.FatBlock as IMyGyro; * if (thruster != null) * { * _ECU.assign_thruster(thruster); ++_num_thrusters; * } * if (gyro != null) * _ECU.assign_gyroscope(gyro); * } * } * * * block_list.Clear(); * _grid.GetBlocks(block_list, * delegate (IMySlimBlock block) * { * return block.FatBlock is IMyCockpit || block.FatBlock is IMyRemoteControl; * } * ); * foreach (var cur_controller in block_list) * { * _ship_controllers.Add((IMyControllableEntity) cur_controller.FatBlock); * var RC_block = cur_controller.FatBlock as IMyRemoteControl; * if (RC_block != null) * _RC_blocks.Add(RC_block); * } */ }
private void GetOB(IMyCubeGrid grid) { builder = (MyObjectBuilder_CubeGrid)grid.GetObjectBuilder(true); foreach (var cube in ((MyCubeGrid)grid).GetFatBlocks()) { if (cube is IMyAttachableTopBlock) { definition = cube.BlockDefinition; return; } } }
public static MyObjectBuilder_CubeGrid CleanGrid(IMyCubeGrid ent) { MyObjectBuilder_CubeGrid grid = (MyObjectBuilder_CubeGrid)ent.GetObjectBuilder(); grid.EntityId = 0; grid.AngularVelocity = new SerializableVector3(); grid.LinearVelocity = new SerializableVector3(); grid.PositionAndOrientation = new MyPositionAndOrientation(new Vector3D(), new Vector3(0, 0, 1), new Vector3(0, 1, 0)); grid.XMirroxPlane = null; grid.YMirroxPlane = null; grid.ZMirroxPlane = null; grid.IsStatic = false; grid.CreatePhysics = true; grid.IsRespawnGrid = false; foreach (var block in grid.CubeBlocks) { block.EntityId = 0; } return(grid); }
static public float CalculateMass(IMyEntity entity) { if (!(entity is IMyCubeGrid)) { return(0f); } float mass = 0f; IMyCubeGrid grid = (IMyCubeGrid)entity; MyObjectBuilder_CubeGrid gridObject = (MyObjectBuilder_CubeGrid)grid.GetObjectBuilder(); List <IMySlimBlock> blocks = new List <IMySlimBlock>(); grid.GetBlocks(blocks, null); foreach (IMySlimBlock block in blocks) { MyObjectBuilder_CubeBlock blockObject = block.GetCopyObjectBuilder(); MyCubeBlockDefinition cubeDef = MyDefinitionManager.Static.GetCubeBlockDefinition(blockObject); mass += cubeDef.Mass; } return(mass); }
static MyObjectBuilder_CubeGrid CreateNewGridOB(IMyCubeGrid grid, MyObjectBuilder_CubeBlock blockOb, string gridName) { MyCubeGrid internalGrid = (MyCubeGrid)grid; MyObjectBuilder_CubeGrid gridOb = null; int blockCount = internalGrid.BlocksCount; if (blockCount > 1000) { gridOb = FastGridOBClone(internalGrid, blockOb, gridName); } else { gridOb = (MyObjectBuilder_CubeGrid)grid.GetObjectBuilder(); gridOb.DisplayName = gridName; gridOb.IsStatic = false; gridOb.ConveyorLines = null; if (gridOb.OxygenAmount != null && gridOb.OxygenAmount.Length > 0) { gridOb.OxygenAmount = new float[0]; } if (gridOb.BlockGroups != null) { gridOb.BlockGroups.Clear(); } gridOb.CubeBlocks.Clear(); gridOb.CubeBlocks.Add(blockOb); } MyAPIGateway.Entities.RemapObjectBuilder(gridOb); return(gridOb); }
public void LoadFromCubeGrid(IMyCubeGrid grid) { base.LoadFromEntity(grid as IMyEntity); IngameGrid = grid; //IngameGrid = grid; DisplayName = grid.DisplayName; // ToDo: get all owners instead of big (for targeting) BigOwners = grid.BigOwners; // ToDo: get real spawn owners (for spawning) SpawnOwners = grid.BigOwners; //IMyEntity entity = grid as IMyEntity; Builder = grid.GetObjectBuilder() as MyObjectBuilder_CubeGrid; if (Builder == null) { Log.Error("Got null builder for entity " + EntityId + ". We will be unable to save it now.", "LoadFromCubeGrid"); } else { //Log.Error("Filling builder nulls for " + EntityId, "LoadFromCubeGrid"); //Builder.FillNullsWithDefaults(); } }
public static MyObjectBuilder_CubeGrid SafeGetObjectBuilder( IMyCubeGrid grid ) { MyObjectBuilder_CubeGrid gridBuilder = null; try { gridBuilder = (MyObjectBuilder_CubeGrid)grid.GetObjectBuilder( ); } catch { } return gridBuilder; }
// /admin movefrom x y z x y z radius public override bool HandleCommand(ulong userId, string command) { string[] words = command.Split(' '); HashSet <IMyEntity> entities = new HashSet <IMyEntity>( ); Wrapper.GameAction(() => { MyAPIGateway.Entities.GetEntities(entities, x => x is IMyCubeGrid); }); HashSet <long> playerOwners = new HashSet <long>(); foreach (IMyEntity entity in entities) { IMyCubeGrid grid = (IMyCubeGrid)entity; MyObjectBuilder_CubeGrid gridBlock = (MyObjectBuilder_CubeGrid)grid.GetObjectBuilder(); foreach (MyObjectBuilder_CubeBlock block in gridBlock.CubeBlocks) { if (block.Owner == 0) { continue; } if (!playerOwners.Contains(block.Owner)) { playerOwners.Add(block.Owner); } } } Communication.SendPrivateInformation(userId, string.Format("Total block owners: {0}", playerOwners.Count)); int count = 0; foreach (long owner in playerOwners) { ulong steamId = PlayerMap.Instance.GetPlayerItemFromPlayerId(owner).SteamId; if (steamId == 0) { count++; } } Communication.SendPrivateInformation(userId, string.Format("Total owners without a steam Id: {0}", count)); HashSet <long> badPlayers = new HashSet <long>(); HashSet <long> noLogin = new HashSet <long>(); foreach (long owner in playerOwners) { MyObjectBuilder_Checkpoint.PlayerItem item = PlayerMap.Instance.GetPlayerItemFromPlayerId(owner); if (item.SteamId == 0) { continue; } if (!Players.Instance.PlayerLogins.ContainsKey(item.SteamId)) { Communication.SendPrivateInformation(userId, string.Format("No login information: {0}", item.Name)); noLogin.Add(owner); continue; } PlayerItem playerItem = Players.Instance.PlayerLogins[item.SteamId]; if (DateTime.Now - playerItem.LastLogin > TimeSpan.FromDays(20)) { Communication.SendPrivateInformation(userId, string.Format("Player hasn't logged in 20 days: {0}", item.Name)); badPlayers.Add(owner); } } Communication.SendPrivateInformation(userId, string.Format("Users not logged in the last 20 days: {0}", badPlayers.Count)); Communication.SendPrivateInformation(userId, string.Format("Users with no login information: {0}", noLogin.Count)); /* * count = 0; * List<CubeGridEntity> grids = SectorObjectManager.Instance.GetTypedInternalData<CubeGridEntity>(); * foreach(CubeGridEntity grid in grids) * { * Thread.Sleep(100); * foreach (CubeBlockEntity block in grid.CubeBlocks) * { * MyObjectBuilder_CubeBlock blockBuilder = (MyObjectBuilder_CubeBlock)block.Export(); * if (badPlayers.Contains(blockBuilder.Owner) || noLogin.Contains(blockBuilder.Owner)) * { * //grid.DeleteCubeBlock(block); * block.Dispose(); * count++; * } * } * } */ Wrapper.GameAction(() => { MyAPIGateway.Entities.GetEntities(entities, x => x is IMyCubeGrid); foreach (IMyEntity entity in entities) { IMyCubeGrid grid = (IMyCubeGrid)entity; List <IMySlimBlock> blocks = new List <IMySlimBlock>(); grid.GetBlocks(blocks, x => x.FatBlock != null && x.FatBlock.OwnerId != 0); foreach (IMySlimBlock block in blocks) { IMyCubeBlock cubeBlock = (IMyCubeBlock)block.FatBlock; if (badPlayers.Contains(cubeBlock.OwnerId) || noLogin.Contains(cubeBlock.OwnerId)) { grid.RazeBlock(cubeBlock.Min); count++; } } } }); Communication.SendPrivateInformation(userId, string.Format("Blocks disposed: {0}", count)); return(true); }
private void Process(CommandFeedback feedback, IMyCubeGrid grid) { if (grid.CustomName == null || !grid.CustomName.StartsWithICase("EqProcBuild")) { return; } var ob = grid.GetObjectBuilder(true) as MyObjectBuilder_CubeGrid; if (ob == null) { return; } this.Info("Begin processing {0}", grid.CustomName); feedback?.Invoke("Processing {0}", grid.CustomName); try { var dummyDel = new List <MyTuple <MyObjectBuilder_CubeBlock, string> >(); var blockKeep = new List <MyObjectBuilder_CubeBlock>(); var blockMap = new Dictionary <Vector3I, MyObjectBuilder_CubeBlock>(Vector3I.Comparer); foreach (var block in ob.CubeBlocks) { var mount = false; foreach (var name in block.ConfigNames()) { if (!name.StartsWithICase(MountDelegated) && !name.StartsWithICase(ReservedSpaceDelegated)) { continue; } dummyDel.Add(MyTuple.Create(block, name)); mount = true; break; } if (mount) { continue; } var blockMin = (Vector3I)block.Min; Vector3I blockMax; BlockTransformations.ComputeBlockMax(block, out blockMax); for (var rangeItr = new Vector3I_RangeIterator(ref blockMin, ref blockMax); rangeItr.IsValid(); rangeItr.MoveNext()) { blockMap[rangeItr.Current] = block; } blockKeep.Add(block); } this.Info("Found {0} blocks to keep, {1} block mounts to remap", blockKeep.Count, dummyDel.Count); foreach (var pair in dummyDel) { var block = pair.Item1; var useName = pair.Item2; IEnumerable <Base6Directions.Direction> dirs = Base6Directions.EnumDirections; var def = MyDefinitionManager.Static.GetCubeBlockDefinition(pair.Item1); var transform = new MatrixI(block.BlockOrientation); if (def?.MountPoints != null) { var mountDirs = new HashSet <Base6Directions.Direction>(); foreach (var mount in def.MountPoints) { mountDirs.Add(Base6Directions.GetDirection(Vector3I.TransformNormal(mount.Normal, ref transform))); } } var args = useName.Split(' '); var keepArgs = new List <string>(args.Length); foreach (var arg in args) { if (arg.StartsWithICase(PartDummyUtils.ArgumentMountDirection)) { Base6Directions.Direction dir; if (Enum.TryParse(arg.Substring(2), out dir)) { dirs = new[] { transform.GetDirection(Base6Directions.GetOppositeDirection(dir)) } } ; else { this.Error("Failed to parse direction argument \"{0}\"", arg); feedback?.Invoke("Error: Failed to parse direction argument \"{0}\"", arg); } } else { keepArgs.Add(arg); } } useName = string.Join(" ", keepArgs); MyObjectBuilder_CubeBlock outputBlock = null; var outputDir = Base6Directions.Direction.Forward; foreach (var dir in dirs) { MyObjectBuilder_CubeBlock tmp; if (!blockMap.TryGetValue(block.Min + Base6Directions.GetIntVector(dir), out tmp)) { continue; } if (tmp.ConfigNames().Any(x => x.StartsWithICase(MountDelegated))) { continue; } if (outputBlock != null) { this.Error("Multiple directions found for {0}", pair.Item2); feedback?.Invoke("Error: Multiple directions found for {0}", pair.Item2); } outputBlock = tmp; outputDir = dir; } if (outputBlock == null || !ApplyDelegate(ob, block, useName, outputBlock, outputDir)) { this.Error("Failed to find delegated mount point for {0}", pair.Item2); feedback?.Invoke("Error: Failed to find delegated mount point for {0}", pair.Item2); } } ob.CubeBlocks = blockKeep; // Grab related grids! var relatedGrids = new HashSet <IMyCubeGrid> { grid }; var scanRelated = new Queue <IMyCubeGrid>(); var relatedGridController = new Dictionary <IMyCubeGrid, IMyCubeBlock>(); scanRelated.Enqueue(grid); while (scanRelated.Count > 0) { var subGrid = scanRelated.Dequeue(); IMyCubeBlock controllerForThisGrid = null; relatedGridController.TryGetValue(subGrid, out controllerForThisGrid); subGrid.GetBlocks(null, (y) => { var x = y?.FatBlock; if (x == null) { return(false); } var childGrid = (x as IMyMechanicalConnectionBlock)?.TopGrid; if (childGrid != null && relatedGrids.Add(childGrid)) { scanRelated.Enqueue(childGrid); relatedGridController[childGrid] = x.CubeGrid == grid ? x : controllerForThisGrid; } var parentGrid = (x as IMyAttachableTopBlock)?.Base?.CubeGrid; // ReSharper disable once InvertIf if (parentGrid != null && relatedGrids.Add(parentGrid)) { scanRelated.Enqueue(parentGrid); relatedGridController[parentGrid] = x.CubeGrid == grid ? x : controllerForThisGrid; } return(false); }); } relatedGrids.Remove(grid); var removedNoController = relatedGrids.RemoveWhere(x => !relatedGridController.ContainsKey(x)); if (removedNoController > 0) { this.Error("Failed to find the mechanical connection block for all subgrids. {0} will be excluded", removedNoController); feedback?.Invoke("Error: Failed to find the mechanical connection block for all subgrids. {0} will be excluded", removedNoController); } // Need to add reserved space for subgrids so they don't overlap. So compute that. Yay! foreach (var rel in relatedGrids) { IMyCubeBlock root; if (!relatedGridController.TryGetValue(rel, out root)) { this.Error("Unable to find the mechanical connection for grid {0}", rel.CustomName); feedback?.Invoke("Error: Unable to find the mechanical connection for grid {0}", rel.CustomName); continue; } MyObjectBuilder_CubeBlock blockDest; if (blockMap.TryGetValue(root.Min, out blockDest)) { var blockLocal = (MatrixD) new MatrixI(blockDest.BlockOrientation).GetFloatMatrix(); blockLocal.Translation = (Vector3I)blockDest.Min * grid.GridSize; var blockWorld = MatrixD.Multiply(blockLocal, grid.WorldMatrix); var worldAABB = rel.WorldAABB; worldAABB = Utilities.TransformBoundingBox(worldAABB, MatrixD.Invert(blockWorld)); var gridAABB = new BoundingBoxI(Vector3I.Floor(worldAABB.Min / grid.GridSize), Vector3I.Ceiling(worldAABB.Max / grid.GridSize)); var code = $"{PartMetadata.ReservedSpacePrefix} NE:{gridAABB.Min.X}:{gridAABB.Min.Y}:{gridAABB.Min.Z} PE:{gridAABB.Max.X}:{gridAABB.Max.Y}:{gridAABB.Max.Z}"; this.Info("Added reserved space for subgrid {0}: Spec is \"{1}\"", rel.CustomName, code); if (blockDest.Name == null || blockDest.Name.Trim().Length == 0) { blockDest.Name = code; } else { blockDest.Name += PartMetadata.MultiUseSentinel + code; } } else { this.Error("Unable to find the OB for grid block {0} ({1}, {2}, {3}). Is it a delegate?", (root as IMyTerminalBlock)?.CustomName ?? root.Name, root.Min.X, root.Min.Y, root.Min.Z); feedback?.Invoke("Unable to the find OB for grid block {0} ({1}, {2}, {3}). Was it a delegate?", (root as IMyTerminalBlock)?.CustomName ?? root.Name, root.Min.X, root.Min.Y, root.Min.Z); } } var allGrids = new List <MyObjectBuilder_CubeGrid>(relatedGrids.Count + 1) { ob }; allGrids.AddRange(relatedGrids.Select(relGrid => relGrid.GetObjectBuilder(false)).OfType <MyObjectBuilder_CubeGrid>()); // Compose description: TODO I'd love if this actually worked :/ // var storage = new MyPartMetadata(); // storage.InitFromGrids(ob, allGrids); // var data = Convert.ToBase64String(MyAPIGateway.Utilities.SerializeToBinary(storage.GetObjectBuilder())); var defOut = new MyObjectBuilder_PrefabDefinition() { Id = new SerializableDefinitionId(typeof(MyObjectBuilder_PrefabDefinition), grid.CustomName), CubeGrids = allGrids.ToArray() }; var fileName = grid.CustomName + ".sbc"; this.Info("Saving {1} grids as {0}", fileName, defOut.CubeGrids.Length); feedback?.Invoke("Saving {1} grids as {0}", fileName, defOut.CubeGrids.Length); var mishMash = new MyObjectBuilder_Definitions() { Prefabs = new MyObjectBuilder_PrefabDefinition[] { defOut } }; var writer = MyAPIGateway.Utilities.WriteBinaryFileInLocalStorage(fileName, typeof(DesignTools)); var obCode = MyAPIGateway.Utilities.SerializeToXML(mishMash); obCode = obCode.Replace("encoding=\"utf-16\"", "encoding=\"utf-8\""); writer.Write(Encoding.UTF8.GetBytes(obCode)); writer.Close(); } catch (Exception e) { this.Error("Failed to parse. Error:\n{0}", e.ToString()); } }
/// <summary> /// Rebuilds our conveyor dictionary. This lets us check if two entities are connected by conveyors quickly. /// </summary> /// <param name="entities"></param> public static void RebuildConveyorList(HashSet <IMyEntity> entities) { m_rebuild = false; m_lastRebuild = DateTime.Now; DateTime start = DateTime.Now; try { //Logging.Instance.WriteLine(String.Format("Count: {0}", entities.Count)); m_conveyorCache.Clear(); m_conveyorConnected.Clear(); foreach (IMyEntity entity in entities) { if (!(entity is IMyCubeGrid)) { continue; } IMyCubeGrid grid = (IMyCubeGrid)entity; MyObjectBuilder_CubeGrid gridObject = (MyObjectBuilder_CubeGrid)grid.GetObjectBuilder(); if (gridObject == null || gridObject.ConveyorLines == null) { continue; } foreach (MyObjectBuilder_ConveyorLine line in gridObject.ConveyorLines) { /* * if (slimBlockStart != null && slimBlockStart.FatBlock != null && slimBlockStart.FatBlock.BlockDefinition.TypeId == typeof(MyObjectBuilder_ConveyorConnector)) * { * // Logging.Instance.WriteLine(string.Format("Conveyor Functional: {0} - {1} - {2} - {3} - {4} - {5}", slimBlockStart.FatBlock.IsFunctional, slimBlockStart.FatBlock.IsWorking, IsFunctional(slimBlockStart.FatBlock), slimBlockStart.BuildIntegrity, slimBlockStart.BuildLevelRatio, slimBlockStart.MaxIntegrity)); * } * * if (slimBlockEnd != null && slimBlockEnd.FatBlock != null && slimBlockEnd.FatBlock.BlockDefinition.TypeId == typeof(MyObjectBuilder_ConveyorConnector)) * { * // Logging.Instance.WriteLine(string.Format("Conveyor Functional: {0} - {1} - {2} - {3} - {4} - {5}", slimBlockEnd.FatBlock.IsFunctional, slimBlockEnd.FatBlock.IsWorking, IsFunctional(slimBlockEnd.FatBlock), slimBlockEnd.BuildIntegrity, slimBlockEnd.BuildLevelRatio, slimBlockEnd.MaxIntegrity)); * } * * Logging.Instance.WriteLine(string.Format("Start: {0}", slimBlockStart.FatBlock.BlockDefinition.SubtypeName)); * Logging.Instance.WriteLine(string.Format("End: {0}", slimBlockEnd.FatBlock.BlockDefinition.SubtypeName)); */ IMySlimBlock slimBlockStart = grid.GetCubeBlock((Vector3I)line.StartPosition); if (slimBlockStart == null || slimBlockStart.FatBlock == null || !slimBlockStart.FatBlock.IsFunctional) { continue; } IMySlimBlock slimBlockEnd = grid.GetCubeBlock((Vector3I)line.EndPosition); if (slimBlockEnd == null || slimBlockEnd.FatBlock == null || !slimBlockEnd.FatBlock.IsFunctional) { continue; } ConnectConveyorBlocks(slimBlockStart, slimBlockEnd); } if (m_conveyorConnected.ContainsKey(grid.EntityId)) { long[] connectedBlockId = m_conveyorConnected[grid.EntityId]; m_conveyorConnected.Remove(grid.EntityId); ConnectConveyorBlocks(connectedBlockId); } } foreach (KeyValuePair <long, long[]> p in m_conveyorConnected) { ConnectConveyorBlocks(p.Value); } //Logging.Instance.WriteLine(String.Format("Size: {0}", m_conveyorCache.Count)); } catch (Exception ex) { Logging.Instance.WriteLine(String.Format("RebuildConveyorList: {0}", ex.ToString())); } if (Core.Debug) { Logging.Instance.WriteLine(String.Format("RebuildConveyorList {0}ms", (DateTime.Now - start).Milliseconds)); } }
public override bool HandleCommand(ulong userId, string[] words) { if (!PluginSettings.Instance.DockingEnabled) { return(false); } if (words.Length < 1) { Communication.SendPrivateInformation(userId, GetHelp()); return(true); } String pylonName = String.Join(" ", words); /* * int timeLeft; * if (Entity.CheckCoolDown(pylonName, out timeLeft)) * { * Communication.Message(String.Format("The docking zone '{0}' is on cooldown. Please wait a {1} seconds before trying to dock/undock again.", pylonName, Math.Max(0, timeLeft))); * return; * } */ if (PlayerMap.Instance.GetPlayerIdsFromSteamId(userId).Count < 1) { Communication.SendPrivateInformation(userId, string.Format("Unable to find player Id: {0}", userId)); return(true); } long playerId = PlayerMap.Instance.GetPlayerIdsFromSteamId(userId).First(); Dictionary <String, List <IMyCubeBlock> > testList; List <IMyCubeBlock> beaconList; DockingZone.FindByName(pylonName, out testList, out beaconList, playerId); if (beaconList.Count == 4) { // Check ownership foreach (IMyCubeBlock entityBlock in beaconList) { IMyTerminalBlock terminal = (IMyTerminalBlock)entityBlock; if (!terminal.HasPlayerAccess(playerId)) { Communication.SendPrivateInformation(userId, string.Format("You do not have permission to use '{0}'. You must either own all the beacons or they must be shared with faction.", pylonName)); return(true); } } // Check for bounding box intsection of other docking zones int intersectElement = 0; if (Entity.CheckForIntersection(testList, beaconList, out intersectElement)) { Communication.SendPrivateInformation(userId, string.Format("The docking zone '{0}' intersects with docking zone '{1}'. Make sure you place your docking zones so they don't overlap.", pylonName, testList.ElementAt(intersectElement).Key)); return(true); } // Check if ship already docked in this zone IMyCubeBlock e = beaconList[0]; IMyCubeGrid parent = (IMyCubeGrid)e.Parent; long[] beaconListIds = beaconList.Select(b => b.EntityId).ToArray(); long ownerId = beaconList.First().OwnerId; List <DockingItem> checkItems = Docking.Instance.Find(d => d.PlayerId == ownerId && d.TargetEntityId == parent.EntityId && d.DockingBeaconIds.Intersect(beaconListIds).Count() == 4); if (checkItems.Count >= PluginSettings.Instance.DockingShipsPerZone) { Communication.SendPrivateInformation(userId, string.Format("Docking zone already '{0}' already contains the maximum capacity of ships.", pylonName)); return(true); } // Figure out center of docking area, and other distance information double maxDistance = 99; Vector3D vPos = new Vector3D(0, 0, 0); foreach (IMyCubeBlock b in beaconList) { Vector3D beaconPos = Entity.GetBlockEntityPosition(b); vPos += beaconPos; } vPos = vPos / 4; foreach (IMyCubeBlock b in beaconList) { Vector3D beaconPos = Entity.GetBlockEntityPosition(b); maxDistance = Math.Min(maxDistance, Vector3D.Distance(vPos, beaconPos)); } // Find ship in docking area IMyCubeGrid dockingEntity = null; HashSet <IMyEntity> cubeGrids = new HashSet <IMyEntity>(); MyAPIGateway.Entities.GetEntities(cubeGrids, f => f is IMyCubeGrid); foreach (IMyCubeGrid gridCheck in cubeGrids) { if (gridCheck.IsStatic || gridCheck == parent) { continue; } double distance = Vector3D.Distance(gridCheck.GetPosition(), vPos); if (distance < maxDistance) { dockingEntity = gridCheck; break; } } // Figure out if the ship fits in docking area, and then save ship if (dockingEntity != null) { // Get bounding box of both the docking zone and docking ship OrientedBoundingBoxD targetBounding = Entity.GetBoundingBox(beaconList); OrientedBoundingBoxD dockingBounding = Entity.GetBoundingBox(dockingEntity); // Make sure the docking zone contains the docking ship. If they intersect or are disjointed, then fail if (!Entity.GreaterThan(dockingBounding.HalfExtent * 2, targetBounding.HalfExtent * 2)) { Communication.SendPrivateInformation(userId, string.Format("The ship '{0}' is too large for it's carrier. The ship's bounding box must fit inside the docking zone bounding box!", dockingEntity.Name)); return(true); } if (targetBounding.Contains(ref dockingBounding) != ContainmentType.Contains) { Communication.SendPrivateInformation(userId, string.Format("The ship '{0}' is not fully inside the docking zone '{1}'. Make sure the ship is fully contained inside the docking zone", dockingEntity.Name, pylonName)); return(true); } // Calculate the mass and ensure the docking ship is less than half the mass of the dock float parentMass = Entity.CalculateMass(parent); float dockingMass = Entity.CalculateMass(dockingEntity); if (dockingMass > parentMass) { Communication.SendPrivateInformation(userId, string.Format("The ship you're trying to dock is too heavy for it's carrier. The ship mass must be less than half the large ship / stations mass! (DM={0}kg CM={1}kg)", dockingMass, parentMass)); return(true); } // Check to see if the ship is piloted, if it is, error out. // TODO: Check to see if we can get a real time copy of this entity? List <IMySlimBlock> blocks = new List <IMySlimBlock>(); dockingEntity.GetBlocks(blocks, x => x.FatBlock != null && x.FatBlock.BlockDefinition.TypeId == typeof(MyObjectBuilder_Cockpit)); foreach (IMySlimBlock slim_cbe in blocks) { MyObjectBuilder_Cockpit c = (MyObjectBuilder_Cockpit)slim_cbe.FatBlock.GetObjectBuilderCubeBlock(); if (c.Pilot != null) { Communication.SendPrivateInformation(userId, string.Format("Ship in docking zone '{0}' has a pilot! Please exit the ship before trying to dock. (Sometimes this can lag a bit. Wait 10 seconds and try again)", pylonName)); return(true); } } // Save position and rotation information. Some fun stuff here. // Get our dock rotation as a quaternion Quaternion saveQuat = Quaternion.CreateFromRotationMatrix(parent.WorldMatrix.GetOrientation()); // Transform docked ship's local position by inverse of the the parent (unwinds parent) and save it for when we undock Vector3D savePos = Vector3D.Transform(dockingEntity.GetPosition() - parent.GetPosition(), Quaternion.Inverse(saveQuat)); // Get local rotation of dock ship, and save it for when we undock saveQuat = Quaternion.Inverse(saveQuat) * Quaternion.CreateFromRotationMatrix(dockingEntity.WorldMatrix.GetOrientation()); // Serialize and save ship to file, then remove it // Save item DockingItem dockItem = new DockingItem(); dockItem.DockedEntityId = dockingEntity.EntityId; dockItem.TargetEntityId = parent.EntityId; dockItem.PlayerId = ownerId; dockItem.DockingBeaconIds = beaconList.Select(s => s.EntityId).ToArray(); dockItem.DockedName = dockingEntity.DisplayName; dockItem.SavePos = savePos; dockItem.SaveQuat = saveQuat; Docking.Instance.Add(dockItem); // Save ship to file and remove FileInfo info = new FileInfo(Essentials.PluginPath + String.Format("\\Docking\\docked_{0}_{1}_{2}.sbc", ownerId, parent.EntityId, dockingEntity.EntityId)); CubeGridEntity dockingGrid = new CubeGridEntity((MyObjectBuilder_CubeGrid)dockingEntity.GetObjectBuilder(), dockingEntity); if (!CubeGrids.WaitForLoadingEntity(dockingGrid)) { Communication.SendPrivateInformation(userId, string.Format("Failed to load entity for export: {0}", dockingGrid.EntityId)); return(true); } dockingGrid.Export(info); dockingGrid.Dispose(); Communication.SendPrivateInformation(userId, string.Format("Docked ship '{0}' in docking zone '{1}'.", dockItem.DockedName, pylonName)); /* * // Add a cool down * DockingCooldownItem cItem = new DockingCooldownItem(); * cItem.name = pylonName; * cItem.startTime = DateTime.Now; * PluginDocking.CooldownList.Add(cItem); */ } else { Communication.SendPrivateInformation(userId, string.Format("No ships in docking zone '{0}'.", pylonName)); } } else if (beaconList.Count > 4) { Communication.SendPrivateInformation(userId, string.Format("Too many beacons with the name or another zone with the name '{0}'. Place only 4 beacons to create a zone or try a different zone name.", pylonName)); } else { Communication.SendPrivateInformation(userId, string.Format("Can not locate docking zone '{0}'. There must be 4 beacons with the name '{0}' to create a docking zone. Beacons must be fully built!", pylonName)); } return(true); }