private List <LayerData> CompileWindData(Vector3 basepos)
        {
            var mlist       = new List <LayerData>();
            var patchesList = new List <LayerPatch>();
            var patchX      = new LayerPatch();
            var patchY      = new LayerPatch();

            /* round to nearest low pos */
            bool rX = basepos.X % 256 >= 128;
            bool rY = basepos.Y % 256 >= 128;

            basepos.X = Math.Floor(basepos.X / 256) * 256;
            basepos.Y = Math.Floor(basepos.Y / 256) * 256;

            for (int y = 0; y < 16; ++y)
            {
                for (int x = 0; x < 16; ++x)
                {
                    Vector3 actpos = basepos;
                    actpos.X += x * 4;
                    actpos.Y += y * 4;
                    if (rX && x < 8)
                    {
                        actpos.X += 128;
                    }
                    if (rY && y < 8)
                    {
                        actpos.Y += 128;
                    }
                    Vector3 w = Wind[actpos];
                    patchX[x, y] = (float)w.X;
                    patchY[x, y] = (float)w.Y;
                }
            }

            patchesList.Add(patchX);
            patchesList.Add(patchY);

            var layerType = LayerData.LayerDataType.Wind;

            if (BASE_REGION_SIZE < m_Scene.SizeX || BASE_REGION_SIZE < m_Scene.SizeY)
            {
                layerType = LayerData.LayerDataType.WindExtended;
            }
            int offset = 0;

            while (offset < patchesList.Count)
            {
                int remaining = Math.Min(patchesList.Count - offset, LayerCompressor.MESSAGES_PER_WIND_LAYER_PACKET);
                int actualused;
                mlist.Add(LayerCompressor.ToLayerMessage(patchesList, layerType, offset, remaining, out actualused));
                offset += actualused;
            }
            return(mlist);
        }
        /*
         * public IList<TerrainPatch> GetTerrainDistanceSorted(Vector3 v)
         * {
         *  SortedList<int, TerrainPatch> sorted = new SortedList<int, TerrainPatch>();
         *  uint x;
         *  uint y;
         *
         *  if(v.X < 0)
         *  {
         *      x = 0;
         *  }
         *  else if(v.X >= SizeX)
         *  {
         *      x = SizeX - 1;
         *  }
         *  else
         *  {
         *      x = (uint)v.X / TERRAIN_PATCH_SIZE;
         *  }
         *
         *  if (v.Y < 0)
         *  {
         *      y = 0;
         *  }
         *  else if(v.Y >= SizeY)
         *  {
         *      y = SizeY - 1;
         *  }
         *  else
         *  {
         *      y = (uint)v.Y / TERRAIN_PATCH_SIZE;
         *  }
         *
         *  int distance;
         *
         *  for(uint py = 0; py < SizeY / TERRAIN_PATCH_SIZE; ++py)
         *  {
         *      for(uint px = 0; px < SizeX / TERRAIN_PATCH_SIZE; ++px)
         *      {
         *          distance = ((int)px - (int)x) * ((int)px - (int)x) + ((int)py - (int)y) * ((int)py - (int)y);
         *          sorted.Add(distance, new TerrainPatch(px, py, m_Map[py * m_PatchCountX + px]));
         *      }
         *  }
         *
         *  return sorted.Values;
         * }
         */
        private List <LayerData> CompileTerrainData(IAgent agent) => m_TerrainRwLock.AcquireReaderLock(() =>
        {
            int y;
            int x;
            var mlist        = new List <LayerData>();
            var dirtyPatches = new List <LayerPatch>();
            RwLockedDictionary <uint, uint> agentSceneSerials = agent.TransmittedTerrainSerials[m_Scene.ID];

            for (y = 0; y < m_Scene.SizeY / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++y)
            {
                for (x = 0; x < m_Scene.SizeX / LayerCompressor.LAYER_PATCH_NUM_XY_ENTRIES; ++x)
                {
                    LayerPatch patch = m_TerrainPatches[y, x];
                    uint serial;
                    if (agentSceneSerials.TryGetValue(patch.ExtendedPatchID, out serial))
                    {
                        if (serial != patch.Serial)
                        {
                            agentSceneSerials[patch.ExtendedPatchID] = serial;
                            dirtyPatches.Add(m_TerrainPatches[y, x]);
                        }
                    }
                    else
                    {
                        dirtyPatches.Add(m_TerrainPatches[y, x]);
                    }
                }
            }
            var layerType = LayerData.LayerDataType.Land;

            if (BASE_REGION_SIZE < m_Scene.SizeX || BASE_REGION_SIZE < m_Scene.SizeY)
            {
                layerType = LayerData.LayerDataType.LandExtended;
            }
            int offset = 0;
            while (offset < dirtyPatches.Count)
            {
                int remaining  = dirtyPatches.Count - offset;
                int actualused = 0;
                mlist.Add(LayerCompressor.ToLayerMessage(dirtyPatches, layerType, offset, remaining, out actualused));
                offset += actualused;
            }
            return(mlist);
        });