mirror of
https://github.com/Cubitect/cubiomes-viewer.git
synced 2025-01-08 11:57:50 +08:00
Trial chambers etc
* added trial chambers (no icon yet) * added sampling filter for climate noise (#287) * fixed a crash from testing code for stack allocation (#290)
This commit is contained in:
parent
0683518389
commit
8d54874324
2
cubiomes
2
cubiomes
@ -1 +1 @@
|
||||
Subproject commit ae58fc49833db481ae493015ddffce317f1ace9b
|
||||
Subproject commit 0af31b4e7eeb14a58c2bd9a4c4c68b97b4a7d6e8
|
@ -13,7 +13,7 @@ QT += core widgets
|
||||
CHARSET = -finput-charset=UTF-8 -fexec-charset=UTF-8
|
||||
QMAKE_CFLAGS = $$CHARSET -fwrapv -DSTRUCT_CONFIG_OVERRIDE=1
|
||||
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
|
||||
QMAKE_CXXFLAGS_RELEASE *= -O3
|
||||
QMAKE_CXXFLAGS_RELEASE *= -O3 -g3
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 5) {
|
||||
QMAKE_CXXFLAGS += -std=gnu++17
|
||||
|
@ -60,6 +60,11 @@
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
|
||||
<recommends>
|
||||
<display_length side="shortest">900</display_length>
|
||||
<display_length side="longest">1600</display_length>
|
||||
</recommends>
|
||||
|
||||
<url type="homepage">https://github.com/cubitect/cubiomes-viewer</url>
|
||||
<url type="bugtracker">https://github.com/cubitect/cubiomes-viewer/issues</url>
|
||||
|
||||
|
@ -83,5 +83,7 @@
|
||||
<file>icons/zoom_in.png</file>
|
||||
<file>icons/zoom_out.png</file>
|
||||
<file>icons/zoom.png</file>
|
||||
<file>icons/chambers.png</file>
|
||||
<file>icons/chambers_d.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
BIN
rc/icons/chambers.png
Normal file
BIN
rc/icons/chambers.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 135 B |
BIN
rc/icons/chambers_d.png
Normal file
BIN
rc/icons/chambers_d.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 135 B |
@ -107,13 +107,17 @@ ConditionDialog::ConditionDialog(FormConditions *parent, MapView *mapview, Confi
|
||||
ui->lineBiomeSize->setValidator(new QIntValidator(1, INT_MAX, this));
|
||||
ui->lineTolerance->setValidator(new QIntValidator(0, 255, this));
|
||||
|
||||
ui->comboY->lineEdit()->setValidator(new QIntValidator(-64, 320, this));
|
||||
initComboY(ui->comboY1, initcond ? initcond->y : 256);
|
||||
initComboY(ui->comboY2, initcond ? initcond->y : 256);
|
||||
|
||||
ui->lineMin->setValidator(new QDoubleValidator(-1e6, 1e6, 4, this));
|
||||
ui->lineMax->setValidator(new QDoubleValidator(-1e6, 1e6, 4, this));
|
||||
QDoubleValidator *paraval = new QDoubleValidator(-1e6, 1e6, 4, this);
|
||||
ui->lineMin->setValidator(paraval);
|
||||
ui->lineMax->setValidator(paraval);
|
||||
|
||||
ui->lineCoverage->setValidator(new QDoubleValidator(0.0001, 100.0000, 4, this));
|
||||
ui->lineConfidence->setValidator(new QDoubleValidator(0.0001, 99.9999, 4, this));
|
||||
ui->lineCoverage2->setValidator(new QDoubleValidator(0.0001, 100.0000, 4, this));
|
||||
ui->lineCoverage1->setValidator(new QDoubleValidator(0.0001, 100.0000, 4, this));
|
||||
ui->lineConfidence1->setValidator(new QDoubleValidator(0.0001, 99.9999, 4, this));
|
||||
ui->lineConfidence2->setValidator(new QDoubleValidator(0.0001, 99.9999, 4, this));
|
||||
|
||||
//qobject_cast<QListView*>(ui->comboCat->view())->setSpacing(1);
|
||||
//qobject_cast<QListView*>(ui->comboType->view())->setSpacing(1);
|
||||
@ -301,8 +305,10 @@ ConditionDialog::ConditionDialog(FormConditions *parent, MapView *mapview, Confi
|
||||
ui->checkSkipRef->setChecked(false);
|
||||
ui->radioSquare->setChecked(true);
|
||||
ui->checkRadius->setChecked(false);
|
||||
ui->lineCoverage->setText("50");
|
||||
ui->lineConfidence->setText("95");
|
||||
ui->lineCoverage1->setText("50");
|
||||
ui->lineCoverage2->setText("50");
|
||||
ui->lineConfidence1->setText("95");
|
||||
ui->lineConfidence2->setText("95");
|
||||
ui->comboScale->setCurrentIndex(1);
|
||||
onCheckStartChanged(false);
|
||||
on_comboClimatePara_currentIndexChanged(0);
|
||||
@ -341,8 +347,11 @@ ConditionDialog::ConditionDialog(FormConditions *parent, MapView *mapview, Confi
|
||||
on_comboClimatePara_currentIndexChanged(cond.para);
|
||||
ui->comboOctaves->setCurrentIndex(cond.octave);
|
||||
ui->comboMinMax->setCurrentIndex((cond.minmax & Condition::E_LOCATE_MAX) ? 1 : 0);
|
||||
ui->lineMin->setText((cond.minmax & Condition::E_TEST_LOWER) ? QString::number(cond.vmin) : "");
|
||||
ui->lineMax->setText((cond.minmax & Condition::E_TEST_UPPER) ? QString::number(cond.vmax) : "");
|
||||
QString vmin, vmax;
|
||||
if (cond.minmax & Condition::E_TEST_LOWER) vmin = QString::number(cond.vmin);
|
||||
if (cond.minmax & Condition::E_TEST_UPPER) vmax = QString::number(cond.vmax);
|
||||
ui->lineMin->setText(vmin);
|
||||
ui->lineMax->setText(vmax);
|
||||
ui->checkInvertRange->setChecked(cond.flags & Condition::FLG_INVERT);
|
||||
|
||||
updateMode();
|
||||
@ -357,19 +366,10 @@ ConditionDialog::ConditionDialog(FormConditions *parent, MapView *mapview, Confi
|
||||
ui->checkApprox->setChecked(cond.flags & Condition::FLG_APPROX);
|
||||
ui->checkMatchAny->setChecked(cond.flags & Condition::FLG_MATCH_ANY);
|
||||
ui->checkSamplePos->setChecked(cond.count == 1);
|
||||
ui->lineCoverage->setText(QString::number(cond.converage ? cond.converage * 100 : 50));
|
||||
ui->lineConfidence->setText(QString::number(cond.confidence ? cond.confidence * 100 : 95));
|
||||
|
||||
int i, n = ui->comboY->count();
|
||||
for (i = 0; i < n; i++)
|
||||
if (ui->comboY->itemText(i).section(' ', 0, 0).toInt() == cond.y)
|
||||
break;
|
||||
if (i >= n)
|
||||
{
|
||||
ui->comboY->addItem(QString::number(cond.y));
|
||||
ui->comboY2->addItem(QString::number(cond.y));
|
||||
}
|
||||
ui->comboY->setCurrentIndex(i);
|
||||
ui->lineCoverage1->setText(QString::number(cond.converage ? cond.converage * 100 : 50));
|
||||
ui->lineCoverage2->setText(QString::number(cond.converage ? cond.converage * 100 : 50));
|
||||
ui->lineConfidence1->setText(QString::number(cond.confidence ? cond.confidence * 100 : 95));
|
||||
ui->lineConfidence2->setText(QString::number(cond.confidence ? cond.confidence * 100 : 95));
|
||||
|
||||
if (cond.x1 == cond.z1 && cond.x1 == -cond.x2 && cond.x1 == -cond.z2)
|
||||
{
|
||||
@ -486,6 +486,19 @@ void ConditionDialog::addTempCat(int temp, QString name)
|
||||
}
|
||||
}
|
||||
|
||||
void ConditionDialog::initComboY(QComboBox *cb, int y)
|
||||
{
|
||||
if (!cb->lineEdit()->validator())
|
||||
cb->lineEdit()->setValidator(new QIntValidator(-64, 320, this));
|
||||
int i, n = cb->count();
|
||||
for (i = 0; i < n; i++)
|
||||
if (cb->itemText(i).section(' ', 0, 0).toInt() == y)
|
||||
break;
|
||||
if (i >= n)
|
||||
cb->addItem(QString::number(y));
|
||||
cb->setCurrentIndex(i);
|
||||
}
|
||||
|
||||
void ConditionDialog::updateMode()
|
||||
{
|
||||
int filterindex = ui->comboType->currentData().toInt();
|
||||
@ -566,7 +579,8 @@ void ConditionDialog::updateMode()
|
||||
ui->checkSkipRef->setEnabled(cnt);
|
||||
|
||||
ui->labelY->setEnabled(ft.hasy);
|
||||
ui->comboY->setEnabled(ft.hasy);
|
||||
ui->comboY1->setEnabled(ft.hasy);
|
||||
ui->comboY2->setEnabled(ft.hasy);
|
||||
|
||||
if (filterindex == F_TEMPS)
|
||||
{
|
||||
@ -578,7 +592,15 @@ void ConditionDialog::updateMode()
|
||||
}
|
||||
else if (filterindex == F_CLIMATE_MINMAX)
|
||||
{
|
||||
ui->stackedWidget->setCurrentWidget(ui->pageMinMax);
|
||||
ui->stackedWidget->setCurrentWidget(ui->pageNoise);
|
||||
ui->stackedNoise->setCurrentWidget(ui->pageNoiseMinMax);
|
||||
ui->groupBoxNoise->setTitle("Locate climate minimum/maximum");
|
||||
}
|
||||
else if (filterindex == F_NOISE_SAMPLE)
|
||||
{
|
||||
ui->stackedWidget->setCurrentWidget(ui->pageNoise);
|
||||
ui->stackedNoise->setCurrentWidget(ui->pageNoiseSample);
|
||||
ui->groupBoxNoise->setTitle("Climate noise samples");
|
||||
}
|
||||
else if (filterindex == F_BIOME_CENTER || filterindex == F_BIOME_CENTER_256)
|
||||
{
|
||||
@ -1035,7 +1057,7 @@ void ConditionDialog::onAccept()
|
||||
else
|
||||
c.rmax = 0;
|
||||
|
||||
c.y = ui->comboY->currentText().section(' ', 0, 0).toInt();
|
||||
c.y = ui->comboY1->currentText().section(' ', 0, 0).toInt();
|
||||
|
||||
c.flags = 0;
|
||||
if (ui->checkApprox->isChecked())
|
||||
@ -1071,8 +1093,8 @@ void ConditionDialog::onAccept()
|
||||
}
|
||||
}
|
||||
c.count = ui->checkSamplePos->isChecked() ? 1 : 0;
|
||||
c.converage = ui->lineCoverage->text().toFloat() / 100.0;
|
||||
c.confidence = ui->lineConfidence->text().toFloat() / 100.0;
|
||||
c.converage = ui->lineCoverage1->text().toFloat() / 100.0;
|
||||
c.confidence = ui->lineConfidence1->text().toFloat() / 100.0;
|
||||
c.step = 0;
|
||||
if (c.type == F_BIOME || c.type == F_BIOME_NETHER || c.type == F_BIOME_END)
|
||||
c.step = ui->comboScale->currentData().toInt();
|
||||
@ -1082,15 +1104,15 @@ void ConditionDialog::onAccept()
|
||||
if (ui->stackedWidget->currentWidget() == ui->pageBiomeCenter)
|
||||
{
|
||||
c.biomeId = ui->comboMatchBiome->currentData().toInt();
|
||||
c.y = ui->comboY2->currentText().section(' ', 0, 0).toInt();
|
||||
c.biomeSize = ui->lineBiomeSize->text().toInt();
|
||||
c.tol = ui->lineTolerance->text().toInt();
|
||||
}
|
||||
if (ui->stackedWidget->currentWidget() == ui->pageMinMax)
|
||||
if (ui->stackedWidget->currentWidget() == ui->pageNoise)
|
||||
{
|
||||
c.para = ui->comboClimatePara->currentData().toInt();
|
||||
c.octave = ui->comboOctaves->currentIndex();
|
||||
c.minmax = ui->comboMinMax->currentIndex() == 0 ?
|
||||
Condition::E_LOCATE_MIN : Condition::E_LOCATE_MAX;
|
||||
c.minmax = ui->comboMinMax->currentIndex() == 0 ? Condition::E_LOCATE_MIN : Condition::E_LOCATE_MAX;
|
||||
bool ok1, ok2;
|
||||
c.vmin = ui->lineMin->text().toFloat(&ok1);
|
||||
if (ok1) c.minmax |= Condition::E_TEST_LOWER;
|
||||
@ -1098,6 +1120,9 @@ void ConditionDialog::onAccept()
|
||||
if (ok2) c.minmax |= Condition::E_TEST_UPPER;
|
||||
if (ok1 && ok2 && c.vmin > c.vmax)
|
||||
std::swap(c.vmin, c.vmax);
|
||||
c.count = ui->checkSamplePos2->isChecked() ? 1 : 0;
|
||||
c.converage = ui->lineCoverage2->text().toFloat() / 100.0;
|
||||
c.confidence = ui->lineConfidence2->text().toFloat() / 100.0;
|
||||
}
|
||||
if (ui->stackedWidget->currentWidget() == ui->pageTemps)
|
||||
{
|
||||
@ -1653,13 +1678,13 @@ void ConditionDialog::on_comboOctaves_currentIndexChanged(int)
|
||||
ui->comboOctaves->setToolTip(ui->comboOctaves->currentData(Qt::ToolTipRole).toString());
|
||||
}
|
||||
|
||||
void ConditionDialog::on_comboY_currentTextChanged(const QString &text)
|
||||
void ConditionDialog::on_comboY1_currentTextChanged(const QString &text)
|
||||
{
|
||||
if (ui->comboY2->currentText() != text)
|
||||
ui->comboY2->setCurrentText(text);
|
||||
}
|
||||
void ConditionDialog::on_comboY2_currentTextChanged(const QString &text)
|
||||
{
|
||||
if (ui->comboY->currentText() != text)
|
||||
ui->comboY->setCurrentText(text);
|
||||
if (ui->comboY1->currentText() != text)
|
||||
ui->comboY1->setCurrentText(text);
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ public:
|
||||
virtual ~ConditionDialog();
|
||||
|
||||
void addTempCat(int temp, QString name);
|
||||
void initComboY(QComboBox *cb, int y);
|
||||
void updateMode();
|
||||
void updateBiomeSelection();
|
||||
bool warnIfBad(Condition cond);
|
||||
@ -112,7 +113,7 @@ private slots:
|
||||
void on_comboClimatePara_currentIndexChanged(int index);
|
||||
void on_comboOctaves_currentIndexChanged(int index);
|
||||
|
||||
void on_comboY_currentTextChanged(const QString &text);
|
||||
void on_comboY1_currentTextChanged(const QString &text);
|
||||
void on_comboY2_currentTextChanged(const QString &text);
|
||||
|
||||
private:
|
||||
|
@ -392,7 +392,7 @@ QPushButton:hover {
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>2</number>
|
||||
<number>5</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="pageNone">
|
||||
<property name="enabled">
|
||||
@ -631,14 +631,14 @@ yield each sampled position individually</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineCoverage">
|
||||
<widget class="QLineEdit" name="lineCoverage1">
|
||||
<property name="toolTip">
|
||||
<string>Proportion of the area that has to be of the included biomes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineConfidence">
|
||||
<widget class="QLineEdit" name="lineConfidence1">
|
||||
<property name="toolTip">
|
||||
<string>Statistical confidence that the coverage has been reached</string>
|
||||
</property>
|
||||
@ -649,7 +649,7 @@ yield each sampled position individually</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="StyledComboBox" name="comboY">
|
||||
<widget class="StyledComboBox" name="comboY1">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@ -1100,7 +1100,7 @@ yield each sampled position individually</string>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageMinMax">
|
||||
<widget class="QWidget" name="pageNoise">
|
||||
<layout class="QGridLayout" name="gridLayout_23">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
@ -1115,18 +1115,196 @@ yield each sampled position individually</string>
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_10">
|
||||
<widget class="QGroupBox" name="groupBoxNoise">
|
||||
<property name="title">
|
||||
<string>Locate climate minimum/maximum</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_24">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="lineMin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Lower bound (inclusive)</p></body></html></string>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="StyledComboBox" name="comboClimatePara"/>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="5">
|
||||
<widget class="QStackedWidget" name="stackedNoise">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>-Infinity</string>
|
||||
<widget class="QWidget" name="pageNoiseMinMax">
|
||||
<layout class="QGridLayout" name="gridLayout_33">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="StyledComboBox" name="comboMinMax">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Minimum</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Maximum</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Yield position of:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>180</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="pageNoiseSample">
|
||||
<layout class="QGridLayout" name="gridLayout_32">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="checkSamplePos2">
|
||||
<property name="toolTip">
|
||||
<string>Instead of estimating the center of the allowed biome area,
|
||||
yield each sampled position individually</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Yield individual samples</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineCoverage2"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_27">
|
||||
<property name="toolTip">
|
||||
<string>Statistical confidence that the coverage has been reached</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Confidence (%):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<spacer name="verticalSpacer_9">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineConfidence2">
|
||||
<property name="toolTip">
|
||||
<string>Statistical confidence that the coverage has been reached</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="text">
|
||||
<string>Required coverage (%):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>180</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="text">
|
||||
<string>If value is in range:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="4">
|
||||
<widget class="StyledComboBox" name="comboOctaves">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -1137,36 +1315,6 @@ yield each sampled position individually</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>252</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QCheckBox" name="checkInvertRange">
|
||||
<property name="toolTip">
|
||||
<string>Only match if value is outside the given range</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Invert range</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
<string>Yield position of:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLineEdit" name="lineMax">
|
||||
<property name="toolTip">
|
||||
@ -1184,45 +1332,41 @@ yield each sampled position individually</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_9">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="lineMin">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Lower bound (inclusive)</p></body></html></string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>-Infinity</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QCheckBox" name="checkInvertRange">
|
||||
<property name="toolTip">
|
||||
<string>Only match if value is outside the given range</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>If value is in range:</string>
|
||||
<string>Invert range</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="4">
|
||||
<widget class="StyledComboBox" name="comboMinMax">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Minimum</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Maximum</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="4">
|
||||
<widget class="StyledComboBox" name="comboClimatePara"/>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>-</string>
|
||||
<item row="5" column="0">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="4">
|
||||
<widget class="StyledComboBox" name="comboOctaves">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Preferred</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>180</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -148,7 +148,7 @@ QString mapopt2display(int opt)
|
||||
case D_VILLAGE: return QApplication::translate("Map", "Village");
|
||||
case D_MANSION: return QApplication::translate("Map", "Woodland Mansion");
|
||||
case D_MONUMENT: return QApplication::translate("Map", "Ocean Monument");
|
||||
case D_RUINS: return QApplication::translate("Map", "Ocean Ruins");
|
||||
case D_OCEANRUIN: return QApplication::translate("Map", "Ocean Ruin");
|
||||
case D_SHIPWRECK: return QApplication::translate("Map", "Shipwreck");
|
||||
case D_TREASURE: return QApplication::translate("Map", "Buried Treasure");
|
||||
case D_MINESHAFT: return QApplication::translate("Map", "Mineshaft");
|
||||
@ -156,7 +156,8 @@ QString mapopt2display(int opt)
|
||||
case D_GEODE: return QApplication::translate("Map", "Geode");
|
||||
case D_OUTPOST: return QApplication::translate("Map", "Pillager Outpost");
|
||||
case D_ANCIENTCITY: return QApplication::translate("Map", "Ancient City");
|
||||
case D_TRAILS: return QApplication::translate("Map", "Trail Ruins");
|
||||
case D_TRAILRUINS: return QApplication::translate("Map", "Trail Ruins");
|
||||
case D_CHAMBERS: return QApplication::translate("Map", "Trial Chambers");
|
||||
case D_PORTAL: return QApplication::translate("Map", "Ruined Portal");
|
||||
case D_PORTALN: return QApplication::translate("Map", "Ruined Portal (Nether)");
|
||||
case D_SPAWN: return QApplication::translate("Map", "Spawn");
|
||||
@ -182,7 +183,7 @@ const char *mapopt2str(int opt) // to resource string
|
||||
case D_VILLAGE: return "village";
|
||||
case D_MANSION: return "mansion";
|
||||
case D_MONUMENT: return "monument";
|
||||
case D_RUINS: return "ruins";
|
||||
case D_OCEANRUIN: return "ruins";
|
||||
case D_SHIPWRECK: return "shipwreck";
|
||||
case D_TREASURE: return "treasure";
|
||||
case D_MINESHAFT: return "mineshaft";
|
||||
@ -190,7 +191,8 @@ const char *mapopt2str(int opt) // to resource string
|
||||
case D_GEODE: return "geode";
|
||||
case D_OUTPOST: return "outpost";
|
||||
case D_ANCIENTCITY: return "ancient_city";
|
||||
case D_TRAILS: return "trails";
|
||||
case D_TRAILRUINS: return "trails";
|
||||
case D_CHAMBERS: return "chambers";
|
||||
case D_PORTAL: return "portal";
|
||||
case D_PORTALN: return "portaln";
|
||||
case D_SPAWN: return "spawn";
|
||||
@ -214,7 +216,7 @@ int str2mapopt(const char *s) // from resource string
|
||||
if (!strcmp(s, "village")) return D_VILLAGE;
|
||||
if (!strcmp(s, "mansion")) return D_MANSION;
|
||||
if (!strcmp(s, "monument")) return D_MONUMENT;
|
||||
if (!strcmp(s, "ruins")) return D_RUINS;
|
||||
if (!strcmp(s, "ruins")) return D_OCEANRUIN;
|
||||
if (!strcmp(s, "shipwreck")) return D_SHIPWRECK;
|
||||
if (!strcmp(s, "treasure")) return D_TREASURE;
|
||||
if (!strcmp(s, "mineshaft")) return D_MINESHAFT;
|
||||
@ -222,7 +224,8 @@ int str2mapopt(const char *s) // from resource string
|
||||
if (!strcmp(s, "geode")) return D_GEODE;
|
||||
if (!strcmp(s, "outpost")) return D_OUTPOST;
|
||||
if (!strcmp(s, "ancient_city")) return D_ANCIENTCITY;
|
||||
if (!strcmp(s, "trails")) return D_TRAILS;
|
||||
if (!strcmp(s, "trails")) return D_TRAILRUINS;
|
||||
if (!strcmp(s, "chambers")) return D_CHAMBERS;
|
||||
if (!strcmp(s, "portal")) return D_PORTAL;
|
||||
if (!strcmp(s, "portaln")) return D_PORTALN;
|
||||
if (!strcmp(s, "spawn")) return D_SPAWN;
|
||||
@ -245,7 +248,7 @@ int mapopt2stype(int opt)
|
||||
case D_VILLAGE: return Village;
|
||||
case D_MANSION: return Mansion;
|
||||
case D_MONUMENT: return Monument;
|
||||
case D_RUINS: return Ocean_Ruin;
|
||||
case D_OCEANRUIN: return Ocean_Ruin;
|
||||
case D_SHIPWRECK: return Shipwreck;
|
||||
case D_TREASURE: return Treasure;
|
||||
case D_MINESHAFT: return Mineshaft;
|
||||
@ -253,7 +256,8 @@ int mapopt2stype(int opt)
|
||||
case D_GEODE: return Geode;
|
||||
case D_OUTPOST: return Outpost;
|
||||
case D_ANCIENTCITY: return Ancient_City;
|
||||
case D_TRAILS: return Trail_Ruin;
|
||||
case D_TRAILRUINS: return Trail_Ruins;
|
||||
case D_CHAMBERS: return Trial_Chambers;
|
||||
case D_PORTAL: return Ruined_Portal;
|
||||
case D_PORTALN: return Ruined_Portal_N;
|
||||
case D_FORTESS: return Fortress;
|
||||
|
@ -109,7 +109,7 @@ enum {
|
||||
D_VILLAGE,
|
||||
D_MANSION,
|
||||
D_MONUMENT,
|
||||
D_RUINS,
|
||||
D_OCEANRUIN,
|
||||
D_SHIPWRECK,
|
||||
D_TREASURE,
|
||||
D_MINESHAFT,
|
||||
@ -117,7 +117,8 @@ enum {
|
||||
D_GEODE,
|
||||
D_OUTPOST,
|
||||
D_ANCIENTCITY,
|
||||
D_TRAILS,
|
||||
D_TRAILRUINS,
|
||||
D_CHAMBERS,
|
||||
D_PORTAL,
|
||||
D_PORTALN,
|
||||
D_FORTESS,
|
||||
|
@ -155,7 +155,7 @@ FormSearchControl::FormSearchControl(MainWindow *parent)
|
||||
FormSearchControl::~FormSearchControl()
|
||||
{
|
||||
stimer.stop();
|
||||
sthread.stop(); // tell search to stop at next convenience
|
||||
sthread.stopSearch();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@ -227,9 +227,7 @@ bool FormSearchControl::setSearchConfig(SearchConfig s, bool quiet)
|
||||
|
||||
void FormSearchControl::stopSearch()
|
||||
{
|
||||
sthread.stop();
|
||||
//sthread.quit(); // tell the event loop to exit
|
||||
//sthread.wait(); // wait for search to finish
|
||||
sthread.stopSearch();
|
||||
onBufferTimeout();
|
||||
}
|
||||
|
||||
@ -394,7 +392,7 @@ void FormSearchControl::on_buttonStart_clicked()
|
||||
searchLockUi(true);
|
||||
nextupdate = 0;
|
||||
updt = 20;
|
||||
sthread.start();
|
||||
sthread.startSearch();
|
||||
elapsed.start();
|
||||
stimer.start(250);
|
||||
}
|
||||
@ -635,12 +633,12 @@ int FormSearchControl::searchResultsAdd(std::vector<uint64_t> seeds, bool counto
|
||||
|
||||
if (n >= config.maxMatching)
|
||||
{
|
||||
sthread.stop();
|
||||
sthread.stopSearch();
|
||||
discarded = true;
|
||||
}
|
||||
if (n + (ssize_t)seeds.size() > config.maxMatching)
|
||||
{
|
||||
sthread.stop();
|
||||
sthread.stopSearch();
|
||||
discarded = true;
|
||||
seeds.resize(config.maxMatching - n);
|
||||
}
|
||||
@ -671,7 +669,7 @@ int FormSearchControl::searchResultsAdd(std::vector<uint64_t> seeds, bool counto
|
||||
|
||||
int addcnt = n - nold;
|
||||
if (ui->checkStop->isChecked() && addcnt)
|
||||
sthread.stop();
|
||||
sthread.stopSearch();
|
||||
|
||||
if (!countonly && discarded)
|
||||
{
|
||||
|
@ -149,7 +149,7 @@ void Headless::run()
|
||||
session.writeHeader(resultstream);
|
||||
resultstream.flush();
|
||||
|
||||
sthread.start();
|
||||
sthread.startSearch();
|
||||
elapsed.start();
|
||||
|
||||
if (resultfile.isOpen())
|
||||
|
@ -73,7 +73,7 @@ bool getLayerOptionInfo(LayerOptInfo *info, int mode, int disp, WorldInfo wi)
|
||||
|
||||
if (disp == 0)
|
||||
{
|
||||
txt += QString("%1.. x%2").arg(QChar(0x03A3)).arg(amptot, 0, 'f', 6);
|
||||
txt += QString("%1.. (all) x%2").arg(QChar(0x03A3)).arg(amptot, 0, 'f', 6);
|
||||
tip += QApplication::translate("LayerDialog", "All octaves");
|
||||
}
|
||||
else
|
||||
|
@ -174,7 +174,7 @@ MainWindow::MainWindow(QString sessionpath, QString resultspath, QWidget *parent
|
||||
addMapAction(D_MONUMENT);
|
||||
addMapAction(D_IGLOO);
|
||||
addMapAction(D_MANSION);
|
||||
addMapAction(D_RUINS);
|
||||
addMapAction(D_OCEANRUIN);
|
||||
addMapAction(D_SHIPWRECK);
|
||||
addMapAction(D_TREASURE);
|
||||
addMapAction(D_WELL);
|
||||
@ -182,7 +182,8 @@ MainWindow::MainWindow(QString sessionpath, QString resultspath, QWidget *parent
|
||||
addMapAction(D_OUTPOST);
|
||||
addMapAction(D_PORTAL);
|
||||
addMapAction(D_ANCIENTCITY);
|
||||
addMapAction(D_TRAILS);
|
||||
addMapAction(D_TRAILRUINS);
|
||||
addMapAction(D_CHAMBERS);
|
||||
ui->toolBar->addSeparator();
|
||||
addMapAction(D_FORTESS);
|
||||
addMapAction(D_BASTION);
|
||||
|
@ -381,6 +381,7 @@ void MapView::showContextMenu(const QPoint &pos)
|
||||
std::vector<_cpy_dat> cpy_dat;
|
||||
|
||||
VarPos vp = getActivePos();
|
||||
const QPixmap *icon = 0;
|
||||
|
||||
if (vp.type != -1)
|
||||
{ // structure has a known size / location
|
||||
@ -389,7 +390,7 @@ void MapView::showContextMenu(const QPoint &pos)
|
||||
{
|
||||
const Piece& pc = vp.pieces[0];
|
||||
midx = (pc.bb0.x + pc.bb1.x) >> 1;
|
||||
midy = (pc.bb0.y);
|
||||
midy = (pc.bb0.y) + 1;
|
||||
midz = (pc.bb0.z + pc.bb1.z) >> 1;
|
||||
}
|
||||
else
|
||||
@ -405,6 +406,7 @@ void MapView::showContextMenu(const QPoint &pos)
|
||||
}
|
||||
}
|
||||
cpy_dat.push_back({ tr("Copy tp:"), QString::asprintf("/tp @p %d %d %d", midx, midy, midz) });
|
||||
icon = &getMapIcon(world ? world->selopt : -1, &vp);
|
||||
}
|
||||
cpy_dat.push_back({ tr("Copy tp:"), QString::asprintf("/tp @p %d ~ %d", vp.p.x, vp.p.z) });
|
||||
cpy_dat.push_back({ tr("Copy coords:"), QString::asprintf("%d %d", vp.p.x, vp.p.z) });
|
||||
@ -434,7 +436,10 @@ void MapView::showContextMenu(const QPoint &pos)
|
||||
while (txtWidth(menu->fontMetrics(), txt + " ") < wmax)
|
||||
txt += " ";
|
||||
txt += it.cpy;
|
||||
menu->addAction(txt, [=](){ this->copyText(it.cpy); });
|
||||
if (icon)
|
||||
menu->addAction(*icon, txt, [=](){ this->copyText(it.cpy); });
|
||||
else
|
||||
menu->addAction(txt, [=](){ this->copyText(it.cpy); });
|
||||
}
|
||||
//menu->addAction(tr("Animation"), this, &MapView::runAni);
|
||||
|
||||
|
206
src/search.cpp
206
src/search.cpp
@ -249,7 +249,15 @@ QString ConditionTree::set(const std::vector<Condition>& cv, int mc)
|
||||
}
|
||||
|
||||
SearchThreadEnv::SearchThreadEnv()
|
||||
: condtree(),mc(),large(),seed(),surfdim(DIM_UNDEF),octaves(),l_states()
|
||||
: condtree()
|
||||
, mc()
|
||||
, large()
|
||||
, seed()
|
||||
, surfdim(DIM_UNDEF)
|
||||
, octaves()
|
||||
, searchpass(PASS_FAST_48)
|
||||
, stop()
|
||||
, l_states()
|
||||
{
|
||||
memset(&g, 0, sizeof(g));
|
||||
memset(&sn, 0, sizeof(sn));
|
||||
@ -323,7 +331,7 @@ void SearchThreadEnv::init4Noise(int nptype, int octaves)
|
||||
{
|
||||
if (octaves <= 0)
|
||||
octaves = INT_MAX;
|
||||
if (g.bn.nptype == nptype && this->octaves >= octaves)
|
||||
if (g.bn.nptype == nptype && this->octaves == octaves)
|
||||
return; // already initialized for parameter
|
||||
if (seed == g.seed && g.bn.nptype == -1)
|
||||
return; // fully initialized biome noise
|
||||
@ -340,12 +348,22 @@ void SearchThreadEnv::prepareSurfaceNoise(int dim)
|
||||
}
|
||||
}
|
||||
|
||||
// The position buffers can exceed the stacksize on some platforms,
|
||||
// and dynamic heap allocation is too slow. So instead, we assign a
|
||||
// static memory region on the heap.
|
||||
static Pos* getPosBuf(uint32_t node)
|
||||
{
|
||||
#if DEBUG
|
||||
if (node >= 100) return NULL; // fatal
|
||||
#endif
|
||||
thread_local std::vector<Pos> buf(100 * MAX_INSTANCES);
|
||||
return &buf[node * MAX_INSTANCES];
|
||||
}
|
||||
|
||||
static
|
||||
int testTreeAt(
|
||||
int _testTreeAt(
|
||||
Pos at, // relative origin
|
||||
SearchThreadEnv * env, // thread-local environment
|
||||
int pass, // search pass
|
||||
std::atomic_bool * abort, // abort signal
|
||||
Pos * path, // output center position(s)
|
||||
int node
|
||||
)
|
||||
@ -356,8 +374,7 @@ int testTreeAt(
|
||||
int st, br;
|
||||
int rx1, rz1, rx2, rz2;
|
||||
Pos pos;
|
||||
|
||||
std::vector<Pos> inst(MAX_INSTANCES);
|
||||
Pos *inst = getPosBuf(node);
|
||||
|
||||
switch (c.type)
|
||||
{
|
||||
@ -424,8 +441,8 @@ int testTreeAt(
|
||||
int sta = COND_OK;
|
||||
for (int b : branches)
|
||||
{
|
||||
int stb = testTreeAt(pos, env, pass, abort, path, b);
|
||||
if (*abort)
|
||||
int stb = _testTreeAt(pos, env, path, b);
|
||||
if (*env->stop)
|
||||
return COND_FAILED;
|
||||
if (stb < sta)
|
||||
sta = stb;
|
||||
@ -471,8 +488,8 @@ int testTreeAt(
|
||||
st = COND_OK;
|
||||
for (int b : branches)
|
||||
{
|
||||
int sta = testTreeAt(pos, env, pass, abort, path, b);
|
||||
if (*abort)
|
||||
int sta = _testTreeAt(pos, env, path, b);
|
||||
if (*env->stop)
|
||||
return COND_FAILED;
|
||||
if (sta < st)
|
||||
st = sta;
|
||||
@ -497,8 +514,8 @@ int testTreeAt(
|
||||
st = COND_FAILED;
|
||||
for (int b : branches)
|
||||
{
|
||||
int sta = testTreeAt(at, env, pass, abort, path, b);
|
||||
if (*abort)
|
||||
int sta = _testTreeAt(at, env, path, b);
|
||||
if (*env->stop)
|
||||
return COND_FAILED;
|
||||
if (sta > st)
|
||||
st = sta;
|
||||
@ -528,8 +545,8 @@ int testTreeAt(
|
||||
st = COND_OK;
|
||||
for (int b : branches)
|
||||
{
|
||||
int sta = testTreeAt(at, env, pass, abort, path, b);
|
||||
if (*abort)
|
||||
int sta = _testTreeAt(at, env, path, b);
|
||||
if (*env->stop)
|
||||
return COND_FAILED;
|
||||
if (sta == COND_OK) { st = COND_FAILED; break; }
|
||||
else if (sta == COND_FAILED) { st = COND_OK; break; }
|
||||
@ -544,8 +561,8 @@ int testTreeAt(
|
||||
Pos *buf = path ? path : &inst[0];
|
||||
for (int b : branches)
|
||||
{
|
||||
int sta = testTreeAt(at, env, pass, abort, buf, b);
|
||||
if (*abort)
|
||||
int sta = _testTreeAt(at, env, buf, b);
|
||||
if (*env->stop)
|
||||
return COND_FAILED;
|
||||
if (sta < st) {
|
||||
st = sta;
|
||||
@ -555,8 +572,8 @@ int testTreeAt(
|
||||
}
|
||||
if (st <= COND_MAYBE_POS_INVAL)
|
||||
return st;
|
||||
int sta = runCheckScript(L, at, env, pass, buf, &c);
|
||||
if (*abort)
|
||||
int sta = runCheckScript(L, at, env, env->searchpass, buf, &c);
|
||||
if (*env->stop)
|
||||
return COND_FAILED;
|
||||
if (sta < st)
|
||||
st = sta;
|
||||
@ -568,7 +585,7 @@ int testTreeAt(
|
||||
if (branches.empty())
|
||||
{ // this is a leaf node => check only for presence of instances
|
||||
int icnt = c.count;
|
||||
st = testCondAt(at, env, pass, abort, &inst[0], &icnt, &c);
|
||||
st = testCondAt(at, env, &inst[0], &icnt, &c);
|
||||
if (path && st >= COND_MAYBE_POS_VALID)
|
||||
{
|
||||
if (icnt == 1)
|
||||
@ -593,7 +610,7 @@ int testTreeAt(
|
||||
}
|
||||
else
|
||||
{
|
||||
st = testCondAt(at, env, pass, abort, &inst[0], NULL, &c);
|
||||
st = testCondAt(at, env, &inst[0], NULL, &c);
|
||||
if (st == COND_FAILED || st == COND_MAYBE_POS_INVAL)
|
||||
return st;
|
||||
pos = inst[0]; // center point of instances
|
||||
@ -602,8 +619,8 @@ int testTreeAt(
|
||||
{
|
||||
if (st == COND_FAILED)
|
||||
break;
|
||||
int sta = testTreeAt(pos, env, pass, abort, path, b);
|
||||
if (*abort)
|
||||
int sta = _testTreeAt(pos, env, path, b);
|
||||
if (*env->stop)
|
||||
return COND_FAILED;
|
||||
if (sta < st)
|
||||
st = sta;
|
||||
@ -616,7 +633,7 @@ int testTreeAt(
|
||||
{ // check each instance individually, splitting the instances into
|
||||
// independent subbranches that are combined via OR
|
||||
int icnt = MAX_INSTANCES;
|
||||
st = testCondAt(at, env, pass, abort, &inst[0], &icnt, &c);
|
||||
st = testCondAt(at, env, &inst[0], &icnt, &c);
|
||||
if (st == COND_FAILED || st == COND_MAYBE_POS_INVAL)
|
||||
return st;
|
||||
int sta = COND_FAILED;
|
||||
@ -627,8 +644,8 @@ int testTreeAt(
|
||||
pos = inst[i];
|
||||
for (int b : branches) // AND dependent conditions
|
||||
{
|
||||
int stc = testTreeAt(pos, env, pass, abort, path, b);
|
||||
if (*abort)
|
||||
int stc = _testTreeAt(pos, env, path, b);
|
||||
if (*env->stop)
|
||||
return COND_FAILED;
|
||||
// worst branch dictates status for instance
|
||||
if (stc < stb)
|
||||
@ -659,17 +676,18 @@ int testTreeAt(
|
||||
Pos at, // relative origin
|
||||
SearchThreadEnv * env, // thread-local environment
|
||||
int pass, // search pass
|
||||
std::atomic_bool * abort, // abort signal
|
||||
Pos * path // ok trigger positions
|
||||
)
|
||||
{
|
||||
if (pass != PASS_FAST_48)
|
||||
{ // do a fast check before continuing with slower checks
|
||||
int st = testTreeAt(at, env, PASS_FAST_48, abort, NULL, 0);
|
||||
env->searchpass = PASS_FAST_48;
|
||||
int st = _testTreeAt(at, env, NULL, 0);
|
||||
if (st == COND_FAILED)
|
||||
return st;
|
||||
}
|
||||
return testTreeAt(at, env, pass, abort, path, 0);
|
||||
env->searchpass = pass;
|
||||
return _testTreeAt(at, env, path, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -1007,6 +1025,48 @@ static int f_biome_sampler(Generator *g, int scale, int x, int y, int z, void *d
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int f_noise_sampler(Generator *g, int scale, int x, int y, int z, void *data)
|
||||
{
|
||||
(void) y;
|
||||
sample_boime_t *info = (sample_boime_t*) data;
|
||||
if (info->stop && *info->stop)
|
||||
return -2;
|
||||
if (info->rmaxsq)
|
||||
{
|
||||
int dx = (x * scale) - info->at.x;
|
||||
int dz = (z * scale) - info->at.z;
|
||||
int64_t rsq = dx*(int64_t)dx + dz*(int64_t)dz;
|
||||
if (rsq >= info->rmaxsq)
|
||||
return -1;
|
||||
}
|
||||
|
||||
const Condition *cond = info->cond;
|
||||
double v = sampleDoublePerlin(&g->bn.climate[cond->para], x, 0, z);
|
||||
double vmin = cond->minmax & Condition::E_TEST_LOWER ? cond->vmin : -INFINITY;
|
||||
double vmax = cond->minmax & Condition::E_TEST_UPPER ? cond->vmax : +INFINITY;
|
||||
|
||||
v *= 10000;
|
||||
|
||||
bool ok = (v > vmin && v < vmax);
|
||||
if (cond->flags & Condition::FLG_INVERT)
|
||||
ok = !ok;
|
||||
|
||||
if (ok)
|
||||
{
|
||||
x *= scale;
|
||||
z *= scale;
|
||||
if (info->imax && info->n < MAX_INSTANCES)
|
||||
info->cent[info->n] = Pos{x, z};
|
||||
info->xsum += x;
|
||||
info->zsum += z;
|
||||
info->n++;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Tests if a condition is satisfied with 'at' as origin for a search pass.
|
||||
* If sufficiently satisfied (check return value) then:
|
||||
* when 'imax' is NULL, the center position is written to 'cent[0]'
|
||||
@ -1018,8 +1078,6 @@ int
|
||||
testCondAt(
|
||||
Pos at, // relative origin
|
||||
SearchThreadEnv * env, // thread-local environment
|
||||
int pass, // search pass
|
||||
std::atomic_bool * abort, // abort signal
|
||||
Pos * cent, // output center position(s)
|
||||
int * imax, // max instances (NULL for avg)
|
||||
const Condition * cond // condition to check
|
||||
@ -1035,7 +1093,7 @@ testCondAt(
|
||||
int i, n, icnt;
|
||||
int64_t s, r, rmin, rmax;
|
||||
const uint64_t *seeds;
|
||||
std::vector<Pos> p(MAX_INSTANCES);
|
||||
Pos *p = getPosBuf(0);
|
||||
|
||||
const FilterInfo& finfo = g_filterinfo.list[cond->type];
|
||||
|
||||
@ -1251,7 +1309,7 @@ L_qm_any:
|
||||
icnt = 0;
|
||||
|
||||
// Note "<="
|
||||
for (rz = rz1; rz <= rz2 && !*abort; rz++)
|
||||
for (rz = rz1; rz <= rz2 && !*env->stop; rz++)
|
||||
{
|
||||
for (rx = rx1; rx <= rx2; rx++)
|
||||
{
|
||||
@ -1271,9 +1329,10 @@ L_qm_any:
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pass == PASS_FULL_64 || (pass == PASS_FULL_48 && !finfo.dep64))
|
||||
if ((env->searchpass == PASS_FULL_64) ||
|
||||
(env->searchpass == PASS_FULL_48 && !finfo.dep64))
|
||||
{
|
||||
if (*abort) return COND_FAILED;
|
||||
if (*env->stop) return COND_FAILED;
|
||||
|
||||
if (st == Village && cond->varflags)
|
||||
{ // we can test for abandoned villages before the
|
||||
@ -1344,9 +1403,9 @@ L_qm_any:
|
||||
return COND_OK;
|
||||
else
|
||||
{
|
||||
if (pass == PASS_FULL_64)
|
||||
if (env->searchpass == PASS_FULL_64)
|
||||
return COND_FAILED;
|
||||
if (pass == PASS_FULL_48 && !finfo.dep64)
|
||||
if (env->searchpass == PASS_FULL_48 && !finfo.dep64)
|
||||
return COND_FAILED;
|
||||
return COND_MAYBE_POS_VALID;
|
||||
}
|
||||
@ -1363,9 +1422,9 @@ L_qm_any:
|
||||
cent->z = zt / icnt;
|
||||
}
|
||||
|
||||
if (pass == PASS_FULL_64)
|
||||
if (env->searchpass == PASS_FULL_64)
|
||||
return COND_OK;
|
||||
if (pass == PASS_FULL_48 && !finfo.dep64)
|
||||
if (env->searchpass == PASS_FULL_48 && !finfo.dep64)
|
||||
return COND_OK;
|
||||
// some non-exhaustive structure clusters do not
|
||||
// have known center positions with 48-bit seeds
|
||||
@ -1460,10 +1519,10 @@ L_qm_any:
|
||||
case F_SPAWN:
|
||||
|
||||
cent->x = cent->z = 0;
|
||||
if (pass != PASS_FULL_64)
|
||||
if (env->searchpass != PASS_FULL_64)
|
||||
return COND_MAYBE_POS_INVAL;
|
||||
|
||||
if (*abort) return COND_FAILED;
|
||||
if (*env->stop) return COND_FAILED;
|
||||
env->init4Dim(DIM_OVERWORLD);
|
||||
pc = getSpawn(&env->g);
|
||||
if (rmax)
|
||||
@ -1584,7 +1643,7 @@ L_qm_any:
|
||||
return cond->count == 0 ? COND_OK : COND_FAILED;
|
||||
|
||||
// pre-biome-checks complete, the area appears to line up with possible generation positions
|
||||
if (pass != PASS_FULL_64)
|
||||
if (env->searchpass != PASS_FULL_64)
|
||||
{
|
||||
return COND_MAYBE_POS_INVAL;
|
||||
}
|
||||
@ -1602,7 +1661,7 @@ L_qm_any:
|
||||
env->init4Dim(DIM_OVERWORLD);
|
||||
while (nextStronghold(&sh, &env->g) > 0)
|
||||
{
|
||||
if (*abort)
|
||||
if (*env->stop)
|
||||
break;
|
||||
bool inside;
|
||||
if (rmax)
|
||||
@ -1722,13 +1781,16 @@ L_qm_any:
|
||||
|
||||
|
||||
case F_BIOME_SAMPLE:
|
||||
case F_NOISE_SAMPLE:
|
||||
|
||||
if (pass != PASS_FULL_64)
|
||||
if (env->searchpass != PASS_FULL_64)
|
||||
return COND_MAYBE_POS_INVAL;
|
||||
if (cond->confidence <= 0 || cond->confidence >= 1)
|
||||
return COND_FAILED;
|
||||
if (cond->converage <= 0 || cond->converage > 1)
|
||||
return COND_FAILED;
|
||||
if (cond->type == F_NOISE_SAMPLE && env->mc <= MC_1_17)
|
||||
return COND_FAILED;
|
||||
|
||||
s = 2;
|
||||
rx1 = x1 >> s;
|
||||
@ -1739,7 +1801,6 @@ L_qm_any:
|
||||
int w = rx2 - rx1 + 1;
|
||||
int h = rz2 - rz1 + 1;
|
||||
Range r = {1<<s, rx1, rz1, w, h, s == 0 ? cond->y : cond->y >> 2, 1};
|
||||
env->init4Dim(DIM_OVERWORLD);
|
||||
sample_boime_t sample;
|
||||
sample.cond = cond;
|
||||
sample.at = at;
|
||||
@ -1749,14 +1810,24 @@ L_qm_any:
|
||||
sample.zsum = 0;
|
||||
sample.imax = imax;
|
||||
sample.cent = cent;
|
||||
sample.stop = abort;
|
||||
sample.stop = env->stop;
|
||||
|
||||
uint64_t rng;
|
||||
setSeed(&rng, env->seed);
|
||||
|
||||
int ok = monteCarloBiomes(
|
||||
&env->g, r, &rng, cond->converage, cond->confidence,
|
||||
&f_biome_sampler, &sample);
|
||||
int (*f)(Generator *, int, int, int, int, void *);
|
||||
|
||||
if (cond->type == F_NOISE_SAMPLE)
|
||||
{
|
||||
env->init4Noise(cond->para, cond->octave);
|
||||
f = f_noise_sampler;
|
||||
}
|
||||
else
|
||||
{
|
||||
env->init4Dim(DIM_OVERWORLD);
|
||||
f = f_biome_sampler;
|
||||
}
|
||||
int ok = monteCarloBiomes(&env->g, r, &rng, cond->converage, cond->confidence, f, &sample);
|
||||
if (imax && cond->count == 1)
|
||||
{
|
||||
*imax = sample.n;
|
||||
@ -1780,7 +1851,7 @@ L_qm_any:
|
||||
case F_BIOME_4_RIVER:
|
||||
case F_BIOME_256_OTEMP:
|
||||
|
||||
if (env->mc >= MC_1_18)
|
||||
if (env->mc > MC_1_17)
|
||||
return COND_FAILED;
|
||||
|
||||
s = cond->type == F_BIOME_4_RIVER ? 2 : 8;
|
||||
@ -1791,15 +1862,15 @@ L_qm_any:
|
||||
cent->x = (x1 + x2) >> 1;
|
||||
cent->z = (z1 + z2) >> 1;
|
||||
if (imax) *imax = 1;
|
||||
if (pass == PASS_FAST_48)
|
||||
if (env->searchpass == PASS_FAST_48)
|
||||
return COND_MAYBE_POS_VALID;
|
||||
if (pass == PASS_FULL_48)
|
||||
if (env->searchpass == PASS_FULL_48)
|
||||
{
|
||||
if (env->mc < MC_1_13 || cond->type != F_BIOME_256_OTEMP)
|
||||
return COND_MAYBE_POS_VALID;
|
||||
}
|
||||
valid = COND_FAILED;
|
||||
if (rx2 >= rx1 || rz2 >= rz1 || !*abort)
|
||||
if (rx2 >= rx1 || rz2 >= rz1 || !*env->stop)
|
||||
{
|
||||
int w = rx2-rx1+1;
|
||||
int h = rz2-rz1+1;
|
||||
@ -1819,7 +1890,7 @@ L_qm_any:
|
||||
|
||||
|
||||
case F_TEMPS:
|
||||
if (env->mc >= MC_1_18)
|
||||
if (env->mc > MC_1_17)
|
||||
return COND_FAILED;
|
||||
rx1 = x1 >> 10;
|
||||
rz1 = z1 >> 10;
|
||||
@ -1828,7 +1899,7 @@ L_qm_any:
|
||||
cent->x = (x1 + x2) >> 1;
|
||||
cent->z = (z1 + z2) >> 1;
|
||||
if (imax) *imax = 1;
|
||||
if (pass != PASS_FULL_64)
|
||||
if (env->searchpass != PASS_FULL_64)
|
||||
return COND_MAYBE_POS_VALID;
|
||||
env->init4Dim(DIM_OVERWORLD);
|
||||
if (checkForTemps(&env->g.ls, env->seed, rx1, rz1, rx2-rx1+1, rz2-rz1+1, cond->temps))
|
||||
@ -1857,11 +1928,11 @@ L_qm_any:
|
||||
cent->x = (x1 + x2) >> 1;
|
||||
cent->z = (z1 + z2) >> 1;
|
||||
if (imax) *imax = 1;
|
||||
if (pass == PASS_FAST_48)
|
||||
if (env->searchpass == PASS_FAST_48)
|
||||
return COND_MAYBE_POS_VALID;
|
||||
// the Nether and End require only the 48-bit seed
|
||||
// (except voronoi uses the full 64-bits)
|
||||
if (pass != PASS_FULL_64 && (finfo.dep64 || s == 0))
|
||||
if (env->searchpass != PASS_FULL_64 && (finfo.dep64 || s == 0))
|
||||
return COND_MAYBE_POS_VALID;
|
||||
else
|
||||
{
|
||||
@ -1870,14 +1941,14 @@ L_qm_any:
|
||||
int y = (s == 0 ? cond->y : cond->y >> 2);
|
||||
Range r = {1<<s, rx1, rz1, w, h, y, 1};
|
||||
valid = checkForBiomes(&env->g, NULL, r, finfo.dim, env->seed,
|
||||
&cond->bf, (volatile char*)abort) > 0;
|
||||
&cond->bf, (volatile char*)env->stop) > 0;
|
||||
}
|
||||
return valid ? COND_OK : COND_FAILED;
|
||||
|
||||
|
||||
case F_BIOME_CENTER:
|
||||
case F_BIOME_CENTER_256:
|
||||
if (pass == PASS_FULL_64)
|
||||
if (env->searchpass == PASS_FULL_64)
|
||||
{
|
||||
s = cond->type == F_BIOME_CENTER ? 2 : 8;
|
||||
rx1 = x1 >> s;
|
||||
@ -1893,7 +1964,7 @@ L_qm_any:
|
||||
{ // exclusion
|
||||
icnt = getBiomeCenters(
|
||||
cent, NULL, 1, &env->g, r, cond->biomeId, cond->biomeSize, cond->tol,
|
||||
(volatile char*)abort
|
||||
(volatile char*)env->stop
|
||||
);
|
||||
if (icnt == 0)
|
||||
{
|
||||
@ -1907,7 +1978,7 @@ L_qm_any:
|
||||
{ // just check there are at least *inst (== cond->count) instances
|
||||
*imax = icnt = getBiomeCenters(
|
||||
cent, NULL, cond->count, &env->g, r, cond->biomeId, cond->biomeSize, cond->tol,
|
||||
(volatile char*)abort
|
||||
(volatile char*)env->stop
|
||||
);
|
||||
if (cond->skipref && icnt > 0)
|
||||
{ // remove origin instance
|
||||
@ -1928,7 +1999,7 @@ L_qm_any:
|
||||
{ // we need the average position of all instances
|
||||
icnt = getBiomeCenters(
|
||||
&p[0], NULL, MAX_INSTANCES, &env->g, r, cond->biomeId, cond->biomeSize, cond->tol,
|
||||
(volatile char*)abort
|
||||
(volatile char*)env->stop
|
||||
);
|
||||
xt = zt = 0;
|
||||
int j = 0;
|
||||
@ -1952,13 +2023,13 @@ L_qm_any:
|
||||
return COND_MAYBE_POS_INVAL;
|
||||
|
||||
case F_CLIMATE_MINMAX:
|
||||
if (env->mc < MC_1_18 || cond->para >= NP_MAX)
|
||||
if (env->mc <= MC_1_17 || cond->para >= NP_MAX)
|
||||
return COND_FAILED;
|
||||
rx1 = x1 >> 2;
|
||||
rz1 = z1 >> 2;
|
||||
rx2 = x2 >> 2;
|
||||
rz2 = z2 >> 2;
|
||||
if (pass != PASS_FULL_64)
|
||||
if (env->searchpass != PASS_FULL_64)
|
||||
return COND_MAYBE_POS_INVAL;
|
||||
{
|
||||
track_minmax_t info = {at, at, +INFINITY, -INFINITY};
|
||||
@ -2000,7 +2071,7 @@ L_qm_any:
|
||||
}
|
||||
|
||||
case F_CLIMATE_NOISE:
|
||||
if (env->mc < MC_1_18)
|
||||
if (env->mc <= MC_1_17)
|
||||
return COND_FAILED;
|
||||
rx1 = x1 >> 2;
|
||||
rz1 = z1 >> 2;
|
||||
@ -2009,8 +2080,9 @@ L_qm_any:
|
||||
cent->x = (x1 + x2) >> 1;
|
||||
cent->z = (z1 + z2) >> 1;
|
||||
if (imax) *imax = 1;
|
||||
if (pass != PASS_FULL_64)
|
||||
if (env->searchpass != PASS_FULL_64)
|
||||
return COND_MAYBE_POS_VALID;
|
||||
else
|
||||
{
|
||||
int w = rx2 - rx1 + 1;
|
||||
int h = rz2 - rz1 + 1;
|
||||
@ -2069,7 +2141,7 @@ L_qm_any:
|
||||
cent->x = x1;
|
||||
cent->z = z1;
|
||||
if (imax) *imax = 1;
|
||||
if (pass != PASS_FULL_64)
|
||||
if (env->searchpass != PASS_FULL_64)
|
||||
return COND_MAYBE_POS_VALID;
|
||||
env->init4Dim(DIM_OVERWORLD);
|
||||
env->prepareSurfaceNoise(DIM_OVERWORLD);
|
||||
|
63
src/search.h
63
src/search.h
@ -90,6 +90,7 @@ enum
|
||||
F_WELL,
|
||||
F_TRAILS,
|
||||
F_BIOME_SAMPLE,
|
||||
F_NOISE_SAMPLE,
|
||||
// new filters should be added here at the end to keep some downwards compatibility
|
||||
FILTER_MAX,
|
||||
};
|
||||
@ -308,15 +309,23 @@ static const struct FilterList : private FilterInfo
|
||||
};
|
||||
|
||||
list[F_CLIMATE_NOISE] = FilterInfo{
|
||||
CAT_BIOMES, 0, LOC_REC, 0, 4, BR_NONE, MC_1_18, MC_NEWEST, 0, 0, disp++,
|
||||
CAT_BIOMES, 1, LOC_REC, 0, 4, BR_NONE, MC_1_18, MC_NEWEST, 0, 0, disp++,
|
||||
"overworld",
|
||||
QT_TRANSLATE_NOOP("Filter", "Climate parameters"),
|
||||
QT_TRANSLATE_NOOP("Filter",
|
||||
"Custom limits for the required and allowed climate noise parameters that "
|
||||
"the specified area should cover.")
|
||||
};
|
||||
list[F_NOISE_SAMPLE] = FilterInfo{
|
||||
CAT_BIOMES, 1, LOC_RAD, 0, 4, BR_SPLIT, MC_1_18, MC_NEWEST, 0, 0, disp++,
|
||||
"overworld",
|
||||
QT_TRANSLATE_NOOP("Filter", "Climate noise samples"),
|
||||
QT_TRANSLATE_NOOP("Filter",
|
||||
"Samples climate noise in a given area to find if a proportion of the "
|
||||
"biomes match a set of allowed biomes.")
|
||||
};
|
||||
list[F_CLIMATE_MINMAX] = FilterInfo{
|
||||
CAT_BIOMES, 0, LOC_REC, 0, 4, BR_NONE, MC_1_18, MC_NEWEST, 0, 0, disp++,
|
||||
CAT_BIOMES, 1, LOC_REC, 0, 4, BR_NONE, MC_1_18, MC_NEWEST, 0, 0, disp++,
|
||||
"overworld",
|
||||
QT_TRANSLATE_NOOP("Filter", "Locate climate extreme"),
|
||||
QT_TRANSLATE_NOOP("Filter",
|
||||
@ -358,7 +367,7 @@ static const struct FilterList : private FilterInfo
|
||||
""
|
||||
};
|
||||
list[F_HEIGHT] = FilterInfo{
|
||||
CAT_OTHER, 0, LOC_POS, 0, 4, BR_NONE, MC_1_1, MC_NEWEST, 0, 0, disp++,
|
||||
CAT_OTHER, 1, LOC_POS, 0, 4, BR_NONE, MC_1_1, MC_NEWEST, 0, 0, disp++,
|
||||
"height",
|
||||
QT_TRANSLATE_NOOP("Filter", "Surface height"),
|
||||
QT_TRANSLATE_NOOP("Filter",
|
||||
@ -446,7 +455,7 @@ static const struct FilterList : private FilterInfo
|
||||
list[F_RUINS] = FilterInfo{
|
||||
CAT_STRUCT, 1, LOC_RAD, Ocean_Ruin, 1, BR_CLUST, MC_1_13, MC_NEWEST, 0, 0, disp++,
|
||||
"ruins",
|
||||
QT_TRANSLATE_NOOP("Filter", "Ocean ruins"),
|
||||
QT_TRANSLATE_NOOP("Filter", "Ocean ruin"),
|
||||
""
|
||||
};
|
||||
|
||||
@ -489,7 +498,7 @@ static const struct FilterList : private FilterInfo
|
||||
};
|
||||
|
||||
list[F_TRAILS] = FilterInfo{
|
||||
CAT_STRUCT, 1, LOC_RAD, Trail_Ruin, 1, BR_CLUST, MC_1_20, MC_NEWEST, 0, 0, disp++,
|
||||
CAT_STRUCT, 1, LOC_RAD, Trail_Ruins, 1, BR_CLUST, MC_1_20, MC_NEWEST, 0, 0, disp++,
|
||||
"trails",
|
||||
QT_TRANSLATE_NOOP("Filter", "Trail ruins"),
|
||||
""
|
||||
@ -637,6 +646,24 @@ static_assert(
|
||||
"Layout of Condition has changed!"
|
||||
);
|
||||
|
||||
|
||||
#define MAX_INSTANCES 4096 // should be at least 128
|
||||
|
||||
enum
|
||||
{
|
||||
COND_FAILED = 0, // seed does not meet the condition
|
||||
COND_MAYBE_POS_INVAL = 1, // search pass insufficient for result
|
||||
COND_MAYBE_POS_VALID = 2, // search pass insufficient, but known center
|
||||
COND_OK = 3, // seed satisfies the condition
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PASS_FAST_48, // only do fast checks that do not require biome gen
|
||||
PASS_FULL_48, // include possible biome checks for 48-bit seeds
|
||||
PASS_FULL_64, // run full test on a 64-bit seed
|
||||
};
|
||||
|
||||
struct ConditionTree
|
||||
{
|
||||
std::vector<Condition> condvec;
|
||||
@ -658,6 +685,9 @@ struct SearchThreadEnv
|
||||
int surfdim;
|
||||
int octaves;
|
||||
|
||||
int searchpass;
|
||||
std::atomic_bool *stop;
|
||||
|
||||
std::map<uint64_t, lua_State*> l_states;
|
||||
|
||||
SearchThreadEnv();
|
||||
@ -671,24 +701,6 @@ struct SearchThreadEnv
|
||||
void prepareSurfaceNoise(int dim);
|
||||
};
|
||||
|
||||
|
||||
#define MAX_INSTANCES 4096 // should be at least 128
|
||||
|
||||
enum
|
||||
{
|
||||
COND_FAILED = 0, // seed does not meet the condition
|
||||
COND_MAYBE_POS_INVAL = 1, // search pass insufficient for result
|
||||
COND_MAYBE_POS_VALID = 2, // search pass insufficient, but known center
|
||||
COND_OK = 3, // seed satisfies the condition
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PASS_FAST_48, // only do fast checks that do not require biome gen
|
||||
PASS_FULL_48, // include possible biome checks for 48-bit seeds
|
||||
PASS_FULL_64, // run full test on a 64-bit seed
|
||||
};
|
||||
|
||||
/* Checks if a seed satisfies the conditions tree.
|
||||
* Returns the lowest condition fulfillment status.
|
||||
*/
|
||||
@ -696,15 +708,12 @@ int testTreeAt(
|
||||
Pos at, // relative origin
|
||||
SearchThreadEnv * env, // thread-local environment
|
||||
int pass, // search pass
|
||||
std::atomic_bool * abort, // abort signal
|
||||
Pos * path = 0 // ok trigger positions
|
||||
Pos * path // ok trigger positions
|
||||
);
|
||||
|
||||
int testCondAt(
|
||||
Pos at, // relative origin
|
||||
SearchThreadEnv * env, // thread-local environment
|
||||
int pass, // search pass
|
||||
std::atomic_bool * abort, // abort signal
|
||||
Pos * cent, // output center position(s)
|
||||
int * imax, // max instances (NULL for avg)
|
||||
const Condition * cond // condition to check
|
||||
|
@ -129,7 +129,7 @@ bool Session::load(QWidget *widget, QTextStream& stream, bool quiet)
|
||||
SearchMaster::SearchMaster(QWidget *parent)
|
||||
: QObject(parent)
|
||||
, mutex()
|
||||
, abort()
|
||||
, stop()
|
||||
, proghist()
|
||||
, progtimer()
|
||||
, itemtimer()
|
||||
@ -151,11 +151,12 @@ SearchMaster::SearchMaster(QWidget *parent)
|
||||
, smax()
|
||||
, isdone()
|
||||
{
|
||||
env.stop = &stop;
|
||||
}
|
||||
|
||||
SearchMaster::~SearchMaster()
|
||||
{
|
||||
stop();
|
||||
stopSearch();
|
||||
}
|
||||
|
||||
bool SearchMaster::set(QWidget *widget, const Session& s)
|
||||
@ -313,7 +314,7 @@ bool SearchMaster::set(QWidget *widget, const Session& s)
|
||||
this->smin = s.sc.smin;
|
||||
this->smax = s.sc.smax;
|
||||
this->isdone = false;
|
||||
this->abort = false;
|
||||
this->stop = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -393,7 +394,7 @@ static bool applyTranspose(std::vector<uint64_t>& slist,
|
||||
return !slist.empty();
|
||||
}
|
||||
|
||||
void SearchMaster::presearch()
|
||||
void SearchMaster::preSearch()
|
||||
{
|
||||
uint64_t sstart = seed;
|
||||
|
||||
@ -567,13 +568,13 @@ void SearchMaster::presearch()
|
||||
}
|
||||
}
|
||||
|
||||
void SearchMaster::start()
|
||||
void SearchMaster::startSearch()
|
||||
{
|
||||
stop();
|
||||
abort = false;
|
||||
presearch();
|
||||
stopSearch();
|
||||
stop = false;
|
||||
preSearch();
|
||||
|
||||
if (abort)
|
||||
if (stop)
|
||||
{
|
||||
emit searchFinish(false);
|
||||
return;
|
||||
@ -607,9 +608,9 @@ void SearchMaster::start()
|
||||
}
|
||||
}
|
||||
|
||||
void SearchMaster::stop()
|
||||
void SearchMaster::stopSearch()
|
||||
{
|
||||
abort = true;
|
||||
stop = true;
|
||||
if (workers.empty())
|
||||
return;
|
||||
|
||||
@ -871,10 +872,10 @@ bool SearchMaster::requestItem(SearchWorker *item)
|
||||
high = 0;
|
||||
low++;
|
||||
|
||||
for (; low <= MASK48 && !abort; low++)
|
||||
for (; low <= MASK48 && !stop; low++)
|
||||
{
|
||||
env.setSeed(low);
|
||||
if (testTreeAt(origin, &env, PASS_FAST_48, &abort)
|
||||
if (testTreeAt(origin, &env, PASS_FAST_48, nullptr)
|
||||
!= COND_FAILED)
|
||||
{
|
||||
break;
|
||||
@ -909,7 +910,7 @@ void SearchMaster::onWorkerFinished()
|
||||
for (SearchWorker *worker: workers)
|
||||
delete worker;
|
||||
workers.clear();
|
||||
emit searchFinish(isdone && !abort);
|
||||
emit searchFinish(isdone && !stop);
|
||||
}
|
||||
|
||||
|
||||
@ -919,7 +920,6 @@ SearchWorker::SearchWorker(SearchMaster *master)
|
||||
{
|
||||
this->slist = master->slist.empty() ? NULL : master->slist.data();
|
||||
this->len = master->slist.size();
|
||||
this->abort = &master->abort;
|
||||
|
||||
this->prog = master->prog;
|
||||
this->idx = master->idx;
|
||||
@ -927,12 +927,11 @@ SearchWorker::SearchWorker(SearchMaster *master)
|
||||
this->scnt = 0;
|
||||
this->seed = master->seed;
|
||||
|
||||
this->env = new SearchThreadEnv();
|
||||
this->env.stop = &master->stop;
|
||||
}
|
||||
|
||||
SearchWorker::~SearchWorker()
|
||||
{
|
||||
delete env;
|
||||
}
|
||||
|
||||
bool SearchWorker::getNextItem()
|
||||
@ -944,25 +943,21 @@ bool SearchWorker::getNextItem()
|
||||
void SearchWorker::run()
|
||||
{
|
||||
Pos origin = {0,0};
|
||||
env->init(master->mc, master->large, master->condtree);
|
||||
|
||||
volatile char b[1024*1024];
|
||||
for (size_t i = 0; i < sizeof(b); i++)
|
||||
b[i] = (char)i + b[i % 256];
|
||||
env.init(master->mc, master->large, master->condtree);
|
||||
|
||||
switch (master->searchtype)
|
||||
{
|
||||
case SEARCH_LIST:
|
||||
while (!*abort && getNextItem())
|
||||
while (!*env.stop && getNextItem())
|
||||
{ // seed = slist[..]
|
||||
uint64_t ie = idx+scnt < len ? idx+scnt : len;
|
||||
for (uint64_t i = idx; i < ie; i++)
|
||||
{
|
||||
seed = slist[i];
|
||||
env->setSeed(seed);
|
||||
if (testTreeAt(origin, env, PASS_FULL_64, abort) == COND_OK)
|
||||
env.setSeed(seed);
|
||||
if (testTreeAt(origin, &env, PASS_FULL_64, nullptr) == COND_OK)
|
||||
{
|
||||
if (!*abort)
|
||||
if (!*env.stop)
|
||||
emit result(seed);
|
||||
}
|
||||
}
|
||||
@ -972,7 +967,7 @@ void SearchWorker::run()
|
||||
break;
|
||||
|
||||
case SEARCH_48ONLY:
|
||||
while (!*abort && getNextItem())
|
||||
while (!*env.stop && getNextItem())
|
||||
{
|
||||
if (slist)
|
||||
{
|
||||
@ -980,10 +975,10 @@ void SearchWorker::run()
|
||||
for (uint64_t i = idx; i < ie; i++)
|
||||
{
|
||||
seed = slist[i];
|
||||
env->setSeed(seed);
|
||||
if (testTreeAt(origin, env, PASS_FULL_48, abort) != COND_FAILED)
|
||||
env.setSeed(seed);
|
||||
if (testTreeAt(origin, &env, PASS_FULL_48, nullptr) != COND_FAILED)
|
||||
{
|
||||
if (!*abort)
|
||||
if (!*env.stop)
|
||||
emit result(seed);
|
||||
}
|
||||
}
|
||||
@ -993,10 +988,10 @@ void SearchWorker::run()
|
||||
seed = sstart;
|
||||
for (int i = 0; i < scnt; i++)
|
||||
{
|
||||
env->setSeed(seed);
|
||||
if (testTreeAt(origin, env, PASS_FULL_48, abort) != COND_FAILED)
|
||||
env.setSeed(seed);
|
||||
if (testTreeAt(origin, &env, PASS_FULL_48, nullptr) != COND_FAILED)
|
||||
{
|
||||
if (!*abort)
|
||||
if (!*env.stop)
|
||||
emit result(seed);
|
||||
}
|
||||
|
||||
@ -1011,7 +1006,7 @@ void SearchWorker::run()
|
||||
break;
|
||||
|
||||
case SEARCH_INC:
|
||||
while (!*abort && getNextItem())
|
||||
while (!*env.stop && getNextItem())
|
||||
{
|
||||
if (slist)
|
||||
{ // seed = (high << 48) | slist[..]
|
||||
@ -1022,10 +1017,10 @@ void SearchWorker::run()
|
||||
{
|
||||
seed = (high << 48) | slist[lowidx];
|
||||
|
||||
env->setSeed(seed);
|
||||
if (testTreeAt(origin, env, PASS_FULL_64, abort) == COND_OK)
|
||||
env.setSeed(seed);
|
||||
if (testTreeAt(origin, &env, PASS_FULL_64, nullptr) == COND_OK)
|
||||
{
|
||||
if (!*abort)
|
||||
if (!*env.stop)
|
||||
emit result(seed);
|
||||
}
|
||||
|
||||
@ -1044,10 +1039,10 @@ void SearchWorker::run()
|
||||
seed = sstart;
|
||||
for (int i = 0; i < scnt; i++)
|
||||
{
|
||||
env->setSeed(seed);
|
||||
if (testTreeAt(origin, env, PASS_FULL_64, abort) == COND_OK)
|
||||
env.setSeed(seed);
|
||||
if (testTreeAt(origin, &env, PASS_FULL_64, nullptr) == COND_OK)
|
||||
{
|
||||
if (!*abort)
|
||||
if (!*env.stop)
|
||||
emit result(seed);
|
||||
}
|
||||
|
||||
@ -1062,7 +1057,7 @@ void SearchWorker::run()
|
||||
break;
|
||||
|
||||
case SEARCH_BLOCKS:
|
||||
while (!*abort && getNextItem())
|
||||
while (!*env.stop && getNextItem())
|
||||
{ // seed = ([..] << 48) | low
|
||||
if (slist && idx >= len)
|
||||
{
|
||||
@ -1076,8 +1071,8 @@ void SearchWorker::run()
|
||||
else
|
||||
low = sstart & MASK48;
|
||||
|
||||
env->setSeed(low);
|
||||
if (testTreeAt(origin, env, PASS_FULL_48, abort) == COND_FAILED)
|
||||
env.setSeed(low);
|
||||
if (testTreeAt(origin, &env, PASS_FULL_48, nullptr) == COND_FAILED)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -1086,10 +1081,10 @@ void SearchWorker::run()
|
||||
{
|
||||
seed = (high << 48) | low;
|
||||
|
||||
env->setSeed(seed);
|
||||
if (testTreeAt(origin, env, PASS_FULL_64, abort) == COND_OK)
|
||||
env.setSeed(seed);
|
||||
if (testTreeAt(origin, &env, PASS_FULL_64, nullptr) == COND_OK)
|
||||
{
|
||||
if (!*abort)
|
||||
if (!*env.stop)
|
||||
emit result(seed);
|
||||
}
|
||||
|
||||
|
@ -37,10 +37,10 @@ public:
|
||||
|
||||
bool set(QWidget *widget, const Session& s);
|
||||
|
||||
void presearch();
|
||||
void preSearch();
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
void startSearch();
|
||||
void stopSearch();
|
||||
|
||||
// Get search progress:
|
||||
// status : progress status summary
|
||||
@ -69,7 +69,7 @@ public:
|
||||
std::vector<SearchWorker*> workers;
|
||||
|
||||
QMutex mutex;
|
||||
std::atomic_bool abort;
|
||||
std::atomic_bool stop;
|
||||
|
||||
std::deque<TProg> proghist;
|
||||
QElapsedTimer progtimer;
|
||||
@ -114,7 +114,6 @@ public:
|
||||
|
||||
const uint64_t * slist; // candidate list
|
||||
uint64_t len; // number of candidates
|
||||
std::atomic_bool * abort;
|
||||
|
||||
/// current work item
|
||||
uint64_t prog; // search space progress
|
||||
@ -126,7 +125,7 @@ public:
|
||||
// (or the last entry in the seed list)
|
||||
|
||||
private:
|
||||
SearchThreadEnv * env;
|
||||
SearchThreadEnv env;
|
||||
};
|
||||
|
||||
|
||||
|
@ -61,6 +61,12 @@ QTreeWidgetItem *setConditionTreeItems(ConditionTree& ctree, int node, int64_t s
|
||||
return item;
|
||||
}
|
||||
|
||||
AnalysisLocations::AnalysisLocations(QObject *parent)
|
||||
: QThread(parent), wi(),stop(),sidx(),pidx()
|
||||
{
|
||||
env.stop = &stop;
|
||||
}
|
||||
|
||||
QString AnalysisLocations::set(WorldInfo wi, const std::vector<Condition>& conds)
|
||||
{
|
||||
this->wi = wi;
|
||||
@ -85,7 +91,7 @@ void AnalysisLocations::run()
|
||||
|
||||
Pos at = pos[pidx.load()];
|
||||
Pos cpos[MAX_INSTANCES] = {};
|
||||
if (testTreeAt(at, &env, PASS_FULL_64, &stop, cpos)
|
||||
if (testTreeAt(at, &env, PASS_FULL_64, cpos)
|
||||
!= COND_OK)
|
||||
{
|
||||
continue;
|
||||
|
@ -16,8 +16,7 @@ class AnalysisLocations : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AnalysisLocations(QObject *parent = nullptr)
|
||||
: QThread(parent), wi(),stop(),sidx(),pidx() {}
|
||||
explicit AnalysisLocations(QObject *parent = nullptr);
|
||||
|
||||
QString set(WorldInfo wi, const std::vector<Condition>& conds);
|
||||
|
||||
|
@ -80,7 +80,6 @@ struct RandGen
|
||||
// get a random 64-bit integer
|
||||
uint64_t getRnd64();
|
||||
|
||||
|
||||
enum { S_TEXT, S_NUMERIC, S_RANDOM };
|
||||
int str2seed(const QString &str, uint64_t *out);
|
||||
|
||||
|
113
src/world.cpp
113
src/world.cpp
@ -201,11 +201,15 @@ void getStructs(std::vector<VarPos> *out, const StructureConfig sconf,
|
||||
{
|
||||
SurfaceNoise sn;
|
||||
initSurfaceNoise(&sn, DIM_END, wi.seed);
|
||||
id = isViableEndCityTerrain(&g, &sn, p.x, p.z);
|
||||
if (!id)
|
||||
int y = isViableEndCityTerrain(&g, &sn, p.x, p.z);
|
||||
if (!y)
|
||||
continue;
|
||||
int n = getEndCityPieces(pieces, wi.seed, p.x >> 4, p.z >> 4);
|
||||
vp.pieces.assign(pieces, pieces+n);
|
||||
if (n)
|
||||
{
|
||||
vp.pieces.assign(pieces, pieces+n);
|
||||
vp.pieces[0].bb0.y = y; // height of end city pieces are relative to surface
|
||||
}
|
||||
}
|
||||
else if (sconf.structType == Ruined_Portal || sconf.structType == Ruined_Portal_N)
|
||||
{
|
||||
@ -235,12 +239,12 @@ void getStructs(std::vector<VarPos> *out, const StructureConfig sconf,
|
||||
|
||||
static QMutex g_mutex;
|
||||
|
||||
static qreal cubic_hermite(qreal p[4], qreal u)
|
||||
static float cubic_hermite(float p[4], float u)
|
||||
{
|
||||
qreal a = p[1];
|
||||
qreal b = 0.5 * (-p[0] + p[2]);
|
||||
qreal c = p[0] - 2.5*p[1] + 2*p[2] - 0.5*p[3];
|
||||
qreal d = 0.5 * (-p[0] + 3*p[1] - 3*p[2] + p[3]);
|
||||
float a = p[1];
|
||||
float b = 0.5 * (-p[0] + p[2]);
|
||||
float c = p[0] - 2.5*p[1] + 2*p[2] - 0.5*p[3];
|
||||
float d = 0.5 * (-p[0] + 3*p[1] - 3*p[2] + p[3]);
|
||||
return a + b*u + c*u*u + d*u*u*u;
|
||||
}
|
||||
|
||||
@ -262,21 +266,28 @@ void applyHeightShading(unsigned char *rgb, Range r,
|
||||
px -= bd; pz -= bd;
|
||||
pw += 2*bd; ph += 2*bd;
|
||||
}
|
||||
std::vector<qreal> buf(pw * ph);
|
||||
for (int j = 0; j < ph; j++)
|
||||
std::vector<float> buf(pw * ph);
|
||||
if (ps == 0)
|
||||
{
|
||||
for (int i = 0; i < pw; i++)
|
||||
mapApproxHeight(&buf[0], 0, g, sn, px, pz, pw, ph);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0; j < ph; j++)
|
||||
{
|
||||
if (abort && *abort) return;
|
||||
int samplex = (((px + i) << ps)) * r.scale / 4;
|
||||
int samplez = (((pz + j) << ps)) * r.scale / 4;
|
||||
float y = 0;
|
||||
mapApproxHeight(&y, 0, g, sn, samplex, samplez, 1, 1);
|
||||
buf[j*pw+i] = y;
|
||||
for (int i = 0; i < pw; i++)
|
||||
{
|
||||
if (abort && *abort) return;
|
||||
int samplex = (((px + i) << ps)) * r.scale / 4;
|
||||
int samplez = (((pz + j) << ps)) * r.scale / 4;
|
||||
float y = 0;
|
||||
mapApproxHeight(&y, 0, g, sn, samplex, samplez, 1, 1);
|
||||
buf[j*pw+i] = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
// interpolate height
|
||||
std::vector<qreal> height((w+2) * (h+2));
|
||||
std::vector<float> height((w+2) * (h+2));
|
||||
for (int j = 0; j < h+2; j++)
|
||||
{
|
||||
for (int i = 0; i < w+2; i++)
|
||||
@ -284,12 +295,12 @@ void applyHeightShading(unsigned char *rgb, Range r,
|
||||
if (abort && *abort) return;
|
||||
int pi = ((x + i - 1) >> ps) - px - bd;
|
||||
int pj = ((z + j - 1) >> ps) - pz - bd;
|
||||
qreal di = ((x + i - 1) & st) / (qreal)(st + 1);
|
||||
qreal dj = ((z + j - 1) & st) / (qreal)(st + 1);
|
||||
qreal v = 0;
|
||||
float di = ((x + i - 1) & st) / (float)(st + 1);
|
||||
float dj = ((z + j - 1) & st) / (float)(st + 1);
|
||||
float v = 0;
|
||||
if (bicubic)
|
||||
{
|
||||
qreal p[] = {
|
||||
float p[] = {
|
||||
cubic_hermite(&buf.at((pj+0)*pw + pi), di),
|
||||
cubic_hermite(&buf.at((pj+1)*pw + pi), di),
|
||||
cubic_hermite(&buf.at((pj+2)*pw + pi), di),
|
||||
@ -299,10 +310,10 @@ void applyHeightShading(unsigned char *rgb, Range r,
|
||||
}
|
||||
else // bilinear
|
||||
{
|
||||
qreal v00 = buf.at((pj+0)*pw + pi+0);
|
||||
qreal v01 = buf.at((pj+0)*pw + pi+1);
|
||||
qreal v10 = buf.at((pj+1)*pw + pi+0);
|
||||
qreal v11 = buf.at((pj+1)*pw + pi+1);
|
||||
float v00 = buf.at((pj+0)*pw + pi+0);
|
||||
float v01 = buf.at((pj+0)*pw + pi+1);
|
||||
float v10 = buf.at((pj+1)*pw + pi+0);
|
||||
float v11 = buf.at((pj+1)*pw + pi+1);
|
||||
v = lerp2(di, dj, v00, v01, v10, v11);
|
||||
}
|
||||
height[j*(w+2)+i] = v;
|
||||
@ -310,24 +321,24 @@ void applyHeightShading(unsigned char *rgb, Range r,
|
||||
}
|
||||
if (abort && *abort) return;
|
||||
// apply shading based on height changes
|
||||
qreal mul = 0.25 / r.scale;
|
||||
qreal lout = 0.65;
|
||||
qreal lmin = 0.5;
|
||||
qreal lmax = 1.5;
|
||||
qreal ymax = r.scale == 1 ? r.y : r.y << 2;
|
||||
float mul = 0.25 / r.scale;
|
||||
float lout = 0.65;
|
||||
float lmin = 0.5;
|
||||
float lmax = 1.5;
|
||||
float ymax = r.scale == 1 ? r.y : r.y << 2;
|
||||
for (int j = 0; j < h; j++)
|
||||
{
|
||||
for (int i = 0; i < w; i++)
|
||||
{
|
||||
int tw = w+2;
|
||||
qreal t01 = height[(j+0)*tw + i+1];
|
||||
qreal t10 = height[(j+1)*tw + i+0];
|
||||
qreal t11 = height[(j+1)*tw + i+1];
|
||||
qreal t12 = height[(j+1)*tw + i+2];
|
||||
qreal t21 = height[(j+2)*tw + i+1];
|
||||
qreal d0 = t01 + t10;
|
||||
qreal d1 = t12 + t21;
|
||||
qreal light = 1.0;
|
||||
float t01 = height[(j+0)*tw + i+1];
|
||||
float t10 = height[(j+1)*tw + i+0];
|
||||
float t11 = height[(j+1)*tw + i+1];
|
||||
float t12 = height[(j+1)*tw + i+2];
|
||||
float t21 = height[(j+2)*tw + i+1];
|
||||
float d0 = t01 + t10;
|
||||
float d1 = t12 + t21;
|
||||
float light = 1.0;
|
||||
uchar *col = rgb + 3*(j*w + i);
|
||||
if (mode == HV_GRAYSCALE)
|
||||
{
|
||||
@ -336,7 +347,7 @@ void applyHeightShading(unsigned char *rgb, Range r,
|
||||
col[0] = 0xff; col[1] = col[2] = 0;
|
||||
continue;
|
||||
}
|
||||
qreal v = t11;
|
||||
float v = t11;
|
||||
uchar c = (v <= 0) ? 0 : (v > 0xff) ? 0xff : (uchar)(v);
|
||||
col[0] = col[1] = col[2] = c;
|
||||
continue;
|
||||
@ -348,14 +359,14 @@ void applyHeightShading(unsigned char *rgb, Range r,
|
||||
if (light > lmax) light = lmax;
|
||||
if (mode == HV_CONTOURS || mode == HV_CONTOURS_SHADING)
|
||||
{
|
||||
qreal spacing = 16.0;
|
||||
qreal tmin = std::min({t01, t10, t12, t21});
|
||||
float spacing = 16.0;
|
||||
float tmin = std::min({t01, t10, t12, t21});
|
||||
if (floor(tmin / spacing) != floor(t11 / spacing))
|
||||
light *= 0.5;
|
||||
}
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
qreal c = col[k] * light;
|
||||
float c = col[k] * light;
|
||||
col[k] = (c <= 0) ? 0 : (c > 0xff) ? 0xff : (uchar)(c);
|
||||
}
|
||||
}
|
||||
@ -401,7 +412,7 @@ void Quad::run()
|
||||
int nptype = -1;
|
||||
if (g->mc >= MC_1_18) nptype = g->bn.nptype;
|
||||
if (g->mc <= MC_B1_7) nptype = g->bnb.nptype;
|
||||
if (dim == 0 && nptype >= 0)
|
||||
if (dim == DIM_OVERWORLD && nptype >= 0)
|
||||
{ // climate parameter
|
||||
const int *extremes = getBiomeParaExtremes(g->mc);
|
||||
int cmin = extremes[nptype*2 + 0];
|
||||
@ -420,7 +431,7 @@ void Quad::run()
|
||||
g_mutex.unlock();
|
||||
biomesToImage(rgb, g_biomeColors, biomes, w, h, 1, 1);
|
||||
|
||||
if (lopt.mode == LOPT_HEIGHT_4 && dim == 0)
|
||||
if (lopt.mode == LOPT_HEIGHT_4)
|
||||
{
|
||||
int stepbits = (hd ? 0 : 2);
|
||||
applyHeightShading(rgb, r, g, sn, stepbits, lopt.disp[lopt.mode], false, isdel);
|
||||
@ -782,7 +793,7 @@ void QWorld::setDim(int dim, LayerOpt lopt)
|
||||
this->dim = dim;
|
||||
this->lopt = lopt;
|
||||
applySeed(&g, dim, wi.seed);
|
||||
initSurfaceNoise(&sn, DIM_OVERWORLD, g.seed);
|
||||
initSurfaceNoise(&sn, dim, g.seed);
|
||||
|
||||
int pixs, lcnt;
|
||||
if (g.mc >= MC_1_18 || dim != DIM_OVERWORLD)
|
||||
@ -862,15 +873,17 @@ QString QWorld::getBiomeName(Pos p)
|
||||
return c + "=" + QString::number(id);
|
||||
}
|
||||
QString ret = getBiomeDisplay(wi.mc, id);
|
||||
if (lopt.mode == LOPT_HEIGHT_4 && dim == DIM_OVERWORLD)
|
||||
ret = QString::asprintf("Y~%d ", estimateSurface(p)) + ret;
|
||||
if (lopt.mode == LOPT_HEIGHT_4)
|
||||
{
|
||||
int y = estimateSurface(p);
|
||||
if (y > 0)
|
||||
ret = QString::asprintf("Y~%d ", y) + ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int QWorld::estimateSurface(Pos p)
|
||||
{
|
||||
if (dim != DIM_OVERWORLD)
|
||||
return 64;
|
||||
float y = 0;
|
||||
mapApproxHeight(&y, 0, &g, &sn, p.x>>2, p.z>>2, 1, 1);
|
||||
return (int) floor(y);
|
||||
|
Loading…
Reference in New Issue
Block a user