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

Fix for drone deadlock #190

Merged
merged 7 commits into from
Apr 19, 2021
Merged

Conversation

Baldie-dev
Copy link
Contributor

This fix is for better synchronization of drones and it solves deadlocks that can occur due to the delay between host and client.

Two main situations were causing this:

  1. Client sent a drone to build something and the drone will arrive and call "Build". However, we are not building it immediately on the client, we just sent a request to the host and wait for the reply, and then the building is built. So once the drone arrives, the "Build" is called, the request is sent and the drone is going back to the player. This causes that another drone was dispatched to the same building because, from the client's point of view, the building was not finished yet.

    • Solution: transpiler to not dispatch a drone to the buildPreview for which client sent request to be build (another drone already reached it)
  2. Issue is with recycling the prebuild IDs. When you place buildPreview it has Id = -1, when that building is constructed and you place another buildPreview, it has again Id = -1. So due to the delay, client sent a drone to the first build preview (id: -1) because he does not see it build yet. The host will receive info about it, but from the host point of the id: -1 is for the second buildPreview, which the client does not see yet. In short: The client sent a drone to building A, but the host thinks that the drone is going to building B. And both buildings had the same ID.

    • Solution: I have added the position as a target for the drone to check if he is going to the same buildPreview and we think.

@@ -9,16 +9,26 @@ public static class DroneManager
public static int[] DronePriorities = new int[255];
public static Random rnd = new Random();
public static Dictionary<ushort, List<int>> PlayerDroneBuildingPlans = new Dictionary<ushort, List<int>>();
public static List<int> PendingBuildRequests = new List<int>();
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be locked?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe it is modified only from the main thread, from the GameTick() or from the Update() when packets are processed. It is purely used only on the client-side.

Copy link
Contributor

Choose a reason for hiding this comment

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

I might be thinking about it too much, but there's not much clarity or convention on when something can be accessed from Host/Client/Both and what is the source of truth for each one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For this case of PendingBuildRequests it is used by clients to remember, for which prebuilds the request was sent. The issue was following: drone reached the prebuild, client sent request to build it, however from the drone point of view the prebuild still exist and still need to be built. So I have created this list to ignore prebuilds for which the client already sent request and it is just waiting for the response from server.

But it is true, that for the "Manager" classes, it is sometimes hard to see, what is used by clients and what by the host.

Comment on lines 70 to 72
public static void RemoveBuildRequest(int entityId)
{
PendingBuildRequests.Remove(entityId);
Copy link
Contributor

Choose a reason for hiding this comment

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

Allow notifying caller if the entry was removed.

Suggested change
public static void RemoveBuildRequest(int entityId)
{
PendingBuildRequests.Remove(entityId);
public static bool RemoveBuildRequest(int entityId)
{
return PendingBuildRequests.Remove(entityId);

Copy link
Contributor Author

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 it would be helpful, maybe just to print a warning to logs that some exceptional case occured?
Since:

  • Item is added to the array when the build request is sent to the host.
  • item is removed from the array when the response from the host is received.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added 👍

Copy link
Contributor

@Mushroom Mushroom left a comment

Choose a reason for hiding this comment

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

Only a few comments, rest looks good

planet.factory.BuildFinally(GameMain.mainPlayer, packet.PrebuildId);
if (!DroneManager.RemoveBuildRequest(-packet.PrebuildId))
{
Log.Warn($"Build Request was not succesful removed.");
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo, should be "successfully"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed :)

{
PlanetId = planetId;
DroneId = droneId;
EntityId = entityId;
PlayerId = playerId;
Stage = stage;
Priority = priority;
EntityPos = new Float3(entityPos);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we be consistent and use .ToFloat3() instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed :)

@Mushroom Mushroom merged commit 24b7e34 into NebulaModTeam:master Apr 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants