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

[Zoning] Improve zone routing #4428

Merged
merged 3 commits into from
Jul 30, 2024

Conversation

Akkadius
Copy link
Member

@Akkadius Akkadius commented Jul 23, 2024

Description

This PR is necessary to fix a few reported extreme edge cases. It simplifies the routing logic quite a bit. This logic has otherwise been battle tested for a few months now with little to no issues.

  • Using #zoneinstance to a public static instance and being able to not zone
  • Rare chance that the wrong zone data gets matched with an instance route
  • We no longer route players when they matched a zone but didn't match an instance, this is something that should be handled by the rest of the code and normally be returned as zone_id 0 so zoning can continue as normal. This also created the possibility that the wrong zone data could be used in the route.
  • Use zone data from zone_store and reload zone_store data when issuing content_flag data reloads instead of holding a copy of our own zones.

The code now ensures that if the zone in question is an instance, that we match explicitly the instance_id when we are iterating through public static instances. Before, there was a rare chance that the wrong instance could be matched if multiples of the same were in the database.

WorldContentService::FindZoneResult WorldContentService::FindZone(uint32 zone_id, uint32 instance_id)
{
	for (const auto &z: zone_store.GetZones()) {
		for (auto &i: m_zone_static_instances) {
			if (
				z.zoneidnumber == zone_id &&
				DoesZonePassContentFiltering(z) &&
				i.zone == zone_id &&
				i.version == z.version) {

				if (instance_id > 0 && i.id != instance_id) {
					continue;
				}

				LogInfo(
					"Routed player to public static instance [{}] of zone [{}] ({}) version [{}] long_name [{}] notes [{}]",
					i.id,
					z.short_name,
					z.zoneidnumber,
					z.version,
					z.long_name,
					i.notes
				);

				return WorldContentService::FindZoneResult{
					.zone_id = static_cast<uint32>(z.zoneidnumber),
					.instance = i,
					.zone = z
				};
			}
		}
	}

	return WorldContentService::FindZoneResult{.zone_id = 0};
}
// FindZone handles content and context aware zone routing (middleware)
//
// this is a middleware function that is meant to be used in the zone change process
// this hooks all core zone changes within the server and routes the player to the correct zone
// returning a zone_id of non-zero means the middleware will route the player
// returning a zone_id of 0 means the middleware will not route the player
// this is useful for handling multiple versions of the same zone
//
// implementation >
// the zoning and process spawning logic already is handled by two keys "zone_id" and "instance_id"
// we leverage static, never expires instances to handle this and client still sees it as a normal zone
//
// content awareness >
// simply use the zone_id, server content settings and the middleware will handle the rest
// you don't have to think about instances in any data tables (use instance_id 0)
// you don't have to keep track of instance ids in scripts (use instance_id 0)
// the versions of zones are represented by two zone entries that have potentially different min/max expansion and/or different content flags
// we decide to route the client to the correct version of the zone based on the current server side expansion
//
// example >
// we want to route players to the correct version of lavastorm based on the current server side expansion (DoesZonePassContentFiltering)
// lavastorm (pre-don) version 0 (classic)
//   zone table entry for version = 0, min_expansion = 0, max_expansion = 8
//   instance_list table entry for lavastorm has version = 0, is_global = 1, never_expires = 1
// lavastorm (don) version 1
//   zone table entry for version = 1, min_expansion = 9, max_expansion = 99
//   instance_list table entry for lavastorm has version = 1, is_global = 1, never_expires = 1

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Testing

Tested zoning locally

Checklist

  • I have tested my changes
  • I have performed a self-review of my code. Ensuring variables, functions and methods are named in a human-readable way, comments are added only where naming of variables, functions and methods can't give enough context.
  • I own the changes of my code and take responsibility for the potential issues that occur

@Akkadius Akkadius changed the title Akkadius/zone routing algorithm improvements [Zoning] Improve zone routing Jul 23, 2024
@Akkadius
Copy link
Member Author

Akkadius commented Jul 23, 2024

@fryguy503 will have this sitting on his server soon too to test

@fryguy503
Copy link
Contributor

Coupled with PR #4429 This has been working well.

@fryguy503 fryguy503 merged commit 70a96ea into master Jul 30, 2024
2 checks passed
@fryguy503 fryguy503 deleted the akkadius/zone-routing-algorithm-improvements branch July 30, 2024 13:12
@joligario joligario mentioned this pull request Jul 30, 2024
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.

3 participants