diff --git a/README.md b/README.md
index ceec1f5..a125112 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
Cubiomes Viewer provides a graphical interface for the efficient and flexible seed-finding utilities provided by [cubiomes](https://github.com/Cubitect/cubiomes) and a map viewer for the Minecraft biomes and structure generation.
-The tool is designed for high performance and is currently limited to overworld features for Minecraft 1.6 - 1.16.
+The tool is designed for high performance and is currently supports Minecraft Java Edition 1.6 - 1.17.
## Download
diff --git a/cubiomes b/cubiomes
index 6fda1ca..bfbd421 160000
--- a/cubiomes
+++ b/cubiomes
@@ -1 +1 @@
-Subproject commit 6fda1caff80f7e350e0f9bf8e770199d7ea9ccb2
+Subproject commit bfbd421ef5edf9d286dac250723fadbee4bc9265
diff --git a/icons.qrc b/icons.qrc
index e864de2..2383d47 100644
--- a/icons.qrc
+++ b/icons.qrc
@@ -57,5 +57,7 @@
icons/endcity.png
icons/bastion_d.png
icons/bastion.png
+ icons/gateway.png
+ icons/gateway_d.png
diff --git a/icons/gateway.png b/icons/gateway.png
new file mode 100644
index 0000000..486f081
Binary files /dev/null and b/icons/gateway.png differ
diff --git a/icons/gateway_d.png b/icons/gateway_d.png
new file mode 100644
index 0000000..c5fed70
Binary files /dev/null and b/icons/gateway_d.png differ
diff --git a/src/aboutdialog.h b/src/aboutdialog.h
index 30c4ec7..8ea7eb9 100644
--- a/src/aboutdialog.h
+++ b/src/aboutdialog.h
@@ -5,7 +5,7 @@
#define VERS_MAJOR 1
#define VERS_MINOR 8
-#define VERS_PATCH -1 // negative patch number designates a development version
+#define VERS_PATCH -2 // negative patch number designates a development version
// returns +1 if newer, -1 if older and 0 if equal
inline int cmpVers(int major, int minor, int patch)
diff --git a/src/cutil.h b/src/cutil.h
index d44c454..63ab79f 100644
--- a/src/cutil.h
+++ b/src/cutil.h
@@ -13,81 +13,40 @@ extern unsigned char biomeColors[256][3];
extern unsigned char tempsColors[256][3];
-inline const char* mc2str(int mc)
-{
- switch (mc)
- {
- case MC_1_6: return "1.6"; break;
- case MC_1_7: return "1.7"; break;
- case MC_1_8: return "1.8"; break;
- case MC_1_9: return "1.9"; break;
- case MC_1_10: return "1.10"; break;
- case MC_1_11: return "1.11"; break;
- case MC_1_12: return "1.12"; break;
- case MC_1_13: return "1.13"; break;
- case MC_1_14: return "1.14"; break;
- case MC_1_15: return "1.15"; break;
- case MC_1_16: return "1.16"; break;
- default: return NULL;
- }
-}
-
-inline int str2mc(const char *s)
-{
- if (!strcmp(s, "1.16")) return MC_1_16;
- if (!strcmp(s, "1.15")) return MC_1_15;
- if (!strcmp(s, "1.14")) return MC_1_14;
- if (!strcmp(s, "1.13")) return MC_1_13;
- if (!strcmp(s, "1.12")) return MC_1_12;
- if (!strcmp(s, "1.11")) return MC_1_11;
- if (!strcmp(s, "1.10")) return MC_1_10;
- if (!strcmp(s, "1.9")) return MC_1_9;
- if (!strcmp(s, "1.8")) return MC_1_8;
- if (!strcmp(s, "1.7")) return MC_1_7;
- if (!strcmp(s, "1.6")) return MC_1_6;
- return -1;
-}
-
inline const char* struct2str(int stype)
{
switch (stype)
{
- case Desert_Pyramid: return "Desert_Pyramid";
- case Jungle_Pyramid: return "Jungle_Pyramid";
- case Swamp_Hut: return "Swamp_Hut";
- case Igloo: return "Igloo";
- case Village: return "Village";
- case Ocean_Ruin: return "Ocean_Ruin";
- case Shipwreck: return "Shipwreck";
- case Monument: return "Monument";
- case Mansion: return "Mansion";
- case Outpost: return "Outpost";
- case Ruined_Portal: return "Ruined_Portal";
- case Treasure: return "Treasure";
- case Fortress: return "Fortress";
- case Bastion: return "Bastion";
- case End_City: return "End_City";
+ case Desert_Pyramid: return "desert_pyramid";
+ case Jungle_Pyramid: return "jungle_pyramid";
+ case Swamp_Hut: return "swamp_hut";
+ case Igloo: return "igloo";
+ case Village: return "village";
+ case Ocean_Ruin: return "ocean_ruin";
+ case Shipwreck: return "shipwreck";
+ case Monument: return "monument";
+ case Mansion: return "mansion";
+ case Outpost: return "outpost";
+ case Ruined_Portal: return "ruined_portal";
+ case Ruined_Portal_N: return "ruined_portal (nether)";
+ case Treasure: return "treasure";
+ case Fortress: return "fortress";
+ case Bastion: return "bastion";
+ case End_City: return "end_city";
+ case End_Gateway: return "end_gateway";
}
return "?";
}
-inline int structDim(int stype)
-{
- if (stype == Fortress || stype == Bastion)
- return -1;
- if (stype == End_City)
- return 1;
- return 0;
-}
// get a random 64-bit integer
-static inline int64_t getRnd64()
+static inline uint64_t getRnd64()
{
static QMutex mutex;
static std::random_device rd;
static std::mt19937_64 mt(rd());
static uint64_t x = (uint64_t) time(0);
- int64_t ret = 0;
+ uint64_t ret = 0;
mutex.lock();
if (rd.entropy())
{
@@ -102,14 +61,14 @@ static inline int64_t getRnd64()
x ^= x >> 32;
x *= c;
x ^= x >> 32;
- ret = (int64_t) x;
+ ret = x;
}
mutex.unlock();
return ret;
}
enum { S_TEXT, S_NUMERIC, S_RANDOM };
-inline int str2seed(const QString &str, int64_t *out)
+inline int str2seed(const QString &str, uint64_t *out)
{
if (str.isEmpty())
{
@@ -118,7 +77,7 @@ inline int str2seed(const QString &str, int64_t *out)
}
bool ok = false;
- *out = str.toLongLong(&ok);
+ *out = (uint64_t) str.toLongLong(&ok);
if (ok)
{
return S_NUMERIC;
diff --git a/src/formconditions.cpp b/src/formconditions.cpp
index 9e11c86..176ad21 100644
--- a/src/formconditions.cpp
+++ b/src/formconditions.cpp
@@ -158,7 +158,7 @@ void FormConditions::editCondition(QListWidgetItem *item)
{
if (!(item->flags() & Qt::ItemIsSelectable))
return;
- int mc = MC_1_16;
+ int mc = MC_NEWEST;
parent->getSeed(&mc, 0);
FilterDialog *dialog = new FilterDialog(this, mc, item, (Condition*)item->data(Qt::UserRole).data());
QObject::connect(dialog, SIGNAL(setCond(QListWidgetItem*,Condition)), this, SLOT(addItemCondition(QListWidgetItem*,Condition)), Qt::QueuedConnection);
diff --git a/src/formgen48.cpp b/src/formgen48.cpp
index 9d9de4c..3ea5c4c 100644
--- a/src/formgen48.cpp
+++ b/src/formgen48.cpp
@@ -57,8 +57,8 @@ bool FormGen48::setList48(QString path, bool quiet)
slist48path = path;
parent->prevdir = finfo.absolutePath();
- int64_t *l = NULL;
- int64_t len;
+ uint64_t *l = NULL;
+ uint64_t len;
QByteArray ba = path.toLatin1();
l = loadSavedSeeds(ba.data(), &len);
if (l && len > 0)
@@ -175,7 +175,7 @@ uint64_t FormGen48::estimateSeedCnt()
uint64_t w = gen48.x2 - gen48.x1 + 1;
uint64_t h = gen48.z2 - gen48.z1 + 1;
uint64_t n = w*h * cnt;
- if (cnt > 0 && n < PRECOMPUTE48_BUFSIZ*sizeof(int64_t) && n / cnt == w*h)
+ if (cnt > 0 && n < PRECOMPUTE48_BUFSIZ*sizeof(uint64_t) && n / cnt == w*h)
cnt = n;
else
cnt = MASK48+1;
@@ -242,10 +242,20 @@ void FormGen48::updateAutoUi()
}
if (ui->radioAuto->isChecked())
{
- ui->lineEditX1->setText(QString::number(cond.x1));
- ui->lineEditZ1->setText(QString::number(cond.z1));
- ui->lineEditX2->setText(QString::number(cond.x2));
- ui->lineEditZ2->setText(QString::number(cond.z2));
+ if (ui->tabWidget->currentIndex() == GEN48_LIST)
+ {
+ ui->lineEditX1->setText("0");
+ ui->lineEditZ1->setText("0");
+ ui->lineEditX2->setText("0");
+ ui->lineEditZ2->setText("0");
+ }
+ else
+ {
+ ui->lineEditX1->setText(QString::number(cond.x1));
+ ui->lineEditZ1->setText(QString::number(cond.z1));
+ ui->lineEditX2->setText(QString::number(cond.x2));
+ ui->lineEditZ2->setText(QString::number(cond.z2));
+ }
}
}
emit changed();
@@ -272,7 +282,7 @@ void FormGen48::updateMode()
{
int mode = ui->tabWidget->currentIndex();
- if (mode == GEN48_AUTO)
+ //if (mode == GEN48_AUTO)
{
updateAutoUi();
}
diff --git a/src/formgen48.h b/src/formgen48.h
index 60b1df0..b1dbd98 100644
--- a/src/formgen48.h
+++ b/src/formgen48.h
@@ -25,7 +25,7 @@ public:
Gen48Settings getSettings(bool resolveauto = false);
bool setList48(QString path, bool quiet);
- const std::vector& getList48() { return slist48; }
+ const std::vector& getList48() { return slist48; }
uint64_t estimateSeedCnt();
void updateCount();
@@ -57,7 +57,7 @@ private:
Condition cond;
QString slist48path;
- std::vector slist48;
+ std::vector slist48;
};
#endif // FORMGEN48_H
diff --git a/src/formsearchcontrol.cpp b/src/formsearchcontrol.cpp
index 1cc4eae..ba269ba 100644
--- a/src/formsearchcontrol.cpp
+++ b/src/formsearchcontrol.cpp
@@ -20,6 +20,8 @@ FormSearchControl::FormSearchControl(MainWindow *parent)
, stimer()
, slist64path()
, slist64()
+ , smin(0)
+ , smax(~(uint64_t)0)
{
ui->setupUi(this);
@@ -51,13 +53,13 @@ FormSearchControl::~FormSearchControl()
delete ui;
}
-QVector FormSearchControl::getResults()
+QVector FormSearchControl::getResults()
{
int n = ui->listResults->rowCount();
- QVector results = QVector(n);
+ QVector results = QVector(n);
for (int i = 0; i < n; i++)
{
- results[i] = ui->listResults->item(i, 0)->data(Qt::UserRole).toLongLong();
+ results[i] = ui->listResults->item(i, 0)->data(Qt::UserRole).toULongLong();
}
return results;
}
@@ -65,24 +67,26 @@ QVector FormSearchControl::getResults()
SearchConfig FormSearchControl::getSearchConfig()
{
SearchConfig s;
- s.searchmode = ui->comboSearchType->currentIndex();
+ s.searchtype = ui->comboSearchType->currentIndex();
s.threads = ui->spinThreads->value();
s.slist64path = slist64path;
s.startseed = ui->lineStart->text().toLongLong();
s.stoponres = ui->checkStop->isChecked();
+ s.smin = smin;
+ s.smax = smax;
return s;
}
bool FormSearchControl::setSearchConfig(SearchConfig s, bool quiet)
{
bool ok = true;
- if (s.searchmode >= SEARCH_INC && s.searchmode <= SEARCH_LIST)
- ui->comboSearchType->setCurrentIndex(s.searchmode);
+ if (s.searchtype >= SEARCH_INC && s.searchtype <= SEARCH_LIST)
+ ui->comboSearchType->setCurrentIndex(s.searchtype);
else
ok = false;
ui->spinThreads->setValue(s.threads);
- ui->lineStart->setText(QString::asprintf("%" PRId64, s.startseed));
+ ui->lineStart->setText(QString::asprintf("%" PRId64, (int64_t)s.startseed));
ui->checkStop->setChecked(s.stoponres);
return ok && setList64(s.slist64path, quiet);
@@ -100,8 +104,8 @@ bool FormSearchControl::setList64(QString path, bool quiet)
QFileInfo finfo(path);
parent->prevdir = finfo.absolutePath();
slist64path = finfo.fileName();
- int64_t *l = NULL;
- int64_t len;
+ uint64_t *l = NULL;
+ uint64_t len;
QByteArray ba = path.toLatin1();
l = loadSavedSeeds(ba.data(), &len);
if (l && len > 0)
@@ -165,21 +169,22 @@ void FormSearchControl::on_buttonStart_clicked()
{
if (ui->buttonStart->isChecked())
{
- int mc = MC_1_16;
+ int mc = MC_NEWEST;
parent->getSeed(&mc, NULL);
const Config& config = parent->config;
const QVector& condvec = parent->formCond->getConditions();
- int64_t sstart = (int64_t) ui->lineStart->text().toLongLong();
- int searchtype = ui->comboSearchType->currentIndex();
- int threads = ui->spinThreads->value();
+ SearchConfig sc = getSearchConfig();
int ok = true;
+ sc.smin = 1L << 47;
+ sc.smax = 2L << 48;
+
if (condvec.empty())
{
QMessageBox::warning(this, "Warning", "Please define some constraints using the \"Add\" button.", QMessageBox::Ok);
ok = false;
}
- if (searchtype == SEARCH_LIST && slist64.empty())
+ if (sc.searchtype == SEARCH_LIST && slist64.empty())
{
QMessageBox::warning(this, "Warning", "No seed list file selected.", QMessageBox::Ok);
ok = false;
@@ -194,19 +199,19 @@ void FormSearchControl::on_buttonStart_clicked()
{
Gen48Settings gen48 = parent->formGen48->getSettings(true);
// the search can either use a full list or a 48-bit list
- if (searchtype == SEARCH_LIST)
+ if (sc.searchtype == SEARCH_LIST)
slist = slist64;
else if (gen48.mode == GEN48_LIST)
slist = parent->formGen48->getList48();
else
slist.clear();
- ok = sthread.set(parent, searchtype, threads, gen48, slist, sstart, mc, condvec, config.seedsPerItem, config.queueSize);
+ ok = sthread.set(parent, mc, sc, gen48, config, slist, condvec);
}
if (ok)
{
- ui->lineStart->setText(QString::asprintf("%" PRId64, sstart));
+ ui->lineStart->setText(QString::asprintf("%" PRId64, (int64_t)sc.startseed));
ui->buttonStart->setText("Abort search");
ui->buttonStart->setIcon(QIcon(":/icons/cancel.png"));
sthread.start();
@@ -244,7 +249,7 @@ void FormSearchControl::on_listResults_itemSelectionChanged()
int row = ui->listResults->currentRow();
if (row >= 0 && row < ui->listResults->rowCount())
{
- int64_t s = ui->listResults->item(row, 0)->data(Qt::UserRole).toLongLong();
+ uint64_t s = ui->listResults->item(row, 0)->data(Qt::UserRole).toULongLong();
emit selectedSeedChanged(s);
}
}
@@ -303,7 +308,7 @@ int FormSearchControl::pasteList(bool dummy)
{
QClipboard *clipboard = QGuiApplication::clipboard();
QStringList slist = clipboard->text().split('\n');
- QVector seeds;
+ QVector seeds;
for (QString s : slist)
{
@@ -311,7 +316,7 @@ int FormSearchControl::pasteList(bool dummy)
if (s.isEmpty())
continue;
bool ok = true;
- int64_t seed = s.toLongLong(&ok);
+ uint64_t seed = (uint64_t) s.toLongLong(&ok);
if (!ok)
return 0;
seeds.push_back(seed);
@@ -325,7 +330,7 @@ int FormSearchControl::pasteList(bool dummy)
}
-int FormSearchControl::searchResultsAdd(QVector seeds, bool countonly)
+int FormSearchControl::searchResultsAdd(QVector seeds, bool countonly)
{
const Config& config = parent->config;
int ns = ui->listResults->rowCount();
@@ -337,16 +342,16 @@ int FormSearchControl::searchResultsAdd(QVector seeds, bool countonly)
if (seeds.empty())
return 0;
- QSet current;
+ QSet current;
current.reserve(n + seeds.size());
for (int i = 0; i < n; i++)
{
- int64_t seed = ui->listResults->item(i, 0)->data(Qt::UserRole).toLongLong();
+ uint64_t seed = ui->listResults->item(i, 0)->data(Qt::UserRole).toULongLong();
current.insert(seed);
}
ui->listResults->setSortingEnabled(false);
- for (int64_t s : seeds)
+ for (uint64_t s : seeds)
{
if (current.contains(s))
continue;
@@ -361,7 +366,7 @@ int FormSearchControl::searchResultsAdd(QVector seeds, bool countonly)
s48item->setData(Qt::UserRole, QVariant::fromValue(s));
s48item->setText(QString::asprintf("%012llx|%04x",
(qulonglong)(s & MASK48), (uint)(s >> 48) & 0xffff));
- seeditem->setData(Qt::DisplayRole, QVariant::fromValue(s));
+ seeditem->setData(Qt::DisplayRole, QVariant::fromValue((int64_t)s));
ui->listResults->insertRow(n);
ui->listResults->setItem(n, 0, s48item);
ui->listResults->setItem(n, 1, seeditem);
@@ -455,7 +460,7 @@ void FormSearchControl::copyResults()
int n = ui->listResults->rowCount();
for (int i = 0; i < n; i++)
{
- int64_t seed = ui->listResults->item(i, 0)->data(Qt::UserRole).toLongLong();
+ uint64_t seed = ui->listResults->item(i, 0)->data(Qt::UserRole).toULongLong();
text += QString::asprintf("%" PRId64 "\n", seed);
}
diff --git a/src/formsearchcontrol.h b/src/formsearchcontrol.h
index 0adf8e8..fc3c80a 100644
--- a/src/formsearchcontrol.h
+++ b/src/formsearchcontrol.h
@@ -23,7 +23,7 @@ public:
explicit FormSearchControl(MainWindow *parent);
~FormSearchControl();
- QVector getResults();
+ QVector getResults();
SearchConfig getSearchConfig();
bool setSearchConfig(SearchConfig s, bool quiet);
@@ -35,7 +35,7 @@ public:
void setSearchMode(int mode);
signals:
- void selectedSeedChanged(int64_t seed);
+ void selectedSeedChanged(uint64_t seed);
void searchStatusChanged(bool running);
void resultsAdded(int cnt);
@@ -53,7 +53,7 @@ public slots:
void pasteResults();
int pasteList(bool dummy);
- int searchResultsAdd(QVector seeds, bool countonly);
+ int searchResultsAdd(QVector seeds, bool countonly);
void searchProgressReset();
void searchProgress(uint64_t last, uint64_t end, int64_t seed);
void searchFinish();
@@ -69,10 +69,13 @@ private:
// the seed list option is not stored in a widget but is loaded with the "..." button
QString slist64path;
- std::vector slist64;
+ std::vector slist64;
// buffer for seed candidates while search is running
- std::vector slist;
+ std::vector slist;
+
+ // min and max seeds values
+ uint64_t smin, smax;
};
#endif // FORMSEARCHCONTROL_H
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 6f1669b..34d28ae 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -149,6 +149,7 @@ MainWindow::MainWindow(QWidget *parent)
addMapAction(D_BASTION, "bastion", "Show bastions");
ui->toolBar->addSeparator();
addMapAction(D_ENDCITY, "endcity", "Show end cities");
+ addMapAction(D_GATEWAY, "gateway", "Show end gateways");
saction[D_GRID]->setChecked(true);
@@ -159,7 +160,7 @@ MainWindow::MainWindow(QWidget *parent)
qRegisterMetaType< int64_t >("int64_t");
qRegisterMetaType< uint64_t >("uint64_t");
- qRegisterMetaType< QVector >("QVector");
+ qRegisterMetaType< QVector >("QVector");
qRegisterMetaType< Config >("Config");
QIntValidator *intval = new QIntValidator(this);
@@ -183,7 +184,7 @@ MainWindow::~MainWindow()
delete ui;
}
-QAction *MainWindow::addMapAction(int stype, const char *iconpath, const char *tip)
+QAction *MainWindow::addMapAction(int sopt, const char *iconpath, const char *tip)
{
QIcon icon;
QString inam = QString(":icons/") + iconpath;
@@ -192,10 +193,10 @@ QAction *MainWindow::addMapAction(int stype, const char *iconpath, const char *t
QAction *action = new QAction(icon, tip, this);
action->setCheckable(true);
ui->toolBar->addAction(action);
- if (stype >= 0)
+ if (sopt >= 0)
{
- action->connect(action, &QAction::toggled, [=](bool state){ this->onActionMapToggled(stype, state); });
- saction[stype] = action;
+ action->connect(action, &QAction::toggled, [=](bool state){ this->onActionMapToggled(sopt, state); });
+ saction[sopt] = action;
}
return action;
}
@@ -206,7 +207,7 @@ MapView* MainWindow::getMapView()
return ui->mapView;
}
-bool MainWindow::getSeed(int *mc, int64_t *seed, bool applyrand)
+bool MainWindow::getSeed(int *mc, uint64_t *seed, bool applyrand)
{
bool ok = true;
if (mc)
@@ -215,7 +216,7 @@ bool MainWindow::getSeed(int *mc, int64_t *seed, bool applyrand)
*mc = str2mc(mcs.c_str());
if (*mc < 0)
{
- *mc = MC_1_16;
+ *mc = MC_NEWEST;
qDebug() << "Unknown MC version: " << *mc;
ok = false;
}
@@ -225,13 +226,13 @@ bool MainWindow::getSeed(int *mc, int64_t *seed, bool applyrand)
{
int v = str2seed(ui->seedEdit->text(), seed);
if (applyrand && v == S_RANDOM)
- ui->seedEdit->setText(QString::asprintf("%" PRId64, *seed));
+ ui->seedEdit->setText(QString::asprintf("%" PRId64, (int64_t)*seed));
}
return ok;
}
-bool MainWindow::setSeed(int mc, int64_t seed, int dim)
+bool MainWindow::setSeed(int mc, uint64_t seed, int dim)
{
const char *mcstr = mc2str(mc);
if (!mcstr)
@@ -244,7 +245,7 @@ bool MainWindow::setSeed(int mc, int64_t seed, int dim)
dim = getDim();
ui->comboBoxMC->setCurrentText(mcstr);
- ui->seedEdit->setText(QString::asprintf("%" PRId64, seed));
+ ui->seedEdit->setText(QString::asprintf("%" PRId64, (int64_t)seed));
ui->mapView->setSeed(mc, seed, dim);
return true;
}
@@ -273,8 +274,8 @@ void MainWindow::saveSettings()
settings.setValue("config/queueSize", config.queueSize);
settings.setValue("config/maxMatching", config.maxMatching);
- int mc = MC_1_16;
- int64_t seed = 0;
+ int mc = MC_NEWEST;
+ uint64_t seed = 0;
getSeed(&mc, &seed, false);
settings.setValue("map/mc", mc);
settings.setValue("map/seed", (qlonglong)seed);
@@ -319,11 +320,11 @@ void MainWindow::loadSettings()
else
dimactions[0]->setChecked(true);
- int mc = MC_1_16;
- int64_t seed = 0;
+ int mc = MC_NEWEST;
+ uint64_t seed = 0;
getSeed(&mc, &seed, true);
mc = settings.value("map/mc", mc).toInt();
- seed = settings.value("map/seed", QVariant::fromValue(seed)).toLongLong();
+ seed = (uint64_t) settings.value("map/seed", QVariant::fromValue((qlonglong)seed)).toLongLong();
setSeed(mc, seed);
qreal x = ui->mapView->getX();
@@ -334,13 +335,14 @@ void MainWindow::loadSettings()
z = settings.value("map/z", z).toDouble();
scale = settings.value("map/scale", scale).toDouble();
- for (int stype = 0; stype < STRUCT_NUM; stype++)
+ for (int sopt = 0; sopt < STRUCT_NUM; sopt++)
{
- bool show = ui->mapView->getShow(stype);
- QString sopt = QString("map/show_") + mapopt2str(stype);
- show = settings.value(sopt, show).toBool();
- saction[stype]->setChecked(show);
- ui->mapView->setShow(stype, show);
+ bool show = ui->mapView->getShow(sopt);
+ QString soptstr = QString("map/show_") + mapopt2str(sopt);
+ show = settings.value(soptstr, show).toBool();
+ if (saction[sopt])
+ saction[sopt]->setChecked(show);
+ ui->mapView->setShow(sopt, show);
}
mapGoto(x, z, scale);
@@ -375,9 +377,9 @@ bool MainWindow::saveProgress(QString fnam, bool quiet)
SearchConfig searchconf = formControl->getSearchConfig();
Gen48Settings gen48 = formGen48->getSettings(false);
QVector condvec = formCond->getConditions();
- QVector results = formControl->getResults();
+ QVector results = formControl->getResults();
- int mc = MC_1_16;
+ int mc = MC_NEWEST;
getSeed(&mc, 0);
QTextStream stream(&file);
@@ -386,7 +388,7 @@ bool MainWindow::saveProgress(QString fnam, bool quiet)
// MC version of the session should take priority over the one in the settings
stream << "#MC: " << mc2str(mc) << "\n";
- stream << "#Search: " << searchconf.searchmode << "\n";
+ stream << "#Search: " << searchconf.searchtype << "\n";
if (!searchconf.slist64path.isEmpty())
stream << "#List64: " << searchconf.slist64path.replace("\n", "") << "\n";
stream << "#Progress: " << searchconf.startseed << "\n";
@@ -413,8 +415,8 @@ bool MainWindow::saveProgress(QString fnam, bool quiet)
for (Condition &c : condvec)
stream << "#Cond: " << QByteArray((const char*) &c, sizeof(Condition)).toHex() << "\n";
- for (int64_t s : results)
- stream << QString::asprintf("%" PRId64 "\n", s);
+ for (uint64_t s : results)
+ stream << QString::asprintf("%" PRId64 "\n", (int64_t)s);
return true;
}
@@ -434,12 +436,12 @@ bool MainWindow::loadProgress(QString fnam, bool quiet)
SearchConfig searchconf = formControl->getSearchConfig();
Gen48Settings gen48 = formGen48->getSettings(false);
QVector condvec;
- QVector seeds;
+ QVector seeds;
char buf[4096];
int tmp;
- int mc = MC_1_16;
- int64_t seed;
+ int mc = MC_NEWEST;
+ uint64_t seed;
getSeed(&mc, &seed, true);
QTextStream stream(&file);
@@ -462,7 +464,7 @@ bool MainWindow::loadProgress(QString fnam, bool quiet)
if (line.startsWith("#Time:")) continue;
else if (sscanf(p, "#MC: %8[^\n]", buf) == 1) { mc = str2mc(buf); if (mc < 0) return false; }
// SearchConfig
- else if (sscanf(p, "#Search: %d", &searchconf.searchmode) == 1) {}
+ else if (sscanf(p, "#Search: %d", &searchconf.searchtype) == 1) {}
else if (sscanf(p, "#Progress: %" PRId64, &searchconf.startseed) == 1) {}
else if (sscanf(p, "#Threads: %d", &searchconf.threads) == 1) {}
else if (sscanf(p, "#ResStop: %d", &tmp) == 1) { searchconf.stoponres = tmp; }
@@ -492,8 +494,8 @@ bool MainWindow::loadProgress(QString fnam, bool quiet)
}
else
{
- int64_t s;
- if (sscanf(line.toLatin1().data(), "%" PRId64, &s) == 1)
+ uint64_t s;
+ if (sscanf(line.toLatin1().data(), "%" PRId64, (int64_t*)&s) == 1)
seeds.push_back(s);
else return false;
}
@@ -521,7 +523,7 @@ bool MainWindow::loadProgress(QString fnam, bool quiet)
void MainWindow::updateMapSeed()
{
int mc;
- int64_t seed;
+ uint64_t seed;
if (getSeed(&mc, &seed))
setSeed(mc, seed);
}
@@ -563,7 +565,7 @@ void MainWindow::on_seedEdit_editingFinished()
void MainWindow::on_seedEdit_textChanged(const QString &a)
{
- int64_t s;
+ uint64_t s;
int v = str2seed(a, &s);
switch (v)
{
@@ -645,7 +647,7 @@ void MainWindow::on_actionScan_seed_for_Quad_Huts_triggered()
void MainWindow::on_actionOpen_shadow_seed_triggered()
{
int mc;
- int64_t seed;
+ uint64_t seed;
if (getSeed(&mc, &seed))
{
setSeed(mc, getShadow(seed));
@@ -670,10 +672,10 @@ void MainWindow::on_actionPaste_triggered()
void MainWindow::on_actionAddShadow_triggered()
{
- QVector results = formControl->getResults();
- QVector shadows;
+ QVector results = formControl->getResults();
+ QVector shadows;
shadows.reserve(results.size());
- for (int64_t s : results)
+ for (uint64_t s : results)
shadows.push_back( getShadow(s) );
formControl->searchResultsAdd(shadows, false);
}
@@ -745,7 +747,7 @@ void MainWindow::on_buttonAnalysis_clicked()
warning("Warning", "Invalid area for analysis");
return;
}
- if ((int64_t)(x2 - x1) * (int64_t)(z2 - z1) > 100000000LL)
+ if ((uint64_t)(x2 - x1) * (uint64_t)(z2 - z1) > 100000000LL)
{
QString msg = QString::asprintf(
"Area for analysis is very large (%d, %d).\n"
@@ -759,7 +761,7 @@ void MainWindow::on_buttonAnalysis_clicked()
bool everything = ui->radioEverything->isChecked();
int mc;
- int64_t seed;
+ uint64_t seed;
if (!getSeed(&mc, &seed))
return;
@@ -833,21 +835,29 @@ void MainWindow::on_buttonAnalysis_clicked()
item->setData(1, Qt::DisplayRole, QVariant::fromValue(cnt));
}
- tree->insertTopLevelItem(0, item_cat);
+ //tree->insertTopLevelItem(0, item_cat);
std::vector st;
for (int sopt = D_DESERT; sopt < D_SPAWN; sopt++)
{
- if (!everything && !getMapView()->getShow(sopt))
- continue;
+ int sdim = 0;
+ if (sopt == D_FORTESS || sopt == D_BASTION || sopt == D_PORTALN)
+ sdim = -1;
+ if (sopt == D_ENDCITY || sopt == D_GATEWAY)
+ sdim = 1;
+ if (!everything)
+ {
+ if (!getMapView()->getShow(sopt))
+ continue;
+ if (sdim != dim)
+ continue;
+ }
int stype = mapopt2stype(sopt);
- if (dim != structDim(stype))
- continue;
st.clear();
StructureConfig sconf;
if (!getStructureConfig_override(stype, mc, &sconf))
continue;
- getStructs(&st, sconf, mc, seed, x1, z1, x2, z2);
+ getStructs(&st, sconf, mc, sdim, seed, x1, z1, x2, z2);
if (st.empty())
continue;
@@ -868,7 +878,7 @@ void MainWindow::on_buttonAnalysis_clicked()
item->setText(1, "Abandoned");
}
}
- tree->insertTopLevelItem(stype, item_cat);
+ //tree->insertTopLevelItem(stype, item_cat);
}
if (everything || (dim == 0 && getMapView()->getShow(D_SPAWN)))
@@ -976,9 +986,11 @@ void MainWindow::onAutosaveTimeout()
}
}
-void MainWindow::onActionMapToggled(int stype, bool show)
+void MainWindow::onActionMapToggled(int sopt, bool show)
{
- ui->mapView->setShow(stype, show);
+ if (sopt == D_PORTAL) // overworld porals should also control nether
+ ui->mapView->setShow(D_PORTALN, show);
+ ui->mapView->setShow(sopt, show);
}
void MainWindow::onConditionsChanged()
@@ -993,9 +1005,9 @@ void MainWindow::onGen48Changed()
formControl->searchProgressReset();
}
-void MainWindow::onSelectedSeedChanged(int64_t seed)
+void MainWindow::onSelectedSeedChanged(uint64_t seed)
{
- ui->seedEdit->setText(QString::asprintf("%" PRId64, seed));
+ ui->seedEdit->setText(QString::asprintf("%" PRId64, (int64_t)seed));
on_seedEdit_editingFinished();
}
diff --git a/src/mainwindow.h b/src/mainwindow.h
index c5efabb..373aa02 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -43,10 +43,10 @@ public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
- QAction *addMapAction(int stype, const char *iconpath, const char *tip);
+ QAction *addMapAction(int sopt, const char *iconpath, const char *tip);
- bool getSeed(int *mc, int64_t *seed, bool applyrand = true);
- bool setSeed(int mc, int64_t seed, int dim = INT_MAX);
+ bool getSeed(int *mc, uint64_t *seed, bool applyrand = true);
+ bool setSeed(int mc, uint64_t seed, int dim = INT_MAX);
int getDim();
MapView *getMapView();
@@ -95,10 +95,10 @@ private slots:
// internal events
void onAutosaveTimeout();
- void onActionMapToggled(int stype, bool a);
+ void onActionMapToggled(int sopt, bool a);
void onConditionsChanged();
void onGen48Changed();
- void onSelectedSeedChanged(int64_t seed);
+ void onSelectedSeedChanged(uint64_t seed);
void onSearchStatusChanged(bool running);
void onStyleChanged(int style);
void copyCoord();
diff --git a/src/mainwindow.ui b/src/mainwindow.ui
index 6a7ae15..821f6f3 100644
--- a/src/mainwindow.ui
+++ b/src/mainwindow.ui
@@ -26,16 +26,7 @@
-
- 0
-
-
- 0
-
-
- 0
-
-
+
0
-
@@ -88,6 +79,11 @@
Minecraft version
+
-
+
+ 1.17
+
+
-
1.16
@@ -163,16 +159,7 @@
Search
-
- 0
-
-
- 0
-
-
- 0
-
-
+
0
-
@@ -218,8 +205,8 @@ QToolButton {
0
0
- 1232
- 699
+ 1233
+ 705
@@ -518,16 +505,7 @@ QSplitter {
QFrame::Raised
-
- 0
-
-
- 0
-
-
- 0
-
-
+
0
-
@@ -594,7 +572,7 @@ QToolButton:checked {
0
0
1280
- 22
+ 23
- AlignLeading|AlignVCenter
+ AlignLeft|AlignVCenter
@@ -68,7 +68,7 @@
distance to origin
- AlignLeading|AlignVCenter
+ AlignLeft|AlignVCenter
@@ -79,7 +79,7 @@
optimal AFK location
- AlignLeading|AlignVCenter
+ AlignLeft|AlignVCenter
@@ -90,7 +90,7 @@
distance to furthest spawning space from optimal AFK position
- AlignLeading|AlignVCenter
+ AlignLeft|AlignVCenter
@@ -122,6 +122,11 @@
Minecraft version
+ -
+
+ 1.17
+
+
-
1.16
@@ -212,7 +217,8 @@
- ..
+
+
diff --git a/src/search.cpp b/src/search.cpp
index 062284f..255c2fb 100644
--- a/src/search.cpp
+++ b/src/search.cpp
@@ -39,7 +39,7 @@ static bool intersectRectLine(double rx1, double rz1, double rx2, double rz2, do
return false;
}
-static bool isInnerRingOk(int mc, int64_t seed, int x1, int z1, int x2, int z2, int r1, int r2)
+static bool isInnerRingOk(int mc, uint64_t seed, int x1, int z1, int x2, int z2, int r1, int r2)
{
StrongholdIter sh;
Pos p = initFirstStronghold(&sh, mc, seed);
@@ -61,7 +61,7 @@ static bool isInnerRingOk(int mc, int64_t seed, int x1, int z1, int x2, int z2,
}
-int testCond(StructPos *spos, int64_t seed, const Condition *cond, int mc, LayerStack *g, std::atomic_bool *abort)
+int testCond(StructPos *spos, uint64_t seed, const Condition *cond, int mc, LayerStack *g, std::atomic_bool *abort)
{
int x1, x2, z1, z2;
int rx1, rx2, rz1, rz2, rx, rz;
@@ -105,7 +105,7 @@ int testCond(StructPos *spos, int64_t seed, const Condition *cond, int mc, Layer
}
if (scanForQuads(
sconf, 128, (seed) & MASK48, low20QuadHutBarely,
- sizeof(low20QuadHutBarely) / sizeof(int64_t), 20, sconf.salt,
+ sizeof(low20QuadHutBarely) / sizeof(uint64_t), 20, sconf.salt,
rx1, rz1, rx2 - rx1 + 1, rz2 - rz1 + 1, &pc, 1) >= 1)
{
rx = pc.x; rz = pc.z;
@@ -146,7 +146,7 @@ L_qm_any:
}
if (scanForQuads(
sconf, 160, (seed) & MASK48, g_qm_90,
- sizeof(g_qm_90) / sizeof(int64_t), 48,
+ sizeof(g_qm_90) / sizeof(uint64_t), 48,
0, // 0 for salt offset as g_qm_90 are not protobases
rx1, rz1, rx2 - rx1 + 1, rz2 - rz1 + 1, &pc, 1) >= 1)
{
@@ -180,11 +180,13 @@ L_qm_any:
case F_SHIPWRECK:
case F_TREASURE:
case F_PORTAL:
+ case F_PORTALN:
case F_FORTRESS:
case F_BASTION:
case F_ENDCITY:
+ case F_GATEWAY:
x1 = cond->x1;
z1 = cond->z1;
@@ -236,29 +238,31 @@ L_qm_any:
continue;
if (pc.x >= x1 && pc.x <= x2 && pc.z >= z1 && pc.z <= z2)
{
- if (g)
+ if (finfo.dim == 0 && g)
{
- if (finfo.dim == 0 && !isViableStructurePos(sconf.structType, mc, g, seed, pc.x, pc.z))
+ if (!isViableStructurePos(sconf.structType, mc, g, seed, pc.x, pc.z))
continue;
- if (finfo.dim == -1)
+ }
+ // TODO: add another search pass?
+ // (the g!=0 requirement for nether/end is artificial)
+ if (finfo.dim == -1 && g)
+ {
+ NetherNoise nn;
+ if (!isViableNetherStructurePos(sconf.structType, mc, &nn, seed, pc.x, pc.z))
+ continue;
+ }
+ if (finfo.dim == +1 && g)
+ {
+ EndNoise en;
+ if (!isViableEndStructurePos(sconf.structType, mc, &en, seed, pc.x, pc.z))
+ continue;
+ if (sconf.structType == End_City)
{
- NetherNoise nn;
- if (!isViableNetherStructurePos(sconf.structType, mc, &nn, seed, pc.x, pc.z))
+ SurfaceNoise sn; // TODO: store for reuse?
+ initSurfaceNoiseEnd(&sn, seed);
+ if (!isViableEndCityTerrain(&en, &sn, pc.x, pc.z))
continue;
}
- if (finfo.dim == +1)
- {
- EndNoise en;
- if (!isViableEndStructurePos(sconf.structType, mc, &en, seed, pc.x, pc.z))
- continue;
- if (sconf.structType == End_City)
- {
- SurfaceNoise sn; // TODO: store for reuse?
- initSurfaceNoiseEnd(&sn, seed);
- if (!isViableEndCityTerrain(&en, &sn, pc.x, pc.z))
- continue;
- }
- }
}
xt += pc.x;
diff --git a/src/search.h b/src/search.h
index 8e67722..01f8ae1 100644
--- a/src/search.h
+++ b/src/search.h
@@ -77,6 +77,8 @@ enum
F_BIOME_END_4,
F_BIOME_END_16,
F_BIOME_END_64,
+ F_PORTALN,
+ F_GATEWAY,
// new filters should be added here at the end to keep some downwards compatibility
FILTER_MAX,
};
@@ -222,21 +224,21 @@ static const struct FilterList
":icons/nether.png",
"Nether biome filter 1:4",
"Nether biomes with normal noise sampling at scale 1:4. (height: y = 0) "
- "(Nether and End biomes only depend on the lower 48-bits of the seed.)"
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
};
list[F_BIOME_NETHER_16] = FilterInfo{
CAT_NETHER, 1, 1, 0, 0, 16, 0, MC_1_16, -1,
":icons/nether.png",
"Nether biome filter 1:16",
"Nether biomes, but only sampled at scale 1:16. (height: y = 0) "
- "(Nether and End biomes only depend on the lower 48-bits of the seed.)"
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
};
list[F_BIOME_NETHER_64] = FilterInfo{
CAT_NETHER, 1, 1, 0, 0, 64, 0, MC_1_16, -1,
":icons/nether.png",
"Nether biome filter 1:64",
"Nether biomes, but only sampled at scale 1:64, (height: y = 0) "
- "(Nether and End biomes only depend on the lower 48-bits of the seed.)"
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
};
list[F_BIOME_END_1] = FilterInfo{
@@ -250,21 +252,21 @@ static const struct FilterList
":icons/the_end.png",
"End biome filter 1:4",
"End biomes sampled at scale 1:4. Note this is just a simple upscale of 1:16. "
- "(Nether and End biomes only depend on the lower 48-bits of the seed.)"
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
};
list[F_BIOME_END_16] = FilterInfo{
CAT_END, 1, 1, 0, 0, 16, 0, MC_1_9, +1,
":icons/the_end.png",
"End biome filter 1:16",
"End biomes with normal sampling at scale 1:16. "
- "(Nether and End biomes only depend on the lower 48-bits of the seed.)"
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
};
list[F_BIOME_END_64] = FilterInfo{
CAT_END, 1, 1, 0, 0, 64, 0, MC_1_9, +1,
":icons/the_end.png",
"End biome filter 1:64",
"End biomes with lossy sampling at scale 1:64. "
- "(Nether and End biomes only depend on the lower 48-bits of the seed.)"
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
};
list[F_SLIME] = FilterInfo{
@@ -372,25 +374,41 @@ static const struct FilterList
""
};
+ list[F_PORTALN] = FilterInfo{
+ CAT_STRUCT, 1, 1, 0, Ruined_Portal_N, 1, 1, MC_1_16, -1,
+ ":icons/portal.png",
+ "Ruined portal (nether)",
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
+ };
+
list[F_FORTRESS] = FilterInfo{
CAT_STRUCT, 1, 1, 0, Fortress, 1, 1, MC_1_0, -1,
":icons/fortress.png",
"Nether fortress",
- ""
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
};
list[F_BASTION] = FilterInfo{
CAT_STRUCT, 1, 1, 0, Bastion, 1, 1, MC_1_16, -1,
":icons/bastion.png",
"Bastion remnant",
- ""
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
};
list[F_ENDCITY] = FilterInfo{
CAT_STRUCT, 1, 1, 0, End_City, 1, 1, MC_1_9, +1,
":icons/endcity.png",
"End city",
- ""
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
+ };
+
+ list[F_GATEWAY] = FilterInfo{
+ CAT_STRUCT, 1, 1, 0, End_Gateway, 1, 1, MC_1_13, +1,
+ ":icons/gateway.png",
+ "End gateway",
+ "Scattered end gateway return portals, not including those "
+ "generated when defeating the dragon. "
+ "(The Nether and End depend only on the lower 48-bits of the seed.)"
};
}
}
@@ -417,7 +435,7 @@ struct StructPos
};
-int testCond(StructPos *spos, int64_t seed, const Condition *cond, int mc, LayerStack *g, std::atomic_bool *abort);
+int testCond(StructPos *spos, uint64_t seed, const Condition *cond, int mc, LayerStack *g, std::atomic_bool *abort);
#endif // SEARCH_H
diff --git a/src/searchitem.cpp b/src/searchitem.cpp
index 85d1eb2..3a8f0fe 100644
--- a/src/searchitem.cpp
+++ b/src/searchitem.cpp
@@ -23,12 +23,12 @@ void SearchItem::run()
LayerStack g;
setupGenerator(&g, mc);
StructPos spos[100] = {};
- QVector matches;
+ QVector matches;
if (searchtype == SEARCH_LIST)
{ // seed = slist[..]
- int64_t ie = idx+scnt < len ? idx+scnt : len;
- for (int64_t i = idx; i < ie; i++)
+ uint64_t ie = idx+scnt < len ? idx+scnt : len;
+ for (uint64_t i = idx; i < ie; i++)
{
seed = slist[i];
if (testSeed(spos, seed, &g, true))
@@ -41,8 +41,8 @@ void SearchItem::run()
{
if (slist)
{ // seed = (high << 48) | slist[..]
- int64_t high = (sstart >> 48) & 0xffff;
- int64_t lowidx = idx;
+ uint64_t high = (sstart >> 48) & 0xffff;
+ uint64_t lowidx = idx;
for (int i = 0; i < scnt; i++)
{
@@ -70,7 +70,7 @@ void SearchItem::run()
if (testSeed(spos, seed, &g, true))
matches.push_back(seed);
- if (seed == ~(int64_t)0)
+ if (seed == ~(uint64_t)0)
{
isdone = true;
break;
@@ -90,8 +90,8 @@ void SearchItem::run()
break;
}
- int64_t high = (sstart >> 48) & 0xffff;
- int64_t low;
+ uint64_t high = (sstart >> 48) & 0xffff;
+ uint64_t low;
if (slist)
low = slist[idx];
else
@@ -127,38 +127,40 @@ void SearchItem::run()
void SearchItemGenerator::init(
- QObject *mainwin, int mc, const Condition *cond, int ccnt,
- Gen48Settings gen48, const std::vector& seedlist,
- int itemsize, int searchtype, int64_t sstart)
+ QObject *mainwin, int mc,
+ const SearchConfig& sc, const Gen48Settings& gen48, const Config& config,
+ const std::vector& slist, const QVector& cv)
{
this->mainwin = mainwin;
- this->searchtype = searchtype;
+ this->searchtype = sc.searchtype;
this->mc = mc;
- this->cond = cond;
- this->ccnt = ccnt;
+ this->condvec = cv;
this->itemid = 0;
- this->itemsiz = itemsize;
- this->slist = seedlist;
+ this->itemsiz = config.seedsPerItem;
+ this->slist = slist;
this->gen48 = gen48;
this->idx = 0;
this->scnt = ~(uint64_t)0;
- this->seed = sstart;
+ this->seed = sc.startseed;
+ this->idxmin = 0;
+ this->smin = sc.smin;
+ this->smax = sc.smax;
this->isdone = false;
}
-static int check(int64_t s48, void *data)
+static int check(uint64_t s48, void *data)
{
(void) data;
const StructureConfig sconf = {};
return isQuadBaseFeature24(sconf, s48, 7+1, 7+1, 9+1) != 0;
}
-static void genQHBases(QObject *qtobj, int qual, int64_t salt, std::vector& list48)
+static void genQHBases(QObject *qtobj, int qual, uint64_t salt, std::vector& list48)
{
const char *lbstr = NULL;
- const int64_t *lbset = NULL;
- int64_t lbcnt = 0;
+ const uint64_t *lbset = NULL;
+ uint64_t lbcnt = 0;
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
if (path.isEmpty())
path = "protobases";
@@ -169,22 +171,22 @@ static void genQHBases(QObject *qtobj, int qual, int64_t salt, std::vector& slist,
- Gen48Settings gen48, int64_t bufmax)
+bool applyTranspose(std::vector& slist,
+ const Gen48Settings& gen48, uint64_t bufmax)
{
- std::vector list48;
+ std::vector list48;
int x = gen48.x1;
int z = gen48.z1;
@@ -246,7 +248,7 @@ bool applyTranspose(std::vector& slist,
int h = gen48.z2 - z + 1;
// does the set of candidates for this condition fit in memory?
- if ((int64_t)slist.size() * (int64_t)sizeof(int64_t) * w*h >= bufmax)
+ if ((uint64_t)slist.size() * sizeof(int64_t) * w*h >= bufmax)
return false;
try {
@@ -255,10 +257,10 @@ bool applyTranspose(std::vector& slist,
return false;
}
- int64_t *p = list48.data();
+ uint64_t *p = list48.data();
for (int j = 0; j < h; j++)
for (int i = 0; i < w; i++)
- for (int64_t b : slist)
+ for (uint64_t b : slist)
*p++ = moveStructure(b, x+i, z+j);
std::sort(list48.begin(), list48.end());
@@ -270,13 +272,13 @@ bool applyTranspose(std::vector& slist,
void SearchItemGenerator::presearch()
{
- int64_t sstart = seed;
+ uint64_t sstart = seed;
if (searchtype != SEARCH_LIST)
{
if (gen48.mode == GEN48_QH)
{
- int64_t salt = 0;
+ uint64_t salt = 0;
if (gen48.qual == IDEAL_SALTED)
salt = gen48.salt;
else
@@ -290,11 +292,11 @@ void SearchItemGenerator::presearch()
}
else if (gen48.mode == GEN48_QM)
{
- const int64_t *qb = g_qm_90;
- int64_t qn = sizeof(g_qm_90) / sizeof(int64_t);
+ const uint64_t *qb = g_qm_90;
+ uint64_t qn = sizeof(g_qm_90) / sizeof(uint64_t);
slist.clear();
slist.reserve(qn);
- for (int64_t i = 0; i < qn; i++)
+ for (uint64_t i = 0; i < qn; i++)
if (qmonumentQual(qb[i]) >= gen48.qmarea)
slist.push_back(qb[i]);
}
@@ -302,8 +304,8 @@ void SearchItemGenerator::presearch()
{
if (gen48.listsalt)
{
- for (auto& s : slist)
- s += gen48.listsalt;
+ for (uint64_t& rs : slist)
+ rs += gen48.listsalt;
}
}
@@ -326,24 +328,40 @@ void SearchItemGenerator::presearch()
{
if (!slist.empty())
{
+ seed = sstart;
+ if (seed < smin)
+ seed = smin;
scnt = 0x10000 * slist.size();
- int64_t high = (sstart >> 48) & 0xffff;
+ uint64_t high = (seed >> 48) & 0xffff;
for (idx = 0; idx < slist.size(); idx++)
- if (slist[idx] >= (sstart & MASK48))
+ if (slist[idx] >= (seed & MASK48))
break;
if (idx == slist.size())
{
- if (++high >= 0x10000)
+ if (high++ >= (smax >> 48))
isdone = true;
idx = 0;
}
seed = (high << 48) | slist[idx];
+
+ for (idxmin = 0; idxmin < slist.size(); idxmin++)
+ if (slist[idxmin] >= (smin & MASK48))
+ break;
+ for (scnt = 0; scnt < slist.size(); scnt++)
+ if (slist[scnt] >= (smax & MASK48))
+ break;
+ high = ((smax >> 48) - (smin >> 48)) & 0xffff;
+ scnt += high * slist.size() - idxmin;
}
else
{
- scnt = ~(uint64_t)0;
+ scnt = smax - smin;
seed = sstart;
+ if (seed < smin)
+ seed = smin;
}
+ if (seed > smax)
+ isdone = true;
}
if (searchtype == SEARCH_BLOCKS)
@@ -377,9 +395,14 @@ void SearchItemGenerator::getProgress(uint64_t *prog, uint64_t *end)
if (searchtype == SEARCH_INC)
{
if (!slist.empty())
- *prog = ((seed >> 48) & 0xffff) * slist.size() + idx;
+ {
+ uint64_t h = ((seed >> 48) - (smin >> 48)) & 0xffff;
+ *prog = h * slist.size() + idx - idxmin;
+ }
else
- *prog = (uint64_t) seed;
+ {
+ *prog = seed - smin;
+ }
}
if (searchtype == SEARCH_BLOCKS)
@@ -395,7 +418,7 @@ void SearchItemGenerator::getProgress(uint64_t *prog, uint64_t *end)
// does the 48-bit seed meet the conditions c..ce?
-static bool isCandidate(int64_t s48, int mc, const Condition *c, const Condition *ce, std::atomic_bool *abort)
+static bool isCandidate(uint64_t s48, int mc, const Condition *c, const Condition *ce, std::atomic_bool *abort)
{
StructPos spos[100] = {};
for (; c != ce; c++)
@@ -413,8 +436,8 @@ SearchItem *SearchItemGenerator::requestItem()
item->searchtype = searchtype;
item->mc = mc;
- item->cond = cond;
- item->ccnt = ccnt;
+ item->cond = condvec.data();
+ item->ccnt = condvec.size();
item->itemid = itemid++;
item->slist = slist.empty() ? NULL : slist.data();
item->len = slist.size();
@@ -436,28 +459,31 @@ SearchItem *SearchItemGenerator::requestItem()
{
if (!slist.empty())
{
- int64_t high = (seed >> 48) & 0xffff;
+ uint64_t high = (seed >> 48) & 0xffff;
idx += itemsiz;
high += idx / slist.size();
idx %= slist.size();
seed = (high << 48) | slist[idx];
- if (high >= 0x10000)
+ if (high > (smax >> 48))
isdone = true;
}
else
{
- unsigned long long int s;
- if (__builtin_uaddll_overflow(seed, itemsiz, &s))
- isdone = true;
- seed = (int64_t)s;
+ // seed += itemsize; with overflow detection
+ uint64_t s = seed + itemsiz;
+ if (s < seed)
+ isdone = true; // overflow
+ seed = s;
}
+ if (seed > smax)
+ isdone = true;
}
if (searchtype == SEARCH_BLOCKS)
{
if (!slist.empty())
{
- int64_t high = (seed >> 48) & 0xffff;
+ uint64_t high = (seed >> 48) & 0xffff;
high += itemsiz;
if (high >= 0x10000)
{
@@ -471,8 +497,8 @@ SearchItem *SearchItemGenerator::requestItem()
}
else
{
- int64_t high = (seed >> 48) & 0xffff;
- int64_t low = seed & MASK48;
+ uint64_t high = (seed >> 48) & 0xffff;
+ uint64_t low = seed & MASK48;
high += itemsiz;
if (high >= 0x10000)
{
@@ -481,11 +507,12 @@ SearchItem *SearchItemGenerator::requestItem()
low++;
unsigned long long ts = __rdtsc() + (1ULL << 27);
-
- /// === search for next candidate ===
+ const Condition *c = item->cond;
+ const Condition *ce = item->cond+item->ccnt;
+ /// === search for next candiditem->condate ===
for (; low <= MASK48; low++)
{
- if (isCandidate(low, mc, cond, cond+ccnt, abort))
+ if (isCandidate(low, mc, c, ce, abort))
break;
if (__rdtsc() > ts)
{
diff --git a/src/searchitem.h b/src/searchitem.h
index 2d8715f..1f3c5c0 100644
--- a/src/searchitem.h
+++ b/src/searchitem.h
@@ -25,7 +25,7 @@ public:
virtual void run();
- inline bool testSeed(StructPos *spos, int64_t seed, LayerStack *g, bool s48check)
+ inline bool testSeed(StructPos *spos, uint64_t seed, LayerStack *g, bool s48check)
{
const Condition *c, *ce = cond + ccnt;
if (s48check)
@@ -45,8 +45,8 @@ public:
}
signals:
- int results(QVector seeds, bool countonly);
- void itemDone(uint64_t itemid, int64_t seed, bool isdone);
+ int results(QVector seeds, bool countonly);
+ void itemDone(uint64_t itemid, uint64_t seed, bool isdone);
void canceled(uint64_t itemid);
public:
@@ -55,12 +55,12 @@ public:
const Condition * cond;
int ccnt;
uint64_t itemid; // item identifier
- const int64_t * slist; // candidate list
- int64_t len; // number of candidates
- int64_t idx; // current index in candidate buffer
- int64_t sstart; // starting seed
+ const uint64_t * slist; // candidate list
+ uint64_t len; // number of candidates
+ uint64_t idx; // current index in candidate buffer
+ uint64_t sstart; // starting seed
int scnt; // number of seeds to process in this item
- int64_t seed; // (out) current seed while processing
+ uint64_t seed; // (out) current seed while processing
bool isdone; // (out) has the final seed been reached
std::atomic_bool * abort;
@@ -72,9 +72,9 @@ public:
struct SearchItemGenerator
{
void init(
- QObject *mainwin, int mc, const Condition *cond, int ccnt,
- Gen48Settings gen48, const std::vector& seedlist,
- int itemsize, int searchtype, int64_t sstart);
+ QObject *mainwin, int mc,
+ const SearchConfig& sc, const Gen48Settings& gen48, const Config& config,
+ const std::vector& slist, const QVector& cv);
void presearch();
@@ -84,15 +84,17 @@ struct SearchItemGenerator
QObject * mainwin;
int searchtype;
int mc;
- const Condition * cond;
- int ccnt;
+ QVector condvec;
uint64_t itemid; // item incrementor
int itemsiz; // number of seeds per search item
Gen48Settings gen48; // 48-bit generator settings
- std::vector slist; // candidate list
+ std::vector slist; // candidate list
uint64_t idx; // index within candidate list
uint64_t scnt; // size of search space
- int64_t seed; // current seed (next to be processed)
+ uint64_t seed; // current seed (next to be processed)
+ uint64_t idxmin; // idx of smin
+ uint64_t smin;
+ uint64_t smax;
bool isdone;
std::atomic_bool * abort;
};
diff --git a/src/searchthread.cpp b/src/searchthread.cpp
index 16d7a8c..05dfcaa 100644
--- a/src/searchthread.cpp
+++ b/src/searchthread.cpp
@@ -22,9 +22,15 @@ SearchThread::SearchThread(FormSearchControl *parent)
itemgen.abort = &abort;
}
-bool SearchThread::set(QObject *mainwin, int type, int threads, Gen48Settings gen48,
- std::vector& slist, int64_t sstart, int mc,
- const QVector& cv, int itemsize, int queuesize)
+bool SearchThread::set(
+ QObject *mainwin, int mc,
+ const SearchConfig& sc, const Gen48Settings& gen48, const Config& config,
+ std::vector& slist, const QVector& cv)
+ /*
+ QObject *mainwin, int type, int threads, Gen48Settings gen48,
+ std::vector& slist, uint64_t smin, uint64_t smax,
+ uint64_t sstart, int mc, const QVector& cv,
+ int itemsize, int queuesize)*/
{
char refbuf[100] = {};
@@ -87,10 +93,10 @@ bool SearchThread::set(QObject *mainwin, int type, int threads, Gen48Settings ge
}
}
- condvec = cv;
- itemgen.init(mainwin, mc, condvec.data(), condvec.size(), gen48, slist, itemsize, type, sstart);
- pool.setMaxThreadCount(threads);
- recieved.resize(queuesize);
+ itemgen.init(mainwin, mc, sc, gen48, config, slist, cv);
+
+ pool.setMaxThreadCount(sc.threads);
+ recieved.resize(config.queueSize);
lastid = itemgen.itemid;
reqstop = false;
abort = false;
@@ -107,7 +113,7 @@ void SearchThread::run()
itemgen.getProgress(&prog, &end);
emit progress(prog, end, itemgen.seed);
- for (int idx = 0; idx < recieved.size(); idx++)
+ for (int64_t idx = 0; idx < recieved.size(); idx++)
{
recieved[idx].valid = false;
startNextItem();
@@ -133,7 +139,7 @@ SearchItem *SearchThread::startNextItem()
}
-void SearchThread::onItemDone(uint64_t itemid, int64_t seed, bool isdone)
+void SearchThread::onItemDone(uint64_t itemid, uint64_t seed, bool isdone)
{
--activecnt;
@@ -142,8 +148,8 @@ void SearchThread::onItemDone(uint64_t itemid, int64_t seed, bool isdone)
{
if (itemid == lastid)
{
- int64_t len = recieved.size();
- int idx;
+ uint64_t len = recieved.size();
+ uint64_t idx;
for (idx = 1; idx < len; idx++)
{
if (!recieved[idx].valid)
@@ -152,12 +158,12 @@ void SearchThread::onItemDone(uint64_t itemid, int64_t seed, bool isdone)
lastid += idx;
- for (int i = idx; i < len; i++)
+ for (uint64_t i = idx; i < len; i++)
recieved[i-idx] = recieved[i];
- for (int i = len-idx; i < len; i++)
+ for (uint64_t i = len-idx; i < len; i++)
recieved[i].valid = false;
- for (int i = 0; i < idx; i++)
+ for (uint64_t i = 0; i < idx; i++)
startNextItem();
uint64_t prog, end;
@@ -166,7 +172,7 @@ void SearchThread::onItemDone(uint64_t itemid, int64_t seed, bool isdone)
}
else
{
- int idx = itemid - lastid;
+ int64_t idx = itemid - lastid;
if (idx < 0 || idx >= recieved.size())
{
QMessageBox::critical(parent, "Fatal Error",
diff --git a/src/searchthread.h b/src/searchthread.h
index 6e6a9f1..4a179e5 100644
--- a/src/searchthread.h
+++ b/src/searchthread.h
@@ -19,14 +19,14 @@ public:
struct CheckedSeed
{
uint8_t valid;
- int64_t seed;
+ uint64_t seed;
};
SearchThread(FormSearchControl *parent);
- bool set(QObject *mainwin, int type, int threads, Gen48Settings gen48,
- std::vector& slist, int64_t sstart, int mc,
- const QVector& cv, int itemsize, int queuesize);
+ bool set(QObject *mainwin, int mc,
+ const SearchConfig& sc, const Gen48Settings& gen48, const Config& config,
+ std::vector& slist, const QVector& cv);
virtual void run() override;
@@ -34,12 +34,12 @@ public:
SearchItem *startNextItem();
signals:
- void progress(uint64_t last, uint64_t end, int64_t seed);
+ void progress(uint64_t last, uint64_t end, uint64_t seed);
void searchEnded(); // search thread is exiting (e.g. abort or done)
void searchFinish(); // search ended and is comlete
public slots:
- void onItemDone(uint64_t itemid, int64_t seed, bool isdone);
+ void onItemDone(uint64_t itemid, uint64_t seed, bool isdone);
void onItemCanceled(uint64_t itemid);
public:
diff --git a/src/seedtables.h b/src/seedtables.h
index 7982738..32b54bc 100644
--- a/src/seedtables.h
+++ b/src/seedtables.h
@@ -5,7 +5,7 @@
// Quad monument bases are too expensive to generate on the fly and there are
// so few of them that they can be hard coded, rather than loading from a file.
-static const int64_t g_qm_90[] = {
+static const uint64_t g_qm_90[] = {
35624347962,
775379617447,
3752024106001,
@@ -115,7 +115,7 @@ static const int64_t g_qm_90[] = {
265956688913983,
};
-static const int64_t g_qm_95[] = {
+static const uint64_t g_qm_95[] = {
775379617447,
40642997855160,
75345272448242,
@@ -171,7 +171,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(int64_t s48)
+static int qmonumentQual(uint64_t s48)
{
switch ((s48) & ((1LL<<48)-1))
{
diff --git a/src/settings.h b/src/settings.h
index a48196f..93036bd 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -63,21 +63,25 @@ enum { SEARCH_INC = 0, SEARCH_BLOCKS = 1, SEARCH_LIST = 2 };
struct SearchConfig
{
- int searchmode;
+ int searchtype;
QString slist64path;
int threads;
- int64_t startseed;
+ uint64_t startseed;
bool stoponres;
+ uint64_t smin;
+ uint64_t smax;
SearchConfig() { reset(); }
void reset()
{
- searchmode = SEARCH_INC;
+ searchtype = SEARCH_INC;
slist64path = "";
threads = QThread::idealThreadCount();
startseed = 0;
stoponres = true;
+ smin = 0;
+ smax = ~(uint64_t)0;
}
};