--- deliantra/server/common/map.C 2008/12/24 01:37:24 1.154 +++ deliantra/server/common/map.C 2008/12/26 10:36:42 1.155 @@ -1218,17 +1218,17 @@ return vol; } -bool +maptile * maptile::tile_available (int dir, bool load) { - if (!tile_path[dir]) - return 0; - - if (tile_map[dir] && (!load || tile_map[dir]->in_memory == MAP_ACTIVE)) - return 1; + if (tile_path[dir]) + { + if (tile_map[dir] && (!load || tile_map[dir]->in_memory == MAP_ACTIVE)) + return tile_map[dir]; - if ((tile_map[dir] = find_async (tile_path[dir], this, load))) - return 1; + if ((tile_map[dir] = find_async (tile_path[dir], this, load))) + return tile_map[dir]; + } return 0; } @@ -1630,3 +1630,81 @@ } } +static void +split_to_tiles (dynbuf &buf, maptile *m, int x0, int y0, int x1, int y1, int dx, int dy) +{ + // clip to map to the left + if (x0 < 0) + { + if (maptile *tile = m->tile_available (TILE_LEFT, 1)) + split_to_tiles (buf, tile, x0 + tile->width, y0, min (x1 + tile->width, tile->width), y1, dx - tile->width, dy); + + if (x1 < 0) // entirely to the left + return; + + x0 = 0; + } + + // clip to map to the right + if (x1 > m->width) + { + if (maptile *tile = m->tile_available (TILE_RIGHT, 1)) + split_to_tiles (buf, tile, max (x0 - m->width, 0), y0, x1 - m->width, y1, dx + m->width, dy); + + if (x0 > m->width) // entirely to the right + return; + + x1 = m->width; + } + + // clip to map above + if (y0 < 0) + { + if (maptile *tile = m->tile_available (TILE_UP, 1)) + split_to_tiles (buf, tile, x0, y0 + tile->height, x1, min (y1 + tile->height, tile->height), dx, dy - tile->height); + + if (y1 < 0) // entirely above + return; + + y0 = 0; + } + + // clip to map below + if (y1 > m->height) + { + if (maptile *tile = m->tile_available (TILE_DOWN, 1)) + split_to_tiles (buf, tile, x0, max (y0 - m->height, 0), x1, y1 - m->height, dx, dy + m->height); + + if (y0 > m->height) // entirely below + return; + + y1 = m->height; + } + + // if we get here, the rect is within the current map + maprect *r = (maprect *)buf.alloc (sizeof (maprect)); + + r->m = m; + r->x0 = x0; + r->y0 = y0; + r->x1 = x1; + r->y1 = y1; + r->dx = dx; + r->dy = dy; +} + +maprect * +maptile::split_to_tiles (int x0, int y0, int x1, int y1) +{ + static dynbuf buf (sizeof (maprect) * 8, sizeof (maprect) * 8); + buf.clear (); + + ::split_to_tiles (buf, this, x0, y0, x1, y1, 0, 0); + + // add end marker + maprect *r = (maprect *)buf.alloc (sizeof (maprect)); + r->m = 0; + + return (maprect *)buf.linearise (); +} +