Skip to content

Commit

Permalink
Refactor how locomotive spawners work
Browse files Browse the repository at this point in the history
The new documentation explains it better than I could here.
  • Loading branch information
Insprill committed Jul 10, 2023
1 parent 6948c2d commit b6b122e
Show file tree
Hide file tree
Showing 18 changed files with 311 additions and 102 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ trim_trailing_whitespace = false

[*.json]
indent_size = 2

[*.csproj]
ij_xml_space_inside_empty_tag = true
1 change: 1 addition & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Runtime:

Map Creation Package:
- Added the ability to set the default state of switches.
- Refactored how locomotive spawners work. Refer to documentation for more information.
- Fixed validation failing without a directional light (no longer required).
- Fixed stations not initializing properly if their last warehouse machine was removed.

Expand Down
68 changes: 34 additions & 34 deletions Mapify/Mapify.csproj
Original file line number Diff line number Diff line change
@@ -1,57 +1,57 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../UserProperties.props" Condition="Exists('../UserProperties.props')"/>
<Import Project="../UserProperties.props" Condition="Exists('../UserProperties.props')" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>7.3</LangVersion>
<RootNamespace>Mapify</RootNamespace>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../MapifyEditor/MapifyEditor.csproj"/>
<ProjectReference Include="../MapifyEditor/MapifyEditor.csproj" />
</ItemGroup>

<ItemGroup>
<!-- Derail Valley -->
<Reference Include="Assembly-CSharp"/>
<Reference Include="CommandTerminal"/>
<Reference Include="DV.Common"/>
<Reference Include="DV.Interaction"/>
<Reference Include="DV.Inventory"/>
<Reference Include="DV.Localization"/>
<Reference Include="DV.PointSet"/>
<Reference Include="DV.TerrainSystem"/>
<Reference Include="DV.TerrainTools"/>
<Reference Include="DV.ThingTypes"/>
<Reference Include="DV.UI"/>
<Reference Include="DV.UIFramework"/>
<Reference Include="DV.UserManagement"/>
<Reference Include="DV.Utils"/>
<Reference Include="DV.WeatherSystem"/>
<Reference Include="Assembly-CSharp" />
<Reference Include="CommandTerminal" />
<Reference Include="DV.Common" />
<Reference Include="DV.Interaction" />
<Reference Include="DV.Inventory" />
<Reference Include="DV.Localization" />
<Reference Include="DV.PointSet" />
<Reference Include="DV.TerrainSystem" />
<Reference Include="DV.TerrainTools" />
<Reference Include="DV.ThingTypes" />
<Reference Include="DV.UI" />
<Reference Include="DV.UIFramework" />
<Reference Include="DV.UserManagement" />
<Reference Include="DV.Utils" />
<Reference Include="DV.WeatherSystem" />
<!-- Third-party -->
<Reference Include="AwesomeTechnologies.VegetationStudioPro.Runtime"/>
<Reference Include="BezierCurves"/>
<Reference Include="I2.Localization"/>
<Reference Include="net.smkd.vector3d"/>
<Reference Include="Newtonsoft.Json"/>
<Reference Include="sc.posteffects.runtime"/>
<Reference Include="AwesomeTechnologies.VegetationStudioPro.Runtime" />
<Reference Include="BezierCurves" />
<Reference Include="I2.Localization" />
<Reference Include="net.smkd.vector3d" />
<Reference Include="Newtonsoft.Json" />
<Reference Include="sc.posteffects.runtime" />
<!-- Mod Loader -->
<PackageReference Include="BepInEx.Analyzers" Version="1.*" PrivateAssets="all"/>
<PackageReference Include="BepInEx.Core" Version="5.*"/>
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*"/>
<PackageReference Include="BepInEx.Analyzers" Version="1.*" PrivateAssets="all" />
<PackageReference Include="BepInEx.Core" Version="5.*" />
<PackageReference Include="BepInEx.PluginInfoProps" Version="1.*" />
<!-- Unity -->
<Reference Include="Unity.Collections"/>
<Reference Include="Unity.Postprocessing.Runtime"/>
<Reference Include="Unity.TextMeshPro"/>
<Reference Include="UnityEngine.UI"/>
<PackageReference Include="UnityEngine.Modules" Version="2019.4.40" IncludeAssets="compile"/>
<Reference Include="Unity.Collections" />
<Reference Include="Unity.Postprocessing.Runtime" />
<Reference Include="Unity.TextMeshPro" />
<Reference Include="UnityEngine.UI" />
<PackageReference Include="UnityEngine.Modules" Version="2019.4.40" IncludeAssets="compile" />
</ItemGroup>

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<!-- Copy to build folder -->
<Copy SourceFiles="$(TargetPath)" DestinationFolder="../build/runtime"/>
<Copy SourceFiles="$(TargetPath)" DestinationFolder="../build/runtime" />

<!-- Copy to game install folder -->
<Exec Condition="Exists('$(DvInstallDir)') And '$(OS)' == 'Windows_NT'" Command="powershell -executionpolicy bypass -Command &quot;(../package.ps1 -NoArchive -OutputDirectory '$(DvInstallDir)')&quot;"/>
<Exec Condition="Exists('$(DvInstallDir)') And '$(OS)' != 'Windows_NT'" Command="pwsh -Command &quot;(../package.ps1 -NoArchive -OutputDirectory '$(DvInstallDir)')&quot;"/>
<Exec Condition="Exists('$(DvInstallDir)') And '$(OS)' == 'Windows_NT'" Command="powershell -executionpolicy bypass -Command &quot;(../package.ps1 -NoArchive -OutputDirectory '$(DvInstallDir)')&quot;" />
<Exec Condition="Exists('$(DvInstallDir)') And '$(OS)' != 'Windows_NT'" Command="pwsh -Command &quot;(../package.ps1 -NoArchive -OutputDirectory '$(DvInstallDir)')&quot;" />
</Target>
</Project>
31 changes: 6 additions & 25 deletions Mapify/SceneInitializers/GameContent/StationSetup.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq;
using System.Reflection;
using DV.Teleporters;
using DV.ThingTypes;
using DV.ThingTypes.TransitionHelpers;
using DV.Utils;
using HarmonyLib;
using Mapify.Editor;
using Mapify.Editor.Utils;
using Mapify.SceneInitializers.Railway;
using Mapify.Utils;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Mapify.SceneInitializers.GameContent
{
Expand All @@ -22,7 +18,6 @@ public class StationSetup : SceneSetup
public override void Run()
{
Station[] stations = Object.FindObjectsOfType<Station>();
Dictionary<Station, List<LocomotiveSpawner>> locomotiveSpawners = Object.FindObjectsOfType<LocomotiveSpawner>().MapToClosestStation();

stations.SetActive(false);

Expand All @@ -47,7 +42,7 @@ public override void Run()
SetupJobRules(station, stationController);
SetupWarehouseMachines(station, stationController);
SetupTeleportAnchor(station);
SetupLocomotiveSpawners(station, locomotiveSpawners);
SetupLocomotiveSpawners(station);
}

stations.SetActive(true);
Expand Down Expand Up @@ -114,24 +109,10 @@ private static void SetupTeleportAnchor(Station station)
teleporter.playerTeleportMapMarkerAnchor = teleportAnchor;
}

private static void SetupLocomotiveSpawners(Station station, Dictionary<Station, List<LocomotiveSpawner>> locomotiveSpawners)
private static void SetupLocomotiveSpawners(Station station)
{
if (!locomotiveSpawners.TryGetValue(station, out List<LocomotiveSpawner> spawners))
return;
foreach (LocomotiveSpawner locomotiveSpawner in spawners)
{
GameObject gameObject = station.gameObject.NewChild("LocomotiveSpawner");
StationLocoSpawner locoSpawner = gameObject.AddComponent<StationLocoSpawner>();
locoSpawner.spawnRotationFlipped = locomotiveSpawner.flipOrientation;
locoSpawner.locoSpawnTrackName = locomotiveSpawner.Track.name;
locoSpawner.locoTypeGroupsToSpawn = locomotiveSpawner.condensedLocomotiveTypes
.Select(rollingStockTypes =>
new ListTrainCarTypeWrapper(rollingStockTypes.Split(',').Select(rollingStockType =>
((TrainCarType)Enum.Parse(typeof(TrainCarType), rollingStockType)).ToV2()
).ToList()
)
).ToList();
}
foreach (LocomotiveSpawner spawner in station.GetComponentsInChildren<LocomotiveSpawner>())
LocomotiveSpawnerSetup.SetupLocomotiveSpawner(spawner);
}
}
}
32 changes: 32 additions & 0 deletions Mapify/SceneInitializers/Railway/LocomotiveSpawnerSetup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Linq;
using DV;
using Mapify.Editor;
using UnityEngine;

namespace Mapify.SceneInitializers.Railway
{
public class LocomotiveSpawnerSetup : SceneSetup
{
public override void Run()
{
foreach (LocomotiveSpawner spawner in Object.FindObjectsOfType<LocomotiveSpawner>()) SetupLocomotiveSpawner(spawner);
}

public static void SetupLocomotiveSpawner(LocomotiveSpawner spawner)
{
bool wasActive = spawner.gameObject.activeSelf;
spawner.gameObject.SetActive(false);
StationLocoSpawner locoSpawner = spawner.gameObject.AddComponent<StationLocoSpawner>();
locoSpawner.spawnRotationFlipped = spawner.flipOrientation;
locoSpawner.locoSpawnTrackName = spawner.Track.name;
locoSpawner.locoTypeGroupsToSpawn = spawner.condensedLocomotiveTypes
.Select(rollingStockTypes =>
new ListTrainCarTypeWrapper(rollingStockTypes.Split(',').Select(rollingStockType =>
Globals.G.Types.Liveries.Find(l => l.id == rollingStockType)
).ToList()
)
).ToList();
spawner.gameObject.SetActive(wasActive);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using System.Linq;
using Mapify.Editor.Utils;

Expand All @@ -8,8 +9,13 @@ public class LocomotiveSpawnerUpdater : BuildUpdater
{
protected override void Update(Scenes scenes)
{
foreach (LocomotiveSpawner spawner in scenes.railwayScene.GetAllComponents<LocomotiveSpawner>())
spawner.condensedLocomotiveTypes = spawner.locomotiveTypesToSpawn.Select(types => string.Join(",", types.rollingStockTypes.Select(type => type.ToString()))).ToList();
IEnumerable<LocomotiveSpawner> spawners = new[] {
scenes.railwayScene,
scenes.gameContentScene
}.SelectMany(s => s.GetAllComponents<LocomotiveSpawner>());

foreach (LocomotiveSpawner spawner in spawners)
spawner.condensedLocomotiveTypes = spawner.CondenseLocomotiveTypes().ToArray();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,45 @@ public class LocomotiveSpawnerValidator : Validator
{
protected override IEnumerator<Result> Validate(Scenes scenes)
{
foreach (LocomotiveSpawner spawner in scenes.railwayScene.GetAllComponents<LocomotiveSpawner>())
if (spawner.locomotiveTypesToSpawn.Count == 0)
LocomotiveSpawner[] spawners = new[] {
scenes.railwayScene,
scenes.gameContentScene
}.SelectMany(s => s.GetAllComponents<LocomotiveSpawner>()).ToArray();

// this is kinda gross

#region All Spawners

foreach (LocomotiveSpawner spawner in spawners)
{
Track selfTrack = spawner.GetComponent<Track>();
if (!selfTrack && !spawner.GetComponentInParent<Station>())
yield return Result.Error($"Locomotive Spawner's must be the child of a {nameof(Station)} or have a {nameof(Track)} assigned!", spawner);
else if (!selfTrack && spawner.Track == null)
yield return Result.Error($"Failed to find parking track with Station ID '{spawner.loadingTrackStationId}', Yard ID '{spawner.loadingTrackYardId}', Track ID '{spawner.loadingTrackId}'", spawner);
}

#endregion

#region Vanilla Spawners

foreach (VanillaLocomotiveSpawner spawner in spawners.OfType<VanillaLocomotiveSpawner>())
if (spawner.locomotiveGroups.Count == 0)
yield return Result.Error("Locomotive spawners must have at least one group to spawn!", spawner);
else if (spawner.locomotiveTypesToSpawn.Any(group => group.rollingStockTypes.Count == 0))
else if (spawner.locomotiveGroups.Exists(group => group.rollingStock.Count == 0))
yield return Result.Error("Locomotive spawner groups must have at least one type to spawn!", spawner);
else
spawner.condensedLocomotiveTypes = spawner.locomotiveTypesToSpawn.Select(types => string.Join(",", types.rollingStockTypes.Select(type => type.ToString()))).ToList();

#endregion

#region Custom Spawners

foreach (CustomLocomotiveSpawner spawner in spawners.OfType<CustomLocomotiveSpawner>())
if (spawner.locomotiveGroups.Count == 0)
yield return Result.Error("Locomotive spawners must have at least one group to spawn!", spawner);
else if (spawner.locomotiveGroups.Exists(group => group.rollingStock.Count == 0))
yield return Result.Error("Locomotive spawner groups must have at least one type to spawn!", spawner);

#endregion
}
}
}
Expand Down
30 changes: 15 additions & 15 deletions MapifyEditor/MapifyEditor.csproj
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="../UserProperties.props" Condition="Exists('../UserProperties.props')"/>
<Import Project="../UserProperties.props" Condition="Exists('../UserProperties.props')" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>7.3</LangVersion>
<LangVersion>8.0</LangVersion>
<RootNamespace>MapifyEditor</RootNamespace>
<OutDir>bin/$(Configuration)/Runtime</OutDir>
<IsEditor>true</IsEditor>
Expand All @@ -17,33 +17,33 @@
</PropertyGroup>

<ItemGroup Condition="'$(IsEditor)' == 'true'">
<Reference Include="UnityEditor"/>
<Reference Include="UnityEditor" />
</ItemGroup>

<ItemGroup>
<Reference Include="BezierCurves"/>
<Reference Include="Unity.TextMeshPro"/>
<PackageReference Include="UnityEngine.Modules" Version="2019.4.40" IncludeAssets="compile"/>
<Reference Include="BezierCurves" />
<Reference Include="Unity.TextMeshPro" />
<PackageReference Include="UnityEngine.Modules" Version="2019.4.40" IncludeAssets="compile" />
</ItemGroup>

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<!-- Build the runtime version, without any UnityEditor references. This is super sketchy, but I couldn't find a better way to do it. -->
<Exec Condition="'$(IsEditor)' == 'true'" Command="dotnet build -c $(Configuration) -p:IsEditor='false'"/>
<Exec Condition="'$(IsEditor)' == 'true'" Command="dotnet build -c $(Configuration) -p:IsEditor='false'" />

<!-- Copy to build folder -->
<Copy Condition="'$(IsEditor)' == 'true'" SourceFiles="$(TargetPath)" DestinationFolder="../build/editor"/>
<Copy Condition="'$(IsEditor)' != 'true'" SourceFiles="$(TargetPath)" DestinationFolder="../build/runtime"/>
<Copy Condition="'$(IsEditor)' == 'true'" SourceFiles="$(TargetPath)" DestinationFolder="../build/editor" />
<Copy Condition="'$(IsEditor)' != 'true'" SourceFiles="$(TargetPath)" DestinationFolder="../build/runtime" />

<!-- Copy to package build and test map -->
<Copy Condition="'$(IsEditor)' == 'true'" SourceFiles="$(TargetPath);$(OutDir)BezierCurves.dll" DestinationFolder="$(PackageBuilderDir);"/>
<Copy Condition="'$(IsEditor)' == 'true' And Exists('$(TestMapDir)')" SourceFiles="$(TargetPath)" DestinationFolder="$(TestMapDir)"/>
<Copy Condition="'$(IsEditor)' == 'true'" SourceFiles="$(TargetPath);$(OutDir)BezierCurves.dll" DestinationFolder="$(PackageBuilderDir);" />
<Copy Condition="'$(IsEditor)' == 'true' And Exists('$(TestMapDir)')" SourceFiles="$(TargetPath)" DestinationFolder="$(TestMapDir)" />

<!-- Copy to game install folder -->
<Exec Condition="Exists('$(DvInstallDir)') And '$(OS)' == 'Windows_NT' And '$(IsEditor)' != 'true'" Command="powershell -executionpolicy bypass -Command &quot;(../package.ps1 -NoArchive -OutputDirectory '$(DvInstallDir)')&quot;"/>
<Exec Condition="Exists('$(DvInstallDir)') And '$(OS)' != 'Windows_NT' And '$(IsEditor)' != 'true'" Command="pwsh -Command &quot;(../package.ps1 -NoArchive -OutputDirectory '$(DvInstallDir)')&quot;"/>
<Exec Condition="Exists('$(DvInstallDir)') And '$(OS)' == 'Windows_NT' And '$(IsEditor)' != 'true'" Command="powershell -executionpolicy bypass -Command &quot;(../package.ps1 -NoArchive -OutputDirectory '$(DvInstallDir)')&quot;" />
<Exec Condition="Exists('$(DvInstallDir)') And '$(OS)' != 'Windows_NT' And '$(IsEditor)' != 'true'" Command="pwsh -Command &quot;(../package.ps1 -NoArchive -OutputDirectory '$(DvInstallDir)')&quot;" />

<!-- Update package version number -->
<Exec Condition="'$(OS)' == 'Windows_NT' And '$(IsEditor)' == 'true'" Command="powershell $(UpdateVersionCommand)"/>
<Exec Condition="'$(OS)' != 'Windows_NT' And '$(IsEditor)' == 'true'" Command="pwsh $(UpdateVersionCommand)"/>
<Exec Condition="'$(OS)' == 'Windows_NT' And '$(IsEditor)' == 'true'" Command="powershell $(UpdateVersionCommand)" />
<Exec Condition="'$(OS)' != 'Windows_NT' And '$(IsEditor)' == 'true'" Command="pwsh $(UpdateVersionCommand)" />
</Target>
</Project>
13 changes: 13 additions & 0 deletions MapifyEditor/RollingStock/CustomRollingStockList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;

namespace Mapify.Editor
{
[Serializable]
// Unity doing Unity things and not supporting nested lists in the editor
// Unity also doing Unity things by only supporting generics in 2020.1 and up
public class CustomRollingStockList
{
public List<string> rollingStock;
}
}
12 changes: 0 additions & 12 deletions MapifyEditor/RollingStock/RollingStockType.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ namespace Mapify.Editor
{
[Serializable]
// Unity doing Unity things and not supporting nested lists in the editor
public class RollingStockTypes
public class VanillaRollingStockList
{
public List<RollingStockType> rollingStockTypes;
public List<VanillaRollingStockType> rollingStock;
}
}
Loading

0 comments on commit b6b122e

Please sign in to comment.