diff --git a/Commands.cs b/Commands.cs index aed3522..d17f4b4 100644 --- a/Commands.cs +++ b/Commands.cs @@ -1,16 +1,58 @@ using NLog; +using Sandbox.Game.Entities; +using Sandbox.ModAPI; using System; +using System.Collections.Generic; +using System.Linq; using Torch.Commands; using Torch.Commands.Permissions; +using VRage; using VRage.Game.ModAPI; +using VRage.ModAPI; +using VRageMath; namespace ALE_ShipFixer { + public class Commands : CommandModule { public static readonly Logger Log = LogManager.GetCurrentClassLogger(); public ShipFixerPlugin Plugin => (ShipFixerPlugin) Context.Plugin; + [Command("fixshipmod", "Cuts and pastes a ship you are looking at to try to fix various bugs.")] + [Permission(MyPromoteLevel.Moderator)] + public void FixShipMod() { + + IMyPlayer player = Context.Player; + + long playerId = 0L; + + if (player == null) { + + Context.Respond("Console has no Character so cannot use this command. Use !fixshipmod instead!"); + return; + + } else { + playerId = player.IdentityId; + } + + if (player.Character == null) { + Context.Respond("You have no Character currently. Make sure to spawn and be out of cockpit!"); + return; + } + + if (!checkConformation(playerId, "nogrid")) + return; + + try { + + Plugin.fixShip(player.Character, 0, Context); + + } catch (Exception e) { + Log.Error("Error on fixing ship", e); + } + } + [Command("fixshipmod", "Cuts and pastes a ship with the given name to try to fix various bugs.")] [Permission(MyPromoteLevel.Moderator)] public void FixShipMod(string gridName) { @@ -32,6 +74,64 @@ public void FixShipMod(string gridName) { } } + [Command("fixship", "Cuts and pastes a ship you are looking at to try to fix various bugs.")] + [Permission(MyPromoteLevel.None)] + public void FixShip() { + + IMyPlayer player = Context.Player; + + long playerId = 0L; + + if (player == null) { + + Context.Respond("Console has no Grids so cannot use this command. Use !fixshipmod instead!"); + return; + + } else { + playerId = player.IdentityId; + } + + if (player.Character == null) { + Context.Respond("You have no Character currently. Make sure to spawn and be out of cockpit!"); + return; + } + + var currentCooldownMap = Plugin.CurrentCooldownMap; + + CurrentCooldown currentCooldown = null; + + if (currentCooldownMap.TryGetValue(playerId, out currentCooldown)) { + + long remainingSeconds = currentCooldown.getRemainingSeconds(null); + + if (remainingSeconds > 0) { + Log.Info("Cooldown for Player " + player.DisplayName + " still running! " + remainingSeconds + " seconds remaining!"); + Context.Respond("Command is still on cooldown for " + remainingSeconds + " seconds."); + return; + } + + } else { + + currentCooldown = new CurrentCooldown(Plugin.Cooldown); + currentCooldownMap.Add(playerId, currentCooldown); + } + + if (!checkConformation(playerId, "nogrid")) + return; + + try { + + if(Plugin.fixShip(player.Character, playerId, Context)) { + + Log.Info("Cooldown for Player " + player + " started!"); + currentCooldown.startCooldown(null); + } + + } catch (Exception e) { + Log.Error("Error on fixing ship", e); + } + } + [Command("fixship", "Cuts and pastes a ship with the given name to try to fix various bugs.")] [Permission(MyPromoteLevel.None)] public void FixShipPlayer(string gridName) { @@ -42,7 +142,7 @@ public void FixShipPlayer(string gridName) { if (player == null) { - Context.Respond("Console has no Grids so cannot use this command. Use !fixshipmod instead!"); + Context.Respond("Console has no Grids so cannot use this command. Use !fixshipmod instead!"); return; } else { @@ -74,14 +174,15 @@ public void FixShipPlayer(string gridName) { try { - Plugin.fixShip(gridName, playerId, Context); + if(Plugin.fixShip(gridName, playerId, Context)) { + + Log.Info("Cooldown for Player " + player + " started!"); + currentCooldown.startCooldown(null); + } } catch (Exception e) { Log.Error("Error on fixing ship", e); } - - Log.Info("Cooldown for Player "+player+" started!"); - currentCooldown.startCooldown(null); } private bool checkConformation(long playerId, string gridName) { diff --git a/ShipFixerPlugin.cs b/ShipFixerPlugin.cs index e79e5db..516015b 100644 --- a/ShipFixerPlugin.cs +++ b/ShipFixerPlugin.cs @@ -19,6 +19,7 @@ using Torch.Commands; using System.IO; using System; +using System.Linq; namespace ALE_ShipFixer { @@ -63,33 +64,45 @@ public override void Init(ITorchBase torch) { } } - public void fixShip(string gridName, long playerId, CommandContext Context) { + public bool fixShip(IMyCharacter character, long playerId, CommandContext Context) { + + ConcurrentBag.Group> groups = FindLookAtGridGroup(character, playerId); + + return fixGroups(groups, Context); + } + + public bool fixShip(string gridName, long playerId, CommandContext Context) { ConcurrentBag.Group> groups = findGridGroupsForPlayer(gridName, playerId); + return fixGroups(groups, Context); + } + + private bool fixGroups(ConcurrentBag.Group> groups, CommandContext Context) { + /* No group or too many groups found */ if (groups.Count < 1) { Context.Respond("Could not find your Grid."); - return; + return false; } /* too many groups found */ if (groups.Count > 1) { Context.Respond("Found multiple Grids with same Name. Rename your grid first to something unique."); - return; + return false; } MyGroups.Group group = null; if (!groups.TryPeek(out group)) { Context.Respond("Could not find your Grid."); - return; + return false; } - fixGroup(group, Context); + return fixGroup(group, Context); } - private void fixGroup(MyGroups.Group group, CommandContext Context) { + private bool fixGroup(MyGroups.Group group, CommandContext Context) { foreach (MyGroups.Node groupNodes in group.Nodes) { @@ -109,21 +122,21 @@ private void fixGroup(MyGroups.Group group, if (landingGear != null && landingGear.IsLocked) { Context.Respond("Some Landing-Gears are still Locked. Please unlock first!"); - return; + return false; } IMyShipConnector connector = block as IMyShipConnector; if (connector != null && connector.Status == MyShipConnectorStatus.Connected) { Context.Respond("Some Connectors are still Locked. Please unlock first!"); - return; + return false; } IMyShipController controller = block as IMyShipController; if (controller != null && controller.IsUnderControl) { Context.Respond("Cockpits or Seats are still occupied. Clear them first! Dont forget to check the toilet!"); - return; + return false; } } } @@ -168,6 +181,80 @@ private void fixGroup(MyGroups.Group group, foreach (var ent in ents) MyAPIGateway.Entities.AddEntity(ent, true); + + return true; + } + + private ConcurrentBag.Group> FindLookAtGridGroup(IMyCharacter controlledEntity, long playerId) { + + const float range = 5000; + Matrix worldMatrix; + Vector3D startPosition; + Vector3D endPosition; + + worldMatrix = controlledEntity.GetHeadMatrix(true, true, false); // dead center of player cross hairs, or the direction the player is looking with ALT. + startPosition = worldMatrix.Translation + worldMatrix.Forward * 0.5f; + endPosition = worldMatrix.Translation + worldMatrix.Forward * (range + 0.5f); + + var entites = new HashSet(); + MyAPIGateway.Entities.GetEntities(entites, e => e != null); + + var list = new Dictionary.Group, double>(); + var ray = new RayD(startPosition, worldMatrix.Forward); + + foreach(var group in MyCubeGridGroups.Static.Physical.Groups) { + + foreach (MyGroups.Node groupNodes in group.Nodes) { + + IMyCubeGrid cubeGrid = groupNodes.NodeData; + + if (cubeGrid != null) { + + if (cubeGrid.Physics == null) + continue; + + /* We are not the server and playerId is not owner */ + if (playerId != 0 && !cubeGrid.BigOwners.Contains(playerId)) + continue; + + // check if the ray comes anywhere near the Grid before continuing. + if (ray.Intersects(cubeGrid.WorldAABB).HasValue) { + + Vector3I? hit = cubeGrid.RayCastBlocks(startPosition, endPosition); + + if (hit.HasValue) { + + double distance = (startPosition - cubeGrid.GridIntegerToWorld(hit.Value)).Length(); + + double oldDistance; + + if (list.TryGetValue(group, out oldDistance)) { + + if (distance < oldDistance) { + list.Remove(group); + list.Add(group, distance); + } + + } else { + + list.Add(group, distance); + } + } + } + } + } + } + + ConcurrentBag.Group> bag = new ConcurrentBag.Group>(); + + if (list.Count == 0) + return bag; + + // find the closest Entity. + var item = list.OrderBy(f => f.Value).First(); + bag.Add(item.Key); + + return bag; } private ConcurrentBag.Group> findGridGroupsForPlayer(string gridName, long playerId) {