-
Notifications
You must be signed in to change notification settings - Fork 85
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
Cache the relationship between Lane ID (NetLane) and Lane Index (NetInfo.Lane) #1526
Cache the relationship between Lane ID (NetLane) and Lane Index (NetInfo.Lane) #1526
Conversation
Would the |
Probably outside scope of this PR, but...When a segment change is detected, could we iterate the lanes and compile:
With that lane summary stored on an Maybe have extensions like public static bool MayHaveCustomSpeedLimits(this ref NetSegment segment) =>
segment.IsValid() &&
segment.Directions != 0 && // extension that gets the compiled direction flags
segment.Matches(
laneTypes: SpeedLimitManager.LANE_TYPES,
vehicleTypes: SpeedLimitManager.VEHICLE_TYPES); The original is checking service/subservice however that can be problematic as there's often decorative networks in workshop that are using the service/subservice that TMPE is interested in so we get false positives when checking at the segment level. We could probably merge that stuff in to a dedicate 'quick check' extension something like: public static bool IsApplicable(
this ref NetSegment segment,
NetInfo.LaneType? laneTypes = null,
VehicleInfo.VehicleType? vehicleTypes = null) {
if (!segment.m_flags.CheckFlags(
required: NetSegment.Flags.Created,
forbidden: NetSegment.Flags.Collapsed | NetSegment.Flags.Deleted))
return false;
var extSeg = ...
return
extSeg.Directions != 0 &&
(laneTypes == null || (extSeg.laneTypes & laneTypes) != 0) &&
(vehicleTypes == null || (extSeg.vehicleTypes & vehicleTypes) != 0);
} Then we can quick check if a segment is relevant to a TMPE tool: if (someSegment.IsApplicable(someTool.LANE_TYPES, someTool.VEHICLE_TYPES) {
...
} If there's an interface that ensures // elswhere
if (someSegment.IsApplicableTo(SpeedLimitManager) ... |
It is possible long-term, and in my opinion that wouldn't be a bad thing. I dislike the whole paradigm of infrastructure code knowing about all of its consumers. But I created |
Can we have a single threaded benchmark? there is a benchmark project. |
// based on an ID-derived index. | ||
private static object GetLockObject(ushort segmentId) => lockObject; | ||
|
||
private bool CheckLanes(ref ExtSegment segment) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be better to call this extSegment. but this is OK too.
} | ||
|
||
private void HandleInvalidSegmentImpl(ushort segmentId) { | ||
private void ReleasingSegment(ushort segmentId, ref NetSegment segment) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe rename to OnReleasingSegment()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on the second thought this is fine too.
https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-type-members#names-of-events
CS uses the On...
convention.
Notifier uses events that begin with On
. also we have OnSegmentChange/Modified/Replacement
and several other events like this.
In other places we don't use the On...
naming convention. So its a mixed bag so far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition to the naming convention on the page you linked to, Microsoft's convention, at least as implemented in places like WinForms, is that "On..." is used on virtual methods that are called by event handlers. So basically, it's a second layer of event handling within the context of a specific class that monitors an event.
"PreReleaseSegmentImplementation", | ||
new[] { typeof(ushort), typeof(NetSegment), typeof(bool) }, | ||
new[] { ArgumentType.Normal, ArgumentType.Ref, ArgumentType.Normal } | ||
)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Note]
maybe you can create this attribute:
public class HarmonyPatch2 : HarmonyLib.HarmonyPatch {
public HarmonyPatch2(Type delcaringType, Type delegateType, bool instance = false){
info.declaringType = delcaringType;
info.methodName = delegateType.Name;
var args = delegateType.GetMethod("Invoke").GetParameters().Select(p => p.ParameterType); // or use what we have in transpiler utils.
if (instance) args = args.Skip(1); // skip arg0 because its instance method.
info.argumentTypes = args.ToArray();
}
}
And then use it like this:
private delegate void PreReleaseSegmentImplementation(ushort segment, ref NetSegment data, bool keepNodes);
[HarmonyPatch2(typeof(NetManager), typeof(PreReleaseSegmentImplementation))]
The advantage of doing it this way is that you are less likely to make mistake copy pasting the function from dnSpy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't even using dnSpy. I did this all from within Visual Studio. But I'm still enough of a novice with Harmony that I'd rather wait to do things like this until I have a better handle on the big picture of how it works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[lower priority] simple benchmark.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if benchmark is possible with Unity objects like NetInfo. So I am approving this as it is. if you managed to do any speed comparison between the current code and the previous lane util code that would be nice.
Where are we at on this? It would probably be good to get it merged soonish if it's going to be accepted, since the conflicts with #354 are starting to get messy. |
/// <summary> | ||
/// The Lane IDs as an array for fast lookup by index. | ||
/// </summary> | ||
public uint[] lanes; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this supposed to be in the API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want it to be that way, but that's how ExtSegmentManager
is written. As much as I'd like to secure my reputation as the API killer, I'd rather not change that unless forced to as I basically was in the traffic light stuff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not really an API. It's exactly the same mess as the traffic light stuff.
@krzychu124 do you have an opinion on this? The nice thing in this case is, it's a much smaller problem, and easier to define, than the traffic light stuff. If we did want to clean it up, we could make sure there's new API in place to do whatever people might have needed with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would leave it like it is. For now nothing knows about its existence and before it will go to Stable we might have few chances to throw it away from there 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good, I'm not sure yet if should go before or after #1479
Both affect lane connector so could be released to Test at the same time.
I think it might be easier to merge it after since this one does not change logic, just replaces calls.
@kianzarrin any thoughts in which order it could be easier to proceed if we want to move forward?
Core Functionality
This adds the following method to
IExtSegmentManager
:and adds a new
IExtLaneManager
with the following methods:Any existing code I could identify that did this work has been replaced with calls to the new methods. I imagine there are probably other places I didn't catch.
Added Bonus
Also, this adds a class under the
Patch
namespace,NetManagerEvents
, which patchesNetManager
to provide simple high-level event notifications that can be consumed by managers ad hoc:ExtLaneManager
uses it exclusively for monitoring network changes.ExtSegmentManager
uses it for monitoring network changes.LaneConnectionManager
has been updated to monitor theReleasingSegment
event instead of overridingHandleInvalidSegment
.The
ReleasingSegment
event will be better in many cases than usingHandleInvalidSegment
because:NetManager
operation. It's just more reliable.HandleInvalidSegment
overrides are acting on data that might not be in a valid state, which may lead to problems.NetManagerEvents.ReleasingSegment
addresses that issue.