diff --git a/cubiomes b/cubiomes index 0af31b4..e49c8c5 160000 --- a/cubiomes +++ b/cubiomes @@ -1 +1 @@ -Subproject commit 0af31b4e7eeb14a58c2bd9a4c4c68b97b4a7d6e8 +Subproject commit e49c8c561bcd238b376b7817182695ea2f993061 diff --git a/cubiomes-viewer.pro b/cubiomes-viewer.pro index 9e8b305..f148e7e 100644 --- a/cubiomes-viewer.pro +++ b/cubiomes-viewer.pro @@ -141,6 +141,7 @@ HEADERS += \ $$CUPATH/finders.h \ $$CUPATH/generator.h \ $$CUPATH/layers.h \ + $$CUPATH/biomes.h \ $$CUPATH/quadbase.h \ $$CUPATH/util.h \ $$LUAPATH/lapi.h \ diff --git a/rc/icons/chambers.png b/rc/icons/chambers.png index 880d34b..55c8a38 100644 Binary files a/rc/icons/chambers.png and b/rc/icons/chambers.png differ diff --git a/rc/icons/chambers_d.png b/rc/icons/chambers_d.png index 880d34b..1c8025b 100644 Binary files a/rc/icons/chambers_d.png and b/rc/icons/chambers_d.png differ diff --git a/src/config.cpp b/src/config.cpp index f695c18..40f6bc2 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -60,7 +60,7 @@ bool WorldInfo::equals(const WorldInfo& wi) const void WorldInfo::reset() { - mc = MC_NEWEST; + mc = MC_DEFAULT; large = false; seed = 0; y = 255; @@ -92,7 +92,7 @@ bool WorldInfo::read(const QString& line) { mc = str2mc(buf); if (mc < 0) - mc = MC_NEWEST; + mc = MC_DEFAULT; return true; } if (sscanf(p, "#Large: %d", &tmp) == 1) diff --git a/src/config.h b/src/config.h index 4909816..35fdd55 100644 --- a/src/config.h +++ b/src/config.h @@ -15,6 +15,7 @@ #define PRECOMPUTE48_BUFSIZ ((int64_t)1 << 30) +enum { MC_DEFAULT = MC_1_21_2 }; struct ExtGenConfig { @@ -77,7 +78,7 @@ enum { LOPT_NOOCEAN_1, LOPT_BETA_T_1, LOPT_BETA_H_1, - LOPT_HEIGHT_4, + LOPT_HEIGHT, LOPT_STRUCTS, LOPT_MAX, }; diff --git a/src/formsearchcontrol.cpp b/src/formsearchcontrol.cpp index 6e32bae..0605023 100644 --- a/src/formsearchcontrol.cpp +++ b/src/formsearchcontrol.cpp @@ -336,6 +336,17 @@ void FormSearchControl::setSearchRange(uint64_t smin, uint64_t smax) searchProgressReset(); } +bool FormSearchControl::getSeed(int row, uint64_t *seed) +{ + QAbstractItemModel *model = ui->results->model(); + if (row < 0 || row >= model->rowCount()) + return false; + QModelIndex idx = model->index(row, SeedTableModel::COL_SEED); + *seed = model->data(idx, Qt::UserRole).toULongLong(); + return true; +} + + void FormSearchControl::on_buttonClear_clicked() { model->reset(); @@ -444,13 +455,9 @@ void FormSearchControl::on_buttonMore_clicked() void FormSearchControl::onSeedSelectionChanged() { - int row = ui->results->currentIndex().row(); - if (row >= 0 && row < ui->results->model()->rowCount()) - { - QModelIndex idx = ui->results->model()->index(row, SeedTableModel::COL_SEED); - uint64_t s = ui->results->model()->data(idx, Qt::UserRole).toULongLong(); + uint64_t s; + if (getSeed(ui->results->currentIndex().row(), &s)) emit selectedSeedChanged(s); - } } void FormSearchControl::on_results_clicked(const QModelIndex &) @@ -809,10 +816,9 @@ void FormSearchControl::removeCurrent() void FormSearchControl::copySeed() { - QModelIndex index = ui->results->currentIndex(); - if (index.isValid()) + uint64_t seed; + if (getSeed(ui->results->currentIndex().row(), &seed)) { - uint64_t seed = ui->results->model()->data(index, Qt::UserRole).toULongLong(); QClipboard *clipboard = QGuiApplication::clipboard(); clipboard->setText(QString::asprintf("%" PRId64, seed)); } @@ -824,11 +830,10 @@ void FormSearchControl::copyResults() int n = ui->results->model()->rowCount(); for (int i = 0; i < n; i++) { - QModelIndex idx = ui->results->model()->index(i, SeedTableModel::COL_SEED); - uint64_t seed = ui->results->model()->data(idx, Qt::UserRole).toULongLong(); - text += QString::asprintf("%" PRId64 "\n", seed); + uint64_t seed; + if (getSeed(i, &seed)) + text += QString::asprintf("%" PRId64 "\n", seed); } - QClipboard *clipboard = QGuiApplication::clipboard(); clipboard->setText(text); } diff --git a/src/formsearchcontrol.h b/src/formsearchcontrol.h index 13a3691..64338ce 100644 --- a/src/formsearchcontrol.h +++ b/src/formsearchcontrol.h @@ -114,6 +114,8 @@ public: void setSearchMode(int mode); + bool getSeed(int row, uint64_t *seed); + signals: void selectedSeedChanged(uint64_t seed); void searchStatusChanged(bool running); diff --git a/src/headless.cpp b/src/headless.cpp index 914c727..aaf1f7b 100644 --- a/src/headless.cpp +++ b/src/headless.cpp @@ -5,8 +5,11 @@ #include #include +#include #include +#include + #if defined(_WIN32) #include short get_term_width() @@ -34,19 +37,20 @@ static QTextStream& qOut() return out; } -Headless::Headless(QString sessionpath, QString resultspath, QObject *parent) +Headless::Headless(QString sessionpath, QString resultspath, bool reset, QObject *parent) : QThread(parent) , sthread(nullptr) , sessionpath(sessionpath) , resultfile(resultspath) , resultstream(stdout) + , progressfp() { sthread.isdone = true; QSettings settings(APP_STRING, APP_STRING); g_extgen.load(settings); - if (!loadSession(sessionpath)) + if (!loadSession(sessionpath, reset)) return; if (!sthread.set(nullptr, session)) @@ -82,7 +86,7 @@ static bool load_seeds(std::vector& seeds, QString path) return false; } -bool Headless::loadSession(QString sessionpath) +bool Headless::loadSession(QString sessionpath, bool reset) { qOut() << "Loading session: \"" << sessionpath << "\"\n"; qOut().flush(); @@ -100,6 +104,11 @@ bool Headless::loadSession(QString sessionpath) return false; } + if (reset) + session.sc.startseed = 0; + else + results = session.slist; + if (session.cv.empty()) { warn(nullptr, "Session defines no search constraints."); @@ -149,15 +158,32 @@ void Headless::run() session.writeHeader(resultstream); resultstream.flush(); - sthread.startSearch(); - elapsed.start(); - if (resultfile.isOpen()) { + // open a separate write channel to the same result file and + // reserve space for a progress field after the header + QByteArray path = QFileInfo(resultfile).absoluteFilePath().toLocal8Bit(); + progressfp = fopen(path.data(), "rb+"); + if (progressfp) + { + fseek(progressfp, resultfile.size(), SEEK_SET); + resultstream << QString::asprintf("#Progress: %20" PRId64 "\n", session.sc.startseed); + resultstream.flush(); + } + + for (uint64_t s : results) + { + resultstream << (int64_t) s << "\n"; + resultstream.flush(); + } + qOut() << "\n\n\n\n\n\n\n"; qOut().flush(); timer.start(250); } + + sthread.startSearch(); + elapsed.start(); } void Headless::searchResult(uint64_t seed) @@ -174,6 +200,11 @@ void Headless::searchFinish(bool done) timer.stop(); progressTimeout(); } + if (progressfp) + { + fclose(progressfp); + progressfp = NULL; + } if (done) qOut() << "Search done!\n"; qOut() << "Stopping event loop.\n"; @@ -188,6 +219,13 @@ void Headless::progressTimeout() qreal min, avg, max; sthread.getProgress(&status, &prog, &end, &seed, &min, &avg, &max); + if (progressfp) + { + long pos = ftell(progressfp); + fprintf(progressfp, "#Progress: %20" PRId64 "\n", seed); + fseek(progressfp, pos, SEEK_SET); + } + short width = get_term_width(); if (width <= 24) return; diff --git a/src/headless.h b/src/headless.h index 40b5e6c..2b29a1a 100644 --- a/src/headless.h +++ b/src/headless.h @@ -12,10 +12,10 @@ class Headless : public QThread Q_OBJECT public: - Headless(QString sessionpath, QString resultspath, QObject *parent = 0); + Headless(QString sessionpath, QString resultspath, bool reset, QObject *parent = 0); virtual ~Headless(); - bool loadSession(QString sessionpath); + bool loadSession(QString sessionpath, bool reset); public slots: void run(); @@ -33,6 +33,7 @@ public: std::vector results; QFile resultfile; QTextStream resultstream; + FILE *progressfp; QTimer timer; QElapsedTimer elapsed; }; diff --git a/src/layerdialog.cpp b/src/layerdialog.cpp index e507256..a794916 100644 --- a/src/layerdialog.cpp +++ b/src/layerdialog.cpp @@ -20,7 +20,7 @@ bool getLayerOptionInfo(LayerOptInfo *info, int mode, int disp, WorldInfo wi) if (disp == 3) txt = "1:64"; if (disp == 4) txt = "1:256"; break; - case LOPT_HEIGHT_4: + case LOPT_HEIGHT: if (disp == 0) txt = QApplication::translate("LayerDialog", "Grayscale"); if (disp == 1) txt = QApplication::translate("LayerDialog", "Shaded biome map"); if (disp == 2) txt = QApplication::translate("LayerDialog", "Contours on biomes"); @@ -113,7 +113,7 @@ LayerDialog::LayerDialog(QWidget *parent, WorldInfo wi) radio[LOPT_NOOCEAN_1] = ui->radioNoOcean; radio[LOPT_BETA_T_1] = ui->radioBetaT; radio[LOPT_BETA_H_1] = ui->radioBetaH; - radio[LOPT_HEIGHT_4] = ui->radioHeight; + radio[LOPT_HEIGHT] = ui->radioHeight; radio[LOPT_STRUCTS] = ui->radioStruct; combo[LOPT_BIOMES] = ui->comboBiomes; @@ -122,7 +122,7 @@ LayerDialog::LayerDialog(QWidget *parent, WorldInfo wi) combo[LOPT_NOISE_C_4] = ui->comboNoiseC; combo[LOPT_NOISE_E_4] = ui->comboNoiseE; combo[LOPT_NOISE_W_4] = ui->comboNoiseW; - combo[LOPT_HEIGHT_4] = ui->comboHeight; + combo[LOPT_HEIGHT] = ui->comboHeight; for (int i = 0; i < LOPT_MAX; i++) { diff --git a/src/main.cpp b/src/main.cpp index 31e6b54..b059251 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -34,6 +34,7 @@ int main(int argc, char *argv[]) bool version = false; bool nogui = false; + bool clear = false; bool reset = false; bool usage = false; QString sessionpath; @@ -45,6 +46,8 @@ int main(int argc, char *argv[]) version = true; else if (strcmp(argv[i], "--nogui") == 0) nogui = true; + else if (strcmp(argv[i], "--reset") == 0) + clear = true; else if (strcmp(argv[i], "--reset-all") == 0) reset = true; else if (strncmp(argv[i], "--session=", 10) == 0) @@ -67,6 +70,7 @@ int main(int argc, char *argv[]) " --help Display this help and exit.\n" " --version Output version information and exit.\n" " --nogui Run in headless search mode.\n" + " --reset Discard results and reset starting seed.\n" " --reset-all Clear settings and remove all session data.\n" " --session=file Open this session file.\n" " --out=file Write matching seeds to this file while searching.\n" @@ -105,7 +109,7 @@ int main(int argc, char *argv[]) if (nogui) { QCoreApplication app(argc, argv); - Headless headless(sessionpath, resultspath, &app); + Headless headless(sessionpath, resultspath, clear, &app); QObject::connect(&headless, SIGNAL(finished()), &app, SLOT(quit())); QTimer::singleShot(0, &headless, SLOT(run())); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index cfcdf51..0af5343 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -111,7 +111,7 @@ MainWindow::MainWindow(QString sessionpath, QString resultspath, QWidget *parent laction[LOPT_NOOCEAN_1] = ui->actionNoOceans; laction[LOPT_BETA_T_1] = ui->actionBetaTemperature; laction[LOPT_BETA_H_1] = ui->actionBetaHumidity; - laction[LOPT_HEIGHT_4] = ui->actionHeight; + laction[LOPT_HEIGHT] = ui->actionHeight; laction[LOPT_STRUCTS] = ui->actionStructures; QActionGroup *grp = new QActionGroup(this); @@ -365,7 +365,7 @@ bool MainWindow::getSeed(WorldInfo *wi, bool applyrand) { if (applyrand) qDebug() << "Unknown MC version: " << mcs.c_str(); - wi->mc = MC_NEWEST; + wi->mc = MC_DEFAULT; ok = false; } @@ -697,13 +697,13 @@ void MainWindow::setMCList(bool experimental) if (ui->comboBoxMC->count()) getSeed(&wi, false); else - wi.mc = MC_NEWEST; + wi.mc = MC_DEFAULT; QStringList mclist; for (int mc = MC_NEWEST; mc > MC_UNDEF; mc--) { if (!experimental && mc != wi.mc) { - if (mc <= MC_1_0 || mc == MC_1_16_1 || mc == MC_1_19_2) + if (mc <= MC_1_0 || mc == MC_1_16_1 || mc == MC_1_19_2 || mc == MC_1_21_3) continue; } const char *mcs = mc2str(mc); diff --git a/src/mapview.cpp b/src/mapview.cpp index 5ac7bed..f76d919 100644 --- a/src/mapview.cpp +++ b/src/mapview.cpp @@ -502,7 +502,7 @@ void MapView::paintEvent(QPaintEvent *) QPoint cur = mapFromGlobal(QCursor::pos()); qreal bx = (cur.x() - width()/2.0) / blocks2pix + fx; qreal bz = (cur.y() - height()/2.0) / blocks2pix + fz; - Pos p = {(int)clampimax(bx), (int)clampimax(bz)}; + Pos p = {(int)clampimax(floor(bx)), (int)clampimax(floor(bz))}; overlay->pos = p; overlay->bname = world->getBiomeName(p); diff --git a/src/search.cpp b/src/search.cpp index 0f830fe..effbdbf 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -1275,6 +1275,7 @@ L_qm_any: case F_PORTALN: case F_ANCIENT_CITY: case F_TRAILS: + case F_CHAMBERS: case F_FORTRESS: case F_BASTION: diff --git a/src/search.h b/src/search.h index d0c9f77..084e331 100644 --- a/src/search.h +++ b/src/search.h @@ -91,6 +91,7 @@ enum F_TRAILS, F_BIOME_SAMPLE, F_NOISE_SAMPLE, + F_CHAMBERS, // new filters should be added here at the end to keep some downwards compatibility FILTER_MAX, }; @@ -504,6 +505,13 @@ static const struct FilterList : private FilterInfo "" }; + list[F_CHAMBERS] = FilterInfo{ + CAT_STRUCT, 1, LOC_RAD, Trial_Chambers, 1, BR_CLUST, MC_1_21, MC_NEWEST, 0, 0, disp++, + "chambers", + QT_TRANSLATE_NOOP("Filter", "Trial chambers"), + "" + }; + list[F_PORTAL] = FilterInfo{ CAT_STRUCT, 0, LOC_RAD, Ruined_Portal, 1, BR_CLUST, MC_1_16_1, MC_NEWEST, 0, 0, disp++, "portal", diff --git a/src/util.cpp b/src/util.cpp index bb08dc5..3bdc7b6 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -156,6 +156,8 @@ QString getBiomeDisplay(int mc, int id) case mangrove_swamp: return QApplication::translate("Biome", "Mangrove Swamp"); // 1.20 case cherry_grove: return QApplication::translate("Biome", "Cherry Grove"); + // 1.21.3 (Winter Drop Version TBA) + case pale_garden: return QApplication::translate("Biome", "Pale Garden"); } const char *name = biome2str(mc, id); return name ? name : ""; diff --git a/src/world.cpp b/src/world.cpp index 418cb47..90b06e5 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -136,7 +136,7 @@ QStringList VarPos::detail() const Quad::Quad(const Level* l, int64_t i, int64_t j) - : wi(l->wi),dim(l->dim),lopt(l->lopt),g(&l->g),sn(&l->sn),hd(l->hd),scale(l->scale) + : wi(l->wi),dim(l->dim),lopt(l->lopt),g(&l->g),sn(&l->sn),highres(l->highres),scale(l->scale) , ti(i),tj(j),blocks(l->blocks),pixs(l->pixs),sopt(l->sopt) , biomes(),rgb(),img(),spos() { @@ -267,7 +267,12 @@ void applyHeightShading(unsigned char *rgb, Range r, pw += 2*bd; ph += 2*bd; } std::vector buf(pw * ph); - if (ps == 0) + if (ps == 0 && r.scale <= 8 && g->dim == DIM_END) + { + mapEndSurfaceHeight(&buf[0], &g->en, sn, px, pz, pw, ph, r.scale, 0); + mapEndIslandHeight(&buf[0], &g->en, g->seed, px, pz, pw, ph, r.scale); + } + else if (ps == 0 && r.scale == 4) { mapApproxHeight(&buf[0], 0, g, sn, px, pz, pw, ph); } @@ -286,6 +291,7 @@ void applyHeightShading(unsigned char *rgb, Range r, } } } + // interpolate height std::vector height((w+2) * (h+2)); for (int j = 0; j < h+2; j++) @@ -382,7 +388,8 @@ void Quad::run() if (pixs > 0) { - if (lopt.mode == LOPT_STRUCTS && dim == DIM_OVERWORLD) + if ((lopt.mode == LOPT_STRUCTS && dim == DIM_OVERWORLD) || + (g->mc <= MC_1_17 && scale > 256 && dim == DIM_OVERWORLD)) { img = new QImage(); done = true; @@ -431,9 +438,13 @@ void Quad::run() g_mutex.unlock(); biomesToImage(rgb, g_biomeColors, biomes, w, h, 1, 1); - if (lopt.mode == LOPT_HEIGHT_4) + if (lopt.mode == LOPT_HEIGHT) { - int stepbits = (hd ? 0 : 2); + int stepbits = 0; // interpolated_step = (1 << stepbits) + if (scale > 16) + { + stepbits = 1; + } applyHeightShading(rgb, r, g, sn, stepbits, lopt.disp[lopt.mode], false, isdel); } } @@ -459,7 +470,7 @@ void Quad::run() Level::Level() : cells(),g(),sn(),entry(),lopt(),wi(),dim() , tx(),tz(),tw(),th() - , hd(),scale(),blocks(),pixs() + , highres(),scale(),blocks(),pixs() , sopt() { } @@ -480,7 +491,7 @@ void Level::init4map(QWorld *w, int pix, int layerscale) tx = tz = tw = th = 0; - hd = (layerscale == 1); + highres = (layerscale == 1); scale = layerscale; pixs = pix; blocks = pix * layerscale; @@ -504,7 +515,7 @@ void Level::init4map(QWorld *w, int pix, int layerscale) case LOPT_NOISE_E_4: case LOPT_NOISE_D_4: case LOPT_NOISE_W_4: - case LOPT_HEIGHT_4: + //case LOPT_HEIGHT_4: case LOPT_RIVER_4: case LOPT_STRUCTS: optlscale = 4; @@ -796,7 +807,13 @@ void QWorld::setDim(int dim, LayerOpt lopt) initSurfaceNoise(&sn, dim, g.seed); int pixs, lcnt; - if (g.mc >= MC_1_18 || dim != DIM_OVERWORLD) + if (lopt.mode == LOPT_HEIGHT) + { + pixs = 32; + lcnt = 6; + qual = 4.0; + } + else if (g.mc > MC_1_17 || dim != DIM_OVERWORLD) { pixs = 128; lcnt = 6; @@ -873,7 +890,7 @@ QString QWorld::getBiomeName(Pos p) return c + "=" + QString::number(id); } QString ret = getBiomeDisplay(wi.mc, id); - if (lopt.mode == LOPT_HEIGHT_4) + if (lopt.mode == LOPT_HEIGHT) { int y = estimateSurface(p); if (y > 0) @@ -885,7 +902,15 @@ QString QWorld::getBiomeName(Pos p) int QWorld::estimateSurface(Pos p) { float y = 0; - mapApproxHeight(&y, 0, &g, &sn, p.x>>2, p.z>>2, 1, 1); + if (g.dim == DIM_END) + { // use end surface generator for 1:1 scale + mapEndSurfaceHeight(&y, &g.en, &sn, p.x, p.z, 1, 1, 1, 0); + mapEndIslandHeight(&y, &g.en, g.seed, p.x, p.z, 1, 1, 1); + } + else + { + mapApproxHeight(&y, 0, &g, &sn, p.x>>2, p.z>>2, 1, 1); + } return (int) floor(y); } @@ -1094,9 +1119,9 @@ struct SpawnStronghold : public Scheduled } }; -static bool draw_grid_rec(QPainter& painter, QRect &rec, qreal pix, int64_t x, int64_t z) +static bool draw_grid_rec(QPainter& painter, QColor col, QRect &rec, qreal pix, int64_t x, int64_t z) { - painter.setPen(QPen(QColor(0, 0, 0, 96), 1)); + painter.setPen(QPen(col, 1)); painter.drawRect(rec); if (pix < 50) return false; @@ -1142,6 +1167,7 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz, smallfont.setPointSize(oldfont.pointSize() - 2); painter.setFont(smallfont); + QColor gridcol = lopt.mode == LOPT_HEIGHT ? QColor(192, 0, 0, 96) : QColor(0, 0, 0, 96); int gridpix = 128; // 128px is approximately the size of: //gridpix = painter.fontMetrics().boundingRect("-30000000,-30000000").width(); @@ -1166,7 +1192,7 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz, if (sshow[D_GRID] && !gridspacing) { - draw_grid_rec(painter, rec, ps, q->ti*q->blocks, q->tj*q->blocks); + draw_grid_rec(painter, gridcol, rec, ps, q->ti*q->blocks, q->tj*q->blocks); } } } @@ -1190,7 +1216,7 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz, qreal px = vw/2.0 + (x+i) * ps - focusx * blocks2pix; qreal pz = vh/2.0 + (z+j) * ps - focusz * blocks2pix; QRect rec(px, pz, ps, ps); - draw_grid_rec(painter, rec, ps, (x+i)*gs, (z+j)*gs); + draw_grid_rec(painter, gridcol, rec, ps, (x+i)*gs, (z+j)*gs); } } break; @@ -1264,6 +1290,41 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz, } } + if (showBB && sshow[D_GATEWAY] && dim == DIM_END && g.mc > MC_1_12) + { + if (endgates.empty()) + { + endgates.resize(40); + getFixedEndGateways(g.mc, g.seed, &endgates[0]); + for (int i = 0; i < 20; i++) + endgates[20 + i] = getLinkedGatewayPos(&g.en, &sn, g.seed, endgates[i]); + } + + for (int i = 0; i < 20; i++) + { + qreal xsrc = vw/2.0 + (0.5 + endgates[i].x - focusx) * blocks2pix; + qreal ysrc = vh/2.0 + (0.5 + endgates[i].z - focusz) * blocks2pix; + qreal xdst = vw/2.0 + (0.5 + endgates[i+20].x - focusx) * blocks2pix; + qreal ydst = vh/2.0 + (0.5 + endgates[i+20].z - focusz) * blocks2pix; + + QPen pen = painter.pen(); + painter.setPen(QPen(QColor(192, 0, 0, 160), i == 0 ? 1.5 : 0.5)); + painter.drawLine(QPointF(xsrc,ysrc), QPointF(xdst,ydst)); + painter.setPen(pen); + + if (blocks2pix >= 1.0 && abs(xsrc) < vw && abs(ysrc) < vh) + { + QString s = QString::number(i+1); + QRect rec = painter.fontMetrics().boundingRect(s); + qreal dx = xsrc - xdst; + qreal dy = ysrc - ydst; + qreal df = rec.height() / sqrt(dx*dx + dy*dy); + rec.moveCenter(QPoint(xsrc + dx * df, ysrc + dy * df)); + painter.drawText(rec, s); + } + } + } + for (Shape& s : shapes) { if (s.dim != DIM_UNDEF && s.dim != dim) diff --git a/src/world.h b/src/world.h index ba31c48..aeefb79 100644 --- a/src/world.h +++ b/src/world.h @@ -64,7 +64,7 @@ struct Quad : public Scheduled LayerOpt lopt; const Generator *g; const SurfaceNoise *sn; - int hd; + int highres; int scale; int ti, tj; int blocks; @@ -101,7 +101,7 @@ struct Level WorldInfo wi; int dim; int tx, tz, tw, th; - int hd; + int highres; int scale; int blocks; int pixs; @@ -204,6 +204,7 @@ public: QAtomicPointer spawn; QAtomicPointer strongholds; QAtomicPointer> qsinfo; + QVector endgates; // isdel is a flag for the worker thread to stop std::atomic_bool isdel;