diff --git a/cubiomes b/cubiomes
index 3899100..e61f4f1 160000
--- a/cubiomes
+++ b/cubiomes
@@ -1 +1 @@
-Subproject commit 389910035a5483022e7d42e5f37bc0c9440efef0
+Subproject commit e61f4f1ebf0bda93d16309ca45a216d632c23acc
diff --git a/src/configdialog.cpp b/src/configdialog.cpp
index 1252045..1b366f0 100644
--- a/src/configdialog.cpp
+++ b/src/configdialog.cpp
@@ -23,6 +23,7 @@ ConfigDialog::~ConfigDialog()
void ConfigDialog::initSettings(Config *config)
{
ui->checkSmooth->setChecked(config->smoothMotion);
+ ui->checkBBoxes->setChecked(config->showBBoxes);
ui->checkRestore->setChecked(config->restoreSession);
ui->checkAutosave->setChecked(config->autosaveCycle != 0);
if (config->autosaveCycle)
@@ -36,6 +37,7 @@ void ConfigDialog::initSettings(Config *config)
Config ConfigDialog::getSettings()
{
conf.restoreSession = ui->checkRestore->isChecked();
+ conf.showBBoxes = ui->checkBBoxes->isChecked();
conf.autosaveCycle = ui->checkAutosave->isChecked() ? ui->spinAutosave->value() : 0;
conf.smoothMotion = ui->checkSmooth->isChecked();
conf.uistyle = ui->comboStyle->currentIndex();
diff --git a/src/configdialog.ui b/src/configdialog.ui
index dca4587..917f1bc 100644
--- a/src/configdialog.ui
+++ b/src/configdialog.ui
@@ -2,14 +2,6 @@
ConfigDialog
-
-
- 0
- 0
- 411
- 252
-
-
Preferences
@@ -18,14 +10,14 @@
:/icons/map.png:/icons/map.png
- -
+
-
Maximum number of matching seeds:
- -
+
-
Qt::Horizontal
@@ -35,7 +27,7 @@
- -
+
-
Size of search item queue:
@@ -43,7 +35,7 @@
- -
+
-
Seeds per thread search item:
@@ -60,17 +52,10 @@
- -
+
-
- -
-
-
- Restore previous session at launch
-
-
-
- -
+
-
@@ -80,17 +65,17 @@
- -
+
-
- -
+
-
Autosave every:
- -
+
-
min
@@ -106,14 +91,14 @@
- -
+
-
GUI style:
- -
+
-
@@ -133,6 +118,20 @@
+ -
+
+
+ Outline known bounding boxes
+
+
+
+ -
+
+
+ Restore previous session at launch
+
+
+
diff --git a/src/formgen48.cpp b/src/formgen48.cpp
index 3ea5c4c..2f2506e 100644
--- a/src/formgen48.cpp
+++ b/src/formgen48.cpp
@@ -8,7 +8,48 @@
#include
#include
#include
+#include
+#include
+#include
+
+class SetSpinBox : public QSpinBox
+{
+public:
+ SetSpinBox(QWidget *parent)
+ : QSpinBox(parent)
+ {
+ std::set vset;
+ for (int i = 0, n = sizeof(g_qm_90) / sizeof(int64_t); i < n; i++)
+ vset.insert(qmonumentQual(g_qm_90[i]));
+ for (int v : vset)
+ vlist.push_back(v);
+
+ setRange(vlist.front(), vlist.last());
+ setValue(vlist.front());
+ }
+ virtual ~SetSpinBox() {}
+
+ virtual void stepBy(int steps) override
+ {
+ int val = value();
+ int idx = 0;
+ for (int i = 0, n = vlist.size(); i < n; i++)
+ {
+ if (vlist[i] > val)
+ break;
+ idx = i;
+ }
+ idx += steps;
+ if (idx < 0)
+ idx = 0;
+ if (idx >= vlist.size())
+ idx = vlist.size() - 1;
+ setValue(vlist[idx]);
+ }
+
+ QList vlist;
+};
FormGen48::FormGen48(MainWindow *parent)
: QWidget(parent)
@@ -29,7 +70,10 @@ FormGen48::FormGen48(MainWindow *parent)
connect(ui->lineEditX2, SIGNAL(editingFinished()), SLOT(onChange()));
connect(ui->lineEditZ2, SIGNAL(editingFinished()), SLOT(onChange()));
- connect(ui->spinMonumentArea, SIGNAL(editingFinished()), SLOT(onChange()));
+ spinMonumentArea = new SetSpinBox(this);
+ ui->tabQuadM->layout()->addWidget(spinMonumentArea);
+
+ connect(spinMonumentArea, SIGNAL(editingFinished()), SLOT(onChange()));
connect(ui->lineSalt, SIGNAL(editingFinished()), SLOT(onChange()));
connect(ui->lineListSalt, SIGNAL(editingFinished()), SLOT(onChange()));
@@ -45,6 +89,7 @@ FormGen48::FormGen48(MainWindow *parent)
FormGen48::~FormGen48()
{
delete ui;
+ delete spinMonumentArea;
}
bool FormGen48::setList48(QString path, bool quiet)
@@ -89,7 +134,7 @@ void FormGen48::setSettings(const Gen48Settings& gen48, bool quiet)
{
ui->tabWidget->setCurrentIndex(gen48.mode);
ui->comboLow20->setCurrentIndex(gen48.qual);
- ui->spinMonumentArea->setValue(gen48.qmarea);
+ spinMonumentArea->setValue(gen48.qmarea);
ui->lineSalt->setText(QString::number(gen48.salt));
ui->lineListSalt->setText(QString::number(gen48.listsalt));
ui->lineEditX1->setText(QString::number(gen48.x1));
@@ -113,7 +158,7 @@ Gen48Settings FormGen48::getSettings(bool resolveauto)
s.mode = ui->tabWidget->currentIndex();
s.qual = ui->comboLow20->currentIndex();
- s.qmarea = ui->spinMonumentArea->value();
+ s.qmarea = spinMonumentArea->value();
s.salt = ui->lineSalt->text().toLongLong();
s.listsalt = ui->lineListSalt->text().toLongLong();
s.manualarea = ui->radioManual->isChecked();
@@ -238,7 +283,7 @@ void FormGen48::updateAutoUi()
if (isqh)
ui->comboLow20->setCurrentIndex(cond.type - F_QH_IDEAL);
else if (isqm)
- ui->spinMonumentArea->setValue((int) ceil( 58*58*4 * (cond.type == F_QM_95 ? 0.95 : 0.90) ));
+ spinMonumentArea->setValue((int) ceil( 58*58*4 * (cond.type == F_QM_95 ? 0.95 : 0.90) ));
}
if (ui->radioAuto->isChecked())
{
diff --git a/src/formgen48.h b/src/formgen48.h
index b1dbd98..21e8a6d 100644
--- a/src/formgen48.h
+++ b/src/formgen48.h
@@ -12,6 +12,7 @@ class FormGen48;
}
class MainWindow;
+class SetSpinBox;
class FormGen48 : public QWidget
{
@@ -52,6 +53,7 @@ private slots:
private:
MainWindow *parent;
Ui::FormGen48 *ui;
+ SetSpinBox *spinMonumentArea;
// main condition for "auto" mode (updated when conditions change)
Condition cond;
diff --git a/src/formgen48.ui b/src/formgen48.ui
index fc9223e..1aab511 100644
--- a/src/formgen48.ui
+++ b/src/formgen48.ui
@@ -20,31 +20,13 @@
Form
-
- 0
-
-
- 0
-
-
- 0
-
-
+
0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
+
0
-
@@ -57,16 +39,7 @@
Auto/None
-
- 4
-
-
- 4
-
-
- 4
-
-
+
4
-
@@ -90,16 +63,7 @@
Quad-feature
-
- 4
-
-
- 4
-
-
- 4
-
-
+
4
-
@@ -171,20 +135,8 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
Quad-monument
-
-
- 4
-
-
- 4
-
-
- 4
-
-
- 4
-
-
-
+
+
-
Number of planar spawning spaces inside monuments that are within 128 blocks of a center position
@@ -195,19 +147,6 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
- -
-
-
- 12115
-
-
- 13028
-
-
- 13028
-
-
-
@@ -215,16 +154,7 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
Seed list
-
- 4
-
-
- 4
-
-
- 4
-
-
+
4
-
@@ -296,16 +226,7 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
QFrame::Plain
-
- 0
-
-
- 0
-
-
- 0
-
-
+
0
-
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 48926e8..0b88a72 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -84,11 +84,9 @@ MainWindow::MainWindow(QWidget *parent)
"The generator mode Auto is recommended for general use, which "
"automatically selects suitable options based on the conditions list."
"
"
- "The Quad-feature generator mode uses certain low bits to "
- "produce a list of candidates for structures in ideal proximity. This "
- "only works for structures with uniform distributions of region-size=32 "
- "and chunk-gap=8. For swamp huts this can be extended to include more "
- "constellations with all bounding boxes within 128 blocks."
+ "The Quad-feature mode produces candidates for "
+ "quad‑structures that have a uniform distribution of "
+ "region‑size=32 and chunk‑gap=8, such as swamp huts."
"
"
"A perfect Quad-monument structure constellation does not "
"actually exist, but some extremely rare structure seed bases get close, "
@@ -280,6 +278,7 @@ void MainWindow::saveSettings()
settings.setValue("mainwindow/pos", pos());
settings.setValue("mainwindow/prevdir", prevdir);
settings.setValue("config/restoreSession", config.restoreSession);
+ settings.setValue("config/showBBoxes", config.showBBoxes);
settings.setValue("config/autosaveCycle", config.autosaveCycle);
settings.setValue("config/smoothMotion", config.smoothMotion);
settings.setValue("config/uistyle", config.uistyle);
@@ -324,6 +323,7 @@ void MainWindow::loadSettings()
move(settings.value("mainwindow/pos", pos()).toPoint());
prevdir = settings.value("mainwindow/prevdir", pos()).toString();
config.smoothMotion = settings.value("config/smoothMotion", config.smoothMotion).toBool();
+ config.showBBoxes = settings.value("config/showBBoxes", config.showBBoxes).toBool();
config.restoreSession = settings.value("config/restoreSession", config.restoreSession).toBool();
config.autosaveCycle = settings.value("config/autosaveCycle", config.autosaveCycle).toInt();
config.uistyle = settings.value("config/uistyle", config.uistyle).toInt();
@@ -331,6 +331,7 @@ void MainWindow::loadSettings()
config.queueSize = settings.value("config/queueSize", config.queueSize).toInt();
config.maxMatching = settings.value("config/maxMatching", config.maxMatching).toInt();
+ ui->mapView->setShowBB(config.showBBoxes);
ui->mapView->setSmoothMotion(config.smoothMotion);
onStyleChanged(config.uistyle);
@@ -650,6 +651,7 @@ void MainWindow::on_actionPreferences_triggered()
{
Config oldConfig = config;
config = dialog->getSettings();
+ ui->mapView->setShowBB(config.showBBoxes);
ui->mapView->setSmoothMotion(config.smoothMotion);
if (oldConfig.uistyle != config.uistyle)
onStyleChanged(config.uistyle);
@@ -866,7 +868,7 @@ void MainWindow::on_buttonAnalysis_clicked()
QTreeWidgetItem* item_cat;
item_cat = new QTreeWidgetItem(tree);
- item_cat->setText(0, "Biomes");
+ item_cat->setText(0, "biomes");
item_cat->setData(1, Qt::DisplayRole, QVariant::fromValue(bcnt));
for (int id = 0; id < 256; id++)
@@ -922,7 +924,7 @@ void MainWindow::on_buttonAnalysis_clicked()
if (vp.variant)
{
if (stype == Village)
- item->setText(1, "Abandoned");
+ item->setText(1, "abandoned");
}
}
//tree->insertTopLevelItem(stype, item_cat);
@@ -934,7 +936,7 @@ void MainWindow::on_buttonAnalysis_clicked()
if (pos.x >= x1 && pos.x <= x2 && pos.z >= z1 && pos.z <= z2)
{
item_cat = new QTreeWidgetItem(tree);
- item_cat->setText(0, "Spawn");
+ item_cat->setText(0, "spawn");
item_cat->setData(1, Qt::DisplayRole, QVariant::fromValue(1));
QTreeWidgetItem* item = new QTreeWidgetItem(item_cat);
item->setData(0, Qt::UserRole, QVariant::fromValue(pos));
@@ -957,7 +959,7 @@ void MainWindow::on_buttonAnalysis_clicked()
if (!shp.empty())
{
item_cat = new QTreeWidgetItem(tree);
- item_cat->setText(0, "Stronghold");
+ item_cat->setText(0, "stronghold");
item_cat->setData(1, Qt::DisplayRole, QVariant::fromValue(shp.size()));
for (Pos pos : shp)
{
diff --git a/src/mapview.cpp b/src/mapview.cpp
index a6be426..f5902ac 100644
--- a/src/mapview.cpp
+++ b/src/mapview.cpp
@@ -96,13 +96,6 @@ void MapView::setSeed(WorldInfo wi, int dim)
update(2);
}
-void MapView::setShow(int stype, bool v)
-{
- sshow[stype] = v;
- settingsToWorld();
- update(2);
-}
-
void MapView::setView(qreal x, qreal z, qreal scale)
{
if (scale > 0)
@@ -115,6 +108,20 @@ void MapView::setView(qreal x, qreal z, qreal scale)
update(2);
}
+void MapView::setShow(int stype, bool v)
+{
+ sshow[stype] = v;
+ settingsToWorld();
+ update(2);
+}
+
+void MapView::setShowBB(bool show)
+{
+ showBB = show;
+ settingsToWorld();
+ update(2);
+}
+
void MapView::setSmoothMotion(bool smooth)
{
hasinertia = smooth;
@@ -126,6 +133,7 @@ void MapView::settingsToWorld()
return;
for (int s = 0; s < STRUCT_NUM; s++)
world->sshow[s] = sshow[s];
+ world->showBB = showBB;
}
qreal MapView::getX()
diff --git a/src/mapview.h b/src/mapview.h
index 3f01334..7cb888d 100644
--- a/src/mapview.h
+++ b/src/mapview.h
@@ -42,6 +42,7 @@ public:
bool getShow(int stype) { return stype >= 0 && stype < STRUCT_NUM ? sshow[stype] : false; }
void setShow(int stype, bool v);
+ void setShowBB(bool show);
void setSmoothMotion(bool smooth);
void timeout();
@@ -87,6 +88,7 @@ private:
int updatecounter;
bool sshow[STRUCT_NUM];
+ bool showBB;
bool hasinertia;
};
diff --git a/src/quad.cpp b/src/quad.cpp
index 0d8ae1f..f7a6520 100644
--- a/src/quad.cpp
+++ b/src/quad.cpp
@@ -409,8 +409,10 @@ QWorld::QWorld(WorldInfo wi, int dim)
, cachedbiomes()
, cachedstruct()
, cachesize()
+ , showBB()
, spawn()
, strongholds()
+ , qsinfo()
, isdel()
, slimeimg()
, slimex()
@@ -509,6 +511,7 @@ QWorld::~QWorld()
{
delete spawn;
delete strongholds;
+ delete qsinfo;
}
}
@@ -642,6 +645,15 @@ struct SpawnStronghold : public QRunnable
}
world->strongholds = shp;
+
+ std::vector *qsinfo = new std::vector;
+
+ if (!world->isdel)
+ findQuadStructs(Swamp_Hut, wi.mc, &g, wi.seed, qsinfo);
+ if (!world->isdel)
+ findQuadStructs(Monument, wi.mc, &g, wi.seed, qsinfo);
+
+ world->qsinfo = qsinfo;
}
};
@@ -738,6 +750,26 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
}
+ if (showBB && blocks2pix >= 1.0 && qsinfo && dim == 0)
+ {
+ for (QuadInfo qi : *qsinfo)
+ {
+ if (qi.typ == Swamp_Hut && !sshow[D_HUT])
+ continue;
+ if (qi.typ == Monument && !sshow[D_MONUMENT])
+ continue;
+
+ qreal x = vw/2.0 + (qi.afk.x - focusx) * blocks2pix;
+ qreal y = vh/2.0 + (qi.afk.z - focusz) * blocks2pix;
+ qreal r = 128.0 * blocks2pix;
+ painter.setPen(QPen(QColor(192, 0, 0, 160), 1));
+ painter.drawEllipse(QRectF(x-r, y-r, 2*r, 2*r));
+ r = 16;
+ painter.drawLine(QPointF(x-r,y), QPointF(x+r,y));
+ painter.drawLine(QPointF(x,y-r), QPointF(x,y+r));
+ }
+ }
+
for (int sopt = D_DESERT; sopt < D_SPAWN; sopt++)
{
Level& l = lvs[sopt];
@@ -759,23 +791,44 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
if (x < 0 || x >= vw || y < 0 || y >= vh)
continue;
- QPointF d = QPointF(x, y);
- QRectF r = icons[sopt].rect();
- if (sopt == D_VILLAGE)
+ if (showBB && blocks2pix > 1.0)
{
- if (vp.variant) {
- painter.drawPixmap(x-r.width()/2, y-r.height()/2, iconzvil);
- } else {
- frags.push_back(QPainter::PixmapFragment::create(d, r));
+ int sx = 0, sz = 0;
+ if (sopt == D_DESERT)
+ {
+ sx = 21; sz = 21;
+ }
+ else if (sopt == D_JUNGLE)
+ {
+ sx = 12; sz = 15;
+ }
+ else if (sopt == D_HUT)
+ {
+ sx = 7; sz = 9;
+ }
+ else if (sopt == D_MONUMENT)
+ {
+ x -= 29 * blocks2pix;
+ y -= 29 * blocks2pix;
+ sx = 58; sz = 58;
+ }
+
+ if (sx && sz)
+ { // draw bounding box and move icon to its center
+ qreal dx = sx * blocks2pix;
+ qreal dy = sz * blocks2pix;
+ painter.setPen(QPen(QColor(192, 0, 0, 160), 1));
+ painter.drawRect(QRect(x, y, dx, dy));
+ x += dx / 2;
+ y += dy / 2;
}
}
- else
- {
- frags.push_back(QPainter::PixmapFragment::create(d, r));
- }
+
+ QPointF d = QPointF(x, y);
if (seldo)
- {
+ { // check for structure selection
+ QRectF r = icons[sopt].rect();
r.moveCenter(d);
if (r.contains(selx, selz))
{
@@ -784,6 +837,23 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
selvar = vp.variant;
}
}
+ if (seltype != sopt || selpos.x != vp.p.x || selpos.z != vp.p.z)
+ { // draw unselected structures
+ QRectF r = icons[sopt].rect();
+ if (sopt == D_VILLAGE)
+ {
+ if (vp.variant) {
+ int ix = d.x()-r.width()/2, iy = d.y()-r.height()/2;
+ painter.drawPixmap(ix, iy, iconzvil);
+ } else {
+ frags.push_back(QPainter::PixmapFragment::create(d, r));
+ }
+ }
+ else
+ {
+ frags.push_back(QPainter::PixmapFragment::create(d, r));
+ }
+ }
}
}
@@ -857,10 +927,13 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
}
// start the spawn and stronghold worker thread if this is the first run
- if (spawn == NULL && (sshow[D_SPAWN] || sshow[D_STRONGHOLD]))
+ if (spawn == NULL)
{
- spawn = (Pos*) -1;
- QThreadPool::globalInstance()->start(new SpawnStronghold(this, wi));
+ if (sshow[D_SPAWN] || sshow[D_STRONGHOLD] || (showBB && blocks2pix >= 1.0))
+ {
+ spawn = (Pos*) -1;
+ QThreadPool::globalInstance()->start(new SpawnStronghold(this, wi));
+ }
}
if (seldo)
diff --git a/src/quad.h b/src/quad.h
index 3010d0d..464fd2d 100644
--- a/src/quad.h
+++ b/src/quad.h
@@ -2,6 +2,7 @@
#define QUAD_H
#include "settings.h"
+#include "search.h"
#include
#include
@@ -222,10 +223,13 @@ struct QWorld
unsigned int cachesize;
bool sshow[STRUCT_NUM];
+ bool showBB;
- // spawn and strongholds will be filled by a designated worker thread once results are done
+ // some features such as the world spawn and strongholds will be filled by
+ // a designated worker thread once results are done
QAtomicPointer spawn;
QAtomicPointer> strongholds;
+ QAtomicPointer> qsinfo;
// isdel is a flag for the worker thread to stop
std::atomic_bool isdel;
diff --git a/src/quadlistdialog.cpp b/src/quadlistdialog.cpp
index f53a24a..da18185 100644
--- a/src/quadlistdialog.cpp
+++ b/src/quadlistdialog.cpp
@@ -21,9 +21,10 @@ QuadListDialog::QuadListDialog(MainWindow *mainwindow)
QFont mono = QFont("Monospace", 9);
mono.setStyleHint(QFont::TypeWriter);
ui->listQuadStruct->setFont(mono);
- ui->listQuadStruct->setColumnWidth(0, 100);
+ ui->listQuadStruct->setColumnWidth(0, 120);
ui->listQuadStruct->setColumnWidth(1, 80);
ui->listQuadStruct->setColumnWidth(2, 160);
+ ui->listQuadStruct->setColumnWidth(3, 120);
loadSeed();
refresh();
@@ -89,120 +90,57 @@ void QuadListDialog::refresh()
LayerStack g;
setupGeneratorLargeBiomes(&g, wi.mc, wi.large);
- StructureConfig sconf;
- getStructureConfig_override(Swamp_Hut, wi.mc, &sconf);
+ std::vector qsinfo;
- const int maxq = 1000;
- Pos *qlist = new Pos[maxq];
- int r = 3e7 / 512;
- int qcnt;
+ findQuadStructs(Swamp_Hut, wi.mc, &g, wi.seed, &qsinfo);
+ findQuadStructs(Monument, wi.mc, &g, wi.seed, &qsinfo);
- qcnt = scanForQuads(
- sconf, 128, (wi.seed) & MASK48,
- low20QuadHutBarely, sizeof(low20QuadHutBarely) / sizeof(uint64_t), 20, sconf.salt,
- -r, -r, 2*r, 2*r, qlist, maxq);
-
- if (qcnt >= maxq)
- QMessageBox::warning(this, "Warning", "Quad-hut scanning buffer exhausted, results will be incomplete.");
-
- ui->listQuadStruct->setSortingEnabled(false);
int row = 0, qhn = 0, qmn = 0;
- for (int i = 0; i < qcnt; i++)
+ for (QuadInfo& qi : qsinfo)
{
- Pos qh[4];
- getStructurePos(sconf.structType, wi.mc, wi.seed, qlist[i].x+0, qlist[i].z+0, qh+0);
- getStructurePos(sconf.structType, wi.mc, wi.seed, qlist[i].x+0, qlist[i].z+1, qh+1);
- getStructurePos(sconf.structType, wi.mc, wi.seed, qlist[i].x+1, qlist[i].z+0, qh+2);
- getStructurePos(sconf.structType, wi.mc, wi.seed, qlist[i].x+1, qlist[i].z+1, qh+3);
- if (isViableStructurePos(sconf.structType, wi.mc, &g, wi.seed, qh[0].x, qh[0].z) &&
- isViableStructurePos(sconf.structType, wi.mc, &g, wi.seed, qh[1].x, qh[1].z) &&
- isViableStructurePos(sconf.structType, wi.mc, &g, wi.seed, qh[2].x, qh[2].z) &&
- isViableStructurePos(sconf.structType, wi.mc, &g, wi.seed, qh[3].x, qh[3].z))
+ const char *label;
+ if (qi.typ == Swamp_Hut)
{
- ui->listQuadStruct->insertRow(row);
- Pos afk;
- afk = getOptimalAfk(qh, 7,7,9, 0);
- float rad = isQuadBase(sconf, moveStructure(wi.seed, -qlist[i].x, -qlist[i].z), 128);
- int dist = (int) round(sqrt(afk.x * (qreal)afk.x + afk.z * (qreal)afk.z));
- QVariant var = QVariant::fromValue(afk);
-
- QTableWidgetItem* stritem = new QTableWidgetItem("Quad-Hut");
- stritem->setData(Qt::UserRole, var);
- ui->listQuadStruct->setItem(row, 0, stritem);
-
- QTableWidgetItem* distitem = new QTableWidgetItem();
- distitem->setData(Qt::UserRole, var);
- distitem->setData(Qt::DisplayRole, dist);
- ui->listQuadStruct->setItem(row, 1, distitem);
-
- QTableWidgetItem* afkitem = new QTableWidgetItem();
- afkitem->setData(Qt::UserRole, var);
- afkitem->setText(QString::asprintf("(%d,%d)", afk.x, afk.z));
- ui->listQuadStruct->setItem(row, 2, afkitem);
-
- QTableWidgetItem* raditem = new QTableWidgetItem();
- raditem->setData(Qt::UserRole, var);
- raditem->setText(QString::asprintf("%.1f", rad));
- ui->listQuadStruct->setItem(row, 3, raditem);
- row++;
+ label = "Quad-Hut";
+ qhn++;
}
- }
- qhn = row;
-
- if (wi.mc >= MC_1_8)
- {
- getStructureConfig_override(Monument, wi.mc, &sconf);
- qcnt = scanForQuads(
- sconf, 160, wi.seed & MASK48,
- g_qm_90, sizeof(g_qm_90) / sizeof(uint64_t), 48, sconf.salt,
- -r, -r, 2*r, 2*r, qlist, maxq);
-
- if (qcnt >= maxq)
- QMessageBox::warning(this, "Warning", "Quad-monument scanning buffer exhausted, results will be incomplete.");
-
- for (int i = 0; i < qcnt; i++)
+ else
{
- Pos qm[4];
- getStructurePos(sconf.structType, wi.mc, wi.seed, qlist[i].x+0, qlist[i].z+0, qm+0);
- getStructurePos(sconf.structType, wi.mc, wi.seed, qlist[i].x+0, qlist[i].z+1, qm+1);
- getStructurePos(sconf.structType, wi.mc, wi.seed, qlist[i].x+1, qlist[i].z+0, qm+2);
- getStructurePos(sconf.structType, wi.mc, wi.seed, qlist[i].x+1, qlist[i].z+1, qm+3);
- if (isViableStructurePos(sconf.structType, wi.mc, &g, wi.seed, qm[0].x, qm[0].z) &&
- isViableStructurePos(sconf.structType, wi.mc, &g, wi.seed, qm[1].x, qm[1].z) &&
- isViableStructurePos(sconf.structType, wi.mc, &g, wi.seed, qm[2].x, qm[2].z) &&
- isViableStructurePos(sconf.structType, wi.mc, &g, wi.seed, qm[3].x, qm[3].z))
- {
- ui->listQuadStruct->insertRow(row);
- Pos afk;
- afk = getOptimalAfk(qm, 58,23,58, 0);
- afk.x -= 29; afk.z -= 29; // monuments position is centered
- float rad = isQuadBase(sconf, moveStructure(wi.seed, -qlist[i].x, -qlist[i].z), 160);
- int dist = (int) round(sqrt(afk.x * (qreal)afk.x + afk.z * (qreal)afk.z));
- QVariant var = QVariant::fromValue(afk);
-
- QTableWidgetItem* stritem = new QTableWidgetItem("Quad-Monument");
- stritem->setData(Qt::UserRole, var);
- ui->listQuadStruct->setItem(row, 0, stritem);
-
- QTableWidgetItem* distitem = new QTableWidgetItem();
- distitem->setData(Qt::UserRole, var);
- distitem->setData(Qt::DisplayRole, dist);
- ui->listQuadStruct->setItem(row, 1, distitem);
-
- QTableWidgetItem* afkitem = new QTableWidgetItem();
- afkitem->setData(Qt::UserRole, var);
- afkitem->setText(QString::asprintf("(%d,%d)", afk.x, afk.z));
- ui->listQuadStruct->setItem(row, 2, afkitem);
-
- QTableWidgetItem* raditem = new QTableWidgetItem();
- raditem->setData(Qt::UserRole, var);
- raditem->setText(QString::asprintf("%.1f", rad));
- ui->listQuadStruct->setItem(row, 3, raditem);
- row++;
- }
+ label = "Quad-Monument";
+ qmn++;
}
+
+ QVariant var = QVariant::fromValue(qi.afk);
+ qreal dist = qi.afk.x*(qreal)qi.afk.x + qi.afk.z*(qreal)qi.afk.z;
+ dist = sqrt(dist);
+
+ ui->listQuadStruct->insertRow(row);
+
+ QTableWidgetItem* stritem = new QTableWidgetItem(label);
+ stritem->setData(Qt::UserRole, var);
+ ui->listQuadStruct->setItem(row, 0, stritem);
+
+ QTableWidgetItem* distitem = new QTableWidgetItem();
+ distitem->setData(Qt::UserRole, var);
+ distitem->setData(Qt::DisplayRole, (int)round(dist));
+ ui->listQuadStruct->setItem(row, 1, distitem);
+
+ QTableWidgetItem* afkitem = new QTableWidgetItem();
+ afkitem->setData(Qt::UserRole, var);
+ afkitem->setText(QString::asprintf("(%d,%d)", qi.afk.x, qi.afk.z));
+ ui->listQuadStruct->setItem(row, 2, afkitem);
+
+ QTableWidgetItem* raditem = new QTableWidgetItem();
+ raditem->setData(Qt::UserRole, var);
+ raditem->setText(QString::asprintf("%.1f", qi.rad));
+ ui->listQuadStruct->setItem(row, 3, raditem);
+
+ QTableWidgetItem* cntitem = new QTableWidgetItem();
+ cntitem->setData(Qt::UserRole, var);
+ cntitem->setText(QString::asprintf("%d", qi.spcnt));
+ ui->listQuadStruct->setItem(row, 4, cntitem);
+ row++;
}
- qmn = row - qhn;
ui->listQuadStruct->setSortingEnabled(true);
ui->listQuadStruct->sortByColumn(1, Qt::AscendingOrder);
@@ -215,8 +153,6 @@ void QuadListDialog::refresh()
ui->labelMsg->setText(QString::asprintf("World contains %d quad-hut%s.", qhn, qhn==1?"":"s"));
else if (qmn)
ui->labelMsg->setText(QString::asprintf("World contains %d quad-monument%s.", qmn, qmn==1?"":"s"));
-
- delete[] qlist;
}
void QuadListDialog::on_buttonGo_clicked()
diff --git a/src/quadlistdialog.ui b/src/quadlistdialog.ui
index 8721d02..2d28556 100644
--- a/src/quadlistdialog.ui
+++ b/src/quadlistdialog.ui
@@ -6,8 +6,8 @@
0
0
- 540
- 333
+ 700
+ 321
@@ -21,7 +21,7 @@
-
- Quad-Huts
+ Quad-Structures
-
@@ -43,6 +43,9 @@
QAbstractItemView::SelectRows
+
+ QAbstractItemView::ScrollPerPixel
+
true
@@ -57,7 +60,7 @@
Structure
- AlignLeading|AlignVCenter
+ AlignLeft|AlignVCenter
@@ -68,7 +71,7 @@
distance to origin
- AlignLeading|AlignVCenter
+ AlignLeft|AlignVCenter
@@ -79,18 +82,29 @@
optimal AFK location
- AlignLeading|AlignVCenter
+ AlignLeft|AlignVCenter
- Spawn range
+ Enclosing range
distance to furthest spawning space from optimal AFK position
- AlignLeading|AlignVCenter
+ AlignLeft|AlignVCenter
+
+
+
+
+ Spawn area
+
+
+ horizontal area in a 128 block range
+
+
+ AlignLeft|AlignVCenter
@@ -223,7 +237,8 @@
- ..
+
+
diff --git a/src/search.cpp b/src/search.cpp
index 5edf82a..fd1d916 100644
--- a/src/search.cpp
+++ b/src/search.cpp
@@ -61,7 +61,12 @@ static bool isInnerRingOk(int mc, uint64_t seed, int x1, int z1, int x2, int z2,
}
-int testCond(StructPos *spos, uint64_t seed, const Condition *cond, int mc, LayerStack *g, std::atomic_bool *abort)
+int
+testCond(
+ StructPos *spos, const Condition *cond,
+ int mc, LayerStack *g, uint64_t seed,
+ std::atomic_bool *abort
+ )
{
int x1, x2, z1, z2;
int rx1, rx2, rz1, rz2, rx, rz;
@@ -607,3 +612,94 @@ L_nether_end:
return 1;
}
+
+
+void findQuadStructs(
+ int styp, int mc, LayerStack *g, uint64_t seed,
+ std::vector *out
+ )
+{
+ StructureConfig sconf;
+ if (!getStructureConfig_override(styp, mc, &sconf))
+ return;
+
+ int qmax = 1000;
+ Pos *qlist = new Pos[qmax];
+ int r = 3e7 / 512;
+ int qcnt;
+
+ if (styp == Swamp_Hut)
+ {
+ qcnt = scanForQuads(
+ sconf, 128, seed & MASK48,
+ low20QuadHutBarely, sizeof(low20QuadHutBarely) / sizeof(uint64_t),
+ 20, sconf.salt,
+ -r, -r, 2*r, 2*r, qlist, qmax
+ );
+
+ for (int i = 0; i < qcnt; i++)
+ {
+ Pos qr = qlist[i];
+ Pos qs[4];
+ getStructurePos(styp, mc, seed, qr.x+0, qr.z+0, qs+0);
+ getStructurePos(styp, mc, seed, qr.x+0, qr.z+1, qs+1);
+ getStructurePos(styp, mc, seed, qr.x+1, qr.z+0, qs+2);
+ getStructurePos(styp, mc, seed, qr.x+1, qr.z+1, qs+3);
+ if (isViableStructurePos(styp, mc, g, seed, qs[0].x, qs[0].z) &&
+ isViableStructurePos(styp, mc, g, seed, qs[1].x, qs[1].z) &&
+ isViableStructurePos(styp, mc, g, seed, qs[2].x, qs[2].z) &&
+ isViableStructurePos(styp, mc, g, seed, qs[3].x, qs[3].z))
+ {
+ QuadInfo qinfo;
+ for (int j = 0; j < 4; j++)
+ qinfo.p[j] = qs[j];
+ qinfo.typ = styp;
+ qinfo.afk = getOptimalAfk(qs, 7,7,9, &qinfo.spcnt);
+ qinfo.rad = isQuadBase(sconf, moveStructure(seed,-qr.x,-qr.z), 160);
+ out->push_back(qinfo);
+ }
+ }
+ }
+ else if (styp == Monument)
+ {
+ qcnt = scanForQuads(
+ sconf, 160, seed & MASK48,
+ g_qm_90, sizeof(g_qm_90) / sizeof(uint64_t),
+ 48, sconf.salt,
+ -r, -r, 2*r, 2*r, qlist, qmax
+ );
+
+ for (int i = 0; i < qcnt; i++)
+ {
+ Pos qr = qlist[i];
+ Pos qs[4];
+ getStructurePos(styp, mc, seed, qr.x+0, qr.z+0, qs+0);
+ getStructurePos(styp, mc, seed, qr.x+0, qr.z+1, qs+1);
+ getStructurePos(styp, mc, seed, qr.x+1, qr.z+0, qs+2);
+ getStructurePos(styp, mc, seed, qr.x+1, qr.z+1, qs+3);
+ if (isViableStructurePos(styp, mc, g, seed, qs[0].x, qs[0].z) &&
+ isViableStructurePos(styp, mc, g, seed, qs[1].x, qs[1].z) &&
+ isViableStructurePos(styp, mc, g, seed, qs[2].x, qs[2].z) &&
+ isViableStructurePos(styp, mc, g, seed, qs[3].x, qs[3].z))
+ {
+ QuadInfo qinfo;
+ for (int j = 0; j < 4; j++)
+ qinfo.p[j] = qs[j];
+ qinfo.typ = styp;
+ qinfo.afk = getOptimalAfk(qs, 58,0/*23*/,58, &qinfo.spcnt);
+ qinfo.afk.x -= 29;
+ qinfo.afk.z -= 29;
+ qinfo.rad = isQuadBase(sconf, moveStructure(seed,-qr.x,-qr.z), 160);
+ out->push_back(qinfo);
+ }
+ }
+ }
+
+ delete[] qlist;
+}
+
+
+
+
+
+
diff --git a/src/search.h b/src/search.h
index 6335c3c..10d1f03 100644
--- a/src/search.h
+++ b/src/search.h
@@ -4,6 +4,7 @@
#include "cubiomes/finders.h"
#include
+#include
#define PRECOMPUTE48_BUFSIZ ((int64_t)1 << 30)
@@ -442,8 +443,22 @@ struct StructPos
int cx, cz; // effective center position
};
+int testCond(
+ StructPos *spos, const Condition *cond,
+ int mc, LayerStack *g, uint64_t seed, std::atomic_bool *abort);
-int testCond(StructPos *spos, uint64_t seed, const Condition *cond, int mc, LayerStack *g, std::atomic_bool *abort);
+struct QuadInfo
+{
+ Pos p[4]; // individual positions
+ Pos afk; // optimal afk position
+ int typ; // type of structure
+ int spcnt; // number of planar spawning spaces
+ float rad; // enclosing radius
+};
+
+void findQuadStructs(
+ int styp, int mc, LayerStack *g, uint64_t seed,
+ std::vector *out);
#endif // SEARCH_H
diff --git a/src/searchitem.cpp b/src/searchitem.cpp
index e2638ff..aad9f38 100644
--- a/src/searchitem.cpp
+++ b/src/searchitem.cpp
@@ -425,7 +425,7 @@ static bool isCandidate(uint64_t s48, int mc, const Condition *c, const Conditio
{
StructPos spos[100] = {};
for (; c != ce; c++)
- if (!testCond(spos, s48, c, mc, NULL, abort))
+ if (!testCond(spos, c, mc, NULL, s48, abort))
return false;
return true;
}
diff --git a/src/searchitem.h b/src/searchitem.h
index 1ba5514..eba8141 100644
--- a/src/searchitem.h
+++ b/src/searchitem.h
@@ -31,14 +31,14 @@ public:
if (s48check)
{
for (c = cond; c != ce; c++)
- if (!testCond(spos, seed, c, mc, NULL, abort))
+ if (!testCond(spos, c, mc, NULL, seed, abort))
return false;
}
for (c = cond; c != ce; c++)
{
if (g_filterinfo.list[c->type].cat == CAT_QUAD)
continue;
- if (!testCond(spos, seed, c, mc, g, abort))
+ if (!testCond(spos, c, mc, g, seed, abort))
return false;
}
return true;
diff --git a/src/seedtables.h b/src/seedtables.h
index d33baed..c0c0530 100644
--- a/src/seedtables.h
+++ b/src/seedtables.h
@@ -120,11 +120,16 @@ static const uint64_t g_qm_95[] = {
40643008242473ULL,
75345282835555ULL,
85241165147001ULL,
- 143737608964985ULL,
+ 117558666299491ULL,
+ 141849622061865ULL,
+ 157050661340383ULL,
+ 184103120915339ULL,
+ 197672678105184ULL,
201305970722015ULL,
- 206145729365528ULL,
220178926586908ULL,
+ 206145729365528ULL,
226043537443714ULL,
+ 143737608964985ULL,
};
@@ -169,6 +174,7 @@ static int qhutQual(int low20)
}
}
+
// returns for a >90% quadmonument the number of blocks, by area, in spawn range
__attribute__((const, used))
static int qmonumentQual(uint64_t s48)
@@ -224,24 +230,24 @@ static int qmonumentQual(uint64_t s48)
case 96363295408208ULL: return 12253;
case 96666172090448ULL: return 12470;
case 97326737469569ULL: return 12165;
- case 108818308997907ULL: return 12150;
- case 110070523643664ULL: return 12400;
- case 110929723321216ULL: return 12348;
- case 113209246256383ULL: return 12130;
- case 117558666299491ULL: return 12687;
- case 121197818285311ULL: return 12130;
- case 141209514904082ULL: return 12147;
- case 141849622061865ULL: return 12630;
- case 143737608964985ULL: return 12938;
- case 152637010423035ULL: return 12130;
- case 157050661340383ULL: return 12588;
- case 170156314248098ULL: return 12348;
- case 177801560427026ULL: return 12389;
- case 183906223213433ULL: return 12358;
- case 184103120915339ULL: return 12630;
- case 185417015970809ULL: return 12186;
- case 195760082985897ULL: return 12118;
- case 197672678105184ULL: return 12553;
+ case 108818308997907ULL: return 12609;
+ case 110070523643664ULL: return 12758;
+ case 110929723321216ULL: return 12780;
+ case 113209246256383ULL: return 12499;
+ case 117558666299491ULL: return 12948;
+ case 121197818285311ULL: return 12499;
+ case 141209514904082ULL: return 12583;
+ case 141849622061865ULL: return 12983;
+ case 143737608964985ULL: return 13188; // < best
+ case 152637010423035ULL: return 12499;
+ case 157050661340383ULL: return 12912;
+ case 170156314248098ULL: return 12780;
+ case 177801560427026ULL: return 12762;
+ case 183906223213433ULL: return 12748;
+ case 184103120915339ULL: return 12983;
+ case 185417015970809ULL: return 12632;
+ case 195760082985897ULL: return 12589;
+ case 197672678105184ULL: return 12895;
case 201305970722015ULL: return 12948;
case 206145729365528ULL: return 12796;
case 208212283032595ULL: return 12317;
@@ -257,7 +263,7 @@ static int qmonumentQual(uint64_t s48)
case 222407767385304ULL: return 12458;
case 222506989413161ULL: return 12632;
case 223366727763152ULL: return 12296;
- case 226043537443714ULL: return 13028; // best
+ case 226043537443714ULL: return 13028;
case 226089485745383ULL: return 12285;
case 226837069851090ULL: return 12305;
case 228023683672163ULL: return 12742;
diff --git a/src/settings.h b/src/settings.h
index 8b1220b..2c782cf 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -51,6 +51,7 @@ enum { STYLE_SYSTEM, STYLE_DARK };
struct Config
{
bool smoothMotion;
+ bool showBBoxes;
bool restoreSession;
int autosaveCycle;
int uistyle;
@@ -63,6 +64,7 @@ struct Config
void reset()
{
smoothMotion = true;
+ showBBoxes = true;
restoreSession = true;
autosaveCycle = 10;
uistyle = STYLE_SYSTEM;