mirror of
https://github.com/minetest/minetestmapper.git
synced 2024-11-21 23:13:53 +01:00
Zoom implementation (--zoom option)
This commit is contained in:
parent
7c1989a6b2
commit
15fae27b85
29
README.rst
29
README.rst
@ -43,41 +43,44 @@ Parameters
|
|||||||
^^^^^^^^^^
|
^^^^^^^^^^
|
||||||
|
|
||||||
bgcolor:
|
bgcolor:
|
||||||
Background color of image, `--bgcolor #ffffff`
|
Background color of image, e.g. ``--bgcolor #ffffff``
|
||||||
|
|
||||||
scalecolor:
|
scalecolor:
|
||||||
Color of scale, `--scalecolor #000000`
|
Color of scale, e.g. ``--scalecolor #000000``
|
||||||
|
|
||||||
playercolor:
|
playercolor:
|
||||||
Color of player indicators, `--playercolor #ff0000`
|
Color of player indicators, e.g. ``--playercolor #ff0000``
|
||||||
|
|
||||||
origincolor:
|
origincolor:
|
||||||
Color of origin indicator, `--origincolor #ff0000`
|
Color of origin indicator, e.g. ``--origincolor #ff0000``
|
||||||
|
|
||||||
drawscale:
|
drawscale:
|
||||||
Draw tick marks, `--drawscale`
|
Draw tick marks, ``--drawscale``
|
||||||
|
|
||||||
drawplayers:
|
drawplayers:
|
||||||
Draw player indicators, `--drawplayers`
|
Draw player indicators, ``--drawplayers``
|
||||||
|
|
||||||
draworigin:
|
draworigin:
|
||||||
Draw origin indicator, `--draworigin`
|
Draw origin indicator, ``--draworigin``
|
||||||
|
|
||||||
drawalpha:
|
drawalpha:
|
||||||
Allow nodes to be drawn with transparency, `--drawalpha`
|
Allow nodes to be drawn with transparency, ``--drawalpha``
|
||||||
|
|
||||||
noshading:
|
noshading:
|
||||||
Don't draw shading on nodes, `--noshading`
|
Don't draw shading on nodes, ``--noshading``
|
||||||
|
|
||||||
min-y:
|
min-y:
|
||||||
Don't draw nodes below this y value, `--min-y -25`
|
Don't draw nodes below this y value, e.g. ``--min-y -25``
|
||||||
|
|
||||||
max-y:
|
max-y:
|
||||||
Don't draw nodes above this y value, `--max-y 75`
|
Don't draw nodes above this y value, e.g. ``--max-y 75``
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
Use specific map backend, supported: sqlite3, leveldb, redis, `--backend leveldb`
|
Use specific map backend, supported: *sqlite3*, *leveldb*, *redis*, e.g. ``--backend leveldb``
|
||||||
|
|
||||||
geometry:
|
geometry:
|
||||||
Limit area to specific geometry, `--geometry -800:-800+1600+1600`
|
Limit area to specific geometry, e.g. ``--geometry -800:-800+1600+1600``
|
||||||
|
|
||||||
|
zoom:
|
||||||
|
"Zoom" the image by using more than one pixel per node, e.g. ``--zoom 4``
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ static inline int rgb2int(uint8_t r, uint8_t g, uint8_t b, uint8_t a=0xFF)
|
|||||||
|
|
||||||
static inline int color2int(Color c)
|
static inline int color2int(Color c)
|
||||||
{
|
{
|
||||||
return rgb2int(c.r, c.g, c.b, c.a);
|
return rgb2int(c.r, c.g, c.b, c.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// rounds n (away from 0) to a multiple of f while preserving the sign of n
|
// rounds n (away from 0) to a multiple of f while preserving the sign of n
|
||||||
@ -87,15 +87,15 @@ static inline int colorSafeBounds(int color)
|
|||||||
|
|
||||||
static inline Color mixColors(Color a, Color b)
|
static inline Color mixColors(Color a, Color b)
|
||||||
{
|
{
|
||||||
Color result;
|
Color result;
|
||||||
double a1 = a.a / 255.0;
|
double a1 = a.a / 255.0;
|
||||||
double a2 = b.a / 255.0;
|
double a2 = b.a / 255.0;
|
||||||
|
|
||||||
result.r = (int) (a1 * a.r + a2 * (1 - a1) * b.r);
|
result.r = (int) (a1 * a.r + a2 * (1 - a1) * b.r);
|
||||||
result.g = (int) (a1 * a.g + a2 * (1 - a1) * b.g);
|
result.g = (int) (a1 * a.g + a2 * (1 - a1) * b.g);
|
||||||
result.b = (int) (a1 * a.b + a2 * (1 - a1) * b.b);
|
result.b = (int) (a1 * a.b + a2 * (1 - a1) * b.b);
|
||||||
result.a = (int) (255 * (a1 + a2 * (1 - a1)));
|
result.a = (int) (255 * (a1 + a2 * (1 - a1)));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TileGenerator::TileGenerator():
|
TileGenerator::TileGenerator():
|
||||||
@ -120,7 +120,8 @@ TileGenerator::TileGenerator():
|
|||||||
m_geomX(-2048),
|
m_geomX(-2048),
|
||||||
m_geomY(-2048),
|
m_geomY(-2048),
|
||||||
m_geomX2(2048),
|
m_geomX2(2048),
|
||||||
m_geomY2(2048)
|
m_geomY2(2048),
|
||||||
|
m_zoom(1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,6 +149,14 @@ void TileGenerator::setPlayerColor(const std::string &playerColor)
|
|||||||
m_playerColor = parseColor(playerColor);
|
m_playerColor = parseColor(playerColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TileGenerator::setZoom(int zoom)
|
||||||
|
{
|
||||||
|
if (zoom < 1) {
|
||||||
|
throw std::runtime_error("Zoom level needs to be a number: 1 or higher");
|
||||||
|
}
|
||||||
|
m_zoom = zoom;
|
||||||
|
}
|
||||||
|
|
||||||
Color TileGenerator::parseColor(const std::string &color)
|
Color TileGenerator::parseColor(const std::string &color)
|
||||||
{
|
{
|
||||||
Color parsed;
|
Color parsed;
|
||||||
@ -186,7 +195,7 @@ void TileGenerator::setDrawScale(bool drawScale)
|
|||||||
|
|
||||||
void TileGenerator::setDrawAlpha(bool drawAlpha)
|
void TileGenerator::setDrawAlpha(bool drawAlpha)
|
||||||
{
|
{
|
||||||
m_drawAlpha = drawAlpha;
|
m_drawAlpha = drawAlpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileGenerator::setShading(bool shading)
|
void TileGenerator::setShading(bool shading)
|
||||||
@ -346,10 +355,10 @@ void TileGenerator::createImage()
|
|||||||
{
|
{
|
||||||
m_mapWidth = (m_xMax - m_xMin + 1) * 16;
|
m_mapWidth = (m_xMax - m_xMin + 1) * 16;
|
||||||
m_mapHeight = (m_zMax - m_zMin + 1) * 16;
|
m_mapHeight = (m_zMax - m_zMin + 1) * 16;
|
||||||
m_image = gdImageCreateTrueColor(m_mapWidth + m_border, m_mapHeight + m_border);
|
m_image = gdImageCreateTrueColor((m_mapWidth * m_zoom) + m_border, (m_mapHeight * m_zoom) + m_border);
|
||||||
m_blockPixelAttributes.setWidth(m_mapWidth);
|
m_blockPixelAttributes.setWidth(m_mapWidth);
|
||||||
// Background
|
// Background
|
||||||
gdImageFilledRectangle(m_image, 0, 0, m_mapWidth + m_border - 1, m_mapHeight + m_border -1, color2int(m_bgColor));
|
gdImageFilledRectangle(m_image, 0, 0, (m_mapWidth * m_zoom) + m_border - 1, (m_mapHeight * m_zoom) + m_border -1, color2int(m_bgColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileGenerator::renderMap()
|
void TileGenerator::renderMap()
|
||||||
@ -497,12 +506,12 @@ inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPo
|
|||||||
int minY = (pos.y * 16 > m_yMin) ? 0 : m_yMin - pos.y * 16;
|
int minY = (pos.y * 16 > m_yMin) ? 0 : m_yMin - pos.y * 16;
|
||||||
int maxY = (pos.y * 16 < m_yMax) ? 15 : m_yMax - pos.y * 16;
|
int maxY = (pos.y * 16 < m_yMax) ? 15 : m_yMax - pos.y * 16;
|
||||||
for (int z = 0; z < 16; ++z) {
|
for (int z = 0; z < 16; ++z) {
|
||||||
int imageY = getImageY(zBegin + 15 - z);
|
int imageY = zBegin + 15 - z;
|
||||||
for (int x = 0; x < 16; ++x) {
|
for (int x = 0; x < 16; ++x) {
|
||||||
if (m_readPixels[z] & (1 << x)) {
|
if (m_readPixels[z] & (1 << x)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int imageX = getImageX(xBegin + x);
|
int imageX = xBegin + x;
|
||||||
|
|
||||||
for (int y = maxY; y >= minY; --y) {
|
for (int y = maxY; y >= minY; --y) {
|
||||||
int position = x + (y << 4) + (z << 8);
|
int position = x + (y << 4) + (z << 8);
|
||||||
@ -523,7 +532,7 @@ inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPo
|
|||||||
else
|
else
|
||||||
m_color[z][x] = mixColors(m_color[z][x], c);
|
m_color[z][x] = mixColors(m_color[z][x], c);
|
||||||
if(m_color[z][x].a == 0xFF) {
|
if(m_color[z][x].a == 0xFF) {
|
||||||
m_image->tpixels[imageY][imageX] = color2int(m_color[z][x]);
|
setZoomed(m_image,imageY,imageX,color2int(m_color[z][x]));
|
||||||
m_readPixels[z] |= (1 << x);
|
m_readPixels[z] |= (1 << x);
|
||||||
m_blockPixelAttributes.attribute(15 - z, xBegin + x).thickness = m_thickness[z][x];
|
m_blockPixelAttributes.attribute(15 - z, xBegin + x).thickness = m_thickness[z][x];
|
||||||
} else {
|
} else {
|
||||||
@ -531,7 +540,7 @@ inline void TileGenerator::renderMapBlock(const ustring &mapBlock, const BlockPo
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
m_image->tpixels[imageY][imageX] = color2int(c);
|
setZoomed(m_image,imageY,imageX,color2int(c));
|
||||||
m_readPixels[z] |= (1 << x);
|
m_readPixels[z] |= (1 << x);
|
||||||
}
|
}
|
||||||
if(!(m_readInfo[z] & (1 << x))) {
|
if(!(m_readInfo[z] & (1 << x))) {
|
||||||
@ -553,15 +562,15 @@ inline void TileGenerator::renderMapBlockBottom(const BlockPos &pos)
|
|||||||
int xBegin = (pos.x - m_xMin) * 16;
|
int xBegin = (pos.x - m_xMin) * 16;
|
||||||
int zBegin = (m_zMax - pos.z) * 16;
|
int zBegin = (m_zMax - pos.z) * 16;
|
||||||
for (int z = 0; z < 16; ++z) {
|
for (int z = 0; z < 16; ++z) {
|
||||||
int imageY = getImageY(zBegin + 15 - z);
|
int imageY = zBegin + 15 - z;
|
||||||
for (int x = 0; x < 16; ++x) {
|
for (int x = 0; x < 16; ++x) {
|
||||||
if (m_readPixels[z] & (1 << x)) {
|
if (m_readPixels[z] & (1 << x)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int imageX = getImageX(xBegin + x);
|
int imageX = xBegin + x;
|
||||||
|
|
||||||
if (m_drawAlpha) {
|
if (m_drawAlpha) {
|
||||||
m_image->tpixels[imageY][imageX] = color2int(m_color[z][x]);
|
setZoomed(m_image,imageY,imageX, color2int(m_color[z][x]));
|
||||||
m_readPixels[z] |= (1 << x);
|
m_readPixels[z] |= (1 << x);
|
||||||
m_blockPixelAttributes.attribute(15 - z, xBegin + x).thickness = m_thickness[z][x];
|
m_blockPixelAttributes.attribute(15 - z, xBegin + x).thickness = m_thickness[z][x];
|
||||||
}
|
}
|
||||||
@ -577,7 +586,6 @@ inline void TileGenerator::renderShading(int zPos)
|
|||||||
if (imageY >= m_mapHeight) {
|
if (imageY >= m_mapHeight) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
imageY = getImageY(imageY);
|
|
||||||
for (int x = 0; x < m_mapWidth; ++x) {
|
for (int x = 0; x < m_mapWidth; ++x) {
|
||||||
if (!m_blockPixelAttributes.attribute(z, x).valid_height() || !m_blockPixelAttributes.attribute(z, x - 1).valid_height() || !m_blockPixelAttributes.attribute(z - 1, x).valid_height()) {
|
if (!m_blockPixelAttributes.attribute(z, x).valid_height() || !m_blockPixelAttributes.attribute(z, x - 1).valid_height() || !m_blockPixelAttributes.attribute(z - 1, x).valid_height()) {
|
||||||
continue;
|
continue;
|
||||||
@ -592,15 +600,14 @@ inline void TileGenerator::renderShading(int zPos)
|
|||||||
// more thickness -> less visible shadows: t=0 -> 100% visible, t=255 -> 0% visible
|
// more thickness -> less visible shadows: t=0 -> 100% visible, t=255 -> 0% visible
|
||||||
if (m_drawAlpha)
|
if (m_drawAlpha)
|
||||||
d = d * ((0xFF - m_blockPixelAttributes.attribute(z, x).thickness) / 255.0);
|
d = d * ((0xFF - m_blockPixelAttributes.attribute(z, x).thickness) / 255.0);
|
||||||
int sourceColor = m_image->tpixels[imageY][getImageX(x)] & 0xffffff;
|
int sourceColor = m_image->tpixels[getImageY(imageY)][getImageX(x)] & 0xffffff;
|
||||||
uint8_t r = (sourceColor & 0xff0000) >> 16;
|
uint8_t r = (sourceColor & 0xff0000) >> 16;
|
||||||
uint8_t g = (sourceColor & 0x00ff00) >> 8;
|
uint8_t g = (sourceColor & 0x00ff00) >> 8;
|
||||||
uint8_t b = (sourceColor & 0x0000ff);
|
uint8_t b = (sourceColor & 0x0000ff);
|
||||||
r = colorSafeBounds(r + d);
|
r = colorSafeBounds(r + d);
|
||||||
g = colorSafeBounds(g + d);
|
g = colorSafeBounds(g + d);
|
||||||
b = colorSafeBounds(b + d);
|
b = colorSafeBounds(b + d);
|
||||||
|
setZoomed(m_image,imageY,x, rgb2int(r, g, b));
|
||||||
m_image->tpixels[imageY][getImageX(x)] = rgb2int(r, g, b);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_blockPixelAttributes.scroll();
|
m_blockPixelAttributes.scroll();
|
||||||
@ -619,7 +626,7 @@ void TileGenerator::renderScale()
|
|||||||
buf << i * 16;
|
buf << i * 16;
|
||||||
scaleText = buf.str();
|
scaleText = buf.str();
|
||||||
|
|
||||||
int xPos = m_xMin * -16 + i * 16 + m_border;
|
int xPos = (m_xMin * -16 + i * 16)*m_zoom + m_border;
|
||||||
gdImageString(m_image, gdFontGetMediumBold(), xPos + 2, 0, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color);
|
gdImageString(m_image, gdFontGetMediumBold(), xPos + 2, 0, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color);
|
||||||
gdImageLine(m_image, xPos, 0, xPos, m_border - 1, color);
|
gdImageLine(m_image, xPos, 0, xPos, m_border - 1, color);
|
||||||
}
|
}
|
||||||
@ -629,7 +636,7 @@ void TileGenerator::renderScale()
|
|||||||
buf << i * 16;
|
buf << i * 16;
|
||||||
scaleText = buf.str();
|
scaleText = buf.str();
|
||||||
|
|
||||||
int yPos = m_mapHeight - 1 - (i * 16 - m_zMin * 16) + m_border;
|
int yPos = (m_mapHeight - 1 - (i * 16 - m_zMin * 16))*m_zoom + m_border;
|
||||||
gdImageString(m_image, gdFontGetMediumBold(), 2, yPos, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color);
|
gdImageString(m_image, gdFontGetMediumBold(), 2, yPos, reinterpret_cast<unsigned char *>(const_cast<char *>(scaleText.c_str())), color);
|
||||||
gdImageLine(m_image, 0, yPos, m_border - 1, yPos, color);
|
gdImageLine(m_image, 0, yPos, m_border - 1, yPos, color);
|
||||||
}
|
}
|
||||||
@ -637,8 +644,8 @@ void TileGenerator::renderScale()
|
|||||||
|
|
||||||
void TileGenerator::renderOrigin()
|
void TileGenerator::renderOrigin()
|
||||||
{
|
{
|
||||||
int imageX = -m_xMin * 16 + m_border;
|
int imageX = (-m_xMin * 16)*m_zoom + m_border;
|
||||||
int imageY = m_mapHeight - m_zMin * -16 + m_border;
|
int imageY = (m_mapHeight - m_zMin * -16)*m_zoom + m_border;
|
||||||
gdImageArc(m_image, imageX, imageY, 12, 12, 0, 360, color2int(m_originColor));
|
gdImageArc(m_image, imageX, imageY, 12, 12, 0, 360, color2int(m_originColor));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -648,8 +655,8 @@ void TileGenerator::renderPlayers(const std::string &inputPath)
|
|||||||
|
|
||||||
PlayerAttributes players(inputPath);
|
PlayerAttributes players(inputPath);
|
||||||
for (PlayerAttributes::Players::iterator player = players.begin(); player != players.end(); ++player) {
|
for (PlayerAttributes::Players::iterator player = players.begin(); player != players.end(); ++player) {
|
||||||
int imageX = player->x / 10 - m_xMin * 16 + m_border;
|
int imageX = (player->x / 10 - m_xMin * 16)*m_zoom + m_border;
|
||||||
int imageY = m_mapHeight - (player->z / 10 - m_zMin * 16) + m_border;
|
int imageY = (m_mapHeight - (player->z / 10 - m_zMin * 16))*m_zoom + m_border;
|
||||||
|
|
||||||
gdImageArc(m_image, imageX, imageY, 5, 5, 0, 360, color);
|
gdImageArc(m_image, imageX, imageY, 5, 5, 0, 360, color);
|
||||||
gdImageString(m_image, gdFontGetMediumBold(), imageX + 2, imageY + 2, reinterpret_cast<unsigned char *>(const_cast<char *>(player->name.c_str())), color);
|
gdImageString(m_image, gdFontGetMediumBold(), imageX + 2, imageY + 2, reinterpret_cast<unsigned char *>(const_cast<char *>(player->name.c_str())), color);
|
||||||
@ -694,10 +701,19 @@ void TileGenerator::printUnknown()
|
|||||||
|
|
||||||
inline int TileGenerator::getImageX(int val) const
|
inline int TileGenerator::getImageX(int val) const
|
||||||
{
|
{
|
||||||
return val + m_border;
|
return (m_zoom*val) + m_border;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int TileGenerator::getImageY(int val) const
|
inline int TileGenerator::getImageY(int val) const
|
||||||
{
|
{
|
||||||
return val + m_border;
|
return (m_zoom*val) + m_border;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void TileGenerator::setZoomed(gdImagePtr image, int y, int x, int color) {
|
||||||
|
int xx,yy;
|
||||||
|
for (xx = 0; xx < m_zoom; xx++) {
|
||||||
|
for (yy = 0; yy < m_zoom; yy++) {
|
||||||
|
image->tpixels[m_border + (y*m_zoom) + xx][m_border + (x*m_zoom) + yy] = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,6 +71,7 @@ public:
|
|||||||
void parseColorsFile(const std::string &fileName);
|
void parseColorsFile(const std::string &fileName);
|
||||||
void setBackend(std::string backend);
|
void setBackend(std::string backend);
|
||||||
void generate(const std::string &input, const std::string &output);
|
void generate(const std::string &input, const std::string &output);
|
||||||
|
void setZoom(int zoom);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parseColorsStream(std::istream &in);
|
void parseColorsStream(std::istream &in);
|
||||||
@ -89,6 +90,7 @@ private:
|
|||||||
void printUnknown();
|
void printUnknown();
|
||||||
int getImageX(int val) const;
|
int getImageX(int val) const;
|
||||||
int getImageY(int val) const;
|
int getImageY(int val) const;
|
||||||
|
void setZoomed(gdImagePtr image, int x, int y, int color);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Color m_bgColor;
|
Color m_bgColor;
|
||||||
@ -129,6 +131,7 @@ private:
|
|||||||
|
|
||||||
int m_blockAirId;
|
int m_blockAirId;
|
||||||
int m_blockIgnoreId;
|
int m_blockIgnoreId;
|
||||||
|
int m_zoom;
|
||||||
}; // class TileGenerator
|
}; // class TileGenerator
|
||||||
|
|
||||||
#endif // TILEGENERATOR_HEADER
|
#endif // TILEGENERATOR_HEADER
|
||||||
|
12
mapper.cpp
12
mapper.cpp
@ -36,6 +36,7 @@ void usage()
|
|||||||
" --max-y <y>\n"
|
" --max-y <y>\n"
|
||||||
" --backend <backend>\n"
|
" --backend <backend>\n"
|
||||||
" --geometry x:y+w+h\n"
|
" --geometry x:y+w+h\n"
|
||||||
|
" --zoom <zoomlevel>\n"
|
||||||
"Color format: '#000000'\n";
|
"Color format: '#000000'\n";
|
||||||
std::cout << usage_text;
|
std::cout << usage_text;
|
||||||
}
|
}
|
||||||
@ -59,7 +60,8 @@ int main(int argc, char *argv[])
|
|||||||
{"backend", required_argument, 0, 'd'},
|
{"backend", required_argument, 0, 'd'},
|
||||||
{"geometry", required_argument, 0, 'g'},
|
{"geometry", required_argument, 0, 'g'},
|
||||||
{"min-y", required_argument, 0, 'a'},
|
{"min-y", required_argument, 0, 'a'},
|
||||||
{"max-y", required_argument, 0, 'c'}
|
{"max-y", required_argument, 0, 'c'},
|
||||||
|
{"zoom", required_argument, 0, 'z'}
|
||||||
};
|
};
|
||||||
|
|
||||||
string input;
|
string input;
|
||||||
@ -148,6 +150,14 @@ int main(int argc, char *argv[])
|
|||||||
generator.setGeometry(x, y, w, h);
|
generator.setGeometry(x, y, w, h);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'z': {
|
||||||
|
istringstream iss;
|
||||||
|
iss.str(optarg);
|
||||||
|
int zoom;
|
||||||
|
iss >> zoom;
|
||||||
|
generator.setZoom(zoom);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user