using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ShiftOS.Engine { public static class Hacking { private static List _activeConnections = new List(); private static List Hackables = new List(); private static List Loot = new List(); public static HackableSystem CurrentHackable { get; private set; } public static Objects.Hackable[] AvailableToHack { get { return Hackables.Where(x => Shiftorium.UpgradeInstalled(x.Dependencies) && !Shiftorium.UpgradeInstalled(x.ID)).ToArray(); } } public static HackableSystem[] ActiveConnections { get { return _activeConnections.ToArray(); } } public static HackableSystem[] PwnedConnections { get { return _activeConnections.Where(x => x.IsPwn3d).ToArray(); } } public static HackableSystem[] TimedConnections { get { return _activeConnections.Where(x => x.Data.ConnectionTimeoutLevel > 0&&!x.IsPwn3d).ToArray(); } } public static void InitHack(Objects.Hackable data) { var hsys = new HackableSystem(); hsys.Data = data; hsys.IsPwn3d = false; var fs = new Objects.ShiftFS.Directory(); fs.Name = data.FriendlyName; Objects.ShiftFS.Utils.Mounts.Add(fs); var mountid = Objects.ShiftFS.Utils.Mounts.IndexOf(fs); Objects.ShiftFS.Utils.Mounts.Remove(fs); hsys.Filesystem = fs; hsys.FirewallCracked = (data.FirewallStrength == 0); hsys.DoConnectionTimeout = (data.ConnectionTimeoutLevel > 0); if (hsys.DoConnectionTimeout) { hsys.MillisecondsCountdown = 1000 * (240 / data.ConnectionTimeoutLevel); } else { hsys.MillisecondsCountdown = 0; } hsys.PortsToUnlock = new List(); if (data.SystemType.HasFlag(Objects.SystemType.EmailServer)) hsys.PortsToUnlock.Add(new Port { Value = 25, Name = "SMTP mailserver (unencrypted)", }); if (data.SystemType.HasFlag(Objects.SystemType.FileServer)) hsys.PortsToUnlock.Add(new Port { Value = 22, Name = "File Transfer Protocol", }); if (data.SystemType.HasFlag(Objects.SystemType.SSHServer)) hsys.PortsToUnlock.Add(new Port { Value = 21, Name = "ShiftSSH server", }); if (data.SystemType.HasFlag(Objects.SystemType.Database)) hsys.PortsToUnlock.Add(new Port { Value = 3306, Name = "MySQL database", }); CurrentHackable = hsys; } public static void FailHack() { if (CurrentHackable == null) throw new NaughtyDeveloperException("Someone tried to fail a non-existent hack."); if (CurrentHackable.IsPwn3d) throw new NaughtyDeveloperException("A developer tried to un-pwn a pwn3d hackable."); if (!string.IsNullOrWhiteSpace(CurrentHackable.Data.OnHackFailedStoryEvent)) Story.Start(CurrentHackable.Data.OnHackFailedStoryEvent); if (Objects.ShiftFS.Utils.Mounts.Contains(CurrentHackable.Filesystem)) Objects.ShiftFS.Utils.Mounts.Remove(CurrentHackable.Filesystem); CurrentHackable = null; } public static void Initiate() { foreach(var type in ReflectMan.Types.Where(x => x.GetInterfaces().Contains(typeof(IHackableProvider)))) { var @interface = (IHackableProvider)Activator.CreateInstance(type, null); Hackables.AddRange(@interface.GetHackables()); var lootinfo = @interface.GetLootInfo(); foreach(var loot in lootinfo) { var existing = Loot.FirstOrDefault(x => x.Info.Filename == loot.Filename); if (existing != null) throw new DataConflictException("Data conflict encountered while reading loot data. Two or more loot resources with the filename \"" + loot.Filename + "\" were found. This can cause major bugs and confusion in the game."); var @new = new Objects.Loot(loot, @interface.GetLootFromResource(loot.ResourceId)); Loot.Add(@new); } } var hackable = Hackables.FirstOrDefault(x => Hackables.Where(y => x.SystemName == y.SystemName).Count() > 1); if(hackable != null) { throw new DataConflictException("Data conflict encountered while initiating the hacking engine. Two or more hackables were found with the same hostname \"" + hackable.SystemName + "\". This is a direct violation of the ShiftOS save system and Shiftorium backend."); } } } /// /// An exception which is thrown when a developer deliberately tries to cause a bug. /// public class NaughtyDeveloperException : Exception { /// /// Create a new instance of the , with the specified message, which will cause Visual Studio to call the person who caused the exception a scrotem. /// /// The message you want to yell at the user. public NaughtyDeveloperException(string message) : base(message + " - FIX IT, YOU SCROTEM") { } } public class DataConflictException : Exception { public DataConflictException(string message) : base(message) { } } public interface IHackableProvider { Objects.Hackable[] GetHackables(); Objects.LootInfo[] GetLootInfo(); byte[] GetLootFromResource(string resId); } public class HackableSystem { public Objects.Hackable Data { get; set; } public List PortsToUnlock { get; set; } public bool FirewallCracked { get; set; } public Objects.ShiftFS.Directory Filesystem { get; set; } public double MillisecondsCountdown { get; set; } public bool DoConnectionTimeout { get; set; } public bool IsPwn3d { get; set; } } public class Port { public string Name { get; set; } public int Value { get; set; } } }