/** * Generates the system prefab from the configuration * @return System prefab object **/ public PSystem Generate() { // Dictionary of bodies generated Dictionary <string, Body> bodies = new Dictionary <string, Body> (); // Retrieve the root config node ConfigNode rootConfig = GameDatabase.Instance.GetConfigs(rootNodeName) [0].config; // Stage 1 - Load all of the bodies foreach (ConfigNode bodyNode in rootConfig.GetNodes(bodyNodeName)) { // Load this body from the Body body = Parser.CreateObjectFromConfigNode <Body> (bodyNode); bodies.Add(body.name, body); Debug.Log("[Kopernicus]: Configuration.Loader: Loaded Body: " + body.name); } // Stage 2 - create a new planetary system object GameObject gameObject = new GameObject("Kopernicus"); gameObject.transform.parent = Utility.Deactivator; PSystem system = gameObject.AddComponent <PSystem> (); // Set the planetary system defaults (pulled from PSystemManager.Instance.systemPrefab) system.systemName = "Kopernicus"; system.systemTimeScale = 1.0; system.systemScale = 1.0; system.mainToolbarSelected = 2; // initial value in stock systemPrefab. Unknown significance. // Stage 3 - Glue all the orbits together in the defined pattern foreach (KeyValuePair <string, Body> body in bodies) { // If this body is in orbit around another body if (body.Value.referenceBody != null) { // Get the Body object for the reference body Body parent = null; if (!bodies.TryGetValue(body.Value.referenceBody, out parent)) { throw new Exception("\"" + body.Value.referenceBody + "\" not found."); } // Setup the orbit of the body parent.generatedBody.children.Add(body.Value.generatedBody); body.Value.generatedBody.orbitDriver.referenceBody = parent.generatedBody.celestialBody; body.Value.generatedBody.orbitDriver.orbit.referenceBody = parent.generatedBody.celestialBody; } // Parent the generated body to the PSystem body.Value.generatedBody.transform.parent = system.transform; } // Stage 4 - elect root body system.rootBody = bodies.First(p => p.Value.referenceBody == null).Value.generatedBody; // Stage 5 - sort by distance from parent (discover how this effects local bodies) RecursivelySortBodies(system.rootBody); return(system); }
bool SystemTurretPlacementRequest(IArea currentArea, Player player, int turretID, ref float xPos, ref float yPos, out string resultMessage) { if (currentArea.AreaType != AreaTypes.System) { resultMessage = "Not in a system.";//Client shouldn't ever see this... return(false); } PSystem system = ((PSystem)(currentArea)); if (!currentArea.CanAddStructure(player, StructureTypes.LaserTurret, xPos, yPos, out resultMessage)) { return(false); } else if (player.GetActiveShip().Cargo.IsCargoInHolds(turretID) != StatefulCargoTypes.LaserTurret) { resultMessage = "Turret not found in ship cargo."; return(false); } else if (!system.GetValidStructurePosition(StructureStatManager.GetStats(StructureTypes.LaserTurret), ref xPos, ref yPos)) { resultMessage = "Invalid structure position."; return(false); } resultMessage = "Success"; return(true); }
public void TakeDamage(int damage) { if (Health < 0) { return; } if (Fortified) { damage = (int)(damage * .8f); } health -= damage; // Add armour to the equation if (EntityBar != null) { EntityBar.GetComponent <EntityBar>().SetHealthSize(health / maxHealth); } Debug.Log(String.Format("{0} took {1} points of damage, {2} health remaining.", name, damage, Health)); if (Destroyed()) { //gameObject.SetActive(false); if (PSystem != null) { PSystem.Play(); } Destroy(this.gameObject, 1f); } }
// Awake() is the first function called in the lifecycle of a Unity3D MonoBehaviour. In the case of KSP, // it happens to be called right before the game's PSystem is instantiated from PSystemManager.Instance.systemPrefab public void Awake() { // Abort, if KSP isn't compatible if (!CompatibilityChecker.IsCompatible()) { string supported = CompatibilityChecker.version_major + "." + CompatibilityChecker.version_minor + "." + CompatibilityChecker.Revision; string current = Versioning.version_major + "." + Versioning.version_minor + "." + Versioning.Revision; Debug.LogWarning("[Kopernicus] Detected incompatible install.\nCurrent version of KSP: " + current + ".\nSupported version of KSP: " + supported + ".\nPlease wait, until Kopernicus gets updated to match your version of KSP."); Debug.Log("[Kopernicus] Aborting..."); // Abort Destroy(this); return; } // We're ALIVE Logger.Default.SetAsActive(); Logger.Default.Log("Injector.Awake(): Begin"); // Parser Config ParserOptions.Register("Kopernicus", new ParserOptions.Data { errorCallback = e => Logger.Active.LogException(e), logCallback = s => Logger.Active.Log(s) }); // Yo garbage collector - we have work to do man DontDestroyOnLoad(this); // If the planetary manager does not work, well, error out if (PSystemManager.Instance == null) { // Log the error Logger.Default.Log("Injector.Awake(): If PSystemManager.Instance is null, there is nothing to do"); return; } // Backup the old prefab StockSystemPrefab = PSystemManager.Instance.systemPrefab; // Get the current time DateTime start = DateTime.Now; // Get the configNode ConfigNode kopernicus = GameDatabase.Instance.GetConfigs(rootNodeName)[0].config; // THIS IS WHERE THE MAGIC HAPPENS - OVERWRITE THE SYSTEM PREFAB SO KSP ACCEPTS OUR CUSTOM SOLAR SYSTEM AS IF IT WERE FROM SQUAD PSystemManager.Instance.systemPrefab = Parser.CreateObjectFromConfigNode <Loader>(kopernicus, "Kopernicus").systemPrefab; // Clear space center instance so it will accept nouveau Kerbin SpaceCenter.Instance = null; // Add a handler so that we can do post spawn fixups. PSystemManager.Instance.OnPSystemReady.Add(PostSpawnFixups); // Done executing the awake function TimeSpan duration = (DateTime.Now - start); Logger.Default.Log("Injector.Awake(): Completed in: " + duration.TotalMilliseconds + " ms"); Logger.Default.Flush(); }
public void TestAreCompatible() { PSystem PSystem = new PSystem(v_TestDeserializedMSystemObjects); var c1 = v_TestDeserializedMSystemObjects.Tiles["q1"].Connectors[0]; var c2 = v_TestDeserializedMSystemObjects.Tiles["q1"].Connectors[1]; var c3 = v_TestDeserializedMSystemObjects.Tiles["s1"].Connectors[1]; Assert.IsTrue(PSystem.AreCompatible(c1, c2)); Assert.IsFalse(PSystem.AreCompatible(c1, c3)); }
static void Main(string[] args) { PSystem system = new PSystem() { new FixedObject(new Vector2(5, 0), 1e+6f), new FixedObject(new Vector2(-5, 0), 1e+6f) }; var f = PLine.ElectricFieldLine(system, new Vector2(5, 6), 6 * (int)6e3 + 1).ToArray(); for (int i = 0; i <= 100; ++i) { Console.WriteLine(f[i * 50]); } }
private void _handleMessageStartUpdatingSystems(object sender, NetworkMessageContainer messageData) { var data = messageData?.MessageData as MessageStartUpdatingSystems; // Return if this isn't the target slave if (data.SlaveServerID != _mySlaveID) { return; } PSystemsLoaded = false; if (data.ClearCurrentSystems) { _galaxyManager.ClearLocalSystems(); } #if DEBUG Stopwatch s1 = new Stopwatch(); s1.Start(); #endif var loadedSystemModels = _databaseManager.GetAreasAsync(data.IDsToSimulate).Result; foreach (PSystemModel p in loadedSystemModels) { PSystem s = Deserializer.DeserializePSystemAsync(p, _redisServer, _locatorService, _registrationManager, _databaseManager).Result; } foreach (var a in _galaxyManager.AllAreas) { //Clear existing subscriptions to prevent doubles (for hot loading) _redisServer.UnSubscribe(ChannelTypes.WebToSlave, a.Value.Id, _routedMessageProcessor); //Subscribe _redisServer.Subscribe(ChannelTypes.WebToSlave, a.Value.Id, _routedMessageProcessor); } #if DEBUG ConsoleManager.WriteLine(_galaxyManager.AllAreas.Count.ToString() + " total areas currently loaded.", ConsoleMessageType.Debug); s1.Stop(); ConsoleManager.WriteLine(s1.ElapsedMilliseconds + " ms to load " + _galaxyManager.Systems.Count + " systems.", ConsoleMessageType.Debug); #endif PSystemsLoaded = true; }
public static PSystemBody GenerateSystemBody(PSystem system, PSystemBody parent, string templateName, string name, Orbit orbit) { // Look up the template body PSystemBody template = Utility.FindBody(system.rootBody, templateName); // Create a new celestial body as a clone of this template PSystemBody clone = system.AddBody(parent); clone.name = name; // Set up the celestial body of the clone (back up the orbit driver) Utility.CopyObjectFields <CelestialBody> (template.celestialBody, clone.celestialBody); clone.celestialBody.bodyName = name; clone.celestialBody.orbitingBodies = null; clone.celestialBody.orbitDriver = clone.orbitDriver; clone.flightGlobalsIndex = 100 + template.flightGlobalsIndex; // Setup the orbit driver clone.orbitRenderer.orbitColor = template.orbitRenderer.orbitColor; clone.orbitDriver.orbit = orbit; clone.orbitDriver.celestialBody = clone.celestialBody; clone.orbitDriver.updateMode = OrbitDriver.UpdateMode.UPDATE; // Setup the deactivator object GameObject deactivator = new GameObject("Deactivator"); deactivator.SetActive(false); UnityEngine.Object.DontDestroyOnLoad(deactivator); // Clone the template's PQS clone.pqsVersion = UnityEngine.Object.Instantiate(template.pqsVersion) as PQS; clone.pqsVersion.transform.parent = deactivator.transform; clone.pqsVersion.name = name; // Clone the scaled space clone.scaledVersion = UnityEngine.Object.Instantiate(template.scaledVersion) as GameObject; clone.scaledVersion.transform.parent = deactivator.transform; clone.scaledVersion.name = name; return(clone); }
// This function generates a duplicate of a PSystem public static PSystem DuplicateSystem(PSystem originalSystem) { // Create a new planetary system object GameObject gameObject = new GameObject (originalSystem.systemName); UnityEngine.Object.DontDestroyOnLoad (gameObject); PSystem system = gameObject.AddComponent<PSystem> (); // Set the planetary system defaults (pulled from PSystemManager.Instance.systemPrefab) system.systemName = originalSystem.systemName; system.systemTimeScale = 1.0; system.systemScale = 1.0; system.mainToolbarSelected = 2; // initial value in stock systemPrefab. Unknown significance. // Clone the root body of the system (we could set it up from scratch, but we do need the pqsVersion entries, which this DOES NOT copy GameObject rootBody = (GameObject) UnityEngine.Object.Instantiate (originalSystem.rootBody.gameObject); UnityEngine.Object.DontDestroyOnLoad (rootBody); system.rootBody = rootBody.GetComponent<PSystemBody> (); // Return the new system return system; }
// This function generates a duplicate of a PSystem public static PSystem DuplicateSystem(PSystem originalSystem) { // Create a new planetary system object GameObject gameObject = new GameObject(originalSystem.systemName); UnityEngine.Object.DontDestroyOnLoad(gameObject); PSystem system = gameObject.AddComponent <PSystem> (); // Set the planetary system defaults (pulled from PSystemManager.Instance.systemPrefab) system.systemName = originalSystem.systemName; system.systemTimeScale = 1.0; system.systemScale = 1.0; system.mainToolbarSelected = 2; // initial value in stock systemPrefab. Unknown significance. // Clone the root body of the system (we could set it up from scratch, but we do need the pqsVersion entries, which this DOES NOT copy GameObject rootBody = (GameObject)UnityEngine.Object.Instantiate(originalSystem.rootBody.gameObject); UnityEngine.Object.DontDestroyOnLoad(rootBody); system.rootBody = rootBody.GetComponent <PSystemBody> (); // Return the new system return(system); }
// This function returns a PSystem that will replace the stock systemPrefab // with one of the modder's design. KSP then loads the replacement planetary // system just as it would have loaded the stock system. public static PSystem GenerateSystem() { // If the planetary manager does not work, well, error out if (PSystemManager.Instance == null) { // Log the error Debug.LogError("[Kopernicus]: KopernicusSystemSource.GenerateSystem() can not be called if PSystemManager.Instance is null"); return(null); } // Setup the template solar system object from the original game PSystem system = DuplicateSystem(PSystemManager.Instance.systemPrefab); // Create "Kopernicus" // Note that due to the way AddBody works, this is a function with side effects // rather than something that returns a planet. Perhaps it should be named differently // from the GenerateSystem method to emphasize this difference in usage?? KopernicusPlanetSource.GeneratePlanet(system, "Kopernicus"); //StockPlanetSource.GeneratePlanet(system, "Laythe", "Bob", new Orbit (0.0, 0.0, 47500000000, 0, 0, 0, 0, system.rootBody.celestialBody)); // Return the newly created planetary system return(system); }
public static PSystemBody GenerateSystemBody(PSystem system, PSystemBody parent, String name, Orbit orbit = null) { PSystemBody Jool = Utility.FindBody(system.rootBody, "Jool"); // Need the geosphere for scaled version PSystemBody Laythe = Utility.FindBody(system.rootBody, "Laythe"); // Need pqs and ocean definitions //Utility.DumpObject (Laythe.celestialBody, " Laythe Celestial Body "); //Utility.DumpObject (Laythe.pqsVersion, " Laythe PQS "); //Transform laytheOcean = Utility.FindInChildren (Laythe.pqsVersion.transform, "LaytheOcean"); //Utility.DumpObject (laytheOcean.GetComponent<PQS> (), " Laythe Ocean PQS "); // AddBody makes the GameObject and stuff. It also attaches it to the system and parent. PSystemBody body = system.AddBody(parent); // set up the various parameters body.name = name; body.flightGlobalsIndex = 100; // Some parameters of the celestialBody, which represents the actual planet... // PSystemBody is more of a container that associates the planet with its orbit // and position in the planetary system, etc. body.celestialBody.bodyName = name; body.celestialBody.bodyDescription = "Merciful Kod, this thing just APPEARED! And unlike last time, it wasn't bird droppings on the telescope."; body.celestialBody.Radius = 320000; //body.celestialBody.Radius = 3380100; body.celestialBody.GeeASL = 0.3; //body.celestialBody.Mass = 6.4185E+23; body.celestialBody.Mass = 4.5154812E+21; body.celestialBody.timeWarpAltitudeLimits = (float[])Laythe.celestialBody.timeWarpAltitudeLimits.Clone(); body.celestialBody.rotationPeriod = 88642.6848; body.celestialBody.rotates = true; body.celestialBody.BiomeMap = GenerateCBAttributeMapSO(name); //Dres.celestialBody.BiomeMap;// body.celestialBody.scienceValues = Laythe.celestialBody.scienceValues; body.celestialBody.ocean = false; // Presumably true of Kerbin. I do not know what the consequences are of messing with this exactly. // I think this just affects where the Planetarium/Tracking station starts. body.celestialBody.isHomeWorld = false; // Setup the orbit of "Kopernicus." The "Orbit" class actually is built to support serialization straight // from Squad, so storing these to files (and loading them) will be pretty easy. body.orbitRenderer.orbitColor = Color.magenta; body.orbitDriver.celestialBody = body.celestialBody; body.orbitDriver.updateMode = OrbitDriver.UpdateMode.UPDATE; if (orbit == null) { body.orbitDriver.orbit = new Orbit(0.0, 0.0, 47500000000, 0, 0, 0, 0, system.rootBody.celestialBody); } else { body.orbitDriver.orbit = orbit; } #region PSystemBody.pqsVersion generation // Create the PQS controller game object for Kopernicus GameObject controllerRoot = new GameObject(name); controllerRoot.layer = Constants.GameLayers.LocalSpace; controllerRoot.transform.parent = Utility.Deactivator; // Create the PQS object and pull all the values from Dres (has some future proofing i guess? adapts to PQS changes) body.pqsVersion = controllerRoot.AddComponent <PQS>(); Utility.CopyObjectFields(Laythe.pqsVersion, body.pqsVersion); //body.pqsVersion.surfaceMaterial = new PQSProjectionSurfaceQuad(); //body.pqsVersion.fallbackMaterial = new PQSProjectionFallback(); body.pqsVersion.surfaceMaterial = new PQSProjectionAerialQuadRelative(Laythe.pqsVersion.surfaceMaterial); // use until we determine all the functions of the shader textures body.pqsVersion.fallbackMaterial = new PQSProjectionFallback(Laythe.pqsVersion.fallbackMaterial); body.pqsVersion.radius = body.celestialBody.Radius; body.pqsVersion.mapOcean = false; // Debug Utility.DumpObjectProperties(body.pqsVersion.surfaceMaterial, " Surface Material "); Utility.DumpObjectProperties(body.pqsVersion.fallbackMaterial, " Fallback Material "); // Detail defaults body.pqsVersion.maxQuadLenghtsPerFrame = 0.03f; body.pqsVersion.minLevel = 1; body.pqsVersion.maxLevel = 10; body.pqsVersion.minDetailDistance = 8; // Create the celestial body transform GameObject mod = new GameObject("_CelestialBody"); mod.transform.parent = controllerRoot.transform; PQSMod_CelestialBodyTransform celestialBodyTransform = mod.AddComponent <PQSMod_CelestialBodyTransform>(); celestialBodyTransform.sphere = body.pqsVersion; celestialBodyTransform.forceActivate = false; celestialBodyTransform.deactivateAltitude = 115000; celestialBodyTransform.forceRebuildOnTargetChange = false; celestialBodyTransform.planetFade = new PQSMod_CelestialBodyTransform.AltitudeFade(); celestialBodyTransform.planetFade.fadeFloatName = "_PlanetOpacity"; celestialBodyTransform.planetFade.fadeStart = 100000.0f; celestialBodyTransform.planetFade.fadeEnd = 110000.0f; celestialBodyTransform.planetFade.valueStart = 0.0f; celestialBodyTransform.planetFade.valueEnd = 1.0f; celestialBodyTransform.planetFade.secondaryRenderers = new List <GameObject>(); celestialBodyTransform.secondaryFades = new PQSMod_CelestialBodyTransform.AltitudeFade[0]; celestialBodyTransform.requirements = PQS.ModiferRequirements.Default; celestialBodyTransform.modEnabled = true; celestialBodyTransform.order = 10; // Create the color PQS mods mod = new GameObject("_Color"); mod.transform.parent = controllerRoot.transform; PQSMod_VertexSimplexNoiseColor vertexSimplexNoiseColor = mod.AddComponent <PQSMod_VertexSimplexNoiseColor>(); vertexSimplexNoiseColor.sphere = body.pqsVersion; vertexSimplexNoiseColor.seed = 45; vertexSimplexNoiseColor.blend = 1.0f; vertexSimplexNoiseColor.colorStart = new Color(0.768656731f, 0.6996614f, 0.653089464f, 1); vertexSimplexNoiseColor.colorEnd = new Color(0.0f, 0.0f, 0.0f, 1.0f); vertexSimplexNoiseColor.octaves = 12.0; vertexSimplexNoiseColor.persistence = 0.5; vertexSimplexNoiseColor.frequency = 2.0; vertexSimplexNoiseColor.requirements = PQS.ModiferRequirements.MeshColorChannel; vertexSimplexNoiseColor.modEnabled = true; vertexSimplexNoiseColor.order = 200; PQSMod_HeightColorMap heightColorMap = mod.AddComponent <PQSMod_HeightColorMap>(); heightColorMap.sphere = body.pqsVersion; List <PQSMod_HeightColorMap.LandClass> landClasses = new List <PQSMod_HeightColorMap.LandClass>(); PQSMod_HeightColorMap.LandClass landClass = new PQSMod_HeightColorMap.LandClass("AbyPl", 0.0, 0.5, new Color(0.0f, 0.0f, 0.0f, 1.0f), Color.white, double.NaN); landClass.lerpToNext = true; landClasses.Add(landClass); landClass = new PQSMod_HeightColorMap.LandClass("Beach", 0.5, 0.550000011920929, new Color(0.164179087f, 0.164179087f, 0.164179087f, 1.0f), Color.white, double.NaN); landClass.lerpToNext = true; landClasses.Add(landClass); landClass = new PQSMod_HeightColorMap.LandClass("Beach", 0.550000011920929, 1.0, new Color(0.373134315f, 0.373134315f, 0.373134315f, 1.0f), Color.white, double.NaN); landClass.lerpToNext = false; landClasses.Add(landClass); // Generate an array from the land classes list heightColorMap.landClasses = landClasses.ToArray(); heightColorMap.blend = 0.7f; heightColorMap.lcCount = 3; heightColorMap.requirements = PQS.ModiferRequirements.MeshColorChannel; heightColorMap.modEnabled = true; heightColorMap.order = 201; // Create the alititude alpha mods mod = new GameObject("_Material_ModProjection"); mod.transform.parent = controllerRoot.transform; PQSMod_AltitudeAlpha altitudeAlpha = mod.AddComponent <PQSMod_AltitudeAlpha>(); altitudeAlpha.sphere = body.pqsVersion; altitudeAlpha.atmosphereDepth = 4000.0; altitudeAlpha.invert = false; altitudeAlpha.requirements = PQS.ModiferRequirements.Default; altitudeAlpha.modEnabled = false; altitudeAlpha.order = 999999999; // Create the aerial perspective material mod = new GameObject("_Material_AerialPerspective"); mod.transform.parent = controllerRoot.transform; PQSMod_AerialPerspectiveMaterial aerialPerspectiveMaterial = mod.AddComponent <PQSMod_AerialPerspectiveMaterial>(); aerialPerspectiveMaterial.sphere = body.pqsVersion; aerialPerspectiveMaterial.globalDensity = -0.00001f; aerialPerspectiveMaterial.heightFalloff = 6.75f; aerialPerspectiveMaterial.atmosphereDepth = 150000; aerialPerspectiveMaterial.DEBUG_SetEveryFrame = true; aerialPerspectiveMaterial.cameraAlt = 0; aerialPerspectiveMaterial.cameraAtmosAlt = 0; aerialPerspectiveMaterial.heightDensAtViewer = 0; aerialPerspectiveMaterial.requirements = PQS.ModiferRequirements.Default; aerialPerspectiveMaterial.modEnabled = true; aerialPerspectiveMaterial.order = 100; // Create the UV planet relative position mod = new GameObject("_Material_SurfaceQuads"); mod.transform.parent = controllerRoot.transform; PQSMod_UVPlanetRelativePosition planetRelativePosition = mod.AddComponent <PQSMod_UVPlanetRelativePosition>(); planetRelativePosition.sphere = body.pqsVersion; planetRelativePosition.requirements = PQS.ModiferRequirements.Default; planetRelativePosition.modEnabled = true; planetRelativePosition.order = 999999; // Create the height noise module mod = new GameObject("_HeightNoise"); mod.transform.parent = controllerRoot.transform; PQSMod_VertexHeightMap vertexHeightMap = mod.gameObject.AddComponent <PQSMod_VertexHeightMap>(); vertexHeightMap.sphere = body.pqsVersion; //vertexHeightMap.heightMapDeformity = 29457.0; vertexHeightMap.heightMapDeformity = 10000.0; vertexHeightMap.heightMapOffset = -1000.0; vertexHeightMap.scaleDeformityByRadius = false; vertexHeightMap.requirements = PQS.ModiferRequirements.MeshCustomNormals | PQS.ModiferRequirements.VertexMapCoords; vertexHeightMap.modEnabled = true; vertexHeightMap.order = 20; // Load the heightmap for this planet Texture2D map = new Texture2D(4, 4, TextureFormat.Alpha8, false); map.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Height.png")); vertexHeightMap.heightMap = ScriptableObject.CreateInstance <MapSO>(); vertexHeightMap.heightMap.CreateMap(MapSO.MapDepth.Greyscale, map); UnityEngine.Object.DestroyImmediate(map); // Create the simplex height module PQSMod_VertexSimplexHeight vertexSimplexHeight = mod.AddComponent <PQSMod_VertexSimplexHeight>(); vertexSimplexHeight.sphere = body.pqsVersion; vertexSimplexHeight.seed = 670000; vertexSimplexHeight.deformity = 1700.0; vertexSimplexHeight.octaves = 12.0; vertexSimplexHeight.persistence = 0.5; vertexSimplexHeight.frequency = 4.0; vertexSimplexHeight.requirements = PQS.ModiferRequirements.MeshCustomNormals; vertexSimplexHeight.modEnabled = true; vertexSimplexHeight.order = 21; // SERIOUSLY RECOMMENDED FOR NO OCEAN WORLDS // Create the flatten ocean module PQSMod_FlattenOcean flattenOcean = mod.AddComponent <PQSMod_FlattenOcean>(); flattenOcean.sphere = body.pqsVersion; flattenOcean.oceanRadius = 1.0; flattenOcean.requirements = PQS.ModiferRequirements.MeshCustomNormals; flattenOcean.modEnabled = true; flattenOcean.order = 25; // Creat the vertex height noise module PQSMod_VertexHeightNoise vertexHeightNoise = mod.AddComponent <PQSMod_VertexHeightNoise>(); vertexHeightNoise.sphere = body.pqsVersion; vertexHeightNoise.noiseType = PQSMod_VertexHeightNoise.NoiseType.RiggedMultifractal; vertexHeightNoise.deformity = 1000.0f; vertexHeightNoise.seed = 5906; vertexHeightNoise.frequency = 2.0f; vertexHeightNoise.lacunarity = 2.5f; vertexHeightNoise.persistance = 0.5f; vertexHeightNoise.octaves = 4; vertexHeightNoise.mode = LibNoise.Unity.QualityMode.Low; vertexHeightNoise.requirements = PQS.ModiferRequirements.MeshColorChannel; vertexHeightNoise.modEnabled = true; vertexHeightNoise.order = 22; // Create the material direction mod = new GameObject("_Material_SunLight"); mod.transform.parent = controllerRoot.gameObject.transform; PQSMod_MaterialSetDirection materialSetDirection = mod.AddComponent <PQSMod_MaterialSetDirection>(); materialSetDirection.sphere = body.pqsVersion; materialSetDirection.valueName = "_sunLightDirection"; materialSetDirection.requirements = PQS.ModiferRequirements.Default; materialSetDirection.modEnabled = true; materialSetDirection.order = 100; // Crete the quad mesh colliders mod = new GameObject("QuadMeshColliders"); mod.transform.parent = controllerRoot.gameObject.transform; PQSMod_QuadMeshColliders quadMeshColliders = mod.AddComponent <PQSMod_QuadMeshColliders>(); quadMeshColliders.sphere = body.pqsVersion; quadMeshColliders.maxLevelOffset = 0; quadMeshColliders.physicsMaterial = new PhysicMaterial(); quadMeshColliders.physicsMaterial.name = "Ground"; quadMeshColliders.physicsMaterial.dynamicFriction = 0.6f; quadMeshColliders.physicsMaterial.staticFriction = 0.8f; quadMeshColliders.physicsMaterial.bounciness = 0.0f; quadMeshColliders.physicsMaterial.frictionDirection2 = Vector3.zero; quadMeshColliders.physicsMaterial.dynamicFriction2 = 0.0f; quadMeshColliders.physicsMaterial.staticFriction2 = 0.0f; quadMeshColliders.physicsMaterial.frictionCombine = PhysicMaterialCombine.Maximum; quadMeshColliders.physicsMaterial.bounceCombine = PhysicMaterialCombine.Average; quadMeshColliders.requirements = PQS.ModiferRequirements.Default; quadMeshColliders.modEnabled = true; quadMeshColliders.order = 100; // Create the simplex height absolute mod = new GameObject("_FineDetail"); mod.transform.parent = controllerRoot.gameObject.transform; PQSMod_VertexSimplexHeightAbsolute vertexSimplexHeightAbsolute = mod.AddComponent <PQSMod_VertexSimplexHeightAbsolute>(); vertexSimplexHeightAbsolute.sphere = body.pqsVersion; vertexSimplexHeightAbsolute.seed = 4234; vertexSimplexHeightAbsolute.deformity = 400.0; vertexSimplexHeightAbsolute.octaves = 6.0; vertexSimplexHeightAbsolute.persistence = 0.5; vertexSimplexHeightAbsolute.frequency = 18.0; vertexSimplexHeightAbsolute.requirements = PQS.ModiferRequirements.Default; vertexSimplexHeightAbsolute.modEnabled = true; vertexSimplexHeightAbsolute.order = 30; // Surface color map mod = new GameObject("_LandClass"); mod.transform.parent = body.pqsVersion.gameObject.transform; PQSMod_VertexColorMap colorMap = mod.AddComponent <PQSMod_VertexColorMap>(); colorMap.sphere = body.pqsVersion; colorMap.order = 500; colorMap.modEnabled = true; // Decompress and load the color map = new Texture2D(4, 4, TextureFormat.RGB24, false); map.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Color.png")); colorMap.vertexColorMap = ScriptableObject.CreateInstance <MapSO>(); colorMap.vertexColorMap.CreateMap(MapSO.MapDepth.RGB, map); UnityEngine.Object.DestroyImmediate(map); #endregion #region PSystemBody.scaledVersion generation // Create the scaled version of the planet for use in map view body.scaledVersion = new GameObject(name); body.scaledVersion.layer = Constants.GameLayers.ScaledSpace; body.scaledVersion.transform.parent = Utility.Deactivator; // DEPRECATED - USE PQSMeshWrapper // Make sure the scaled version cooresponds to the size of the body // Turns out that the localScale is directly related to the planet size. // Jool's local scale is {1,1,1}, Kerbin's is {0.1,0.1,0.1}. Jool's // radius is 6000 km, Kerbin's is 600 km. Notice the relation? float scale = (float)body.celestialBody.Radius / 6000000.0f; body.scaledVersion.transform.localScale = new Vector3(scale, scale, scale); // Generate a mesh to fit the PQS we generated (it would be cool to generate this FROM the PQS) Mesh mesh = new Mesh(); Utility.CopyMesh(Jool.scaledVersion.GetComponent <MeshFilter>().sharedMesh, mesh); // Iterate though the UVs // Geosphere with a radius of 1000, cooresponds to an object 6000km in radius Vector3[] vertices = mesh.vertices; for (int i = 0; i < mesh.vertexCount; i++) { // Get the height offset from the height map Vector2 uv = mesh.uv[i]; float displacement = vertexHeightMap.heightMap.GetPixelFloat(uv.x, uv.y); // Since this is a geosphere, normalizing the vertex gives the vector to translate on Vector3 v = vertices[i]; v.Normalize(); // Calculate the real height displacement (in meters), normalized vector "v" scale (1 unit = 6 km) displacement = (float)vertexHeightMap.heightMapOffset + (displacement * (float)vertexHeightMap.heightMapDeformity); Vector3 offset = v * ((displacement / 6000.0f) / scale); // Adjust the displacement vertices[i] += offset; } mesh.vertices = vertices; mesh.RecalculateNormals(); // Create the mesh filter MeshFilter meshFilter = body.scaledVersion.AddComponent <MeshFilter> (); meshFilter.mesh = mesh; // Load and compress the color texture for the custom planet Texture2D colorTexture = new Texture2D(4, 4, TextureFormat.RGBA32, true); colorTexture.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Color.png")); colorTexture.Compress(true); colorTexture.Apply(true, true); // Load and compress the color texture for the custom planet Texture2D normalTexture = new Texture2D(4, 4, TextureFormat.RGB24, true); normalTexture.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Normals.png")); //normalTexture = GameDatabase.BitmapToUnityNormalMap(normalTexture); normalTexture.Compress(true); normalTexture.Apply(true, true); // Create the renderer and material for the scaled version MeshRenderer renderer = body.scaledVersion.AddComponent <MeshRenderer>(); //ScaledPlanetSimple material = new ScaledPlanetSimple(); // for atmosphereless planets ScaledPlanetRimAerial material = new ScaledPlanetRimAerial(); material.color = Color.white; material.specColor = Color.black; material.mainTexture = colorTexture; material.bumpMap = normalTexture; renderer.material = material; // Create the sphere collider SphereCollider collider = body.scaledVersion.AddComponent <SphereCollider> (); collider.center = Vector3.zero; collider.radius = 1000.0f; // Create the ScaledSpaceFader to fade the orbit out where we view it (maybe?) ScaledSpaceFader fader = body.scaledVersion.AddComponent <ScaledSpaceFader> (); fader.celestialBody = body.celestialBody; fader.fadeStart = 95000.0f; fader.fadeEnd = 100000.0f; fader.floatName = "_Opacity"; #endregion #region Atmosphere //--------------------- PROPERTIES EXCLUSIVE TO BODIES WITH ATMOSPHERE // Load the atmosphere gradient (compress it, does not need to be high quality) Texture2D atmosphereGradient = new Texture2D(4, 4, TextureFormat.RGB24, true); atmosphereGradient.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/AtmosphereGradient.png")); atmosphereGradient.Compress(true); atmosphereGradient.wrapMode = TextureWrapMode.Clamp; atmosphereGradient.mipMapBias = 0.0f; atmosphereGradient.Apply(true, true); // Set the additional settings in the scaledVersion body's shader material.rimPower = 2.06f; material.rimBlend = 0.3f; material.rimColorRamp = atmosphereGradient; // Atmosphere specific properties (for scaled version root) (copied from duna) MaterialSetDirection materialLightDirection = body.scaledVersion.AddComponent <MaterialSetDirection>(); materialLightDirection.valueName = "_localLightDirection"; // Create the atmosphere shell itself GameObject scaledAtmosphere = new GameObject("atmosphere"); scaledAtmosphere.transform.parent = body.scaledVersion.transform; scaledAtmosphere.layer = Constants.GameLayers.ScaledSpaceAtmosphere; meshFilter = scaledAtmosphere.AddComponent <MeshFilter>(); meshFilter.sharedMesh = Jool.scaledVersion.GetComponent <MeshFilter>().sharedMesh; renderer = scaledAtmosphere.AddComponent <MeshRenderer>(); renderer.material = new Kopernicus.MaterialWrapper.AtmosphereFromGround(); AtmosphereFromGround atmosphereRenderInfo = scaledAtmosphere.AddComponent <AtmosphereFromGround>(); atmosphereRenderInfo.waveLength = new Color(0.509f, 0.588f, 0.643f, 0.000f); // Technical info for atmosphere body.celestialBody.atmosphere = true; body.celestialBody.atmosphereContainsOxygen = true; body.celestialBody.staticPressureASL = 1.0; // can't find anything that references this, especially with the equation in mind - where is this used? body.celestialBody.altitudeMultiplier = 1.4285f; // ditto body.celestialBody.atmosphereScaleHeight = 4.0; // pressure (in atm) = atmosphereMultipler * e ^ -(altitude / (atmosphereScaleHeight * 1000)) body.celestialBody.atmosphereMultiplier = 0.8f; body.celestialBody.atmoshpereTemperatureMultiplier = 1.0f; // how does this coorespond? body.celestialBody.maxAtmosphereAltitude = 55000.0f; // i guess this is so the math doesn't drag out? body.celestialBody.useLegacyAtmosphere = true; body.celestialBody.atmosphericAmbientColor = new Color(0.306f, 0.187f, 0.235f, 1.000f); #endregion #region Ocean // ---------------- FOR BODIES WITH OCEANS ---------- /*body.celestialBody.ocean = true; * * // Setup the laythe ocean info in master pqs * body.pqsVersion.mapOcean = true; * body.pqsVersion.mapOceanColor = new Color(0.117f, 0.126f, 0.157f, 1.000f); * body.pqsVersion.mapOceanHeight = 0.0f; * * // Generate the PQS object * GameObject oceanRoot = new GameObject(name + "Ocean"); * oceanRoot.transform.parent = body.pqsVersion.transform; * oceanRoot.layer = Constants.GameLayers.LocalSpace; * PQS oceanPQS = oceanRoot.AddComponent<PQS>(); * * // Add this new PQS to the secondary renderers of the altitude fade controller * celestialBodyTransform.planetFade.secondaryRenderers.Add(oceanRoot); * * // Setup the PQS object data * Utility.CopyObjectFields<PQS>(laytheOcean.GetComponent<PQS>(), oceanPQS); * oceanPQS.radius = body.pqsVersion.radius; * oceanPQS.surfaceMaterial = new PQSOceanSurfaceQuad(laytheOcean.GetComponent<PQS>().surfaceMaterial); * oceanPQS.fallbackMaterial = new PQSOceanSurfaceQuadFallback(laytheOcean.GetComponent<PQS>().fallbackMaterial); * Utility.DumpObjectProperties(oceanPQS.surfaceMaterial, oceanPQS.surfaceMaterial.ToString()); * Utility.DumpObjectProperties(oceanPQS.fallbackMaterial, oceanPQS.fallbackMaterial.ToString()); * * // Create the aerial perspective material * mod = new GameObject("_Material_AerialPerspective"); * mod.transform.parent = oceanRoot.transform; * aerialPerspectiveMaterial = mod.AddComponent<PQSMod_AerialPerspectiveMaterial>(); * aerialPerspectiveMaterial.sphere = body.pqsVersion; * aerialPerspectiveMaterial.globalDensity = -0.00001f; * aerialPerspectiveMaterial.heightFalloff = 6.75f; * aerialPerspectiveMaterial.atmosphereDepth = 150000; * aerialPerspectiveMaterial.DEBUG_SetEveryFrame = true; * aerialPerspectiveMaterial.cameraAlt = 0; * aerialPerspectiveMaterial.cameraAtmosAlt = 0; * aerialPerspectiveMaterial.heightDensAtViewer = 0; * aerialPerspectiveMaterial.requirements = PQS.ModiferRequirements.Default; * aerialPerspectiveMaterial.modEnabled = true; * aerialPerspectiveMaterial.order = 100; * * // Create the UV planet relative position * mod = new GameObject("_Material_SurfaceQuads"); * mod.transform.parent = oceanRoot.transform; * planetRelativePosition = mod.AddComponent<PQSMod_UVPlanetRelativePosition>(); * planetRelativePosition.sphere = body.pqsVersion; * planetRelativePosition.requirements = PQS.ModiferRequirements.Default; * planetRelativePosition.modEnabled = true; * planetRelativePosition.order = 100; * * // Create the quad map remover (da f**k?) * mod = new GameObject("QuadRemoveMap"); * mod.transform.parent = oceanRoot.transform; * PQSMod_RemoveQuadMap removeQuadMap = mod.AddComponent<PQSMod_RemoveQuadMap>(); * removeQuadMap.mapDeformity = 0.0f; * removeQuadMap.minHeight = 0.0f; * removeQuadMap.maxHeight = 0.5f; * removeQuadMap.requirements = PQS.ModiferRequirements.Default; * removeQuadMap.modEnabled = true; * removeQuadMap.order = 1000; * * // Load the heightmap into whatever the hell this is * map = new Texture2D(4, 4, TextureFormat.Alpha8, false); * map.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Height.png")); * removeQuadMap.map = ScriptableObject.CreateInstance<MapSO>(); * removeQuadMap.map.CreateMap(MapSO.MapDepth.Greyscale, map); * UnityEngine.Object.DestroyImmediate(map); * * // Setup the ocean effects * mod = new GameObject("OceanFX"); * mod.transform.parent = oceanRoot.transform; * PQSMod_OceanFX oceanFX = mod.AddComponent<PQSMod_OceanFX>(); * oceanFX.watermain = Utility.RecursivelyGetComponent<PQSMod_OceanFX>(laytheOcean).watermain.Clone() as Texture2D[]; * oceanFX.requirements = PQS.ModiferRequirements.Default; * oceanFX.modEnabled = true; * oceanFX.order = 100;*/ #endregion // Return the new body return(body); }
public static bool CheckForCollisions(PSystem p, Planet pp) { return(CheckForCollisions(p, pp, planetDistanceApart)); }
public void TestConstructor() { PSystem PSystem = new PSystem(v_TestDeserializedMSystemObjects); // Tiles ReadOnlyDictionary <string, Tile> tiles = PSystem.Tiles; Assert.AreEqual(3, tiles.Count); Tile tileQ1 = tiles["q1"]; var connectors = tileQ1.Connectors; Assert.AreEqual(6, connectors.Count); var connectorC1 = connectors[0]; Assert.AreEqual("c1", connectorC1.Name); Assert.AreEqual(Tile.SideType.undef, connectorC1.Side); Assert.AreEqual(v_TestDeserializedMSystemObjects.Glues["pa"], connectorC1.Glue); Assert.AreEqual(Angle.FromRadians(2.034443935795703), connectorC1.Angle); Assert.AreEqual(2, connectorC1.Positions.Count); Assert.AreEqual(new Point3D(0, 10, 0), connectorC1.Positions[0]); double posY = 10 * Math.Cos((1) * 2 * Math.PI / 5); double posX = 10 * Math.Sin((1) * 2 * Math.PI / 5); Assert.AreEqual(new Point3D(posX, posY, 0), connectorC1.Positions[1]); Glue surfaceGLuePx = tileQ1.SurfaceGlue; Assert.AreEqual("px", surfaceGLuePx.Name); Assert.AreEqual(4, tileQ1.Proteins.Count); Assert.AreEqual("p1", tileQ1.Proteins[0].Name); Assert.AreEqual("p1", tileQ1.Proteins[1].Name); Assert.AreEqual("p2", tileQ1.Proteins[2].Name); Assert.AreEqual("p2", tileQ1.Proteins[3].Name); foreach (var protein in tileQ1.Proteins) { Assert.AreEqual(Point3D.Origin, protein.Position); } Assert.AreEqual(Color.DeepSkyBlue, tileQ1.Color); Tile tileS1 = tiles["s1"]; Assert.AreEqual(2, tileS1.Connectors.Count); Assert.AreEqual(1, tileS1.Proteins.Count); //Initial objects IReadOnlyList <Cytos_v2.Classes.SeedTile> seedTiles = PSystem.SeedTiles; Assert.AreEqual(3, seedTiles.Count); Cytos_v2.Classes.SeedTile seedTileQ1 = seedTiles[0]; Assert.AreEqual("q1", seedTileQ1.Name); Assert.AreEqual(new Point3D(0, 0, 0), seedTileQ1.Position); Assert.AreEqual(new EulerAngles(default(Angle), default(Angle), default(Angle)), seedTileQ1.Angle); //Environmental objects var environmentalObjects = PSystem.FloatingObjects.Values.Where(obj => obj.Concentration > 0).ToList(); Assert.AreEqual(1, environmentalObjects.Count); var environmentalObjectA = environmentalObjects[0]; Assert.AreEqual("b", environmentalObjectA.Name); Assert.AreEqual(2, environmentalObjectA.Concentration); //GlueRadius Assert.AreEqual(0.1, PSystem.GlueRadius); //Mobility Assert.AreEqual(3, PSystem.Mobility); //Tolerance Assert.AreEqual(1E-10, PSystem.Tolerance); //SideDist Assert.AreEqual(5E-10, PSystem.SideDist); //GlueRelation GlueRelation glueTuples = PSystem.GlueRelation; Assert.AreEqual(3, glueTuples.Count); Tuple <Glue, Glue> glueTuplePaPb = glueTuples.Keys.ElementAt(0); Assert.AreEqual("pa", glueTuplePaPb.Item1.Name); Assert.AreEqual("pb", glueTuplePaPb.Item2.Name); Assert.AreEqual(1, glueTuples.Values.ElementAt(0).ToDictionary()["a"]); Tuple <Glue, Glue> glueTuplePaPa = glueTuples.Keys.ElementAt(1); Assert.AreEqual("pa", glueTuplePaPa.Item1.Name); Assert.AreEqual("pa", glueTuplePaPa.Item2.Name); Assert.AreEqual(1, glueTuples.Values.ElementAt(1).ToDictionary().Count); Tuple <Glue, Glue> glueTuplePbPb = glueTuples.Keys.ElementAt(2); Assert.AreEqual("pb", glueTuplePbPb.Item1.Name); Assert.AreEqual("pb", glueTuplePbPb.Item2.Name); Assert.AreEqual(0, glueTuples.Values.ElementAt(2).ToDictionary().Count); //MetabolicRules Dictionary <string, IReadOnlyList <EvoMetabolicRule> > metabolicRules = PSystem.MetabolicRules; Assert.AreEqual(2, metabolicRules.Count); Assert.IsNotNull(metabolicRules["p1"]); Assert.AreEqual(1, metabolicRules["p1"].Count); Assert.IsNotNull(metabolicRules["p2"]); Assert.AreEqual(0, metabolicRules["p2"].Count); EvoMetabolicRule metabolicRule = metabolicRules["p1"][0]; Assert.AreEqual(0, metabolicRule.Priority); Assert.AreEqual(EvolutionRule.RuleType.Metabolic, metabolicRule.Type); Assert.AreEqual(EvoMetabolicRule.MetabolicRuleType.Symport, metabolicRule.SubType); Assert.AreEqual(2, metabolicRule.LeftSideObjects.Count); Assert.AreEqual("a", metabolicRule.LeftSideObjects[0].Name); Assert.AreEqual("p1", metabolicRule.LeftSideObjects[1].Name); Assert.AreEqual(2, metabolicRule.RightSideObjects.Count); Assert.AreEqual("p1", metabolicRule.RightSideObjects[0].Name); Assert.AreEqual("a", metabolicRule.RightSideObjects[1].Name); Assert.AreEqual(0, metabolicRule.MLeftInNames.Count); Assert.AreEqual(1, metabolicRule.MLeftOutNames.Count); Assert.AreEqual(1, metabolicRule.MLeftOutNames.ToDictionary()["a"]); Assert.AreEqual(1, metabolicRule.MRightInNames.Count); Assert.AreEqual(1, metabolicRule.MRightInNames.ToDictionary()["a"]); Assert.AreEqual(0, metabolicRule.MRightOutNames.Count); Assert.AreEqual("p1", metabolicRule.RProtein.Name); //CreationRules Dictionary <Glue, IReadOnlyList <EvoNonMetabolicRule> > createRules = PSystem.CreationRules; Assert.AreEqual(3, createRules.Count); Glue pa = v_TestDeserializedMSystemObjects.Glues["pa"]; Glue pb = v_TestDeserializedMSystemObjects.Glues["pb"]; Glue px = v_TestDeserializedMSystemObjects.Glues["px"]; Assert.IsNotNull(createRules[pa]); Assert.AreEqual(1, createRules[pa].Count); Assert.IsNotNull(createRules[pb]); Assert.AreEqual(1, createRules[pb].Count); Assert.IsNotNull(createRules[px]); Assert.AreEqual(0, createRules[px].Count); // For different glues there is the same creation rule - this is OK. EvoNonMetabolicRule createRulePA = createRules[pa][0]; Assert.AreEqual(1, createRulePA.Priority); Assert.AreEqual(EvolutionRule.RuleType.Create, createRulePA.Type); Assert.AreEqual(3, createRulePA.LeftSideObjects.Count); Assert.AreEqual("a", createRulePA.LeftSideObjects[0].Name); Assert.AreEqual("a", createRulePA.LeftSideObjects[1].Name); Assert.AreEqual("a", createRulePA.LeftSideObjects[2].Name); Assert.AreEqual(1, createRulePA.RightSideObjects.Count); Assert.AreEqual("q1", createRulePA.RightSideObjects[0].Name); Assert.AreEqual(3, createRulePA.MLeftSideFloatingNames.Count); Assert.AreEqual(3, createRulePA.MLeftSideFloatingNames.ToDictionary()["a"]); Assert.AreEqual(0, createRulePA.MRightSideFloatingNames.Count); // For different glues there is the same creation rule - this is OK. EvoNonMetabolicRule createRulePB = createRules[pb][0]; Assert.AreEqual(1, createRulePB.Priority); Assert.AreEqual(EvolutionRule.RuleType.Create, createRulePB.Type); Assert.AreEqual(3, createRulePB.LeftSideObjects.Count); Assert.AreEqual("a", createRulePB.LeftSideObjects[0].Name); Assert.AreEqual("a", createRulePB.LeftSideObjects[1].Name); Assert.AreEqual("a", createRulePB.LeftSideObjects[2].Name); Assert.AreEqual(1, createRulePB.RightSideObjects.Count); Assert.AreEqual("q1", createRulePB.RightSideObjects[0].Name); Assert.AreEqual(3, createRulePB.MLeftSideFloatingNames.Count); Assert.AreEqual(3, createRulePB.MLeftSideFloatingNames.ToDictionary()["a"]); Assert.AreEqual(0, createRulePB.MRightSideFloatingNames.Count); //DestructionRules var destructionRules = PSystem.DestructionRules; Assert.AreEqual(3, destructionRules.Count); Assert.IsNotNull(destructionRules["q1"]); Assert.AreEqual(0, destructionRules["q1"].Count); Assert.IsNotNull(destructionRules["s1"]); Assert.AreEqual(1, destructionRules["s1"].Count); EvoNonMetabolicRule destroyRule = destructionRules["s1"][0]; Assert.AreEqual(1, destroyRule.Priority); Assert.AreEqual(EvolutionRule.RuleType.Destroy, destroyRule.Type); Assert.AreEqual(3, destroyRule.LeftSideObjects.Count); Assert.AreEqual("a", destroyRule.LeftSideObjects[0].Name); Assert.AreEqual("a", destroyRule.LeftSideObjects[1].Name); Assert.AreEqual("s1", destroyRule.LeftSideObjects[2].Name); Assert.AreEqual(2, destroyRule.RightSideObjects.Count); Assert.AreEqual("c", destroyRule.RightSideObjects[0].Name); Assert.AreEqual("c", destroyRule.RightSideObjects[1].Name); Assert.AreEqual(2, destroyRule.MLeftSideFloatingNames.Count); Assert.AreEqual(2, destroyRule.MLeftSideFloatingNames.ToDictionary()["a"]); Assert.AreEqual(2, destroyRule.MRightSideFloatingNames.Count); Assert.AreEqual(2, destroyRule.MRightSideFloatingNames.ToDictionary()["c"]); //DivisionRules var divisionRules = PSystem.DivisionRules; Assert.AreEqual(1, divisionRules.Count); Assert.IsNotNull(divisionRules[pa]); Assert.AreEqual(1, divisionRules[pa].Count); Assert.IsNotNull(divisionRules[pa][pa]); Assert.AreEqual(1, divisionRules[pa][pa].Count); EvoNonMetabolicRule divideRule = divisionRules[pa][pa][0]; Assert.AreEqual(1, divideRule.Priority); Assert.AreEqual(EvolutionRule.RuleType.Divide, divideRule.Type); Assert.AreEqual(4, divideRule.LeftSideObjects.Count); Assert.AreEqual("pa", divideRule.LeftSideObjects[0].Name); Assert.AreEqual("pa", divideRule.LeftSideObjects[1].Name); Assert.AreEqual("a", divideRule.LeftSideObjects[2].Name); Assert.AreEqual("a", divideRule.LeftSideObjects[3].Name); Assert.AreEqual(2, divideRule.RightSideObjects.Count); Assert.AreEqual("pa", divideRule.RightSideObjects[0].Name); Assert.AreEqual("pa", divideRule.RightSideObjects[1].Name); Assert.AreEqual(2, divideRule.MLeftSideFloatingNames.Count); Assert.AreEqual(2, divideRule.MLeftSideFloatingNames.ToDictionary()["a"]); Assert.AreEqual(0, divideRule.MRightSideFloatingNames.Count); }
public static bool CheckForCollisions(PSystem system, Planet pp, int PlanetApartDistanceToCheck) { if (system.PlanetCount >= 1) { float planet1PosX = 0, planet1PosY = 0; float planet2PosX = 0, planet2PosY = 0; float moon2PosX, moon2PosY; foreach (Planet p in system.GetPlanets()) { // Planet 1 Calculation GetPosition(p, out planet1PosX, out planet1PosY); // Planet 2 Calculation GetPosition(pp, out planet2PosX, out planet2PosY); // Distance check between points float Distance = Distance2D(planet1PosX, planet1PosY, planet2PosX, planet2PosY); if (Distance < PlanetApartDistanceToCheck) // Collision between planets { return(true); } } if (system.MoonCount <= 0) // Only continue if we've got moons, otherwise we're done. { return(false); } foreach (Planet m in system.GetMoons()) { if (m.IDToOrbit == pp.Id) // If we're checking parent, skip { continue; } foreach (Planet p in system.GetPlanets()) { if (m.IDToOrbit != p.Id) // If we're checking parent, skip { continue; } // Planet 1 Calculation GetPosition(p, out planet1PosX, out planet1PosY); // Moon calculation GetPosition(m, planet1PosX, planet1PosY, out moon2PosX, out moon2PosY); // Distance check between points float Distance; Distance = Distance2D(planet2PosX, planet2PosY, moon2PosX, moon2PosY); if (Distance < PlanetApartDistanceToCheck) // Collision between planets and moons { return(true); } } } } return(false); // Return false if no collisions }
public static bool CheckForCollisions(PSystem p, Planet pp, Planet moon, GalaxyManager gm) { return(CheckForCollisions(p, pp, moon, planetDistanceApart, moonDistanceFromSun, moonDistanceApart, gm)); }
public static PSystemBody GenerateSystemBody(PSystem system, PSystemBody parent, String name, Orbit orbit = null) { PSystemBody Jool = Utility.FindBody (system.rootBody, "Jool"); // Need the geosphere for scaled version PSystemBody Laythe = Utility.FindBody (system.rootBody, "Laythe"); // Need pqs and ocean definitions //Utility.DumpObject (Laythe.celestialBody, " Laythe Celestial Body "); //Utility.DumpObject (Laythe.pqsVersion, " Laythe PQS "); //Transform laytheOcean = Utility.FindInChildren (Laythe.pqsVersion.transform, "LaytheOcean"); //Utility.DumpObject (laytheOcean.GetComponent<PQS> (), " Laythe Ocean PQS "); // AddBody makes the GameObject and stuff. It also attaches it to the system and parent. PSystemBody body = system.AddBody (parent); // set up the various parameters body.name = name; body.flightGlobalsIndex = 100; // Some parameters of the celestialBody, which represents the actual planet... // PSystemBody is more of a container that associates the planet with its orbit // and position in the planetary system, etc. body.celestialBody.bodyName = name; body.celestialBody.bodyDescription = "Merciful Kod, this thing just APPEARED! And unlike last time, it wasn't bird droppings on the telescope."; body.celestialBody.Radius = 320000; //body.celestialBody.Radius = 3380100; body.celestialBody.GeeASL = 0.3; //body.celestialBody.Mass = 6.4185E+23; body.celestialBody.Mass = 4.5154812E+21; body.celestialBody.timeWarpAltitudeLimits = (float[])Laythe.celestialBody.timeWarpAltitudeLimits.Clone(); body.celestialBody.rotationPeriod = 88642.6848; body.celestialBody.rotates = true; body.celestialBody.BiomeMap = GenerateCBAttributeMapSO(name);//Dres.celestialBody.BiomeMap;// body.celestialBody.scienceValues = Laythe.celestialBody.scienceValues; body.celestialBody.ocean = false; // Presumably true of Kerbin. I do not know what the consequences are of messing with this exactly. // I think this just affects where the Planetarium/Tracking station starts. body.celestialBody.isHomeWorld = false; // Setup the orbit of "Kopernicus." The "Orbit" class actually is built to support serialization straight // from Squad, so storing these to files (and loading them) will be pretty easy. body.orbitRenderer.orbitColor = Color.magenta; body.orbitDriver.celestialBody = body.celestialBody; body.orbitDriver.updateMode = OrbitDriver.UpdateMode.UPDATE; if (orbit == null) body.orbitDriver.orbit = new Orbit (0.0, 0.0, 47500000000, 0, 0, 0, 0, system.rootBody.celestialBody); else body.orbitDriver.orbit = orbit; #region PSystemBody.pqsVersion generation // Create the PQS controller game object for Kopernicus GameObject controllerRoot = new GameObject(name); controllerRoot.layer = Constants.GameLayers.LocalSpace; controllerRoot.transform.parent = Utility.Deactivator; // Create the PQS object and pull all the values from Dres (has some future proofing i guess? adapts to PQS changes) body.pqsVersion = controllerRoot.AddComponent<PQS>(); Utility.CopyObjectFields(Laythe.pqsVersion, body.pqsVersion); //body.pqsVersion.surfaceMaterial = new PQSProjectionSurfaceQuad(); //body.pqsVersion.fallbackMaterial = new PQSProjectionFallback(); body.pqsVersion.surfaceMaterial = new PQSProjectionAerialQuadRelative(Laythe.pqsVersion.surfaceMaterial); // use until we determine all the functions of the shader textures body.pqsVersion.fallbackMaterial = new PQSProjectionFallback(Laythe.pqsVersion.fallbackMaterial); body.pqsVersion.radius = body.celestialBody.Radius; body.pqsVersion.mapOcean = false; // Debug Utility.DumpObjectProperties(body.pqsVersion.surfaceMaterial, " Surface Material "); Utility.DumpObjectProperties(body.pqsVersion.fallbackMaterial, " Fallback Material "); // Detail defaults body.pqsVersion.maxQuadLenghtsPerFrame = 0.03f; body.pqsVersion.minLevel = 1; body.pqsVersion.maxLevel = 10; body.pqsVersion.minDetailDistance = 8; // Create the celestial body transform GameObject mod = new GameObject("_CelestialBody"); mod.transform.parent = controllerRoot.transform; PQSMod_CelestialBodyTransform celestialBodyTransform = mod.AddComponent<PQSMod_CelestialBodyTransform>(); celestialBodyTransform.sphere = body.pqsVersion; celestialBodyTransform.forceActivate = false; celestialBodyTransform.deactivateAltitude = 115000; celestialBodyTransform.forceRebuildOnTargetChange = false; celestialBodyTransform.planetFade = new PQSMod_CelestialBodyTransform.AltitudeFade(); celestialBodyTransform.planetFade.fadeFloatName = "_PlanetOpacity"; celestialBodyTransform.planetFade.fadeStart = 100000.0f; celestialBodyTransform.planetFade.fadeEnd = 110000.0f; celestialBodyTransform.planetFade.valueStart = 0.0f; celestialBodyTransform.planetFade.valueEnd = 1.0f; celestialBodyTransform.planetFade.secondaryRenderers = new List<GameObject>(); celestialBodyTransform.secondaryFades = new PQSMod_CelestialBodyTransform.AltitudeFade[0]; celestialBodyTransform.requirements = PQS.ModiferRequirements.Default; celestialBodyTransform.modEnabled = true; celestialBodyTransform.order = 10; // Create the color PQS mods mod = new GameObject("_Color"); mod.transform.parent = controllerRoot.transform; PQSMod_VertexSimplexNoiseColor vertexSimplexNoiseColor = mod.AddComponent<PQSMod_VertexSimplexNoiseColor>(); vertexSimplexNoiseColor.sphere = body.pqsVersion; vertexSimplexNoiseColor.seed = 45; vertexSimplexNoiseColor.blend = 1.0f; vertexSimplexNoiseColor.colorStart = new Color(0.768656731f, 0.6996614f, 0.653089464f, 1); vertexSimplexNoiseColor.colorEnd = new Color(0.0f, 0.0f, 0.0f, 1.0f); vertexSimplexNoiseColor.octaves = 12.0; vertexSimplexNoiseColor.persistence = 0.5; vertexSimplexNoiseColor.frequency = 2.0; vertexSimplexNoiseColor.requirements = PQS.ModiferRequirements.MeshColorChannel; vertexSimplexNoiseColor.modEnabled = true; vertexSimplexNoiseColor.order = 200; PQSMod_HeightColorMap heightColorMap = mod.AddComponent<PQSMod_HeightColorMap>(); heightColorMap.sphere = body.pqsVersion; List<PQSMod_HeightColorMap.LandClass> landClasses = new List<PQSMod_HeightColorMap.LandClass>(); PQSMod_HeightColorMap.LandClass landClass = new PQSMod_HeightColorMap.LandClass("AbyPl", 0.0, 0.5, new Color(0.0f, 0.0f, 0.0f, 1.0f), Color.white, double.NaN); landClass.lerpToNext = true; landClasses.Add(landClass); landClass = new PQSMod_HeightColorMap.LandClass("Beach", 0.5, 0.550000011920929, new Color(0.164179087f, 0.164179087f, 0.164179087f, 1.0f), Color.white, double.NaN); landClass.lerpToNext = true; landClasses.Add(landClass); landClass = new PQSMod_HeightColorMap.LandClass("Beach", 0.550000011920929, 1.0, new Color(0.373134315f, 0.373134315f, 0.373134315f, 1.0f), Color.white, double.NaN); landClass.lerpToNext = false; landClasses.Add(landClass); // Generate an array from the land classes list heightColorMap.landClasses = landClasses.ToArray(); heightColorMap.blend = 0.7f; heightColorMap.lcCount = 3; heightColorMap.requirements = PQS.ModiferRequirements.MeshColorChannel; heightColorMap.modEnabled = true; heightColorMap.order = 201; // Create the alititude alpha mods mod = new GameObject("_Material_ModProjection"); mod.transform.parent = controllerRoot.transform; PQSMod_AltitudeAlpha altitudeAlpha = mod.AddComponent<PQSMod_AltitudeAlpha>(); altitudeAlpha.sphere = body.pqsVersion; altitudeAlpha.atmosphereDepth = 4000.0; altitudeAlpha.invert = false; altitudeAlpha.requirements = PQS.ModiferRequirements.Default; altitudeAlpha.modEnabled = false; altitudeAlpha.order = 999999999; // Create the aerial perspective material mod = new GameObject("_Material_AerialPerspective"); mod.transform.parent = controllerRoot.transform; PQSMod_AerialPerspectiveMaterial aerialPerspectiveMaterial = mod.AddComponent<PQSMod_AerialPerspectiveMaterial>(); aerialPerspectiveMaterial.sphere = body.pqsVersion; aerialPerspectiveMaterial.globalDensity = -0.00001f; aerialPerspectiveMaterial.heightFalloff = 6.75f; aerialPerspectiveMaterial.atmosphereDepth = 150000; aerialPerspectiveMaterial.DEBUG_SetEveryFrame = true; aerialPerspectiveMaterial.cameraAlt = 0; aerialPerspectiveMaterial.cameraAtmosAlt = 0; aerialPerspectiveMaterial.heightDensAtViewer = 0; aerialPerspectiveMaterial.requirements = PQS.ModiferRequirements.Default; aerialPerspectiveMaterial.modEnabled = true; aerialPerspectiveMaterial.order = 100; // Create the UV planet relative position mod = new GameObject("_Material_SurfaceQuads"); mod.transform.parent = controllerRoot.transform; PQSMod_UVPlanetRelativePosition planetRelativePosition = mod.AddComponent<PQSMod_UVPlanetRelativePosition>(); planetRelativePosition.sphere = body.pqsVersion; planetRelativePosition.requirements = PQS.ModiferRequirements.Default; planetRelativePosition.modEnabled = true; planetRelativePosition.order = 999999; // Create the height noise module mod = new GameObject("_HeightNoise"); mod.transform.parent = controllerRoot.transform; PQSMod_VertexHeightMap vertexHeightMap = mod.gameObject.AddComponent<PQSMod_VertexHeightMap>(); vertexHeightMap.sphere = body.pqsVersion; //vertexHeightMap.heightMapDeformity = 29457.0; vertexHeightMap.heightMapDeformity = 10000.0; vertexHeightMap.heightMapOffset = -1000.0; vertexHeightMap.scaleDeformityByRadius = false; vertexHeightMap.requirements = PQS.ModiferRequirements.MeshCustomNormals | PQS.ModiferRequirements.VertexMapCoords; vertexHeightMap.modEnabled = true; vertexHeightMap.order = 20; // Load the heightmap for this planet Texture2D map = new Texture2D(4, 4, TextureFormat.Alpha8, false); map.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Height.png")); vertexHeightMap.heightMap = ScriptableObject.CreateInstance<MapSO>(); vertexHeightMap.heightMap.CreateMap(MapSO.MapDepth.Greyscale, map); UnityEngine.Object.DestroyImmediate(map); // Create the simplex height module PQSMod_VertexSimplexHeight vertexSimplexHeight = mod.AddComponent<PQSMod_VertexSimplexHeight>(); vertexSimplexHeight.sphere = body.pqsVersion; vertexSimplexHeight.seed = 670000; vertexSimplexHeight.deformity = 1700.0; vertexSimplexHeight.octaves = 12.0; vertexSimplexHeight.persistence = 0.5; vertexSimplexHeight.frequency = 4.0; vertexSimplexHeight.requirements = PQS.ModiferRequirements.MeshCustomNormals; vertexSimplexHeight.modEnabled = true; vertexSimplexHeight.order = 21; // SERIOUSLY RECOMMENDED FOR NO OCEAN WORLDS // Create the flatten ocean module PQSMod_FlattenOcean flattenOcean = mod.AddComponent<PQSMod_FlattenOcean>(); flattenOcean.sphere = body.pqsVersion; flattenOcean.oceanRadius = 1.0; flattenOcean.requirements = PQS.ModiferRequirements.MeshCustomNormals; flattenOcean.modEnabled = true; flattenOcean.order = 25; // Creat the vertex height noise module PQSMod_VertexHeightNoise vertexHeightNoise = mod.AddComponent<PQSMod_VertexHeightNoise>(); vertexHeightNoise.sphere = body.pqsVersion; vertexHeightNoise.noiseType = PQSMod_VertexHeightNoise.NoiseType.RiggedMultifractal; vertexHeightNoise.deformity = 1000.0f; vertexHeightNoise.seed = 5906; vertexHeightNoise.frequency = 2.0f; vertexHeightNoise.lacunarity = 2.5f; vertexHeightNoise.persistance = 0.5f; vertexHeightNoise.octaves = 4; vertexHeightNoise.mode = LibNoise.Unity.QualityMode.Low; vertexHeightNoise.requirements = PQS.ModiferRequirements.MeshColorChannel; vertexHeightNoise.modEnabled = true; vertexHeightNoise.order = 22; // Create the material direction mod = new GameObject("_Material_SunLight"); mod.transform.parent = controllerRoot.gameObject.transform; PQSMod_MaterialSetDirection materialSetDirection = mod.AddComponent<PQSMod_MaterialSetDirection>(); materialSetDirection.sphere = body.pqsVersion; materialSetDirection.valueName = "_sunLightDirection"; materialSetDirection.requirements = PQS.ModiferRequirements.Default; materialSetDirection.modEnabled = true; materialSetDirection.order = 100; // Crete the quad mesh colliders mod = new GameObject("QuadMeshColliders"); mod.transform.parent = controllerRoot.gameObject.transform; PQSMod_QuadMeshColliders quadMeshColliders = mod.AddComponent<PQSMod_QuadMeshColliders>(); quadMeshColliders.sphere = body.pqsVersion; quadMeshColliders.maxLevelOffset = 0; quadMeshColliders.physicsMaterial = new PhysicMaterial(); quadMeshColliders.physicsMaterial.name = "Ground"; quadMeshColliders.physicsMaterial.dynamicFriction = 0.6f; quadMeshColliders.physicsMaterial.staticFriction = 0.8f; quadMeshColliders.physicsMaterial.bounciness = 0.0f; quadMeshColliders.physicsMaterial.frictionDirection2 = Vector3.zero; quadMeshColliders.physicsMaterial.dynamicFriction2 = 0.0f; quadMeshColliders.physicsMaterial.staticFriction2 = 0.0f; quadMeshColliders.physicsMaterial.frictionCombine = PhysicMaterialCombine.Maximum; quadMeshColliders.physicsMaterial.bounceCombine = PhysicMaterialCombine.Average; quadMeshColliders.requirements = PQS.ModiferRequirements.Default; quadMeshColliders.modEnabled = true; quadMeshColliders.order = 100; // Create the simplex height absolute mod = new GameObject("_FineDetail"); mod.transform.parent = controllerRoot.gameObject.transform; PQSMod_VertexSimplexHeightAbsolute vertexSimplexHeightAbsolute = mod.AddComponent<PQSMod_VertexSimplexHeightAbsolute>(); vertexSimplexHeightAbsolute.sphere = body.pqsVersion; vertexSimplexHeightAbsolute.seed = 4234; vertexSimplexHeightAbsolute.deformity = 400.0; vertexSimplexHeightAbsolute.octaves = 6.0; vertexSimplexHeightAbsolute.persistence = 0.5; vertexSimplexHeightAbsolute.frequency = 18.0; vertexSimplexHeightAbsolute.requirements = PQS.ModiferRequirements.Default; vertexSimplexHeightAbsolute.modEnabled = true; vertexSimplexHeightAbsolute.order = 30; // Surface color map mod = new GameObject("_LandClass"); mod.transform.parent = body.pqsVersion.gameObject.transform; PQSMod_VertexColorMap colorMap = mod.AddComponent<PQSMod_VertexColorMap>(); colorMap.sphere = body.pqsVersion; colorMap.order = 500; colorMap.modEnabled = true; // Decompress and load the color map = new Texture2D(4, 4, TextureFormat.RGB24, false); map.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Color.png")); colorMap.vertexColorMap = ScriptableObject.CreateInstance<MapSO>(); colorMap.vertexColorMap.CreateMap(MapSO.MapDepth.RGB, map); UnityEngine.Object.DestroyImmediate(map); #endregion #region PSystemBody.scaledVersion generation // Create the scaled version of the planet for use in map view body.scaledVersion = new GameObject(name); body.scaledVersion.layer = Constants.GameLayers.ScaledSpace; body.scaledVersion.transform.parent = Utility.Deactivator; // DEPRECATED - USE PQSMeshWrapper // Make sure the scaled version cooresponds to the size of the body // Turns out that the localScale is directly related to the planet size. // Jool's local scale is {1,1,1}, Kerbin's is {0.1,0.1,0.1}. Jool's // radius is 6000 km, Kerbin's is 600 km. Notice the relation? float scale = (float) body.celestialBody.Radius / 6000000.0f; body.scaledVersion.transform.localScale = new Vector3(scale, scale, scale); // Generate a mesh to fit the PQS we generated (it would be cool to generate this FROM the PQS) Mesh mesh = new Mesh(); Utility.CopyMesh(Jool.scaledVersion.GetComponent<MeshFilter>().sharedMesh, mesh); // Iterate though the UVs // Geosphere with a radius of 1000, cooresponds to an object 6000km in radius Vector3[] vertices = mesh.vertices; for(int i = 0; i < mesh.vertexCount; i++) { // Get the height offset from the height map Vector2 uv = mesh.uv[i]; float displacement = vertexHeightMap.heightMap.GetPixelFloat(uv.x, uv.y); // Since this is a geosphere, normalizing the vertex gives the vector to translate on Vector3 v = vertices[i]; v.Normalize(); // Calculate the real height displacement (in meters), normalized vector "v" scale (1 unit = 6 km) displacement = (float) vertexHeightMap.heightMapOffset + (displacement * (float) vertexHeightMap.heightMapDeformity); Vector3 offset = v * ((displacement / 6000.0f) / scale); // Adjust the displacement vertices[i] += offset; } mesh.vertices = vertices; mesh.RecalculateNormals(); // Create the mesh filter MeshFilter meshFilter = body.scaledVersion.AddComponent<MeshFilter> (); meshFilter.mesh = mesh; // Load and compress the color texture for the custom planet Texture2D colorTexture = new Texture2D(4, 4, TextureFormat.RGBA32, true); colorTexture.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Color.png")); colorTexture.Compress(true); colorTexture.Apply(true, true); // Load and compress the color texture for the custom planet Texture2D normalTexture = new Texture2D(4, 4, TextureFormat.RGB24, true); normalTexture.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Normals.png")); //normalTexture = GameDatabase.BitmapToUnityNormalMap(normalTexture); normalTexture.Compress(true); normalTexture.Apply(true, true); // Create the renderer and material for the scaled version MeshRenderer renderer = body.scaledVersion.AddComponent<MeshRenderer>(); //ScaledPlanetSimple material = new ScaledPlanetSimple(); // for atmosphereless planets ScaledPlanetRimAerial material = new ScaledPlanetRimAerial(); material.color = Color.white; material.specColor = Color.black; material.mainTexture = colorTexture; material.bumpMap = normalTexture; renderer.material = material; // Create the sphere collider SphereCollider collider = body.scaledVersion.AddComponent<SphereCollider> (); collider.center = Vector3.zero; collider.radius = 1000.0f; // Create the ScaledSpaceFader to fade the orbit out where we view it (maybe?) ScaledSpaceFader fader = body.scaledVersion.AddComponent<ScaledSpaceFader> (); fader.celestialBody = body.celestialBody; fader.fadeStart = 95000.0f; fader.fadeEnd = 100000.0f; fader.floatName = "_Opacity"; #endregion #region Atmosphere //--------------------- PROPERTIES EXCLUSIVE TO BODIES WITH ATMOSPHERE // Load the atmosphere gradient (compress it, does not need to be high quality) Texture2D atmosphereGradient = new Texture2D(4, 4, TextureFormat.RGB24, true); atmosphereGradient.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/AtmosphereGradient.png")); atmosphereGradient.Compress(true); atmosphereGradient.wrapMode = TextureWrapMode.Clamp; atmosphereGradient.mipMapBias = 0.0f; atmosphereGradient.Apply(true, true); // Set the additional settings in the scaledVersion body's shader material.rimPower = 2.06f; material.rimBlend = 0.3f; material.rimColorRamp = atmosphereGradient; // Atmosphere specific properties (for scaled version root) (copied from duna) MaterialSetDirection materialLightDirection = body.scaledVersion.AddComponent<MaterialSetDirection>(); materialLightDirection.valueName = "_localLightDirection"; // Create the atmosphere shell itself GameObject scaledAtmosphere = new GameObject("atmosphere"); scaledAtmosphere.transform.parent = body.scaledVersion.transform; scaledAtmosphere.layer = Constants.GameLayers.ScaledSpaceAtmosphere; meshFilter = scaledAtmosphere.AddComponent<MeshFilter>(); meshFilter.sharedMesh = Jool.scaledVersion.GetComponent<MeshFilter>().sharedMesh; renderer = scaledAtmosphere.AddComponent<MeshRenderer>(); renderer.material = new Kopernicus.MaterialWrapper.AtmosphereFromGround(); AtmosphereFromGround atmosphereRenderInfo = scaledAtmosphere.AddComponent<AtmosphereFromGround>(); atmosphereRenderInfo.waveLength = new Color(0.509f, 0.588f, 0.643f, 0.000f); // Technical info for atmosphere body.celestialBody.atmosphere = true; body.celestialBody.atmosphereContainsOxygen = true; body.celestialBody.staticPressureASL = 1.0; // can't find anything that references this, especially with the equation in mind - where is this used? body.celestialBody.altitudeMultiplier = 1.4285f; // ditto body.celestialBody.atmosphereScaleHeight = 4.0; // pressure (in atm) = atmosphereMultipler * e ^ -(altitude / (atmosphereScaleHeight * 1000)) body.celestialBody.atmosphereMultiplier = 0.8f; body.celestialBody.atmoshpereTemperatureMultiplier = 1.0f; // how does this coorespond? body.celestialBody.maxAtmosphereAltitude = 55000.0f; // i guess this is so the math doesn't drag out? body.celestialBody.useLegacyAtmosphere = true; body.celestialBody.atmosphericAmbientColor = new Color(0.306f, 0.187f, 0.235f, 1.000f); #endregion #region Ocean // ---------------- FOR BODIES WITH OCEANS ---------- /*body.celestialBody.ocean = true; // Setup the laythe ocean info in master pqs body.pqsVersion.mapOcean = true; body.pqsVersion.mapOceanColor = new Color(0.117f, 0.126f, 0.157f, 1.000f); body.pqsVersion.mapOceanHeight = 0.0f; // Generate the PQS object GameObject oceanRoot = new GameObject(name + "Ocean"); oceanRoot.transform.parent = body.pqsVersion.transform; oceanRoot.layer = Constants.GameLayers.LocalSpace; PQS oceanPQS = oceanRoot.AddComponent<PQS>(); // Add this new PQS to the secondary renderers of the altitude fade controller celestialBodyTransform.planetFade.secondaryRenderers.Add(oceanRoot); // Setup the PQS object data Utility.CopyObjectFields<PQS>(laytheOcean.GetComponent<PQS>(), oceanPQS); oceanPQS.radius = body.pqsVersion.radius; oceanPQS.surfaceMaterial = new PQSOceanSurfaceQuad(laytheOcean.GetComponent<PQS>().surfaceMaterial); oceanPQS.fallbackMaterial = new PQSOceanSurfaceQuadFallback(laytheOcean.GetComponent<PQS>().fallbackMaterial); Utility.DumpObjectProperties(oceanPQS.surfaceMaterial, oceanPQS.surfaceMaterial.ToString()); Utility.DumpObjectProperties(oceanPQS.fallbackMaterial, oceanPQS.fallbackMaterial.ToString()); // Create the aerial perspective material mod = new GameObject("_Material_AerialPerspective"); mod.transform.parent = oceanRoot.transform; aerialPerspectiveMaterial = mod.AddComponent<PQSMod_AerialPerspectiveMaterial>(); aerialPerspectiveMaterial.sphere = body.pqsVersion; aerialPerspectiveMaterial.globalDensity = -0.00001f; aerialPerspectiveMaterial.heightFalloff = 6.75f; aerialPerspectiveMaterial.atmosphereDepth = 150000; aerialPerspectiveMaterial.DEBUG_SetEveryFrame = true; aerialPerspectiveMaterial.cameraAlt = 0; aerialPerspectiveMaterial.cameraAtmosAlt = 0; aerialPerspectiveMaterial.heightDensAtViewer = 0; aerialPerspectiveMaterial.requirements = PQS.ModiferRequirements.Default; aerialPerspectiveMaterial.modEnabled = true; aerialPerspectiveMaterial.order = 100; // Create the UV planet relative position mod = new GameObject("_Material_SurfaceQuads"); mod.transform.parent = oceanRoot.transform; planetRelativePosition = mod.AddComponent<PQSMod_UVPlanetRelativePosition>(); planetRelativePosition.sphere = body.pqsVersion; planetRelativePosition.requirements = PQS.ModiferRequirements.Default; planetRelativePosition.modEnabled = true; planetRelativePosition.order = 100; // Create the quad map remover (da f**k?) mod = new GameObject("QuadRemoveMap"); mod.transform.parent = oceanRoot.transform; PQSMod_RemoveQuadMap removeQuadMap = mod.AddComponent<PQSMod_RemoveQuadMap>(); removeQuadMap.mapDeformity = 0.0f; removeQuadMap.minHeight = 0.0f; removeQuadMap.maxHeight = 0.5f; removeQuadMap.requirements = PQS.ModiferRequirements.Default; removeQuadMap.modEnabled = true; removeQuadMap.order = 1000; // Load the heightmap into whatever the hell this is map = new Texture2D(4, 4, TextureFormat.Alpha8, false); map.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Height.png")); removeQuadMap.map = ScriptableObject.CreateInstance<MapSO>(); removeQuadMap.map.CreateMap(MapSO.MapDepth.Greyscale, map); UnityEngine.Object.DestroyImmediate(map); // Setup the ocean effects mod = new GameObject("OceanFX"); mod.transform.parent = oceanRoot.transform; PQSMod_OceanFX oceanFX = mod.AddComponent<PQSMod_OceanFX>(); oceanFX.watermain = Utility.RecursivelyGetComponent<PQSMod_OceanFX>(laytheOcean).watermain.Clone() as Texture2D[]; oceanFX.requirements = PQS.ModiferRequirements.Default; oceanFX.modEnabled = true; oceanFX.order = 100;*/ #endregion // Return the new body return body; }
public static bool CheckForCollisions(PSystem system, Planet pp, Planet moon, int planetDistanceApart, int moonDistanceFromSun, int moonDistanceApart, GalaxyManager galaxyManager) { // Generate locations of: Other planet, basePlanetPos+MoonPos, OtherMoonParentPos+MoonPos if (system.PlanetCount >= 1) { float moon1PosX = 0, moon1PosY = 0; // Outside because used twice float Distance; foreach (Planet p in system.GetPlanets()) { if (moon.IDToOrbit == p.Id) { continue; } // Planet 1 Calculation float planet1PosX, planet1PosY; GetPosition(p, out planet1PosX, out planet1PosY); // Planet 2 Calculation float planet2PosX, planet2PosY; GetPosition(pp, out planet2PosX, out planet2PosY); // Moon 1 Calculation GetPosition(moon, planet2PosX, planet2PosY, out moon1PosX, out moon1PosY); // Distance check between points Distance = Distance2D(planet1PosX, planet1PosY, moon1PosX, moon1PosY); if (Distance < planetDistanceApart) // We don't want moons too close to other planets! { return(true); } // Distance check between points Distance = Distance2D(0, 0, moon1PosX, moon1PosY); // Assuming sun is 0,0 if (Distance < moonDistanceFromSun) // We don't want moons too close to the sun! { return(true); } } // This is in a second forloop because otherwise we do waaaay extra calculations foreach (Planet m in system.GetMoons()) { // We need to get the parent planet to get the location // Planet 1 Calculation float planetParentPosX, planetParentPosY; GetPosition((Planet)galaxyManager.GetArea(m.IDToOrbit), out planetParentPosX, out planetParentPosY); // Moon 2 Calculation float moon2PosX, moon2PosY; GetPosition(m, planetParentPosX, planetParentPosY, out moon2PosX, out moon2PosY); // Distance check between points Distance = Distance2D(moon1PosX, moon1PosY, moon2PosX, moon2PosY); if (Distance < moonDistanceApart) // We don't want moons too close to other moons! { return(true); } } } return(false); // Return false if no collisions }
/// <summary> /// Generates n moons for a single planet, where n is divined from some mystical voodoo black magic related to planet.Scale /// </summary> /// <param name="system"></param> /// <param name="planet"></param> /// <param name="galaxyManager"></param> /// <param name="idManager"></param> /// <param name="rm"></param> /// <param name="pl"></param> /// <param name="al"></param> /// <param name="sl"></param> /// <param name="tl"></param> /// <param name="mem"></param> static void _generateMoons(PSystem system, Planet planet, GalaxyManager galaxyManager, LocalIDManager idManager, GalaxyRegistrationManager rm, LocatorService ls) { // If any moons, add them if (planet.HasMoons) { int parentID = planet.Id; int numMoons = 0; // Creates moon based on scale of size switch (planet.Scale) { case 0: case 1: case 2: case 3: case 4: case 5: planet.PlanetType = (PlanetTypes)r.Next(0, (int)PlanetTypes.OceanicSmall + 1); planet.Scale += 3; // Makes the small sprites scale better break; case 6: case 7: planet.PlanetType = (PlanetTypes)r.Next(0, (int)PlanetTypes.OceanicSmall + 1); if (planet.PlanetType >= PlanetTypes.Crystalline && planet.PlanetType < PlanetTypes.Port) { planet.Scale += 3; // Makes the small sprites scale better } numMoons = r.Next(3) + 2; break; case 8: case 9: numMoons = r.Next(2) + 3; break; case 10: case 11: case 12: numMoons = r.Next(3) + 3; break; } for (int m = 0; m < numMoons; m++) { Planet moon; moon = new Planet(planet, idManager.PopFreeID(), ls); InitializeMoon(moon, m, moonMinimumDistance, moonIncrementOfOrbit * m, moonVariationOfOrbit, planet, planet.Id, r.Next()); if (moon.PlanetType >= PlanetTypes.Crystalline && moon.PlanetType < PlanetTypes.Port) { moon.Scale += 3; // Makes the small sprites scale better } // #Yolo moon.AreaName = planet.AreaName + "abcdefghijklmnopqrstuvwxyz"[m]; bool SatisfiedWithResults = false; int maxAttempts = 200; int numAttempts = 0; while (!SatisfiedWithResults)// While we're not content with the generation { // Add moons moon = new Planet(planet, moon.Id, ls); InitializeMoon(moon, m, moonMinimumDistance, moonIncrementOfOrbit * m, moonVariationOfOrbit, planet, planet.Id, r.Next()); // Add another while here to check for maxDistance, as well as an If for if the system should follow that path of generation SatisfiedWithResults = !CheckForCollisions(system, planet, moon, galaxyManager); // True if we find any collisions. numAttempts++; if (numAttempts >= maxAttempts) { break; // Breaks out of infinite pass if it ever occurs } } if (!SatisfiedWithResults) // Don't add a colliding planet! { //Logger.log(Log_Type.ERROR, "Skipped adding a moon due to MaxAttempts being too much"); idManager.PushFreeID(moon.Id); continue; } moon.IsMoon = true; rm.RegisterObject(moon); system.AddMoon(moon); moon.ParentAreaID = system.Id; } } }
public List <PSystem> generateAndFillGalaxy(int numPlanetsPerSystem, int solID, int numSystems, IEnumerable <PlanetLayout> layouts, GalaxyManager galaxyManager, LocalIDManager IDManager, GalaxyRegistrationManager rm, LocatorService ls) { float warpXPos = 0; float warpYPos = 0; int amount = 0; List <PSystem> generatedSystems = new List <PSystem>(); PSystem sol = GenerateStarsystem(numPlanetsPerSystem, solID, galaxyManager, IDManager, rm, ls); sol.AreaName = "Sol"; amount += sol.PlanetCount; generatedSystems.Add(sol); for (int i = 0; i < numSystems - 1; i++) { tempsys = GenerateStarsystem(numPlanetsPerSystem, IDManager.PopFreeID(), galaxyManager, IDManager, rm, ls); amount += tempsys.PlanetCount; generatedSystems.Add(tempsys); //GalaxyManager.idToSystem.TryAdd(tempsys.ID, tempsys); } //ConsoleManager.WriteToFreeLine("Average of " + amount / numSystems + " planets per system"); //Randomly link the systems //Take each system, iterate through the systems list and randomly connect them, or don't for (int i = 0; i < generatedSystems.Count; i++) { for (int j = i + 1; j < generatedSystems.Count; j++) { if (r.Next(0, 100) <= 30) //30% probability of having the systems link { warpXPos = r.Next(-(generatedSystems[i].AreaSize - 200), (generatedSystems[i].AreaSize - 200)); warpYPos = -(int)Math.Sqrt(Math.Pow((generatedSystems[i].AreaSize - 200f), 2) - Math.Pow(warpXPos, 2)); tempWarp = new Warphole(warpXPos / 100, warpYPos / 100, generatedSystems[i].Id, generatedSystems[j].Id, (byte)generatedSystems[i].Warpholes.Count); tempWarp.DestinationAreaID = generatedSystems[j].Id; generatedSystems[i].Warpholes.Add(tempWarp); //Normalizing the vector warpXPos = warpXPos / (generatedSystems[i].AreaSize - 200f); warpYPos = warpYPos / (generatedSystems[i].AreaSize - 200f); //Converting it to the length for the other system, flipping to other side of system warpXPos = -warpXPos * (generatedSystems[j].AreaSize - 200f); warpYPos = -warpYPos * (generatedSystems[j].AreaSize - 200f); tempWarp = new Warphole(warpXPos / 100, warpYPos / 100, generatedSystems[j].Id, generatedSystems[i].Id, (byte)generatedSystems[j].Warpholes.Count); tempWarp.DestinationAreaID = generatedSystems[i].Id; generatedSystems[j].Warpholes.Add(tempWarp); } } } AssignPlanetLayouts(layouts, generatedSystems); return(generatedSystems); }
public static PSystem GenerateStarsystem(int numberOfPlanets, int ID, GalaxyManager galaxyManager, LocalIDManager idManager, GalaxyRegistrationManager rm, LocatorService ls) { bool hasPort = false; // Add sun float size = r.Next(100, 255) / 100f; float mass = r.Next(50, 255) / 10f; float innerGravity = mass / 1875f; float outerGravity = innerGravity / 6f; var s = (SunTypes[])Enum.GetValues(typeof(SunTypes)); int type = r.Next(0, s.Length); var star = new Star(size, mass, innerGravity, outerGravity, s[type]); var system = new PSystem(star, ID, ls); system.AreaSize = baseBorder + r.Next(0, borderVariation); // Add Name system.AreaName = NameProvider.GetRandomName(); rm.RegisterObject(system); for (int i = 0; i < numberOfPlanets; i++) { Planet planet; bool SatisfiedWithResults = false; int numAttempts = MaxAttempts; system.IsCluster = false; int clusterType = 0; planet = new Planet(system, 0, ls); planet.AreaName = system.AreaName + " " + ToRoman(i + 1); if (r.Next(0, 101) > (100 - chanceOfCluster)) // Chance for planets to cluster { system.IsCluster = true; clusterType = r.Next(0, clusterRadii.Count()); // Get which type of cluster } planet.Init(i, moonChance, minDistance, incrementOfOrbit, variationOfOrbit, 0, r.Next()); SatisfiedWithResults = !CheckForCollisions(system, planet); // True if we find any collisions. while (!SatisfiedWithResults)// While we're not content with the generation { planet.Init(i, moonChance, minDistance, incrementOfOrbit, variationOfOrbit, 0, r.Next()); SatisfiedWithResults = !CheckForCollisions(system, planet); // True if we find any collisions. if (SatisfiedWithResults && system.IsCluster && i > 0) { SatisfiedWithResults = CheckForCollisions(system, planet, clusterRadii[clusterType]); // Cluster planets } numAttempts++; if (numAttempts >= MaxAttempts && !system.IsCluster) { break; // Breaks out of infinite pass if it ever occurs } else if (numAttempts >= MaxAttempts && system.IsCluster) { i = 0; // Reset the whole operation because there's a bad system being generated. foreach (Planet pll in system.GetPlanets()) { system.RemovePlanet(pll); rm.DeRegisterObject(pll); } break; } } if (SatisfiedWithResults == false) // Don't add a colliding planet! { //Logger.log(Log_Type.WARNING, "Skipped adding a planet due to MaxAttempts being too much"); continue; } planet.Id = idManager.PopFreeID(); system.AddPlanet(planet); planet.ParentAreaID = system.Id; rm.RegisterObject(planet); if (system.AreaSize < planet.Distance - baseBorder) // If we're skinny, throw in a little extra space { system.AreaSize = planet.Distance + baseBorder + r.Next(0, borderVariation); } } foreach (Planet p in system.GetPlanets()) { _generateMoons(system, p, galaxyManager, idManager, rm, ls); } foreach (Planet m in system.GetMoons()) { if (system.AreaSize < ls.AreaLocator.GetArea(m.IDToOrbit).Distance + m.Distance + baseBorder) { // If we're skinny, throw in a little extra space system.AreaSize = ls.AreaLocator.GetArea(m.IDToOrbit).Distance + m.Distance + baseBorder + r.Next(0, borderVariation); } } // Port Generation if (r.Next(0, 100) > 100 - portChance && !hasPort) { if (system.MoonCount > 0) { for (int i = 0; i < system.MoonCount; i++) { } int cr = r.Next(0, system.MoonCount + 1); // Finds moon to turn into port. int currentMoon = 0; // Used to get the moon foreach (Planet m in system.GetMoons()) { if (currentMoon == cr) { Planet moonToPort = m; moonToPort.ParentAreaID = system.Id; system.RemoveMoon(m); rm.DeRegisterObject(m); Port por = new Port(idManager.PopFreeID(), moonToPort, system.AreaName, ShipStatManager.StatShipList.ToList <ShipStats>(), ls); // Converts a moon into a port. system.AddPort(por); rm.RegisterObject(por); hasPort = true; break; } currentMoon++; } } } return(system); }
public static PSystemBody GenerateSystemBody(PSystem system, PSystemBody parent, string templateName, string name, Orbit orbit) { // Look up the template body PSystemBody template = Utility.FindBody (system.rootBody, templateName); // Create a new celestial body as a clone of this template PSystemBody clone = system.AddBody (parent); clone.name = name; // Set up the celestial body of the clone (back up the orbit driver) Utility.CopyObjectFields<CelestialBody> (template.celestialBody, clone.celestialBody); clone.celestialBody.bodyName = name; clone.celestialBody.orbitingBodies = null; clone.celestialBody.orbitDriver = clone.orbitDriver; clone.flightGlobalsIndex = 100 + template.flightGlobalsIndex; // Setup the orbit driver clone.orbitRenderer.orbitColor = template.orbitRenderer.orbitColor; clone.orbitDriver.orbit = orbit; clone.orbitDriver.celestialBody = clone.celestialBody; clone.orbitDriver.updateMode = OrbitDriver.UpdateMode.UPDATE; // Setup the deactivator object GameObject deactivator = new GameObject ("Deactivator"); deactivator.SetActive (false); UnityEngine.Object.DontDestroyOnLoad (deactivator); // Clone the template's PQS clone.pqsVersion = UnityEngine.Object.Instantiate (template.pqsVersion) as PQS; clone.pqsVersion.transform.parent = deactivator.transform; clone.pqsVersion.name = name; // Clone the scaled space clone.scaledVersion = UnityEngine.Object.Instantiate (template.scaledVersion) as GameObject; clone.scaledVersion.transform.parent = deactivator.transform; clone.scaledVersion.name = name; return clone; }
public static PSystemBody GeneratePlanet(PSystem system, string templateName, string name, Orbit orbit) { return GenerateSystemBody (system, system.rootBody, templateName, name, orbit); }
public static PSystemBody GeneratePlanet(PSystem system, string templateName, string name, Orbit orbit) { return(GenerateSystemBody(system, system.rootBody, templateName, name, orbit)); }
// Awake() is the first function called in the lifecycle of a Unity3D MonoBehaviour. In the case of KSP, // it happens to be called right before the game's PSystem is instantiated from PSystemManager.Instance.systemPrefab public void Awake() { // Abort, if KSP isn't compatible if (!CompatibilityChecker.IsCompatible()) { string supported = CompatibilityChecker.version_major + "." + CompatibilityChecker.version_minor + "." + CompatibilityChecker.Revision; string current = Versioning.version_major + "." + Versioning.version_minor + "." + Versioning.Revision; Debug.LogWarning("[Kopernicus] Detected incompatible install.\nCurrent version of KSP: " + current + ".\nSupported version of KSP: " + supported + ".\nPlease wait, until Kopernicus gets updated to match your version of KSP."); Debug.Log("[Kopernicus] Aborting..."); // Abort Destroy(this); return; } // We're ALIVE Logger.Default.SetAsActive(); Logger.Default.Log("Injector.Awake(): Begin"); // Yo garbage collector - we have work to do man DontDestroyOnLoad(this); // If the planetary manager does not work, well, error out if (PSystemManager.Instance == null) { // Log the error Logger.Default.Log("Injector.Awake(): If PSystemManager.Instance is null, there is nothing to do"); return; } // Backup the old prefab StockSystemPrefab = PSystemManager.Instance.systemPrefab; // Get the current time DateTime start = DateTime.Now; // Get the configNode ConfigNode kopernicus = GameDatabase.Instance.GetConfigs(rootNodeName)[0].config; // THIS IS WHERE THE MAGIC HAPPENS - OVERWRITE THE SYSTEM PREFAB SO KSP ACCEPTS OUR CUSTOM SOLAR SYSTEM AS IF IT WERE FROM SQUAD PSystemManager.Instance.systemPrefab = Parser.CreateObjectFromConfigNode<Loader>(kopernicus).systemPrefab; // SEARCH FOR THE ARCHIVES CONTROLLER PREFAB AND OVERWRITE IT WITH THE CUSTOM SYSTEM RDArchivesController archivesController = AssetBase.RnDTechTree.GetRDScreenPrefab ().GetComponentsInChildren<RDArchivesController> (true).First (); archivesController.systemPrefab = PSystemManager.Instance.systemPrefab; // Clear space center instance so it will accept nouveau Kerbin SpaceCenter.Instance = null; // Add a handler so that we can do post spawn fixups. PSystemManager.Instance.OnPSystemReady.Add(PostSpawnFixups); // Done executing the awake function TimeSpan duration = (DateTime.Now - start); Logger.Default.Log("Injector.Awake(): Completed in: " + duration.TotalMilliseconds + " ms"); Logger.Default.Flush (); }
/// <summary> /// Instantiates and registers all objects associated with a PSystem (planets, players, ships, etc) /// </summary> public static async Task <PSystem> DeserializePSystemAsync(PSystemModel system, RedisServer redisServer, LocatorService ls, IGalaxyRegistrationManager rm, IDatabaseManager dbm) { PSystem retSys = new PSystem(system, ls); List <IShip> deserializedShips = new List <IShip>(); List <IStructure> loadedStructures = new List <IStructure>(); List <Player> loadedPlayers = new List <Player>(); //For now we just run the whole lambda synchronously in its own thread. Marking it async makes this method return complete before the task is complete, need to investigate... await Task.Factory.StartNew(() => { HashSet <int> colonyIDsToLoad = new HashSet <int>(); HashSet <int> shipIDsToLoad = new HashSet <int>(); HashSet <int> areaIDsToLoad = new HashSet <int>(); List <int> structureIDsToLoad = new List <int>(); HashSet <int> layoutIDsToLoad = new HashSet <int>(); foreach (int id in system.ShipIDs) { if (shipIDsToLoad.Contains(id)) { throw new CorruptStateException("Multiple areas contain the same shipID."); } shipIDsToLoad.Add(id); } foreach (var id in retSys.MoonIDs) { areaIDsToLoad.Add(id); } foreach (var id in retSys.PlanetIDs) { areaIDsToLoad.Add(id); } foreach (var id in retSys.PortIDs) { areaIDsToLoad.Add(id); } IEnumerable <AreaModel> loadedAreaModels = dbm.GetAreasAsync(areaIDsToLoad).Result; foreach (var am in loadedAreaModels) { switch (am.AreaType) { case AreaTypes.Planet: layoutIDsToLoad.Add(((PlanetModel)am).LayoutId); break; } } IEnumerable <PlanetLayout> loadedLayouts = dbm.GetLayoutsAsync(layoutIDsToLoad).Result.Select(s => (PlanetLayout)s); Dictionary <int, PlanetLayout> layouts = new Dictionary <int, PlanetLayout>(); foreach (var l in loadedLayouts) { layouts.Add(l.Id, l); } var loadedAreas = new List <IArea>(); // Instantiate all areas foreach (AreaModel am in loadedAreaModels) { IArea loadedArea = null; structureIDsToLoad.AddRange(am.StructureIDs); // Planets if (am.AreaType == AreaTypes.Planet) { loadedArea = new Planet((PlanetModel)am, layouts[((PlanetModel)am).LayoutId], ls); var p = loadedArea as Planet; //rm.RegisterObject(p); if (p.ColonyID != null) { colonyIDsToLoad.Add((int)p.ColonyID); } } // Ports else if (am.AreaType == AreaTypes.Port) { loadedArea = new Port((PortModel)am, ls); } else { throw new Exception("Error: Loaded area not handled in DeserializePSystem()"); } foreach (var id in am.ShipIDs) { if (shipIDsToLoad.Contains(id)) { throw new CorruptStateException("Multiple areas contain the same shipID."); } shipIDsToLoad.Add(id); } loadedAreas.Add(loadedArea); rm.RegisterObject(loadedArea); } // Colonies IEnumerable <AreaModel> LoadedColonies = dbm.GetAreasAsync(colonyIDsToLoad).Result; List <Colony> deserializedColonies = new List <Colony>(); foreach (AreaModel am in LoadedColonies) { if (am.AreaType == AreaTypes.Colony) { Colony c = new Colony((ColonyModel)am, ls); c.DisableUpdates = true; rm.RegisterObject(c); deserializedColonies.Add(c); } else { throw new Exception("AreaID query resulted in an AreaModel which was not a ColonyModel in DeserializePSystem()"); } foreach (var id in am.ShipIDs) { if (shipIDsToLoad.Contains(id)) { throw new CorruptStateException("Multiple areas contain the same shipID."); } shipIDsToLoad.Add(id); } } // Structures loadedStructures.AddRange(LoadStructures(retSys, dbm, rm, ls.PlayerLocator).Result); foreach (IArea loadedArea in loadedAreas) { if (loadedArea is IHasStructures) { loadedStructures.AddRange(LoadStructures((IHasStructures)loadedArea, dbm, rm, ls.PlayerLocator).Result); } } // Ships IEnumerable <ShipModel> loadedShipModels = dbm.GetShipsAsync(shipIDsToLoad).Result; HashSet <int> playerIDsToLoad = new HashSet <int>(); foreach (var s in loadedShipModels) { var loadedShip = DeserializeShip(s, ls, rm); deserializedShips.Add(loadedShip); if (loadedShip.PlayerID != null) { playerIDsToLoad.Add((int)s.PlayerID); } } // Players IEnumerable <PlayerModel> loadedPlayerModels = dbm.GetPlayersAsync(playerIDsToLoad).Result; HashSet <int> accountIDsToLoad = new HashSet <int>(); foreach (var p in loadedPlayerModels) { if (p.PlayerType == PlayerTypes.Human) { HumanPlayer hp = new HumanPlayer(p, ls); rm.RegisterObject(hp); loadedPlayers.Add(hp); } else { NPCPlayer np = new NPCPlayer(p, ls); np.MessageService = new RedisOutgoingMessageService(redisServer, np); rm.RegisterObject(np); loadedPlayers.Add(np); } if (p.AccountID != null) { accountIDsToLoad.Add((int)p.AccountID); } } //Accounts IEnumerable <AccountModel> loadedAccounts = dbm.GetAccountsAsync(accountIDsToLoad).Result; foreach (var a in loadedAccounts) { rm.RegisterObject(new Account(a)); } foreach (var c in deserializedColonies) { c.DisableUpdates = false; } } ); rm.RegisterObject(retSys); foreach (Player p in loadedPlayers) { if (p.PlayerType == PlayerTypes.NPC) { p.GetArea().MovePlayerHere(p, false); } } foreach (var s in deserializedShips) { IArea a = s.GetArea(); if (a == null)//Corrupt state, the ship's CurrentAreaId doesn't match the list is for an area which hasn't been loaded yet. Abort the ship read. { //I'm not sure that there's a way to gracefully handle this without a major rewrite and a bunch of overhead, so it'll be an exception for now. throw new CorruptStateException("Ship's CurrentAreaId does not match the area from which it was loaded. Expect exceptions."); } else { a.AddShip(s, true); } } return(retSys); }