Added dimensions!
1) updated cubiomes 2) added Nether and End switcher to map viewer 3) added fortress, bastion and end cities and their finders 4) updated analysis function
@ -11,6 +11,9 @@ Precompiled binaries can be found for Linux and Windows under [Releases on githu
|
||||
|
||||
For the linux build you will probably have to add the executable flags to the binary (github seems to remove them upon upload).
|
||||
|
||||
For Arch linux users, the tool may be found in the [AUR](https://aur.archlinux.org/packages/cubiomes-viewer/) thanks to [JakobDev](https://github.com/JakobDev).
|
||||
|
||||
|
||||
## Build from source
|
||||
|
||||
Install Qt5 development files
|
||||
|
2
cubiomes
@ -1 +1 @@
|
||||
Subproject commit 3a6a923553eaf00145b5e162c9e37019e166ad98
|
||||
Subproject commit a4a422686e5703d4add8d910548e68843ac1cd8a
|
12
icons.qrc
@ -47,5 +47,17 @@
|
||||
<file>icons/cancel.png</file>
|
||||
<file>icons/clear.png</file>
|
||||
<file>icons/info.png</file>
|
||||
<file>icons/overworld.png</file>
|
||||
<file>icons/nether.png</file>
|
||||
<file>icons/overworld_d.png</file>
|
||||
<file>icons/the_end_d.png</file>
|
||||
<file>icons/the_end.png</file>
|
||||
<file>icons/nether_d.png</file>
|
||||
<file>icons/fortress_d.png</file>
|
||||
<file>icons/fortress.png</file>
|
||||
<file>icons/endcity_d.png</file>
|
||||
<file>icons/endcity.png</file>
|
||||
<file>icons/bastion_d.png</file>
|
||||
<file>icons/bastion.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
BIN
icons/bastion.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
icons/bastion_d.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
icons/endcity.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
icons/endcity_d.png
Normal file
After Width: | Height: | Size: 4.5 KiB |
BIN
icons/fortress.png
Normal file
After Width: | Height: | Size: 5.5 KiB |
BIN
icons/fortress_d.png
Normal file
After Width: | Height: | Size: 4.7 KiB |
BIN
icons/nether.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
icons/nether_d.png
Normal file
After Width: | Height: | Size: 6.4 KiB |
BIN
icons/overworld.png
Normal file
After Width: | Height: | Size: 836 B |
BIN
icons/overworld_d.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
icons/the_end.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
icons/the_end_d.png
Normal file
After Width: | Height: | Size: 6.6 KiB |
@ -13,8 +13,8 @@ unsigned char tempsColors[256][3];
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
initBiomes();
|
||||
initBiomeColours(biomeColors);
|
||||
initBiomeTypeColours(tempsColors);
|
||||
initBiomeColors(biomeColors);
|
||||
initBiomeTypeColors(tempsColors);
|
||||
|
||||
QApplication a(argc, argv);
|
||||
MainWindow mw;
|
||||
|
@ -71,10 +71,24 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
//ui->toolBar->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QAction *toorigin = new QAction(QIcon(":/icons/origin.png"), "Goto origin", this);
|
||||
toorigin->connect(toorigin, &QAction::triggered, [=](){ this->mapGoto(0,0,16); });
|
||||
connect(toorigin, &QAction::triggered, [=](){ this->mapGoto(0,0,16); });
|
||||
ui->toolBar->addAction(toorigin);
|
||||
ui->toolBar->addSeparator();
|
||||
|
||||
dimactions[0] = addMapAction(-1, "overworld", "Overworld");
|
||||
dimactions[1] = addMapAction(-1, "nether", "Nether");
|
||||
dimactions[2] = addMapAction(-1, "the_end", "End");
|
||||
dimgroup = new QActionGroup(this);
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
connect(dimactions[i], &QAction::triggered, [=](){ this->updateMapSeed(); });
|
||||
ui->toolBar->addAction(dimactions[i]);
|
||||
dimgroup->addAction(dimactions[i]);
|
||||
}
|
||||
dimactions[0]->setChecked(true);
|
||||
ui->toolBar->addSeparator();
|
||||
|
||||
saction.resize(STRUCT_NUM);
|
||||
addMapAction(D_GRID, "grid", "Show grid");
|
||||
addMapAction(D_SLIME, "slime", "Show slime chunks");
|
||||
@ -93,6 +107,11 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
addMapAction(D_PORTAL, "portal", "Show ruined portals");
|
||||
addMapAction(D_SPAWN, "spawn", "Show world spawn");
|
||||
addMapAction(D_STRONGHOLD, "stronghold", "Show strongholds");
|
||||
ui->toolBar->addSeparator();
|
||||
addMapAction(D_FORTESS, "fortress", "Show nether fortresses");
|
||||
addMapAction(D_BASTION, "bastion", "Show bastions");
|
||||
ui->toolBar->addSeparator();
|
||||
addMapAction(D_ENDCITY, "endcity", "Show end cities");
|
||||
|
||||
saction[D_GRID]->setChecked(true);
|
||||
|
||||
@ -135,9 +154,12 @@ QAction *MainWindow::addMapAction(int stype, const char *iconpath, const char *t
|
||||
icon.addPixmap(QPixmap(inam + "_d.png"), QIcon::Normal, QIcon::Off);
|
||||
QAction *action = new QAction(icon, tip, this);
|
||||
action->setCheckable(true);
|
||||
action->connect(action, &QAction::toggled, [=](bool state){ this->onActionMapToggled(stype, state); });
|
||||
ui->toolBar->addAction(action);
|
||||
saction[stype] = action;
|
||||
if (stype >= 0)
|
||||
{
|
||||
action->connect(action, &QAction::toggled, [=](bool state){ this->onActionMapToggled(stype, state); });
|
||||
saction[stype] = action;
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
||||
@ -172,7 +194,7 @@ bool MainWindow::getSeed(int *mc, int64_t *seed, bool applyrand)
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool MainWindow::setSeed(int mc, int64_t seed)
|
||||
bool MainWindow::setSeed(int mc, int64_t seed, int dim)
|
||||
{
|
||||
const char *mcstr = mc2str(mc);
|
||||
if (!mcstr)
|
||||
@ -181,12 +203,25 @@ bool MainWindow::setSeed(int mc, int64_t seed)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dim == INT_MAX)
|
||||
dim = getDim();
|
||||
|
||||
ui->comboBoxMC->setCurrentText(mcstr);
|
||||
ui->seedEdit->setText(QString::asprintf("%" PRId64, seed));
|
||||
ui->mapView->setSeed(mc, seed);
|
||||
ui->mapView->setSeed(mc, seed, dim);
|
||||
return true;
|
||||
}
|
||||
|
||||
int MainWindow::getDim()
|
||||
{
|
||||
QAction *active = dimgroup->checkedAction();
|
||||
if (active == dimactions[1])
|
||||
return -1; // nether
|
||||
if (active == dimactions[2])
|
||||
return +1; // end
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MainWindow::saveSettings()
|
||||
{
|
||||
QSettings settings("cubiomes-viewer", "cubiomes-viewer");
|
||||
@ -205,6 +240,7 @@ void MainWindow::saveSettings()
|
||||
getSeed(&mc, &seed, false);
|
||||
settings.setValue("map/mc", mc);
|
||||
settings.setValue("map/seed", (qlonglong)seed);
|
||||
settings.setValue("map/dim", getDim());
|
||||
settings.setValue("map/x", ui->mapView->getX());
|
||||
settings.setValue("map/z", ui->mapView->getZ());
|
||||
settings.setValue("map/scale", ui->mapView->getScale());
|
||||
@ -235,6 +271,14 @@ void MainWindow::loadSettings()
|
||||
|
||||
ui->mapView->setSmoothMotion(config.smoothMotion);
|
||||
|
||||
int dim = settings.value("map/dim", getDim()).toInt();
|
||||
if (dim == -1)
|
||||
dimactions[1]->setChecked(true);
|
||||
else if (dim == +1)
|
||||
dimactions[2]->setChecked(true);
|
||||
else
|
||||
dimactions[0]->setChecked(true);
|
||||
|
||||
int mc = MC_1_16;
|
||||
int64_t seed = 0;
|
||||
getSeed(&mc, &seed, true);
|
||||
@ -436,7 +480,7 @@ void MainWindow::updateMapSeed()
|
||||
int mc;
|
||||
int64_t seed;
|
||||
if (getSeed(&mc, &seed))
|
||||
ui->mapView->setSeed(mc, seed);
|
||||
setSeed(mc, seed);
|
||||
}
|
||||
|
||||
|
||||
@ -655,30 +699,62 @@ void MainWindow::on_buttonAnalysis_clicked()
|
||||
warning("Warning", "Invalid area for analysis");
|
||||
return;
|
||||
}
|
||||
if ((int64_t)(x2 - x1) * (int64_t)(z2 - z1) > 100000000LL)
|
||||
{
|
||||
QString msg = QString::asprintf(
|
||||
"Area for analysis is very large (%d, %d).\n"
|
||||
"The analysis might take a while. Do you want to continue?",
|
||||
x2-x1+1, z2-z1+1);
|
||||
int button = QMessageBox::warning(this, "Warning", msg, QMessageBox::Cancel, QMessageBox::Yes);
|
||||
if (button != QMessageBox::Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
bool everything = ui->radioEverything->isChecked();
|
||||
|
||||
int mc;
|
||||
int64_t seed;
|
||||
if (!getSeed(&mc, &seed))
|
||||
return;
|
||||
|
||||
ui->buttonAnalysis->setEnabled(false);
|
||||
update();
|
||||
QApplication::processEvents();
|
||||
|
||||
const int step = 512;
|
||||
long idcnt[256] = {0};
|
||||
int dim = getDim();
|
||||
|
||||
LayerStack g;
|
||||
setupGenerator(&g, mc);
|
||||
applySeed(&g, seed);
|
||||
int *ids = allocCache(g.entry_1, step, step);
|
||||
|
||||
long idcnt[256] = {0};
|
||||
for (int x = x1; x <= x2; x += step)
|
||||
{
|
||||
for (int z = z1; z <= z2; z += step)
|
||||
{
|
||||
int w = x2-x+1 < step ? x2-x+1 : step;
|
||||
int h = z2-z+1 < step ? z2-z+1 : step;
|
||||
genArea(g.entry_1, ids, x, z, w, h);
|
||||
|
||||
for (int i = 0; i < w*h; i++)
|
||||
idcnt[ ids[i] & 0xff ]++;
|
||||
if (everything || dim == 0)
|
||||
{
|
||||
genArea(g.entry_1, ids, x, z, w, h);
|
||||
for (int i = 0; i < w*h; i++)
|
||||
idcnt[ ids[i] & 0xff ]++;
|
||||
}
|
||||
if (everything || dim == -1)
|
||||
{
|
||||
genNetherScaled(mc, seed, 1, ids, x, z, w, h, 0, 0);
|
||||
for (int i = 0; i < w*h; i++)
|
||||
idcnt[ ids[i] & 0xff ]++;
|
||||
}
|
||||
if (everything || dim == +1)
|
||||
{
|
||||
genEndScaled(mc, seed, 1, ids, x, z, w, h);
|
||||
for (int i = 0; i < w*h; i++)
|
||||
idcnt[ ids[i] & 0xff ]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -714,13 +790,17 @@ void MainWindow::on_buttonAnalysis_clicked()
|
||||
tree->insertTopLevelItem(0, item_cat);
|
||||
|
||||
std::vector<VarPos> st;
|
||||
for (int stype = Desert_Pyramid; stype <= Treasure; stype++)
|
||||
for (int sopt = D_DESERT; sopt < D_SPAWN; sopt++)
|
||||
{
|
||||
if (!everything && !getMapView()->getShow(sopt))
|
||||
continue;
|
||||
|
||||
st.clear();
|
||||
int stype = mapopt2stype(sopt);
|
||||
StructureConfig sconf;
|
||||
if (!getConfig(stype, mc, &sconf))
|
||||
continue;
|
||||
getStructs(&st, sconf, &g, mc, seed, x1, z1, x2, z2);
|
||||
getStructs(&st, sconf, mc, seed, x1, z1, x2, z2);
|
||||
if (st.empty())
|
||||
continue;
|
||||
|
||||
@ -744,41 +824,48 @@ void MainWindow::on_buttonAnalysis_clicked()
|
||||
tree->insertTopLevelItem(stype, item_cat);
|
||||
}
|
||||
|
||||
Pos pos = getSpawn(mc, &g, NULL, seed);
|
||||
if (pos.x >= x1 && pos.x <= x2 && pos.z >= z1 && pos.z <= z2)
|
||||
if (everything || getMapView()->getShow(D_SPAWN))
|
||||
{
|
||||
item_cat = new QTreeWidgetItem(tree);
|
||||
item_cat->setText(0, "Spawn");
|
||||
item_cat->setData(1, Qt::DisplayRole, QVariant::fromValue(1));
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(item_cat);
|
||||
item->setData(0, Qt::UserRole, QVariant::fromValue(pos));
|
||||
item->setText(0, QString::asprintf("%d,\t%d", pos.x, pos.z));
|
||||
}
|
||||
|
||||
StrongholdIter sh;
|
||||
initFirstStronghold(&sh, mc, seed);
|
||||
std::vector<Pos> shp;
|
||||
while (nextStronghold(&sh, &g, NULL) > 0)
|
||||
{
|
||||
pos = sh.pos;
|
||||
Pos pos = getSpawn(mc, &g, NULL, seed);
|
||||
if (pos.x >= x1 && pos.x <= x2 && pos.z >= z1 && pos.z <= z2)
|
||||
shp.push_back(pos);
|
||||
}
|
||||
|
||||
if (!shp.empty())
|
||||
{
|
||||
item_cat = new QTreeWidgetItem(tree);
|
||||
item_cat->setText(0, "Stronghold");
|
||||
item_cat->setData(1, Qt::DisplayRole, QVariant::fromValue(shp.size()));
|
||||
for (Pos pos : shp)
|
||||
{
|
||||
item_cat = new QTreeWidgetItem(tree);
|
||||
item_cat->setText(0, "Spawn");
|
||||
item_cat->setData(1, Qt::DisplayRole, QVariant::fromValue(1));
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(item_cat);
|
||||
item->setData(0, Qt::UserRole, QVariant::fromValue(pos));
|
||||
item->setText(0, QString::asprintf("%d,\t%d", pos.x, pos.z));
|
||||
}
|
||||
}
|
||||
|
||||
if (everything || getMapView()->getShow(D_STRONGHOLD))
|
||||
{
|
||||
StrongholdIter sh;
|
||||
initFirstStronghold(&sh, mc, seed);
|
||||
std::vector<Pos> shp;
|
||||
while (nextStronghold(&sh, &g, NULL) > 0)
|
||||
{
|
||||
Pos pos = sh.pos;
|
||||
if (pos.x >= x1 && pos.x <= x2 && pos.z >= z1 && pos.z <= z2)
|
||||
shp.push_back(pos);
|
||||
}
|
||||
|
||||
if (!shp.empty())
|
||||
{
|
||||
item_cat = new QTreeWidgetItem(tree);
|
||||
item_cat->setText(0, "Stronghold");
|
||||
item_cat->setData(1, Qt::DisplayRole, QVariant::fromValue(shp.size()));
|
||||
for (Pos pos : shp)
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(item_cat);
|
||||
item->setData(0, Qt::UserRole, QVariant::fromValue(pos));
|
||||
item->setText(0, QString::asprintf("%d,\t%d", pos.x, pos.z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui->buttonExport->setEnabled(true);
|
||||
ui->buttonAnalysis->setEnabled(true);
|
||||
}
|
||||
|
||||
void MainWindow::on_buttonExport_clicked()
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <QTableWidgetItem>
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QWidget>
|
||||
#include <QAction>
|
||||
#include <QActionGroup>
|
||||
|
||||
#include <QTimer>
|
||||
#include <QThreadPool>
|
||||
@ -44,7 +46,8 @@ public:
|
||||
QAction *addMapAction(int stype, const char *iconpath, const char *tip);
|
||||
|
||||
bool getSeed(int *mc, int64_t *seed, bool applyrand = true);
|
||||
bool setSeed(int mc, int64_t seed);
|
||||
bool setSeed(int mc, int64_t seed, int dim = INT_MAX);
|
||||
int getDim();
|
||||
MapView *getMapView();
|
||||
|
||||
protected:
|
||||
@ -110,6 +113,9 @@ public:
|
||||
QTimer autosaveTimer;
|
||||
|
||||
QVector<QAction*> saction;
|
||||
QAction *dimactions[3];
|
||||
QActionGroup *dimgroup;
|
||||
|
||||
ProtoBaseDialog *protodialog;
|
||||
};
|
||||
|
||||
|
@ -62,6 +62,16 @@ QSplitter::handle:vertical {
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="labelSeed">
|
||||
<property name="toolTip">
|
||||
<string>Seed can be an integer or text. Leave empty for a random seed</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>seed:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labeMC">
|
||||
<property name="toolTip">
|
||||
@ -88,16 +98,6 @@ QSplitter::handle:vertical {
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="labelSeed">
|
||||
<property name="toolTip">
|
||||
<string>Seed can be an integer or text. Leave empty for a random seed</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>seed:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="comboBoxMC">
|
||||
<property name="toolTip">
|
||||
@ -283,7 +283,67 @@ QSplitter::handle:vertical {
|
||||
<string>Analysis</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="lineRadius">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QPushButton" name="buttonExport">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Export</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="5">
|
||||
<widget class="QTreeWidget" name="treeAnalysis">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::NoDragDrop</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>280</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>object</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>count</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<layout class="QHBoxLayout" name="layoutArea">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelX1">
|
||||
@ -380,6 +440,13 @@ QSplitter::handle:vertical {
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="3" colspan="2">
|
||||
<widget class="QPushButton" name="buttonFromVisible">
|
||||
<property name="text">
|
||||
<string>From visible</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelSquareArea">
|
||||
<property name="text">
|
||||
@ -387,31 +454,7 @@ QSplitter::handle:vertical {
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QPushButton" name="buttonExport">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Export</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="4">
|
||||
<widget class="QPushButton" name="buttonAnalysis">
|
||||
<property name="text">
|
||||
<string>Analyze</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="lineRadius">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" colspan="2">
|
||||
<item row="0" column="3" colspan="2">
|
||||
<widget class="QCheckBox" name="cboxArea">
|
||||
<property name="toolTip">
|
||||
<string>Specify manual rectangle rather than square</string>
|
||||
@ -424,55 +467,33 @@ QSplitter::handle:vertical {
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="4">
|
||||
<widget class="QTreeWidget" name="treeAnalysis">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
<item row="4" column="0" colspan="5">
|
||||
<widget class="QPushButton" name="buttonAnalysis">
|
||||
<property name="text">
|
||||
<string>Analyze</string>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::NoDragDrop</enum>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="headerDefaultSectionSize">
|
||||
<number>280</number>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>object</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>count</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2" colspan="2">
|
||||
<widget class="QPushButton" name="buttonFromVisible">
|
||||
<property name="text">
|
||||
<string>From visible</string>
|
||||
</property>
|
||||
</widget>
|
||||
<item row="2" column="0" colspan="5">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioStructs">
|
||||
<property name="text">
|
||||
<string>Selected structures</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioEverything">
|
||||
<property name="text">
|
||||
<string>Everything</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -72,7 +72,7 @@ MapView::~MapView()
|
||||
delete overlay;
|
||||
}
|
||||
|
||||
void MapView::setSeed(int mc, int64_t s)
|
||||
void MapView::setSeed(int mc, int64_t s, int dim)
|
||||
{
|
||||
prevx = focusx = getX();
|
||||
prevz = focusz = getZ();
|
||||
@ -80,7 +80,11 @@ void MapView::setSeed(int mc, int64_t s)
|
||||
if (world == NULL || world->mc != mc || world->seed != s)
|
||||
{
|
||||
delete world;
|
||||
world = new QWorld(mc, s);
|
||||
world = new QWorld(mc, s, dim);
|
||||
}
|
||||
else if (world->dim != dim)
|
||||
{
|
||||
world->setDim(dim);
|
||||
}
|
||||
settingsToWorld();
|
||||
update(2);
|
||||
@ -185,7 +189,7 @@ void MapView::paintEvent(QPaintEvent *)
|
||||
qreal bz = (cur.y() - height()/2) / blocks2pix + fz;
|
||||
Pos p = {(int)bx, (int)bz};
|
||||
overlay->pos = p;
|
||||
overlay->id = getBiomeAtPos(&world->g, p);
|
||||
overlay->id = world->getBiome(p);
|
||||
|
||||
if (QThreadPool::globalInstance()->activeThreadCount() > 0 || velx || velz)
|
||||
updatecounter = 2;
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
qreal getZ();
|
||||
qreal getScale() const { return 1.0 / blocks2pix; }
|
||||
|
||||
void setSeed(int mc, int64_t s);
|
||||
void setSeed(int mc, int64_t s, int dim);
|
||||
void setView(qreal x, qreal z, qreal scale = 0);
|
||||
|
||||
bool getShow(int stype) { return stype >= 0 && stype < STRUCT_NUM ? sshow[stype] : false; }
|
||||
|
332
src/quad.cpp
@ -9,8 +9,8 @@
|
||||
|
||||
|
||||
Quad::Quad(const Level* l, int i, int j)
|
||||
: mc(l->mc),entry(l->entry),seed(l->seed)
|
||||
, ti(i),tj(j),blocks(l->blocks),pixs(l->pixs),stype(l->stype)
|
||||
: mc(l->mc),seed(l->seed),dim(l->dim),entry(l->entry)
|
||||
, ti(i),tj(j),blocks(l->blocks),pixs(l->pixs),sopt(l->sopt)
|
||||
, rgb(),img(),spos()
|
||||
, done()
|
||||
, prio(),stopped()
|
||||
@ -26,8 +26,25 @@ Quad::~Quad()
|
||||
}
|
||||
|
||||
void getStructs(std::vector<VarPos> *out, const StructureConfig sconf,
|
||||
LayerStack *g, int mc, int64_t seed, int x0, int z0, int x1, int z1)
|
||||
int mc, int64_t seed, int x0, int z0, int x1, int z1)
|
||||
{
|
||||
union {
|
||||
LayerStack g;
|
||||
NetherNoise nn;
|
||||
EndNoise en;
|
||||
} u;
|
||||
|
||||
int dim;
|
||||
if (sconf.structType == Fortress || sconf.structType == Bastion)
|
||||
dim = -1;
|
||||
else if (sconf.structType == End_City)
|
||||
dim = +1;
|
||||
else
|
||||
{
|
||||
dim = 0;
|
||||
setupGenerator(&u.g, mc);
|
||||
}
|
||||
|
||||
int si0 = (int)floor(x0 / (qreal)(sconf.regionSize * 16));
|
||||
int sj0 = (int)floor(z0 / (qreal)(sconf.regionSize * 16));
|
||||
int si1 = (int)floor((x1-1) / (qreal)(sconf.regionSize * 16));
|
||||
@ -43,7 +60,26 @@ void getStructs(std::vector<VarPos> *out, const StructureConfig sconf,
|
||||
|
||||
if (p.x >= x0 && p.x < x1 && p.z >= z0 && p.z < z1)
|
||||
{
|
||||
int id = isViableStructurePos(sconf.structType, mc, g, seed, p.x, p.z);
|
||||
int id = 0;
|
||||
if (dim == 0)
|
||||
{
|
||||
id = isViableStructurePos(sconf.structType, mc, &u.g, seed, p.x, p.z);
|
||||
}
|
||||
else if (dim == -1)
|
||||
{
|
||||
id = isViableNetherStructurePos(sconf.structType, mc, &u.nn, seed, p.x, p.z);
|
||||
}
|
||||
else if (dim == +1)
|
||||
{
|
||||
id = isViableEndStructurePos(sconf.structType, mc, &u.en, seed, p.x, p.z);
|
||||
if (id)
|
||||
{
|
||||
SurfaceNoise sn;
|
||||
initSurfaceNoiseEnd(&sn, seed);
|
||||
id = isViableEndCityTerrain(&u.en, &sn, p.x, p.z);
|
||||
}
|
||||
}
|
||||
|
||||
if (id)
|
||||
{
|
||||
VarPos vp = { p, 0 };
|
||||
@ -60,6 +96,7 @@ void getStructs(std::vector<VarPos> *out, const StructureConfig sconf,
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Quad::run()
|
||||
{
|
||||
if (done)
|
||||
@ -67,9 +104,23 @@ void Quad::run()
|
||||
|
||||
if (pixs > 0)
|
||||
{
|
||||
int *b = allocCache(entry, pixs, pixs);
|
||||
|
||||
genArea(entry, b, ti*pixs, tj*pixs, pixs, pixs);
|
||||
int x = ti*pixs, z = tj*pixs, w = pixs, h = pixs;
|
||||
int *b = NULL;
|
||||
if (dim == -1)
|
||||
{
|
||||
b = (int*) malloc((pixs+7) * (pixs+7) * sizeof(int));
|
||||
genNetherScaled(mc, seed, blocks / pixs, b, x, z, w, h, 0, 0);
|
||||
}
|
||||
else if (dim == +1) // end
|
||||
{
|
||||
b = (int*) malloc((pixs+7) * (pixs+7) * sizeof(int));
|
||||
genEndScaled(mc, seed, blocks / pixs, b, x, z, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
b = allocCache(entry, pixs, pixs);
|
||||
genArea(entry, b, x, z, w, h);
|
||||
}
|
||||
|
||||
rgb = new uchar[pixs*pixs * 3];
|
||||
biomesToImage(rgb, biomeColors, b, pixs, pixs, 1, 1);
|
||||
@ -78,34 +129,15 @@ void Quad::run()
|
||||
}
|
||||
else
|
||||
{
|
||||
int structureType = -1;
|
||||
|
||||
switch (stype)
|
||||
{
|
||||
case D_DESERT: structureType = Desert_Pyramid; break;
|
||||
case D_JUNGLE: structureType = Jungle_Pyramid; break;
|
||||
case D_IGLOO: structureType = Igloo; break;
|
||||
case D_HUT: structureType = Swamp_Hut; break;
|
||||
case D_VILLAGE: structureType = Village; break;
|
||||
case D_MANSION: structureType = Mansion; break;
|
||||
case D_MONUMENT: structureType = Monument; break;
|
||||
case D_RUINS: structureType = Ocean_Ruin; break;
|
||||
case D_SHIPWRECK: structureType = Shipwreck; break;
|
||||
case D_TREASURE: structureType = Treasure; break;
|
||||
case D_OUTPOST: structureType = Outpost; break;
|
||||
case D_PORTAL: structureType = Ruined_Portal; break;
|
||||
}
|
||||
int structureType = mapopt2stype(sopt);
|
||||
if (structureType >= 0)
|
||||
{
|
||||
LayerStack g;
|
||||
setupGenerator(&g, mc);
|
||||
int x0 = ti*blocks, x1 = (ti+1)*blocks;
|
||||
int z0 = tj*blocks, z1 = (tj+1)*blocks;
|
||||
|
||||
std::vector<VarPos>* st = new std::vector<VarPos>();
|
||||
StructureConfig sconf;
|
||||
if (getConfig(structureType, mc, &sconf))
|
||||
getStructs(st, sconf, &g, mc, seed, x0, z0, x1, z1);
|
||||
getStructs(st, sconf, mc, seed, x0, z0, x1, z1);
|
||||
spos = st;
|
||||
}
|
||||
}
|
||||
@ -114,10 +146,10 @@ void Quad::run()
|
||||
|
||||
|
||||
Level::Level()
|
||||
: cells(),g(),entry(),seed(),mc()
|
||||
: cells(),g(),entry(),seed(),mc(),dim()
|
||||
, tx(),tz(),tw(),th()
|
||||
, scale(),blocks(),pixs()
|
||||
, stype()
|
||||
, sopt()
|
||||
{
|
||||
}
|
||||
|
||||
@ -181,64 +213,70 @@ int mapOceanMixMod(const Layer * l, int * out, int x, int z, int w, int h)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Level::init4map(int mcversion, int64_t ws, int pix, int layerscale)
|
||||
void Level::init4map(int mcversion, int64_t ws, int dim, int pix, int layerscale)
|
||||
{
|
||||
mc = mcversion;
|
||||
seed = ws;
|
||||
setupGenerator(&g, mc);
|
||||
this->mc = mcversion;
|
||||
this->seed = ws;
|
||||
this->dim = dim;
|
||||
|
||||
tx = tz = tw = th = 0;
|
||||
scale = layerscale;
|
||||
pixs = pix;
|
||||
blocks = pix * layerscale;
|
||||
stype = D_NONE;
|
||||
sopt = D_NONE;
|
||||
|
||||
switch (scale)
|
||||
if (dim == 0) // overworld
|
||||
{
|
||||
case 1:
|
||||
entry = g.entry_1;
|
||||
break;
|
||||
case 4:
|
||||
entry = g.entry_4;
|
||||
break;
|
||||
case 16:
|
||||
if (mc >= MC_1_13) {
|
||||
entry = setupLayer(&g, L_VORONOI_1, &mapOceanMixMod, mc, 1, 0, 0, &g.layers[L_SHORE_16], &g.layers[L_ZOOM_16_OCEAN]);
|
||||
} else {
|
||||
entry = g.entry_16;
|
||||
}
|
||||
break;
|
||||
case 64:
|
||||
if (mc >= MC_1_13) {
|
||||
entry = setupLayer(&g, L_VORONOI_1, &mapOceanMixMod, mc, 1, 0, 0, &g.layers[L_SUNFLOWER_64], &g.layers[L_ZOOM_64_OCEAN]);
|
||||
} else {
|
||||
entry = g.entry_64;
|
||||
}
|
||||
break;
|
||||
case 256:
|
||||
if (mc >= MC_1_13) {
|
||||
int layerid = mc >= MC_1_14 ? L_BAMBOO_256 : L_BIOME_256;
|
||||
entry = setupLayer(&g, L_VORONOI_1, &mapOceanMixMod, mc, 1, 0, 0, &g.layers[layerid], &g.layers[L_OCEAN_TEMP_256]);
|
||||
} else {
|
||||
entry = g.entry_256;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Bad scale (%d) for level\n", scale);
|
||||
exit(1);
|
||||
}
|
||||
setupGenerator(&g, mc);
|
||||
|
||||
setLayerSeed(entry, seed);
|
||||
switch (scale)
|
||||
{
|
||||
case 1:
|
||||
entry = g.entry_1;
|
||||
break;
|
||||
case 4:
|
||||
entry = g.entry_4;
|
||||
break;
|
||||
case 16:
|
||||
if (mc >= MC_1_13) {
|
||||
entry = setupLayer(&g, L_VORONOI_1, &mapOceanMixMod, mc, 1, 0, 0, &g.layers[L_SHORE_16], &g.layers[L_ZOOM_16_OCEAN]);
|
||||
} else {
|
||||
entry = g.entry_16;
|
||||
}
|
||||
break;
|
||||
case 64:
|
||||
if (mc >= MC_1_13) {
|
||||
entry = setupLayer(&g, L_VORONOI_1, &mapOceanMixMod, mc, 1, 0, 0, &g.layers[L_SUNFLOWER_64], &g.layers[L_ZOOM_64_OCEAN]);
|
||||
} else {
|
||||
entry = g.entry_64;
|
||||
}
|
||||
break;
|
||||
case 256:
|
||||
if (mc >= MC_1_13) {
|
||||
int layerid = mc >= MC_1_14 ? L_BAMBOO_256 : L_BIOME_256;
|
||||
entry = setupLayer(&g, L_VORONOI_1, &mapOceanMixMod, mc, 1, 0, 0, &g.layers[layerid], &g.layers[L_OCEAN_TEMP_256]);
|
||||
} else {
|
||||
entry = g.entry_256;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Bad scale (%d) for level\n", scale);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
setLayerSeed(entry, seed);
|
||||
}
|
||||
}
|
||||
|
||||
void Level::init4struct(int mcversion, int64_t ws, int b, int structtype, int lv)
|
||||
{
|
||||
mc = mcversion;
|
||||
dim = 0;
|
||||
seed = ws;
|
||||
blocks = b;
|
||||
pixs = -1;
|
||||
scale = -1;
|
||||
stype = structtype;
|
||||
sopt = structtype;
|
||||
viewlv = lv;
|
||||
}
|
||||
|
||||
@ -268,7 +306,7 @@ void Level::resizeLevel(std::vector<Quad*>& cache, int x, int z, int w, int h)
|
||||
int gx = c->ti - x;
|
||||
int gz = c->tj - z;
|
||||
|
||||
if (c->blocks == blocks && c->stype == stype)
|
||||
if (c->blocks == blocks && c->sopt == sopt && c->dim == dim)
|
||||
{
|
||||
// remove outside quads from schedule
|
||||
if (QThreadPool::globalInstance()->tryTake(c))
|
||||
@ -308,6 +346,8 @@ void Level::resizeLevel(std::vector<Quad*>& cache, int x, int z, int w, int h)
|
||||
{
|
||||
g->stopped = false;
|
||||
g->prio = sqdist(i-w/2, j-h/2);
|
||||
if (g->dim != dim)
|
||||
g->prio += 1000000;
|
||||
togen.push_back(g);
|
||||
}
|
||||
}
|
||||
@ -348,13 +388,15 @@ void Level::update(std::vector<Quad*>& cache, qreal bx0, qreal bz0, qreal bx1, q
|
||||
}
|
||||
|
||||
|
||||
QWorld::QWorld(int mc, int64_t seed)
|
||||
QWorld::QWorld(int mc, int64_t seed, int dim)
|
||||
: mc(mc)
|
||||
, seed(seed)
|
||||
, lv()
|
||||
, dim(dim)
|
||||
, sha()
|
||||
, lvb()
|
||||
, lvs()
|
||||
, activelv()
|
||||
, cached()
|
||||
, cachedbiomes()
|
||||
, cachedstruct()
|
||||
, cachesize()
|
||||
, spawn()
|
||||
@ -373,6 +415,7 @@ QWorld::QWorld(int mc, int64_t seed)
|
||||
{
|
||||
setupGenerator(&g, mc);
|
||||
applySeed(&g, seed);
|
||||
sha = getVoronoiSHA(seed);
|
||||
|
||||
activelv = 0;
|
||||
|
||||
@ -390,12 +433,27 @@ QWorld::QWorld(int mc, int64_t seed)
|
||||
lvs[D_TREASURE].init4struct(mc, seed, 2048, D_TREASURE, 1);
|
||||
lvs[D_OUTPOST].init4struct(mc, seed, 2048, D_OUTPOST, 2);
|
||||
lvs[D_PORTAL].init4struct(mc, seed, 2048, D_PORTAL, 1);
|
||||
lv.resize(5);
|
||||
lv[0].init4map(mc, seed, pixs, 1);
|
||||
lv[1].init4map(mc, seed, pixs, 4);
|
||||
lv[2].init4map(mc, seed, pixs, 16);
|
||||
lv[3].init4map(mc, seed, pixs, 64);
|
||||
lv[4].init4map(mc, seed, pixs, 256);
|
||||
lvs[D_FORTESS].init4struct(mc, seed, 2048, D_FORTESS, 1);
|
||||
lvs[D_BASTION].init4struct(mc, seed, 2048, D_BASTION, 1);
|
||||
lvs[D_ENDCITY].init4struct(mc, seed, 2048, D_ENDCITY, 1);
|
||||
|
||||
if (dim == 0)
|
||||
{
|
||||
lvb.resize(5);
|
||||
lvb[0].init4map(mc, seed, dim, pixs, 1);
|
||||
lvb[1].init4map(mc, seed, dim, pixs, 4);
|
||||
lvb[2].init4map(mc, seed, dim, pixs, 16);
|
||||
lvb[3].init4map(mc, seed, dim, pixs, 64);
|
||||
lvb[4].init4map(mc, seed, dim, pixs, 256);
|
||||
}
|
||||
else
|
||||
{
|
||||
lvb.resize(4);
|
||||
lvb[0].init4map(mc, seed, dim, pixs, 1);
|
||||
lvb[1].init4map(mc, seed, dim, pixs, 4);
|
||||
lvb[2].init4map(mc, seed, dim, pixs, 16);
|
||||
lvb[3].init4map(mc, seed, dim, pixs, 64);
|
||||
}
|
||||
cachesize = 100;
|
||||
qual = 1.0;
|
||||
|
||||
@ -415,6 +473,9 @@ QWorld::QWorld(int mc, int64_t seed)
|
||||
icons[D_PORTAL] = QPixmap(":/icons/portal.png");
|
||||
icons[D_SPAWN] = QPixmap(":/icons/spawn.png");
|
||||
icons[D_STRONGHOLD] = QPixmap(":/icons/stronghold.png");
|
||||
icons[D_FORTESS] = QPixmap(":/icons/fortress.png");
|
||||
icons[D_BASTION] = QPixmap(":/icons/bastion.png");
|
||||
icons[D_ENDCITY] = QPixmap(":/icons/endcity.png");
|
||||
|
||||
iconzvil = QPixmap(":/icons/zombie.png");
|
||||
}
|
||||
@ -424,7 +485,7 @@ QWorld::~QWorld()
|
||||
isdel = true;
|
||||
QThreadPool::globalInstance()->clear();
|
||||
QThreadPool::globalInstance()->waitForDone();
|
||||
for (Quad *q : cached)
|
||||
for (Quad *q : cachedbiomes)
|
||||
delete q;
|
||||
for (Quad *q : cachedstruct)
|
||||
delete q;
|
||||
@ -435,6 +496,71 @@ QWorld::~QWorld()
|
||||
}
|
||||
}
|
||||
|
||||
void QWorld::setDim(int dim)
|
||||
{
|
||||
QThreadPool::globalInstance()->clear();
|
||||
QThreadPool::globalInstance()->waitForDone();
|
||||
this->dim = dim;
|
||||
|
||||
// cache existing quads
|
||||
for (Level& l : lvb)
|
||||
{
|
||||
std::vector<Quad*> todel;
|
||||
for (Quad *q : l.cells)
|
||||
{
|
||||
if (q->done)
|
||||
cachedbiomes.push_back(q);
|
||||
else
|
||||
todel.push_back(q);
|
||||
}
|
||||
l.cells.swap(todel);
|
||||
}
|
||||
|
||||
cleancache(cachedbiomes, (int)(cachesize));
|
||||
|
||||
lvb.clear();
|
||||
int pixs = 512;
|
||||
if (dim == 0)
|
||||
{
|
||||
lvb.resize(5);
|
||||
lvb[0].init4map(mc, seed, dim, pixs, 1);
|
||||
lvb[1].init4map(mc, seed, dim, pixs, 4);
|
||||
lvb[2].init4map(mc, seed, dim, pixs, 16);
|
||||
lvb[3].init4map(mc, seed, dim, pixs, 64);
|
||||
lvb[4].init4map(mc, seed, dim, pixs, 256);
|
||||
}
|
||||
else
|
||||
{
|
||||
lvb.resize(4);
|
||||
lvb[0].init4map(mc, seed, dim, pixs, 1);
|
||||
lvb[1].init4map(mc, seed, dim, pixs, 4);
|
||||
lvb[2].init4map(mc, seed, dim, pixs, 16);
|
||||
lvb[3].init4map(mc, seed, dim, pixs, 64);
|
||||
}
|
||||
}
|
||||
|
||||
int QWorld::getBiome(Pos p)
|
||||
{
|
||||
if (dim == -1)
|
||||
{
|
||||
if (mc < MC_1_16)
|
||||
return nether_wastes;
|
||||
NetherNoise nn;
|
||||
setNetherSeed(&nn, seed);
|
||||
voronoiAccess3D(sha, p.x, 0, p.z, &p.x, 0, &p.z);
|
||||
return getNetherBiome(&nn, p.x, 0, p.z, NULL);
|
||||
}
|
||||
else if (dim == 1)
|
||||
{
|
||||
if (mc < MC_1_9)
|
||||
return the_end;
|
||||
int buf[49];
|
||||
genEndScaled(mc, seed, 1, buf, p.x, p.z, 1, 1);
|
||||
return buf[0];
|
||||
}
|
||||
return getBiomeAtPos(&g, p);
|
||||
}
|
||||
|
||||
void QWorld::cleancache(std::vector<Quad*>& cache, unsigned int maxsize)
|
||||
{
|
||||
// try to delete the oldest entries in the cache
|
||||
@ -515,18 +641,18 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
qreal bx1 = focusx + uiw/2;
|
||||
qreal bz1 = focusz + uih/2;
|
||||
|
||||
if (blocks2pix >= qual) activelv = -1;
|
||||
else if (blocks2pix >= qual/4) activelv = 0;
|
||||
else if (blocks2pix >= qual/16) activelv = 1;
|
||||
else if (blocks2pix >= qual/64) activelv = 2;
|
||||
if (blocks2pix >= qual) activelv = -1;
|
||||
else if (blocks2pix >= qual/4) activelv = 0;
|
||||
else if (blocks2pix >= qual/16) activelv = 1;
|
||||
else if (blocks2pix >= qual/64) activelv = 2;
|
||||
else if (blocks2pix >= qual/256) activelv = 3;
|
||||
else activelv = lv.size()-1;
|
||||
else activelv = lvb.size()-1;
|
||||
|
||||
for (int li = activelv+1; li >= activelv; --li)
|
||||
{
|
||||
if (li < 0 || li >= (int)lv.size())
|
||||
if (li < 0 || li >= (int)lvb.size())
|
||||
continue;
|
||||
Level& l = lv[li];
|
||||
Level& l = lvb[li];
|
||||
for (Quad *q : l.cells)
|
||||
{
|
||||
if (!q->img)
|
||||
@ -598,10 +724,10 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
}
|
||||
|
||||
|
||||
for (int stype = D_DESERT; stype < D_SPAWN; stype++)
|
||||
for (int sopt = D_DESERT; sopt < D_SPAWN; sopt++)
|
||||
{
|
||||
Level& l = lvs[stype];
|
||||
if (!sshow[stype] || activelv > l.viewlv)
|
||||
Level& l = lvs[sopt];
|
||||
if (!sshow[sopt] || activelv > l.viewlv)
|
||||
continue;
|
||||
|
||||
std::vector<QPainter::PixmapFragment> frags;
|
||||
@ -615,12 +741,13 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
{
|
||||
qreal x = vw/2 + (vp.p.x - focusx) * blocks2pix;
|
||||
qreal y = vh/2 + (vp.p.z - focusz) * blocks2pix;
|
||||
|
||||
if (x < 0 || x >= vw || y < 0 || y >= vh)
|
||||
continue;
|
||||
|
||||
QPointF d = QPointF(x, y);
|
||||
QRectF r = icons[stype].rect();
|
||||
if (stype == D_VILLAGE)
|
||||
QRectF r = icons[sopt].rect();
|
||||
if (sopt == D_VILLAGE)
|
||||
{
|
||||
if (vp.variant) {
|
||||
painter.drawPixmap(x-r.width()/2, y-r.height()/2, iconzvil);
|
||||
@ -638,7 +765,7 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
r.moveCenter(d);
|
||||
if (r.contains(selx, selz))
|
||||
{
|
||||
seltype = stype;
|
||||
seltype = sopt;
|
||||
selpos = vp.p;
|
||||
selvar = vp.variant;
|
||||
}
|
||||
@ -646,7 +773,7 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
}
|
||||
}
|
||||
|
||||
painter.drawPixmapFragments(frags.data(), frags.size(), icons[stype]);
|
||||
painter.drawPixmapFragments(frags.data(), frags.size(), icons[sopt]);
|
||||
}
|
||||
|
||||
Pos* sp = spawn; // atomic fetch
|
||||
@ -698,17 +825,18 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
painter.drawPixmapFragments(frags.data(), frags.size(), icons[D_STRONGHOLD]);
|
||||
}
|
||||
|
||||
for (int li = lv.size()-1; li >= 0; --li)
|
||||
for (int li = lvb.size()-1; li >= 0; --li)
|
||||
{
|
||||
Level& l = lvb[li];
|
||||
if (li == activelv || li == activelv+1)
|
||||
lv[li].update(cached, bx0, bz0, bx1, bz1);
|
||||
l.update(cachedbiomes, bx0, bz0, bx1, bz1);
|
||||
else
|
||||
lv[li].update(cached, 0, 0, 0, 0);
|
||||
l.update(cachedbiomes, 0, 0, 0, 0);
|
||||
}
|
||||
for (int stype = D_DESERT; stype < D_SPAWN; stype++)
|
||||
for (int sopt = D_DESERT; sopt < D_SPAWN; sopt++)
|
||||
{
|
||||
Level& l = lvs[stype];
|
||||
if (activelv <= l.viewlv && sshow[stype])
|
||||
Level& l = lvs[sopt];
|
||||
if (activelv <= l.viewlv && sshow[sopt])
|
||||
l.update(cachedstruct, bx0, bz0, bx1, bz1);
|
||||
else if (activelv > l.viewlv+1)
|
||||
l.update(cachedstruct, 0, 0, 0, 0);
|
||||
@ -764,7 +892,7 @@ void QWorld::draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz,
|
||||
painter.drawPixmap(iconrec.translated(pad,pad), *icon);
|
||||
}
|
||||
|
||||
cleancache(cached, cachesize);
|
||||
cleancache(cachedbiomes, cachesize);
|
||||
cleancache(cachedstruct, cachesize);
|
||||
}
|
||||
|
||||
|
61
src/quad.h
@ -10,8 +10,10 @@
|
||||
|
||||
enum {
|
||||
D_NONE = -1,
|
||||
// generics
|
||||
D_GRID,
|
||||
D_SLIME,
|
||||
// structures
|
||||
D_DESERT,
|
||||
D_JUNGLE,
|
||||
D_IGLOO,
|
||||
@ -24,6 +26,10 @@ enum {
|
||||
D_TREASURE,
|
||||
D_OUTPOST,
|
||||
D_PORTAL,
|
||||
D_FORTESS,
|
||||
D_BASTION,
|
||||
D_ENDCITY,
|
||||
// non-recurring structures
|
||||
D_SPAWN,
|
||||
D_STRONGHOLD,
|
||||
STRUCT_NUM
|
||||
@ -49,6 +55,9 @@ inline const char *mapopt2str(int opt)
|
||||
case D_PORTAL: return "portal";
|
||||
case D_SPAWN: return "spawn";
|
||||
case D_STRONGHOLD: return "stronghold";
|
||||
case D_FORTESS: return "fortress";
|
||||
case D_BASTION: return "bastion";
|
||||
case D_ENDCITY: return "endcity";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
@ -71,9 +80,36 @@ inline int str2mapopt(const char *s)
|
||||
if (!strcmp(s, "portal")) return D_PORTAL;
|
||||
if (!strcmp(s, "spawn")) return D_SPAWN;
|
||||
if (!strcmp(s, "stronghold")) return D_STRONGHOLD;
|
||||
if (!strcmp(s, "fortress")) return D_FORTESS;
|
||||
if (!strcmp(s, "bastion")) return D_BASTION;
|
||||
if (!strcmp(s, "endcity")) return D_ENDCITY;
|
||||
return D_NONE;
|
||||
}
|
||||
|
||||
inline int mapopt2stype(int opt)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case D_DESERT: return Desert_Pyramid;
|
||||
case D_JUNGLE: return Jungle_Pyramid;
|
||||
case D_IGLOO: return Igloo;
|
||||
case D_HUT: return Swamp_Hut;
|
||||
case D_VILLAGE: return Village;
|
||||
case D_MANSION: return Mansion;
|
||||
case D_MONUMENT: return Monument;
|
||||
case D_RUINS: return Ocean_Ruin;
|
||||
case D_SHIPWRECK: return Shipwreck;
|
||||
case D_TREASURE: return Treasure;
|
||||
case D_OUTPOST: return Outpost;
|
||||
case D_PORTAL: return Ruined_Portal;
|
||||
case D_FORTESS: return Fortress;
|
||||
case D_BASTION: return Bastion;
|
||||
case D_ENDCITY: return End_City;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
struct Level;
|
||||
|
||||
struct VarPos
|
||||
@ -83,7 +119,7 @@ struct VarPos
|
||||
};
|
||||
|
||||
void getStructs(std::vector<VarPos> *out, const StructureConfig sconf,
|
||||
LayerStack *g, int mc, int64_t seed, int x0, int z0, int x1, int z1);
|
||||
int mc, int64_t seed, int x0, int z0, int x1, int z1);
|
||||
|
||||
class Quad : public QRunnable
|
||||
{
|
||||
@ -94,12 +130,13 @@ public:
|
||||
void run();
|
||||
|
||||
int mc;
|
||||
const Layer *entry;
|
||||
int64_t seed;
|
||||
int dim;
|
||||
const Layer *entry;
|
||||
int ti, tj;
|
||||
int blocks;
|
||||
int pixs;
|
||||
int stype;
|
||||
int sopt;
|
||||
|
||||
uchar *rgb;
|
||||
|
||||
@ -121,8 +158,8 @@ struct Level
|
||||
Level();
|
||||
~Level();
|
||||
|
||||
void init4map(int mc, int64_t ws, int pix, int layerscale);
|
||||
void init4struct(int mc, int64_t ws, int blocks, int stype, int viewlv);
|
||||
void init4map(int mc, int64_t ws, int dim, int pix, int layerscale);
|
||||
void init4struct(int mc, int64_t ws, int blocks, int sopt, int viewlv);
|
||||
|
||||
void resizeLevel(std::vector<Quad*>& cache, int x, int z, int w, int h);
|
||||
void update(std::vector<Quad*>& cache, qreal bx0, qreal bz0, qreal bx1, qreal bz1);
|
||||
@ -132,37 +169,43 @@ struct Level
|
||||
Layer *entry;
|
||||
int64_t seed;
|
||||
int mc;
|
||||
int dim;
|
||||
int tx, tz, tw, th;
|
||||
int scale;
|
||||
int blocks;
|
||||
int pixs;
|
||||
int stype;
|
||||
int sopt;
|
||||
int viewlv;
|
||||
};
|
||||
|
||||
|
||||
struct QWorld
|
||||
{
|
||||
QWorld(int mc, int64_t seed);
|
||||
QWorld(int mc, int64_t seed, int dim = 0);
|
||||
~QWorld();
|
||||
|
||||
void setDim(int dim);
|
||||
|
||||
void cleancache(std::vector<Quad*>& cache, unsigned int maxsize);
|
||||
|
||||
void draw(QPainter& painter, int vw, int vh, qreal focusx, qreal focusz, qreal blocks2pix);
|
||||
|
||||
int getBiome(Pos p);
|
||||
|
||||
int mc;
|
||||
int64_t seed;
|
||||
int dim;
|
||||
LayerStack g;
|
||||
int64_t sha;
|
||||
|
||||
// the visible area is managed in Quads of different scales (for biomes and structures),
|
||||
// which are managed in rectangular sections as levels
|
||||
std::vector<Level> lv; // levels for biomes
|
||||
std::vector<Level> lvb; // levels for biomes
|
||||
std::vector<Level> lvs; // levels for structures
|
||||
int activelv; // currently visible level
|
||||
|
||||
// processed Quads are cached until they are too far out of view
|
||||
std::vector<Quad*> cached;
|
||||
std::vector<Quad*> cachedbiomes;
|
||||
std::vector<Quad*> cachedstruct;
|
||||
unsigned int cachesize;
|
||||
|
||||
|
@ -182,6 +182,11 @@ L_qm_any:
|
||||
case F_TREASURE:
|
||||
case F_PORTAL:
|
||||
|
||||
case F_FORTRESS:
|
||||
case F_BASTION:
|
||||
|
||||
case F_ENDCITY:
|
||||
|
||||
x1 = cond->x1;
|
||||
z1 = cond->z1;
|
||||
x2 = cond->x2;
|
||||
@ -232,8 +237,30 @@ L_qm_any:
|
||||
continue;
|
||||
if (pc.x >= x1 && pc.x <= x2 && pc.z >= z1 && pc.z <= z2)
|
||||
{
|
||||
if (g && !isViableStructurePos(sconf.structType, mc, g, seed, pc.x, pc.z))
|
||||
continue;
|
||||
if (g)
|
||||
{
|
||||
if (finfo.dim == 0 && !isViableStructurePos(sconf.structType, mc, g, seed, pc.x, pc.z))
|
||||
continue;
|
||||
if (finfo.dim == -1)
|
||||
{
|
||||
NetherNoise nn;
|
||||
if (!isViableNetherStructurePos(sconf.structType, mc, &nn, seed, 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;
|
||||
zt += pc.z;
|
||||
@ -250,6 +277,7 @@ L_qm_any:
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
||||
case F_SPAWN:
|
||||
// TODO: warn if spawn is used for relative positioning
|
||||
sout->cx = 0;
|
||||
|
83
src/search.h
@ -24,6 +24,7 @@ struct FilterInfo
|
||||
int step; // coordinate multiplier
|
||||
int count; //
|
||||
int mcmin; // minimum version
|
||||
int dim; // dimension
|
||||
const char *icon;
|
||||
const char *name;
|
||||
const char *desription;
|
||||
@ -60,6 +61,9 @@ enum
|
||||
F_RUINS,
|
||||
F_SHIPWRECK,
|
||||
F_PORTAL,
|
||||
F_FORTRESS,
|
||||
F_BASTION,
|
||||
F_ENDCITY,
|
||||
FILTER_MAX,
|
||||
};
|
||||
|
||||
@ -71,14 +75,14 @@ static const struct FilterList
|
||||
FilterList() : list{}
|
||||
{
|
||||
list[F_SELECT] = FilterInfo{
|
||||
CAT_NONE, 0, 0, 0, 0, 0, 0, MC_1_0,
|
||||
CAT_NONE, 0, 0, 0, 0, 0, 0, MC_1_0, 0,
|
||||
NULL,
|
||||
"",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_QH_IDEAL] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4,
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4, 0,
|
||||
":icons/quad.png",
|
||||
"Quad-hut (ideal)",
|
||||
"The lower 48-bits provide potential for four swamp huts in "
|
||||
@ -86,7 +90,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_QH_CLASSIC] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4,
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4, 0,
|
||||
":icons/quad.png",
|
||||
"Quad-hut (classic)",
|
||||
"The lower 48-bits provide potential for four swamp huts in "
|
||||
@ -96,7 +100,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_QH_NORMAL] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4,
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4, 0,
|
||||
":icons/quad.png",
|
||||
"Quad-hut (normal)",
|
||||
"The lower 48-bits provide potential for four swamp huts in "
|
||||
@ -106,7 +110,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_QH_BARELY] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4,
|
||||
CAT_48, 1, 1, 0, Swamp_Hut, 512, 0, MC_1_4, 0,
|
||||
":icons/quad.png",
|
||||
"Quad-hut (barely)",
|
||||
"The lower 48-bits provide potential for four swamp huts in "
|
||||
@ -115,7 +119,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_QM_95] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, Monument, 512, 0, MC_1_8,
|
||||
CAT_48, 1, 1, 0, Monument, 512, 0, MC_1_8, 0,
|
||||
":icons/quad.png",
|
||||
"Quad-ocean-monument (>95%)",
|
||||
"The lower 48-bits provide potential for 95% of the area of "
|
||||
@ -124,7 +128,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_QM_90] = FilterInfo{
|
||||
CAT_48, 1, 1, 0, Monument, 512, 0, MC_1_8,
|
||||
CAT_48, 1, 1, 0, Monument, 512, 0, MC_1_8, 0,
|
||||
":icons/quad.png",
|
||||
"Quad-ocean-monument (>90%)",
|
||||
"The lower 48-bits provide potential for 90% of the area of "
|
||||
@ -133,7 +137,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME] = FilterInfo{
|
||||
CAT_FULL, 1, 1, L_VORONOI_1, 0, 1, 0, MC_1_0,
|
||||
CAT_FULL, 1, 1, L_VORONOI_1, 0, 1, 0, MC_1_0, 0,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:1",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -141,7 +145,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME_4_RIVER] = FilterInfo{
|
||||
CAT_FULL, 1, 1, L_RIVER_MIX_4, 0, 4, 0, MC_1_0,
|
||||
CAT_FULL, 1, 1, L_RIVER_MIX_4, 0, 4, 0, MC_1_0, 0,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:4 RIVER",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -150,7 +154,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME_16_SHORE] = FilterInfo{
|
||||
CAT_FULL, 1, 1, L_SHORE_16, 0, 16, 0, MC_1_0,
|
||||
CAT_FULL, 1, 1, L_SHORE_16, 0, 16, 0, MC_1_0, 0,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:16 SHORE",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -159,7 +163,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME_64_RARE] = FilterInfo{
|
||||
CAT_FULL, 1, 1, L_SUNFLOWER_64, 0, 64, 0, MC_1_7,
|
||||
CAT_FULL, 1, 1, L_SUNFLOWER_64, 0, 64, 0, MC_1_7, 0,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:64 RARE",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -168,7 +172,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME_256_BIOME] = FilterInfo{
|
||||
CAT_FULL, 1, 1, L_BIOME_256, 0, 256, 0, MC_1_0,
|
||||
CAT_FULL, 1, 1, L_BIOME_256, 0, 256, 0, MC_1_0, 0,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:256 BIOME",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -177,7 +181,7 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_BIOME_256_OTEMP] = FilterInfo{
|
||||
CAT_48, 1, 1, L_OCEAN_TEMP_256, 0, 256, 0, MC_1_13,
|
||||
CAT_48, 1, 1, L_OCEAN_TEMP_256, 0, 256, 0, MC_1_13, 0,
|
||||
":icons/map.png",
|
||||
"Biome filter 1:256 O.TEMP",
|
||||
"Only seeds with the included (+) biomes in the specified area and "
|
||||
@ -187,116 +191,137 @@ static const struct FilterList
|
||||
};
|
||||
|
||||
list[F_TEMPS] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 0, 1024, 0, MC_1_7,
|
||||
CAT_FULL, 1, 1, 0, 0, 1024, 0, MC_1_7, 0,
|
||||
":icons/tempcat.png",
|
||||
"Temperature categories",
|
||||
"Checks that the area has a minimum of all the required temperature categories."
|
||||
};
|
||||
|
||||
list[F_SLIME] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 0, 16, 1, MC_1_0,
|
||||
CAT_FULL, 1, 1, 0, 0, 16, 1, MC_1_0, 0,
|
||||
":icons/slime.png",
|
||||
"Slime chunk",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_SPAWN] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 0, 1, 0, MC_1_0,
|
||||
CAT_FULL, 1, 1, 0, 0, 1, 0, MC_1_0, 0,
|
||||
":icons/spawn.png",
|
||||
"Spawn",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_STRONGHOLD] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, 0, 1, 1, MC_1_0,
|
||||
CAT_FULL, 1, 1, 0, 0, 1, 1, MC_1_0, 0,
|
||||
":icons/stronghold.png",
|
||||
"Stronghold",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_DESERT] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Desert_Pyramid, 1, 1, MC_1_3,
|
||||
CAT_FULL, 1, 1, 0, Desert_Pyramid, 1, 1, MC_1_3, 0,
|
||||
":icons/desert.png",
|
||||
"Desert pyramid",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_JUNGLE] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Jungle_Pyramid, 1, 1, MC_1_3,
|
||||
CAT_FULL, 1, 1, 0, Jungle_Pyramid, 1, 1, MC_1_3, 0,
|
||||
":icons/jungle.png",
|
||||
"Jungle temple",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_HUT] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Swamp_Hut, 1, 1, MC_1_4,
|
||||
CAT_FULL, 1, 1, 0, Swamp_Hut, 1, 1, MC_1_4, 0,
|
||||
":icons/hut.png",
|
||||
"Swamp hut",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_IGLOO] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Igloo, 1, 1, MC_1_9,
|
||||
CAT_FULL, 1, 1, 0, Igloo, 1, 1, MC_1_9, 0,
|
||||
":icons/igloo.png",
|
||||
"Igloo",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_MONUMENT] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Monument, 1, 1, MC_1_8,
|
||||
CAT_FULL, 1, 1, 0, Monument, 1, 1, MC_1_8, 0,
|
||||
":icons/monument.png",
|
||||
"Ocean monument",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_VILLAGE] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Village, 1, 1, MC_1_0,
|
||||
CAT_FULL, 1, 1, 0, Village, 1, 1, MC_1_0, 0,
|
||||
":icons/village.png",
|
||||
"Village",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_OUTPOST] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Outpost, 1, 1, MC_1_14,
|
||||
CAT_FULL, 1, 1, 0, Outpost, 1, 1, MC_1_14, 0,
|
||||
":icons/outpost.png",
|
||||
"Pillager outpost",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_MANSION] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Mansion, 1, 1, MC_1_11,
|
||||
CAT_FULL, 1, 1, 0, Mansion, 1, 1, MC_1_11, 0,
|
||||
":icons/mansion.png",
|
||||
"Woodland mansion",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_TREASURE] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Treasure, 1, 1, MC_1_13,
|
||||
CAT_FULL, 1, 1, 0, Treasure, 1, 1, MC_1_13, 0,
|
||||
":icons/treasure.png",
|
||||
"Buried treasure",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_RUINS] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Ocean_Ruin, 1, 1, MC_1_13,
|
||||
CAT_FULL, 1, 1, 0, Ocean_Ruin, 1, 1, MC_1_13, 0,
|
||||
":icons/ruins.png",
|
||||
"Ocean ruins",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_SHIPWRECK] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Shipwreck, 1, 1, MC_1_13,
|
||||
CAT_FULL, 1, 1, 0, Shipwreck, 1, 1, MC_1_13, 0,
|
||||
":icons/shipwreck.png",
|
||||
"Shipwreck",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_PORTAL] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Ruined_Portal, 1, 1, MC_1_16,
|
||||
CAT_FULL, 1, 1, 0, Ruined_Portal, 1, 1, MC_1_16, 0,
|
||||
":icons/portal.png",
|
||||
"Ruined portal",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_FORTRESS] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Fortress, 1, 1, MC_1_0, -1,
|
||||
":icons/fortress.png",
|
||||
"Nether fortress",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_BASTION] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, Bastion, 1, 1, MC_1_16, -1,
|
||||
":icons/bastion.png",
|
||||
"Bastion remnant",
|
||||
""
|
||||
};
|
||||
|
||||
list[F_ENDCITY] = FilterInfo{
|
||||
CAT_FULL, 1, 1, 0, End_City, 1, 1, MC_1_9, +1,
|
||||
":icons/endcity.png",
|
||||
"End city",
|
||||
""
|
||||
};
|
||||
}
|
||||
}
|
||||
g_filterinfo;
|
||||
|