minecraft-dotnet/Substrate

Sort regions by ordinal position in enumerator

Sukasa opened this issue · 2 comments

The default enumerator code for IEnumerator does not sort the .mcr/.mca files when loading them for enumeration, which means client code cannot assume that chunks will be processed in any specific order.

The following snippets of code are a "fix" for this behaviour, and sort the region filenames to ensure that they are loaded in a coherent order (From -X to +X, and then from -Z to +Z every time X wraps)

The following function is added to the Substrate.Core.RegionManager.Enumerator class:

private int RegionSort(string A, string B)
            {
                Regex R = new Regex(".+r\\.(?<x>-?\\d+)\\.(?<y>-?\\d+)\\.mca", RegexOptions.None);
                Match MC = R.Match(A);
                int AX = int.Parse(MC.Groups[1].Value);
                int AZ = int.Parse(MC.Groups[2].Value);
                MC = R.Match(B);
                int BX = int.Parse(MC.Groups[1].Value);
                int BZ = int.Parse(MC.Groups[2].Value);

                if (AZ < BZ)
                    return -1;
                if (AZ > BZ)
                    return 1;
                if (AX < BX)
                    return -1;
                if (AX > BX)
                    return 1;

                return 0;
            }

and the Enumerator (RegionManager rm) function is replaced with this:

public Enumerator (RegionManager rm)
            {
                _regions = new List<IRegion>();
                _pos = -1;

                if (!Directory.Exists(rm.GetRegionPath())) {
                    throw new DirectoryNotFoundException();
                }

                List<string> Files = new List<string>(Directory.GetFiles(rm.GetRegionPath()));
                _regions.Capacity = Files.Count;

                Files.Sort(RegionSort);


                foreach (string file in Files)
                {
                    try {
                        IRegion r = rm.GetRegion(file);
                        _regions.Add(r);
                    }
                    catch (ArgumentException) {
                        continue;
                    }
                }
            }

Adding this in would be a benefit as it would allow code that uses Substrate to safely assume that chunks will be loaded in a specific order, and make any corresponding algorithmic optimizations.

I've integrated your code (with a few fixes/changes in the regex handling), and it's now included in the 1.3.8 release.