Skip to content

Commit

Permalink
Merge pull request #1308 from CitiesSkylinesMods/1307-place-intersect…
Browse files Browse the repository at this point in the history
…ion-restore-bugfix

Place Intersection improvements, bugfixing
  • Loading branch information
krzychu124 authored Jan 25, 2022
2 parents 3e9ba88 + 00f06f5 commit 0f286f2
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 38 deletions.
27 changes: 16 additions & 11 deletions TLM/TLM/Patch/_BuildingDecoration/LoadPathsPatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ namespace TrafficManager.Patches._BuildingDecoration {
using TrafficManager.Util;
using System;
using System.Reflection.Emit;
using JetBrains.Annotations;

//public static void LoadPaths(BuildingInfo info, ushort buildingID, ref Building data, float elevation)
[HarmonyPatch(typeof(BuildingDecoration), nameof(BuildingDecoration.LoadPaths))]
[UsedImplicitly]
public class LoadPathsPatch {
///<summary>Called after intersection is built</summary>
///<summary>Called after intersection is built</summary>
internal static void AfterIntersectionBuilt(BuildingInfo info) {
if (!Shortcuts.InSimulationThread())
return; // only rendering
Expand All @@ -18,21 +20,24 @@ internal static void AfterIntersectionBuilt(BuildingInfo info) {
}

// code from: https://github.com/Strdate/SmartIntersections/blob/master/SmartIntersections/Patch/LoadPathsPatch.cs
[UsedImplicitly]
public static IEnumerable<CodeInstruction> Transpiler(ILGenerator il, IEnumerable<CodeInstruction> instructions) {
var fTempNodeBuffer = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempNodeBuffer))
?? throw new Exception("cound not find NetManager.m_tempNodeBuffer");
var mClear = AccessTools.DeclaredMethod(fTempNodeBuffer.FieldType, nameof(FastList<ushort>.Clear))
?? throw new Exception("cound not find m_tempNodeBuffer.Clear");
var fTempSegmentBuffer = AccessTools.DeclaredField(typeof(NetManager), nameof(NetManager.m_tempSegmentBuffer))
?? throw new Exception("Could not find NetManager.m_tempSegmentBuffer");
var mSize = AccessTools.DeclaredField(fTempSegmentBuffer.FieldType, nameof(FastList<ushort>.m_size))
?? throw new Exception("Could not find m_tempSegmentBuffer.m_size");
var mAfterIntersectionBuilt = AccessTools.DeclaredMethod(
typeof(LoadPathsPatch), nameof(AfterIntersectionBuilt))
?? throw new Exception("cound not find AfterIntersectionBuilt()");
?? throw new Exception("Could not find AfterIntersectionBuilt()");

List<CodeInstruction> codes = TranspilerUtil.ToCodeList(instructions);
bool comp(int i) =>
codes[i].opcode == OpCodes.Ldfld && codes[i].operand == fTempNodeBuffer &&
codes[i + 1].opcode == OpCodes.Callvirt && codes[i + 1].operand == mClear;
int index = TranspilerUtil.SearchGeneric(codes, comp, index: 0, counter: 2);
index -= 1; // index to insert instructions.

bool predicate(int i) =>
codes[i].opcode == OpCodes.Blt &&
codes[i - 1].opcode == OpCodes.Ldfld && codes[i - 1].operand == mSize &&
codes[i - 2].opcode == OpCodes.Ldfld && codes[i - 2].operand == fTempSegmentBuffer;
int index = TranspilerUtil.SearchGeneric(codes, predicate, index: 0, counter: 1);
index += 1; // index to insert instructions. (end of the loop)

var newInstructions = new[] {
new CodeInstruction(OpCodes.Ldarg_0), // load argument info
Expand Down
46 changes: 19 additions & 27 deletions TLM/TLM/Util/PlaceIntersectionUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ namespace TrafficManager.Util {
using System.Collections.Generic;
using System.Linq;
using CSUtil.Commons;
using Manager.Impl;
using TrafficManager.State.Asset;
using TrafficManager.Util;
using TrafficManager.Lifecycle;
using TrafficManager.Util.Extensions;

public static class PlaceIntersectionUtil {
///<summary>maps old netowkr ids to new network ids</summary>
/// <param name="oldSegments">source segment id array created by on asset serialization</param>
/// <param name="newSegmentIds">segment list provided by LoadPaths.</param>
public static void MapSegments(
/// <param name="map">segment map to fill in with pairs (old;new)</param>
private static void FillSegmentsMap(
SegmentNetworkIDs[] oldSegments,
ushort[] newSegmentIds,
Dictionary<InstanceID, InstanceID> map) {
Expand All @@ -34,8 +37,9 @@ public static void MapSegments(
/// </summary>
/// <param name="newSegmentIds">segment list provided by LoadPaths.</param>
public static void ApplyTrafficRules(BuildingInfo intersectionInfo, ushort[] newSegmentIds) {
/*************************
* Prepration: */
/****************/
/* Preparation: */
/****************/

Log._Debug($"PlaceIntersectionUtil.ApplyTrafficRules({intersectionInfo?.ToString() ?? "null"})");

Expand Down Expand Up @@ -64,34 +68,22 @@ public static void ApplyTrafficRules(BuildingInfo intersectionInfo, ushort[] new
var pathNetworkIDs = assetData.PathNetworkIDs;
if (pathNetworkIDs == null) return;

/*************************
* Apply traffic rules: */
/***********************/
/* Create segment map: */
/***********************/
Shortcuts.AssertNotNull(newSegmentIds, "newSegmentIds");
FillSegmentsMap(oldSegments: pathNetworkIDs, newSegmentIds: newSegmentIds, map: map);

MapSegments(oldSegments: pathNetworkIDs, newSegmentIds: newSegmentIds, map: map);
// Note to previous solution:
// Node/segment calculation shouldn't be performed at this state!
// Forcing it here may trigger another 'fake' LoadPaths call breaking other mods attached to that method!

foreach (var item in map)
CalculateNetwork(item.Value);

assetData.Record.Transfer(map);
/*****************************************/
/* Queue traffic rules transfer process: */
/*****************************************/
UtilityManager.Instance.QueueTransferRecordable(assetData.Record, map);

OnPlaceIntersection?.Invoke(intersectionInfo, map);
}

/// <summary>
/// early calculate networks so that we are able to set traffic rules without delay.
/// </summary>
public static void CalculateNetwork(InstanceID instanceId) {
switch (instanceId.Type) {
case InstanceType.NetNode:
ushort nodeId = instanceId.NetNode;
nodeId.ToNode().CalculateNode(nodeId);
break;
case InstanceType.NetSegment:
ushort segmentId = instanceId.NetSegment;
segmentId.ToSegment().CalculateSegment(segmentId);
break;
}
}

}
}

0 comments on commit 0f286f2

Please sign in to comment.