Added some bounding boxes and quad structure fix

1) added bounding box outline to map view for some structures
2) added quad-structure indicators to map view
3) added spawn area to quad-structure dialog
4) fixed some incorrect values for quad-monument area
5) fixed end gateways for 1.17
This commit is contained in:
Cubitect 2021-07-21 22:07:16 +02:00
parent 9179eedb7c
commit 4805092912
19 changed files with 421 additions and 293 deletions

@ -1 +1 @@
Subproject commit 389910035a5483022e7d42e5f37bc0c9440efef0
Subproject commit e61f4f1ebf0bda93d16309ca45a216d632c23acc

View File

@ -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();

View File

@ -2,14 +2,6 @@
<ui version="4.0">
<class>ConfigDialog</class>
<widget class="QDialog" name="ConfigDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>411</width>
<height>252</height>
</rect>
</property>
<property name="windowTitle">
<string>Preferences</string>
</property>
@ -18,14 +10,14 @@
<normaloff>:/icons/map.png</normaloff>:/icons/map.png</iconset>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="8" column="0">
<item row="10" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Maximum number of matching seeds:</string>
</property>
</widget>
</item>
<item row="9" column="0" colspan="2">
<item row="11" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -35,7 +27,7 @@
</property>
</widget>
</item>
<item row="7" column="0">
<item row="9" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Size of search item queue:
@ -43,7 +35,7 @@
</property>
</widget>
</item>
<item row="6" column="0">
<item row="8" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Seeds per thread search item:</string>
@ -60,17 +52,10 @@
</property>
</widget>
</item>
<item row="7" column="1">
<item row="9" column="1">
<widget class="QLineEdit" name="lineQueueSize"/>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="checkRestore">
<property name="text">
<string>Restore previous session at launch</string>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="8" column="1">
<widget class="QComboBox" name="cboxItemSize">
<property name="iconSize">
<size>
@ -80,17 +65,17 @@
</property>
</widget>
</item>
<item row="8" column="1">
<item row="10" column="1">
<widget class="QLineEdit" name="lineMatching"/>
</item>
<item row="4" column="0">
<item row="6" column="0">
<widget class="QCheckBox" name="checkAutosave">
<property name="text">
<string>Autosave every:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="6" column="1">
<widget class="QSpinBox" name="spinAutosave">
<property name="suffix">
<string> min</string>
@ -106,14 +91,14 @@
</property>
</widget>
</item>
<item row="5" column="0">
<item row="7" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>GUI style:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="7" column="1">
<widget class="QComboBox" name="comboStyle">
<property name="iconSize">
<size>
@ -133,6 +118,20 @@
</item>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="checkBBoxes">
<property name="text">
<string>Outline known bounding boxes</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="checkRestore">
<property name="text">
<string>Restore previous session at launch</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources>

View File

@ -8,7 +8,48 @@
#include <QFileDialog>
#include <QFileInfo>
#include <QMessageBox>
#include <QSpinBox>
#include <QList>
#include <set>
class SetSpinBox : public QSpinBox
{
public:
SetSpinBox(QWidget *parent)
: QSpinBox(parent)
{
std::set<int> 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<int> 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())
{

View File

@ -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;

View File

@ -20,31 +20,13 @@
<string>Form</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0" colspan="2">
@ -57,16 +39,7 @@
<string>Auto/None</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>4</number>
</property>
<item row="0" column="0">
@ -90,16 +63,7 @@
<string>Quad-feature</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>4</number>
</property>
<item row="1" column="0">
@ -171,20 +135,8 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
<attribute name="title">
<string>Quad-monument</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item row="0" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="labelQM">
<property name="toolTip">
<string>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
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSpinBox" name="spinMonumentArea">
<property name="minimum">
<number>12115</number>
</property>
<property name="maximum">
<number>13028</number>
</property>
<property name="value">
<number>13028</number>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabList">
@ -215,16 +154,7 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
<string>Seed list</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>4</number>
</property>
<item row="0" column="0">
@ -296,16 +226,7 @@ Applies only to feature-structures of region-size = 32 and chunk-gap = 8, in par
<enum>QFrame::Plain</enum>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<property name="margin">
<number>0</number>
</property>
<item row="0" column="0">

View File

@ -84,11 +84,9 @@ MainWindow::MainWindow(QWidget *parent)
"The generator mode <b>Auto</b> is recommended for general use, which "
"automatically selects suitable options based on the conditions list."
"</p><p>"
"The <b>Quad-feature</b> 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 <b>Quad-feature</b> mode produces candidates for "
"quad&#8209;structures that have a uniform distribution of "
"region&#8209;size=32 and chunk&#8209;gap=8, such as swamp huts."
"</p><p>"
"A perfect <b>Quad-monument</b> 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)
{

View File

@ -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()

View File

@ -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;
};

View File

@ -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<QuadInfo> *qsinfo = new std::vector<QuadInfo>;
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)

View File

@ -2,6 +2,7 @@
#define QUAD_H
#include "settings.h"
#include "search.h"
#include <QRunnable>
#include <QImage>
@ -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<Pos> spawn;
QAtomicPointer<std::vector<Pos>> strongholds;
QAtomicPointer<std::vector<QuadInfo>> qsinfo;
// isdel is a flag for the worker thread to stop
std::atomic_bool isdel;

View File

@ -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<QuadInfo> 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()

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>540</width>
<height>333</height>
<width>700</width>
<height>321</height>
</rect>
</property>
<property name="windowTitle">
@ -21,7 +21,7 @@
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Quad-Huts</string>
<string>Quad-Structures</string>
</property>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0">
@ -43,6 +43,9 @@
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
@ -57,7 +60,7 @@
<string>Structure</string>
</property>
<property name="textAlignment">
<set>AlignLeading|AlignVCenter</set>
<set>AlignLeft|AlignVCenter</set>
</property>
</column>
<column>
@ -68,7 +71,7 @@
<string>distance to origin</string>
</property>
<property name="textAlignment">
<set>AlignLeading|AlignVCenter</set>
<set>AlignLeft|AlignVCenter</set>
</property>
</column>
<column>
@ -79,18 +82,29 @@
<string>optimal AFK location</string>
</property>
<property name="textAlignment">
<set>AlignLeading|AlignVCenter</set>
<set>AlignLeft|AlignVCenter</set>
</property>
</column>
<column>
<property name="text">
<string>Spawn range</string>
<string>Enclosing range</string>
</property>
<property name="toolTip">
<string>distance to furthest spawning space from optimal AFK position</string>
</property>
<property name="textAlignment">
<set>AlignLeading|AlignVCenter</set>
<set>AlignLeft|AlignVCenter</set>
</property>
</column>
<column>
<property name="text">
<string>Spawn area</string>
</property>
<property name="toolTip">
<string>horizontal area in a 128 block range</string>
</property>
<property name="textAlignment">
<set>AlignLeft|AlignVCenter</set>
</property>
</column>
</widget>
@ -223,7 +237,8 @@
</property>
<property name="icon">
<iconset theme="window-close">
<normaloff>.</normaloff>.</iconset>
<normaloff/>
</iconset>
</property>
</widget>
</item>

View File

@ -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<QuadInfo> *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;
}

View File

@ -4,6 +4,7 @@
#include "cubiomes/finders.h"
#include <atomic>
#include <vector>
#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<QuadInfo> *out);
#endif // SEARCH_H

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;