Skip to content

Junction restrictions hook #1579

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d6699b2
Hook API definition
Elesbaan70 May 5, 2022
918ea2d
Fill in missing pieces
Elesbaan70 May 6, 2022
7eaf0e4
No FlagsChanged event until all the redundant mess has been eliminated
Elesbaan70 May 26, 2022
23a1294
Merge branch 'master' into junction-restrictions-hook
Elesbaan70 May 26, 2022
5461b9d
rename "invalid" restrictions to "orphaned"
Elesbaan70 May 27, 2022
1f91a91
Rename antipatterned SegmentEndId class
Elesbaan70 May 27, 2022
5fad9ae
SegmentEndId
Elesbaan70 May 27, 2022
47fd73d
Implement to-be-deprecated APIs privately, eliminate TernaryBool
Elesbaan70 May 27, 2022
438bab0
Remove a lot of redundant code
Elesbaan70 May 27, 2022
a9cfa05
FlagsAttribute missing from JunctionRestrictionFlags
Elesbaan70 May 27, 2022
3c139af
Lazy update of default values
Elesbaan70 May 27, 2022
fca9d25
Cache configurable calculations
Elesbaan70 May 28, 2022
a230ca7
Updates to IJunctionRestrictionsManager
Elesbaan70 May 28, 2022
ed2dd2a
Clean up all the redudant setters
Elesbaan70 May 28, 2022
ef6aa5b
separate and condense deprecated methods
Elesbaan70 May 28, 2022
b00d0e7
clean up some notifications
Elesbaan70 May 28, 2022
2fac55b
Make as many deprecated methods as possible public/obsolete, to help …
Elesbaan70 May 28, 2022
46eb439
several things broken
Elesbaan70 May 28, 2022
211182b
IJunctionRestrictionsHook implementation
Elesbaan70 May 28, 2022
f0a6ba1
If I don't rename this, every future developer will curse me
Elesbaan70 May 29, 2022
4280116
A couple of nasty bugs
Elesbaan70 May 29, 2022
5570ad4
Merge branch 'master' in to junction-restrictions-hook
Elesbaan70 Jun 15, 2022
636d1e2
Reconcile dulicate enum
Elesbaan70 Jun 18, 2022
485305a
Merge branch 'CitiesSkylinesMods:master' into junction-restrictions-hook
Elesbaan70 Jun 18, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions TLM/TLM/Manager/Impl/JunctionRestrictionsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ namespace TrafficManager.Manager.Impl {
using TrafficManager.Util;
using TrafficManager.Util.Extensions;
using TrafficManager.Lifecycle;
using TrafficManager.API.Traffic.Enums;

public class JunctionRestrictionsManager
: AbstractGeometryObservingManager,
Expand All @@ -38,6 +39,8 @@ private JunctionRestrictionsManager() {
invalidSegmentRestrictions = new SegmentJunctionRestrictions[NetManager.MAX_SEGMENT_COUNT];
}

public event Action<IJunctionRestrictionsManager.FlagsChangedEventArgs> FlagsChanged;

private void AddInvalidSegmentJunctionRestrictions(ushort segmentId,
bool startNode,
ref JunctionRestrictions restrictions) {
Expand Down Expand Up @@ -1318,15 +1321,6 @@ public bool LoadData(List<Configuration.SegmentNodeConf> data) {
return ret;
}

private enum JunctionRestrictionFlags {
AllowUTurn = 1 << 0,
AllowNearTurnOnRed = 1 << 1,
AllowFarTurnOnRed = 1 << 2,
AllowForwardLaneChange = 1 << 3,
AllowEnterWhenBlocked = 1 << 4,
AllowPedestrianCrossing = 1 << 5,
}

private struct SegmentJunctionRestrictions {
public JunctionRestrictions startNodeRestrictions;
public JunctionRestrictions endNodeRestrictions;
Expand Down
59 changes: 59 additions & 0 deletions TLM/TMPE.API/Hook/IJunctionRestrictionsHook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TrafficManager.API.Traffic.Enums;

namespace TrafficManager.API.Hook {
public interface IJunctionRestrictionsHook {

/// <summary>
/// An event that allows a handler to modify the results of a <c>GetDefault<i>TrafficRule</i></c> method.
/// </summary>
event Action<FlagsHookArgs> GetDefaults;

/// <summary>
/// An event that allows a handler to modify the results of an <c>Is<i>TrafficRule</i>Configurable</c> method.
/// </summary>
event Action<FlagsHookArgs> GetConfigurable;

/// <summary>
/// Invalidates the specified flags so that they will be recalculated.
/// Recalculation is not guaranteed to happen immediately, but is guaranteed to happen
/// before their next use.
/// </summary>
/// <param name="flags"></param>
public void InvalidateFlags(JunctionRestrictionFlags flags);

public class FlagsHookArgs {

/// <summary>
/// Identifies the segment for which flag data is being returned.
/// </summary>
public ushort SegmentId { get; private set; }

/// <summary>
/// Identifies the node on the segment for which flag data is being returned.
/// </summary>
public bool StartNode { get; private set; }

/// <summary>
/// Identifies which flags are being returned. Unnecessary computation may be avoided
/// by examining this mask to see which flags are being requested.
/// </summary>
public JunctionRestrictionFlags Mask { get; private set; }

/// <summary>
/// The flag return values. Changes to this property alter the outcome of the underlying operation.
/// </summary>
public JunctionRestrictionFlags Result { get; set; }

internal FlagsHookArgs(ushort segmentId, bool startNode, JunctionRestrictionFlags mask, JunctionRestrictionFlags result) {
SegmentId = segmentId;
StartNode = startNode;
Mask = mask;
Result = result;
}
}
}
}
14 changes: 14 additions & 0 deletions TLM/TMPE.API/Manager/IJunctionRestrictionsManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
namespace TrafficManager.API.Manager {
using CSUtil.Commons;
using System;
using TrafficManager.API.Traffic.Enums;

public interface IJunctionRestrictionsManager {
#region Is<Traffic Rule>Configurable
Expand Down Expand Up @@ -574,5 +576,17 @@ bool GetDefaultPedestrianCrossingAllowed(ushort segmentId,
/// Updates the default values for all junction restrictions and segments.
/// </summary>
void UpdateAllDefaults();

event Action<FlagsChangedEventArgs> FlagsChanged;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's incomplete. It's an event that will be invoked when junction restrictions flags change on a segment end, but FlagsChangedEventArgs is missing some properties right now.

Great example of this being a work in progress. I've just created the draft pull request so there's visibility on what I'm doing. 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To further elaborate, it's intended to be a clear and supported way for mods like AN to know when junction restrictions change. That way you don't have to detect changes based on assumptions about the implementation. Instead, you have a direct promise that this will always work.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mods like AN to know when junction restrictions change.

isn't that what notifier does?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mods like AN to know when junction restrictions change.

isn't that what notifier does?

Yes, but INotifier is limited in the amount of specific information it can share about the change. By adding specific events at the manager level, you can provide more useful information. And if implemented correctly, when no one is using them all they cost is a check for null.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notifier does tell which manager caused the update. and it has space for manager specific even args. although the event args is just an object and do not have hard-coded type safety.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

although the event args is just an object and do not have hard-coded type safety.

And that's the key difference. Manager-owned events put less responsibility on the consumer. Fewer opportunities for error.


public class FlagsChangedEventArgs {

public JunctionRestrictionFlags Flags { get; private set; }

public FlagsChangedEventArgs(JunctionRestrictionFlags flags) {
Flags = flags;
}
}

}
}
2 changes: 2 additions & 0 deletions TLM/TMPE.API/TMPE.API.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Harmony.cs" />
<Compile Include="Hook\IJunctionRestrictionsHook.cs" />
<Compile Include="Implementations.cs" />
<Compile Include="Geometry\SegmentEndReplacement.cs" />
<Compile Include="Manager\IAdvancedParkingManager.cs" />
Expand Down Expand Up @@ -144,6 +145,7 @@
<Compile Include="Traffic\Enums\ExtVehicleType.cs" />
<Compile Include="Traffic\Enums\FlowWaitCalcMode.cs" />
<Compile Include="Traffic\Enums\GeometryCalculationMode.cs" />
<Compile Include="Traffic\Enums\JunctionRestrictionFlags.cs" />
<Compile Include="Traffic\Enums\LocaleKeyAttribute.cs" />
<Compile Include="Traffic\Enums\LaneArrows.cs" />
<Compile Include="Traffic\Enums\LaneEndTransitionGroup.cs" />
Expand Down
10 changes: 10 additions & 0 deletions TLM/TMPE.API/Traffic/Enums/JunctionRestrictionFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace TrafficManager.API.Traffic.Enums {
public enum JunctionRestrictionFlags {
AllowUTurn = 1 << 0,
AllowNearTurnOnRed = 1 << 1,
AllowFarTurnOnRed = 1 << 2,
AllowForwardLaneChange = 1 << 3,
AllowEnterWhenBlocked = 1 << 4,
AllowPedestrianCrossing = 1 << 5,
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to control TrafficLights too. not sure if it would fit here. segmnetId would be irrelevant.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this could be a rule override hook?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this could be a rule override hook?

I anticipate that in general, hooks would correspond to managers. There might be exceptions, but since that's the existing organization of the API, it's the pattern that makes sense.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am patching Traffic lights too. and could be causing problems because my patch will break if we overload those methods. I can easily fix my patch but I don't know about NCR.

Traffic light manager does not seem to manage default value for traffic lights though. so that is a difference. I am only patching if traffic lights are configurable.

}