• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

polserver / polserver / 29720407616

20 Jul 2026 05:59AM UTC coverage: 61.394% (-0.03%) from 61.419%
29720407616

push

github

web-flow
Improve uoconvert correctness and speed (#897)

* fix old Tokuno map issue

* quick fixes

* restructure mapwriter to store files in memory until a write is needed

* add dirty flag to only flush files which changed

* change uoconvert use of mapwriter to a stack variable

* added detailed timers to uoconvert map

* precalculate lowest adjacent z so we dont need to calculate again for each tile

* syntax formatting

* read landtiles directly instead of using safe_getmapinfo

* encapsulate the solid block processing result for a single block

* make processing parallel - 5 sec to 2,7 sec for britannia

* add changelog entry

* reduce redundant per-tile work in the solid-block loop

* bucket each static block once instead of rescanning it per tile

readstatics_block() presorts a block's statics by cell in a single pass
(storage order preserved); each tile's bucket then serves directly as the
per-tile scratch, dropping the 64x whole-block rescan and the per-tile copy.
Outputs byte-identical (SHA256 gate, map+maptile, both realms).

* extract merge_shapes and flatten the water-type lookup

- the shape-consolidation loop moves verbatim into merge_shapes(), with
  its invariants and comments; ComputeSolidBlock now reads as
  collect -> filter -> sort -> merge -> emit
- DiscardedWaterTypes is snapshotted into a flat per-graphic table after
  config load; the hot per-static probe drops the tree lookup
Outputs byte-identical (SHA256 gate, map+maptile, both realms).

* name the conversion's magic numbers

MAX_LANDTILE_ID joins LANDTILE_COUNT in plib; wall height, water-discard
window and sand-over-water gap become named constexprs. Landtile classifiers become constexpr in
terrainplane.h with their id lists sourced. Outputs byte-identical.

* unify the block-index math into one helper per layout

realm_block_index (8x8 row-major: base.dat/solidx1/statics.dat),
maptile_index (64x64, rounded-up stride), and staticblock_from_coords
(client mul column-major, reused ... (continued)

513 of 641 new or added lines in 22 files covered. (80.03%)

47 existing lines in 8 files now uncovered.

45116 of 73486 relevant lines covered (61.39%)

516637.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.0
/pol-core/uoconvert/terrainplane.cpp
1
#include "terrainplane.h"
2

3
#include <cstddef>
4
#include <cstdlib>
5

6
#include "../plib/clidata.h"
7
#include "../plib/uofile.h"
8
#include "../plib/ustruct.h"
9
#include "parallel.h"
10

11
namespace Pol::UoConvert
12
{
13
void TerrainPlane::build( int w, int h, bool need_low_z, unsigned threads )
6✔
14
{
15
  width = w;
6✔
16
  height = h;
6✔
17
  const std::size_t n = static_cast<std::size_t>( w ) * static_cast<std::size_t>( h );
6✔
18
  landtile.resize( n );
6✔
19
  avg_z.resize( n );
6✔
20
  eff_z.resize( n );
6✔
21
  if ( need_low_z )
6✔
22
    low_z.resize( n );
4✔
23

24
  // Bulk-extract the raw landtile ids and raw cell z's in one sequential pass, instead of
25
  // four block-indexed rawmapinfo lookups per corner per tile.
26
  std::vector<s8> raw_z( n );
6✔
27
  Plib::rawmap_extract_planes( landtile, raw_z );
6✔
28

29
  // Pass 1: avg_z + eff_z from the flat raw arrays. This replicates safe_getmapinfo
30
  // exactly -- its x+1/y+1 edge clamping, the min-differential diagonal choice, and the
31
  // round-toward-negative-infinity halving -- but reads the four corners from flat memory
32
  // rather than recomputing UO block-index math and copying a USTRUCT_MAPINFO each time.
33
  parallel_for(
6✔
34
      static_cast<std::size_t>( h ),
35
      [&]( std::size_t yy )
6✔
36
      {
37
        const int y = static_cast<int>( yy );
11,775✔
38
        const int yp = ( y + 1 < h ) ? y + 1 : h - 1;
11,775✔
39
        const std::size_t row = static_cast<std::size_t>( y ) * static_cast<std::size_t>( w );
19,031,911✔
40
        const std::size_t rowp = static_cast<std::size_t>( yp ) * static_cast<std::size_t>( w );
11,775✔
41
        for ( int x = 0; x < w; ++x )
9,678,733✔
42
        {
43
          const int xp = ( x + 1 < w ) ? x + 1 : w - 1;
9,329,629✔
44
          const short z1 = raw_z[row + xp];
9,329,629✔
45
          const short z2 = raw_z[row + x];
9,291,103✔
46
          const short z3 = raw_z[rowp + x];
9,429,134✔
47
          const short z4 = raw_z[rowp + xp];
9,619,621✔
48
          const short zsum = ( std::abs( z1 - z3 ) < std::abs( z2 - z4 ) )
17,215,784✔
49
                                 ? static_cast<short>( z1 + z3 )
8,607,892✔
50
                                 : static_cast<short>( z2 + z4 );
8,607,868✔
51
          const s8 avg = static_cast<s8>( zsum >= 0 ? zsum / 2 : ( zsum - 1 ) / 2 );
8,607,892✔
52

53
          const std::size_t i = row + x;
8,607,892✔
54
          avg_z[i] = avg;
8,607,892✔
55

56
          // Caller-side liquid override (UoConvertMain ProcessSolidBlock / create_maptile):
57
          // for water, don't average with surrounding tiles -- use the raw cell z. This lands
58
          // in eff_z only; avg_z stays the plain average because get_lowestadjacentz reads
59
          // neighbors' *un-overridden* averages.
60
          eff_z[i] =
9,784,953✔
61
              ( Plib::landtile_uoflags_read( landtile[i] ) & Plib::USTRUCT_TILE::FLAG_LIQUID )
9,456,774✔
62
                  ? raw_z[i]
9,785,247✔
63
                  : avg;
64
        }
65
      },
349,104✔
66
      threads );
67

68
  if ( !need_low_z )
6✔
69
    return;
2✔
70

71
  // Pass 2: get_lowestadjacentz over the pass-1 arrays. Mirrors the original exactly:
72
  // start from the center's effective z, then min-reduce the eight in-bounds neighbors'
73
  // averages, substituting the center's z for cave-shadow/cave-exit neighbors and
74
  // returning the center's z outright if any neighbor is a no-draw tile.
75
  parallel_for(
4✔
76
      static_cast<std::size_t>( h ),
77
      [&]( std::size_t yy )
4✔
78
      {
79
        const int y = static_cast<int>( yy );
9,984✔
80
        for ( int x = 0; x < w; ++x )
8,085,691✔
81
        {
82
          const std::size_t ci = static_cast<std::size_t>( y ) * static_cast<std::size_t>( w ) + x;
8,114,107✔
83
          const short z_center = eff_z[ci];
8,114,107✔
84
          short lowest = z_center;
7,954,737✔
85
          bool cave_override = false;
7,954,737✔
86

87
          auto consider = [&]( int nx, int ny )
51,229,740✔
88
          {
89
            const std::size_t ni =
51,229,740✔
90
                static_cast<std::size_t>( ny ) * static_cast<std::size_t>( w ) + nx;
51,229,740✔
91
            short z0 = avg_z[ni];
51,229,740✔
92
            const u16 lt = landtile[ni];
51,075,119✔
93
            // raw mul data can hold ids past the landtile range (the conversion warns
94
            // about them later); out-of-range ids classify as plain terrain, exactly
95
            // like the == chains they replace.
96
            const u8 cls = lt < landtile_class.size() ? landtile_class[lt] : 0;
50,316,296✔
97
            if ( cls & LandtileClass::CAVE )
51,398,426✔
NEW
98
              z0 = z_center;
×
99
            if ( cls & LandtileClass::NO_DRAW )
51,398,426✔
NEW
100
              cave_override = true;
×
101
            if ( z0 < lowest )
51,398,426✔
102
              lowest = z0;
63,598✔
103
          };
59,353,163✔
104

105
          if ( x - 1 >= 0 && y - 1 >= 0 )
7,954,737✔
106
            consider( x - 1, y - 1 );
8,100,009✔
107
          if ( x - 1 >= 0 )
7,826,388✔
108
            consider( x - 1, y );
8,094,776✔
109
          if ( x - 1 >= 0 && y + 1 < h )
7,741,501✔
110
            consider( x - 1, y + 1 );
8,124,716✔
111
          if ( y - 1 >= 0 )
7,665,849✔
112
            consider( x, y - 1 );
8,099,060✔
113
          if ( y - 1 >= 0 && x + 1 < w )
7,614,909✔
114
            consider( x + 1, y - 1 );
8,097,956✔
115
          if ( x + 1 < w )
7,547,255✔
116
            consider( x + 1, y );
8,112,393✔
117
          if ( x + 1 < w && y + 1 < h )
7,486,989✔
118
            consider( x + 1, y + 1 );
8,099,834✔
119
          if ( y + 1 < h )
7,453,742✔
120
            consider( x, y + 1 );
8,030,213✔
121

122
          low_z[ci] = static_cast<s8>( cave_override ? z_center : lowest );
8,103,523✔
123
        }
NEW
124
      },
×
125
      threads );
126
}
6✔
127

128
}  // namespace Pol::UoConvert
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc