Skip to content
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

uni-directional lane connections #1211

Merged
merged 48 commits into from
Mar 19, 2022
Merged

uni-directional lane connections #1211

merged 48 commits into from
Mar 19, 2022

Conversation

kianzarrin
Copy link
Collaborator

@kianzarrin kianzarrin commented Dec 2, 2021

fixes #784. please see issue for more details.
Edit: as a happy coincident this change also fixes the issue with lane connector tool that got confused with bidirectional lanes.

every connection made by lane connector used to be bidirectional. Now its uni-directional unless user creates connection both ways.

highlights:

  • moved connection data out of obsolete Flags class and into LaneConnectionManager class.
  • we now need to differentiate between HasConnections() and HasOutGoingConnections().
  • for the sake of backward compatibility, when I load legacy save I restore the connections both ways.
  • I did not change the Routing Manager except for renaming a variable name to be more accurate.

code design: There are 3 layers:
UI layer (Lane Connector Tool) : no modification was needed.
Middle layer (Lane Connection Manager) : performs all the validations and checks before passing calls to base layer
Base Layer (used to be Flags but now is ConnectionData): handles getting/setting lane connection data only

build: https://ci.appveyor.com/api/projects/krzychu124/tmpe/artifacts/TMPE.zip?branch=bidirectional-fix-784

the commits are a mess and I was unable to fix them. just review all the commits together.

TODO:

  • create disabled backward lane connections to speed up the search in HasConnections
  • move some stuff from ConnectionData abstraction layer to lane connection manager
  • ? use dictionary instead of array.
  • test all

@kianzarrin kianzarrin added BUG Defect detected LANE ROUTING Feature: Lane arrows / connectors labels Dec 2, 2021
@kianzarrin kianzarrin self-assigned this Dec 2, 2021
@kianzarrin
Copy link
Collaborator Author

The code is complete. this is draft just because I want to perform a few more tests.

@kianzarrin kianzarrin marked this pull request as ready for review December 2, 2021 20:32
@kianzarrin
Copy link
Collaborator Author

OK I done my tests. deleting other segments and bidirectional lanes work well.

@kianzarrin kianzarrin added this to the 11.7.0 milestone Dec 3, 2021
originalfoo added a commit that referenced this pull request Mar 12, 2022
For some reason the value of `Options.disableDespawning` was
historically inverted during de/serialization. This PR fixes that.

It's based in part on new `Version` field that Kian put in PR #1211.
Copy link
Member

@krzychu124 krzychu124 left a comment

Choose a reason for hiding this comment

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

Another round of questions :)

return (int)(LaneId * 2);
else
return (int)(LaneId * 2 + 1);
}
Copy link
Member

Choose a reason for hiding this comment

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

Here is generated version:

public override int GetHashCode() {
  unchecked {
    return ((int)LaneId * 397) ^ StartNode.GetHashCode();
  }
}

Add also equals and Comparer to speed it up even more (autogenerated):

public bool Equals(LaneEnd other) {
    return LaneId == other.LaneId && StartNode == other.StartNode;
}

public override bool Equals(object obj) {
    return obj is LaneEnd other && Equals(other);
}

public static bool operator ==(LaneEnd left, LaneEnd right) {
    return left.Equals(right);
}

public static bool operator !=(LaneEnd left, LaneEnd right) {
    return !left.Equals(right);
}

private sealed class LaneIdStartNodeEqualityComparer : IEqualityComparer<LaneEnd> {
    public bool Equals(LaneEnd x, LaneEnd y) {
        return x.LaneId == y.LaneId && x.StartNode == y.StartNode;
    }

    public int GetHashCode(LaneEnd obj) {
        unchecked {
            return ((int)obj.LaneId * 397) ^ obj.StartNode.GetHashCode();
        }
    }
}

public static IEqualityComparer<LaneEnd> LaneIdStartNodeComparer { get; } = new LaneIdStartNodeEqualityComparer();

Plus make struct : IEquatable<LaneEnd>

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

why would manually implementing them would speed up code? the auto-generated code seems fine.

using TrafficManager.Util;
using TrafficManager.Util.Extensions;

internal class ConnectionDataBase : Dictionary<LaneEnd, LaneConnectionData[]> {
Copy link
Member

Choose a reason for hiding this comment

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

Add constructor to use correct Comparer since the whole thing is a Dictionary:

public ConnectionDataBase(): base(LaneEnd.LaneIdStartNodeComparer) { }

TLM/TLM/Manager/Impl/LaneConnectionManagerData/LaneEnd.cs Outdated Show resolved Hide resolved
int nodeArrayIndex = startNode ? 0 : 1;
return Flags.laneConnections[laneId][nodeArrayIndex];
var key = new LaneEnd(laneId, startNode);
if (connectionDataBase_.TryGetValue(key, out var targets)) {
Copy link
Member

Choose a reason for hiding this comment

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

I would replace var with the concrete type here :)

TLM/TLM/State/Configuration.cs Outdated Show resolved Hide resolved
@@ -257,6 +287,13 @@ public class ExtCitizenData {
}
}

public const int CURRENT_VERSION = 1;
Copy link
Member

Choose a reason for hiding this comment

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

Change to 2 due to me robbing v1 in PR #1463

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done
I suppose previous intention was to manage version using this:

        private const string DATA_ID = "TrafficManager_v1.0";
        private const string VERSION_INFO_DATA_ID = "TrafficManager_VersionInfo_v1.0";

Now we have inconsistent code.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, that older string-based way of doing it was grim; your int Version approach is far easier to work with... beause it's actually usable lol.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I guess if we moved to XML we need to also change the data ID.


return Flags.laneConnections[sourceLaneId] != null &&
Flags.laneConnections[sourceLaneId][nodeArrayIndex] != null;
return HasOutgoingConnections(sourceLaneId, IsHeadingTowardsStartNode(sourceLaneId));
Copy link
Member

Choose a reason for hiding this comment

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

Although not touched by this PR yet, there might be some issues with IsHeadingTowardsStartNode() to consider as it checks specifically for NetInfo.Direction.Forward (taking in to account inverted etc).

Also, that method uses foreach which is about 2x slower than for loop IIRC?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

its only used by lane arrow manager.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

its not performance critical

Copy link
Member

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. Issue with Avoid flags was before and normal roads where user can manager lane connections are not available so I'm not sure if it's worth to improve that in this PR. IMO a bit out of scope

@kianzarrin
Copy link
Collaborator Author

kianzarrin commented Mar 13, 2022

@krzychu124 if the code is acceptable can you please approve it before more merge conflicts appear?

@originalfoo
Copy link
Member

There will be merge conflict after #1465 which fixes issue with the new Version property in SerializableDataExtension

@krzychu124
Copy link
Member

And also @aubergine10 planned to do a bit more stuff in 11.6.5.2 (probably some of them will be pushed for later anyways) before releasing TEST as stable and moving to next "major version".
I don't plan any changes to lane connector code, and if there will be any necessary (for supporting Aircrafts) your PR will be merged first anyways.
Personally, I don't plan any fixes for 11.6.5.2 as I'm focused on support for Airports DLC/Aircrafts in general

@originalfoo
Copy link
Member

IMO we should be looking to push 11.6.5.1 to STABLE as soon as we're happy it's got no major issues.

I can change 11.6.5.2 milestone to 11.6.6.0 for this PR and continuation of options refactor.

Does this PR facilitate what @Elesbaan70 is planning for the displaced traffic lights stuff?

@Elesbaan70
Copy link
Contributor

Does this PR facilitate what @Elesbaan70 is planning for the displaced traffic lights stuff?

It does not. But based on further discussions on Discord, that may be moot, so I'd say it's up to @krzychu124 to decide if that matters.

@kianzarrin
Copy link
Collaborator Author

@krzychu124 Can I merge now?

@originalfoo originalfoo modified the milestones: 11.7.0, 11.6.5.2 Mar 13, 2022
Copy link
Member

@krzychu124 krzychu124 left a comment

Choose a reason for hiding this comment

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

ok

@kianzarrin kianzarrin merged commit 41322ab into master Mar 19, 2022
@kianzarrin kianzarrin deleted the bidirectional-fix-784 branch March 19, 2022 03:17
@originalfoo originalfoo modified the milestones: 11.6.6.0, 11.6.5.2 Mar 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
BUG Defect detected LANE ROUTING Feature: Lane arrows / connectors
Projects
None yet
Development

Successfully merging this pull request may close these issues.

lane connector is buggy for bidirectional lanes
4 participants