diff --git a/src/db_extractor/db.cpp b/src/db_extractor/db.cpp index c3f0444..2f957cd 100644 --- a/src/db_extractor/db.cpp +++ b/src/db_extractor/db.cpp @@ -20,15 +20,15 @@ #include -string getSqlType(uint32_t ft) +string getSqlType(FieldType type) { - switch (ft) + switch (type) { - case T_STRING: + case FieldType::String: return "TEXT"; - case T_INTEGER: + case FieldType::Integer: return "INTEGER"; - case T_FLOAT: + case FieldType::Float: return "REAL"; default: assert(false); @@ -40,9 +40,6 @@ void table::load(buffer &b) { READ(b, id); READ(b, name); - READ(b, unk1); - READ(b, unk2); - READ(b, unk3); READ(b, unk4); } @@ -51,9 +48,6 @@ void field::load(buffer &b) READ(b, table_id); READ(b, id); READ(b, name); - READ(b, unk1); - READ(b, unk2); - READ(b, unk3); READ(b, type); } @@ -83,20 +77,13 @@ void value::load_index(buffer &b) { READ(b, table_id); READ(b, name); - READ(b, unk1); - READ(b, unk2); - READ(b, unk3); READ(b, offset); READ(b, data_size); } -void value::load_data(buffer &b) -{ - data = buffer(b, data_size, offset); -} - -void value::extract_fields(const tab &tab) +void value::load_fields(const tab &tab, buffer &b) { + buffer data(b, data_size, offset); while (!data.eof()) { field_value fv; @@ -108,16 +95,16 @@ void value::extract_fields(const tab &tab) continue; switch (i->second.type) { - case T_STRING: + case FieldType::String: fv.s.resize(fv.size); READ_N(data, fv.s[0], fv.s.size()); break; - case T_INTEGER: + case FieldType::Integer: READ(data, fv.i); if (fv.size > sizeof(fv.i)) data.skip(fv.size - sizeof(fv.i)); break; - case T_FLOAT: + case FieldType::Float: READ(data, fv.f); if (fv.size > sizeof(fv.i)) data.skip(fv.size - sizeof(fv.i)); diff --git a/src/db_extractor/db.h b/src/db_extractor/db.h index 7005532..c1389e4 100644 --- a/src/db_extractor/db.h +++ b/src/db_extractor/db.h @@ -28,21 +28,18 @@ using namespace std; -enum FieldType +enum class FieldType : uint32_t { - T_STRING, - T_INTEGER, - T_FLOAT, + String, + Integer, + Float, }; -string getSqlType(uint32_t ft); +string getSqlType(FieldType type); struct table { uint32_t id; - char name[0x14]; - uint32_t unk1; - uint32_t unk2; - uint32_t unk3; + char name[0x20]; uint32_t unk4; void load(buffer &b); @@ -52,11 +49,8 @@ struct field { uint32_t table_id; uint32_t id; - char name[0x14]; - uint32_t unk1; - uint32_t unk2; - uint32_t unk3; - uint32_t type; + char name[0x20]; + FieldType type; void load(buffer &b); }; @@ -85,20 +79,13 @@ struct field_value struct value { uint32_t table_id; - char name[0x14]; - uint32_t unk1; - uint32_t unk2; - uint32_t unk3; + char name[0x20]; uint32_t offset; uint32_t data_size; - buffer data; - uint32_t number_of_fields; vector fields; - void extract_fields(const tab &tab); - void load_index(buffer &b); - void load_data(buffer &b); + void load_fields(const tab &tab, buffer &b); }; struct db diff --git a/src/db_extractor/db_extractor.cpp b/src/db_extractor/db_extractor.cpp index 89ad9f2..89cb881 100644 --- a/src/db_extractor/db_extractor.cpp +++ b/src/db_extractor/db_extractor.cpp @@ -30,9 +30,7 @@ void open_db(string path, db &db) db.load(buffer(readFile(path + ".ind"))); buffer b(readFile(path + ".dat")); for (auto &v : db.values) - v.load_data(b); - for (auto &v : db.values) - v.extract_fields(db.t); + v.load_fields(db.t, b); } string str2utf8(string codepage_str) @@ -132,13 +130,13 @@ void create_sql(string path, const db &db) auto fld = db.t.fields.find(f.field_id); switch (fld->second.type) { - case T_STRING: + case FieldType::String: s += str2utf8(f.s.c_str()); break; - case T_INTEGER: + case FieldType::Integer: s += to_string(f.i); break; - case T_FLOAT: + case FieldType::Float: s += to_string(f.f); break; default: diff --git a/src/mmp_extractor/bmp.h b/src/mmp_extractor/bmp.h new file mode 100644 index 0000000..dbec8a1 --- /dev/null +++ b/src/mmp_extractor/bmp.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +using BYTE = uint8_t; +using WORD = uint16_t; +using DWORD = uint32_t; +using LONG = uint32_t; + +#pragma pack(push, 1) + +typedef struct tagBITMAPFILEHEADER { + WORD bfType; + DWORD bfSize; + WORD bfReserved1; + WORD bfReserved2; + DWORD bfOffBits; +} BITMAPFILEHEADER; + +typedef struct tagBITMAPINFOHEADER { + DWORD biSize; + LONG biWidth; + LONG biHeight; + WORD biPlanes; + WORD biBitCount; + DWORD biCompression; + DWORD biSizeImage; + LONG biXPelsPerMeter; + LONG biYPelsPerMeter; + DWORD biClrUsed; + DWORD biClrImportant; +} BITMAPINFOHEADER; + +typedef struct tagRGBQUAD { + BYTE rgbBlue; + BYTE rgbGreen; + BYTE rgbRed; + BYTE rgbReserved; +} RGBQUAD; + +typedef struct tagBITMAPINFO { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[1]; +} BITMAPINFO; + +#pragma pack(pop) diff --git a/src/mmp_extractor/mat.h b/src/mmp_extractor/mat.h new file mode 100644 index 0000000..9550be2 --- /dev/null +++ b/src/mmp_extractor/mat.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include +#include + +template +class mat +{ +public: + using type = T; + +public: + mat(int w = 0, int h = 0) + { + width = w < 0 ? 0 : w; + height = h < 0 ? 0 : h; + data.resize(width * height, T()); + } + + T &operator()(int row, int col) + { + assert(!(row >= height || col >= width || row < 0 || col < 0)); + return data[row * width + col]; + } + const T &operator()(int row, int col) const + { + return (*const_cast(this))(row, col); + } + + void clean() + { + std::fill(data.begin(), data.end(), T()); + } + + int getWidth() const { return width; } + int getHeight() const { return height; } + int size() const { return width * height; } + int getPos(const T *const elem) const { return elem - &data[0]; } + const std::vector &getData() const { return data; } + std::vector &getData() { return data; } + +private: + std::vector data; + int width; + int height; +}; diff --git a/src/mmp_extractor/mmp.cpp b/src/mmp_extractor/mmp.cpp index a38febd..c21b47f 100644 --- a/src/mmp_extractor/mmp.cpp +++ b/src/mmp_extractor/mmp.cpp @@ -18,17 +18,76 @@ #include "mmp.h" -void unk_segment1::load(buffer &b) +#include +#include +#include + +#include "bmp.h" + +template +void write_mat_bmp(const std::string &filename, const mat &m) +{ + FILE *f = fopen(filename.c_str(), "wb"); + if (f == nullptr) + return; + BITMAPFILEHEADER h = { 0 }; + h.bfType = 0x4D42; + h.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) + m.size() * sizeof(T); + h.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO); + BITMAPINFO i = { 0 }; + i.bmiHeader.biSize = sizeof(i.bmiHeader); + i.bmiHeader.biWidth = m.getWidth(); + i.bmiHeader.biHeight = m.getHeight(); + i.bmiHeader.biPlanes = 1; + i.bmiHeader.biBitCount = 32; + i.bmiHeader.biCompression = 0; + i.bmiHeader.biSizeImage = 0; + i.bmiHeader.biXPelsPerMeter = 0; + i.bmiHeader.biYPelsPerMeter = 0; + i.bmiHeader.biClrUsed = 0; + i.bmiHeader.biClrImportant = 0; + fwrite(&h, sizeof(BITMAPFILEHEADER), 1, f); + fwrite(&i, sizeof(BITMAPINFO), 1, f); + fwrite(&m(0, 0), m.size() * sizeof(T), 1, f); + fclose(f); +} + +void write_mat_tga(const std::string &filename, const mat &m) +{ + // http://paulbourke.net/dataformats/tga/ + buffer dst; + dst.write(uint8_t(0xE)); // idlength (comment length) + dst.write(uint8_t(0)); // colourmaptype + dst.write(uint8_t(3)); // datatypecode + dst.write(uint16_t(0)); // colourmaporigin + dst.write(uint16_t(0)); // colourmaplength + dst.write(uint8_t(0)); // colourmapdepth + dst.write(uint16_t(0)); // x_origin + dst.write(uint16_t(0)); // y_origin + dst.write(uint16_t(m.getWidth())); // width + dst.write(uint16_t(m.getHeight())); // height + dst.write(uint8_t(8)); // bitsperpixel + dst.write(uint8_t(0x28)); // imagedescriptor + + const char *label = "AIMMPExtractor"; + dst.write(label, strlen(label)); + + dst.write(m.getData().data(), m.getWidth() * m.getHeight()); + + writeFile(filename, dst.buf()); +} + +void water_segment::load(buffer &b) { while (!b.eof()) { - unk_segment1_1 s; - s.load(b); - segments.push_back(s); + water w; + w.load(b); + segments.push_back(w); } } -void unk_segment1_1::load(buffer &b) +void water::load(buffer &b) { READ(b, unk0); READ(b, name1); @@ -40,7 +99,7 @@ void unk_segment1_1::load(buffer &b) READ(b, unk5); } -void unk_segment2::load(buffer &b) +void weather_segment::load(buffer &b) { READ(b, n_segs); segments.resize(n_segs); @@ -49,22 +108,36 @@ void unk_segment2::load(buffer &b) s.load(b); } -void unk_segment2_1::load(buffer &b) +void weather::load(buffer &b) { - READ(b, name1); - READ(b, name2); - READ(b, name3); - READ(b, name4); - READ(b, name5); + READ(b, name); READ(b, unk0); READ(b, unk1); - READ(b, tex_name0); + READ(b, smoke_1); + READ(b, smoke_3); + READ(b, smokeType); READ(b, unk2); - READ(b, unk_name0); - READ(b, unk3); - READ(b, tex_name1); - READ(b, tex_name2); - READ(b, unk4); + READ(b, cloud_layer1); + READ(b, cloud_layer2); + READ(b, cloud_layer1_speed); + READ(b, cloud_layer2_speed); + READ(b, cloud_layer1_direction); + READ(b, cloud_layer2_direction); + READ(b, sun); + READ(b, general_color); + READ(b, sun_color); + READ(b, moon_color); + READ(b, moon); + READ(b, probability); + READ(b, day_night_gradient_name); + READ(b, dawn_dusk_gradient_name); + READ(b, dawn_dusk_color); + READ(b, effects); + READ(b, smoke_2); + READ(b, smoke_4); + READ(b, slider_3); + READ(b, slider_1); + READ(b, unk8); } header_segment *header::create_segment(buffer &b) @@ -75,11 +148,11 @@ header_segment *header::create_segment(buffer &b) header_segment *segment = 0; switch (type) { - case HeaderSegmentType::unk1: - segment = new unk_segment1; + case HeaderSegmentType::water: + segment = new water_segment; break; - case HeaderSegmentType::unk2: - segment = new unk_segment2; + case HeaderSegmentType::weather: + segment = new weather_segment; break; default: throw std::logic_error("unknown header segment type " + std::to_string((int)type)); @@ -101,8 +174,8 @@ void header::load(buffer &b) READ(b, name2); READ(b, width); READ(b, height); - READ(b, n_segs); - segments.resize(n_segs); + READ(b, n_header_segs); + segments.resize(n_header_segs); READ(b, name); for (auto &s : segments) { @@ -124,8 +197,203 @@ void segment::load(buffer &b) void mmp::load(buffer &b) { h.load(b); - int n_segs = h.width / 64 * h.height / 64; + xsegs = (h.width - 1) / 64; + if ((h.width - 1) % 64 != 0) + xsegs++; + ysegs = (h.height - 1) / 64; + if ((h.height - 1) % 64 != 0) + ysegs++; + int n_segs = xsegs * ysegs; segments.resize(n_segs); for (auto &s : segments) s.load(b); -} \ No newline at end of file + + // check whether all segments were read + if (segments.size()) + { + auto len = segments[0].desc.offset + segments.size() * sizeof(segment::data); + if (len != b.size()) + throw std::logic_error("Some segments were not read"); + } +} + +void mmp::load(const std::string &fn) +{ + filename = fn; + buffer b(readFile(filename)); + load(b); +} + +void mmp::loadTextureNames(const std::string &fn) +{ + std::ifstream ifile(fn); + while (ifile) + { + int id; + std::string name; + ifile >> id >> name; + textures_names[id] = name; + } +} + +void mmp::process() +{ + int k = segment::len; + + for (auto &s : segments) + { + for (auto &i : s.d.Infomap) + textures[i.getTexture()]++; + } + textures.erase(0); + auto textures_per_color = std::max(1U, textures.size() / 3); + auto color_step = 200 / textures.size(); + for (int i = 0; i < textures.size(); i++) + { + int color_id = i / textures_per_color; + color c = { 0 }; + if (color_id == 0) + c.r = 255 - 200 / textures_per_color * (i % textures_per_color); + else if (color_id == 1) + c.g = 255 - 200 / textures_per_color * (i % textures_per_color); + else if (color_id == 2) + c.b = 255 - 200 / textures_per_color * (i % textures_per_color); + auto iter = textures.begin(); + std::advance(iter, i); + textures_map_colored[iter->first] = c; + color c2 = { 0 }; + c2.g = 255 - i * color_step; + textures_map[iter->first] = c2; + } + alpha_maps[0] = mat(h.width, h.height); + for (auto &t : textures_map) + alpha_maps[t.second.g] = mat(h.width, h.height); + + // merge + heightmap = decltype(heightmap)(h.width, h.height); + texmap = decltype(texmap)(h.width, h.height); + texmap_colored = decltype(texmap_colored)(h.width, h.height); + colormap = decltype(colormap)(h.width, h.height); + for (int y = 0; y < h.height; y++) + { + auto ys = y / k * xsegs; + auto yc = y % k * k; + for (int x = 0; x < h.width; x++) + { + auto xs = x / k; + auto xc = x % k; + auto y_rev = h.height - y - 1; + const auto &data = segments[ys + xs].d; + auto height = data.Heightmap[yc + xc]; + auto t = data.Infomap[yc + xc].getTexture(); + auto t_norm = textures_map[t]; + + texmap(y_rev, x) = t_norm; + alpha_maps[t_norm.g](y_rev, x) = color{ 0,255,0,0 }; + texmap_colored(y_rev, x) = textures_map_colored[t]; + colormap(y_rev, x) = data.Colormap[yc + xc]; + + if (x == 0 && y == 0) + { + h_min = height; + h_max = height; + } + else + { + h_min = std::min(h_min, height); + h_max = std::max(h_max, height); + } + } + } + + alpha_maps.erase(0); + scale16 = 0xffff / (h_max - h_min); + + for (int y = 0; y < h.height; y++) + { + auto ys = y / k * xsegs; + auto yc = y % k * k; + for (int x = 0; x < h.width; x++) + { + auto xs = x / k; + auto xc = x % k; + auto height = segments[ys + xs].d.Heightmap[yc + xc]; + auto val = (height - h_min) * scale16; + heightmap(y, x) = val; + } + } +} + +void mmp::writeFileInfo() +{ + std::ofstream ofile(filename + ".info.txt"); + if (!ofile) + return; + ofile << "width: " << h.width << "\n"; + ofile << "height: " << h.height << "\n"; + ofile << "x segments: " << xsegs << "\n"; + ofile << "y segments: " << ysegs << "\n"; + ofile << "h_min: " << h_min << "\n"; + ofile << "h_max: " << h_max << "\n"; + ofile << "h_diff: " << h_max - h_min << "\n"; + ofile << "scale16: " << scale16 << "\n"; +} + +void mmp::writeTexturesList() +{ + std::ofstream ofile(filename + ".textures.txt"); + if (!ofile) + return; + for (auto &t : textures) + { + ofile << t.first; + if (!textures_names.empty()) + { + int c = textures_map[t.first].g; + ofile << "\tcount: " << t.second; + ofile << "\thex: 0x00" << std::hex << c << "0000" << std::dec; + ofile << "\tg: " << c; + ofile << "\tg: " << std::setprecision(3) << std::setw(3) << c / 256.f; + ofile << "\t" << textures_names[t.first]; + } + ofile << "\n"; + } +} + +void mmp::writeHeightMap() +{ + auto fn = filename + ".heightmap16.raw"; + FILE *f = fopen(fn.c_str(), "wb"); + if (f == nullptr) + return; + fwrite(&heightmap(0, 0), heightmap.size() * sizeof(decltype(heightmap)::type), 1, f); + fclose(f); +} + +void mmp::writeTextureMap() +{ + auto fn = filename + ".texmap.bmp"; + write_mat_bmp(fn, texmap); +} + +void mmp::writeTextureAlphaMaps() +{ + for (auto &t : alpha_maps) + { + auto fn = filename + ".texmap." + std::to_string(t.first) + ".bmp"; + write_mat_bmp(fn, t.second); + } +} + +void mmp::writeTextureMapColored() +{ + auto fn = filename + ".texmap.colored.bmp"; + write_mat_bmp(fn, texmap_colored); +} + +void mmp::writeColorMap() +{ + auto fn = filename + ".colormap.bmp"; + write_mat_bmp(fn, colormap); +} + diff --git a/src/mmp_extractor/mmp.h b/src/mmp_extractor/mmp.h index e4d522a..6a7de19 100644 --- a/src/mmp_extractor/mmp.h +++ b/src/mmp_extractor/mmp.h @@ -16,16 +16,60 @@ * along with this program. If not, see . */ +#include +#include #include #include #include #include +#include "mat.h" + +enum class WeatherType : uint32_t +{ + rain = 0x1, + snow = 0x2, + storm = 0x4, +}; + +enum class SmokeType : uint32_t +{ + none, + exp, + biexp, + linear, +}; + +struct color +{ + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t a; + + operator uint32_t() const + { + uint32_t color = 0; + color |= r << 16; + color |= g << 8; + color |= b; + return color; + //return *reinterpret_cast(const_cast(&b)); + } +}; + +struct direction +{ + float x; + float y; + float z; +}; + enum class HeaderSegmentType : uint32_t { - unk1 = 1, - unk2 = 2, + water = 1, + weather = 2, }; struct header_segment @@ -37,7 +81,7 @@ struct header_segment virtual void load(buffer &b) = 0; }; -struct unk_segment1_1 +struct water { float unk0[6]; char name1[0x20]; @@ -51,38 +95,61 @@ struct unk_segment1_1 void load(buffer &b); }; -struct unk_segment1 : public header_segment +struct water_segment : public header_segment { - std::vector segments; + std::vector segments; virtual void load(buffer &b) override; }; -struct unk_segment2_1 +struct weather { - char name1[0x20]; - char name2[0x20]; - char name3[0x20]; - char name4[0x20]; - char name5[0x20]; - float unk0[2]; - uint32_t unk1[6]; - char tex_name0[0x20]; + struct atmospheric_effects + { + direction wind; + WeatherType weatherType; + float strength; + float duration; + float probability; + }; + + char name[0x20]; + char unk0[0x20]; + uint32_t unk1[2]; + color smoke_1; //3? + color smoke_3; //1? + SmokeType smokeType; uint32_t unk2[3]; - char unk_name0[0x20]; - float unk3; - char tex_name1[0x20]; - char tex_name2[0x20]; - uint32_t unk4[23]; + char cloud_layer1[0x20]; + char cloud_layer2[0x20]; + float cloud_layer1_speed; + float cloud_layer2_speed; + direction cloud_layer1_direction; + direction cloud_layer2_direction; + char sun[0x20]; + color general_color; + color sun_color; + color moon_color; + char moon[0x20]; + float probability; + char day_night_gradient_name[0x20]; + char dawn_dusk_gradient_name[0x20]; + color dawn_dusk_color; + atmospheric_effects effects; + color smoke_2; + color smoke_4; + uint32_t slider_3; + uint32_t slider_1; + float unk8[11]; void load(buffer &b); }; -struct unk_segment2 : public header_segment +struct weather_segment : public header_segment { uint32_t n_segs; char name[0xA0]; - std::vector segments; + std::vector segments; virtual void load(buffer &b) override; }; @@ -94,7 +161,7 @@ struct header wchar_t name2[0x20]; uint32_t width; uint32_t height; - uint32_t n_segs; + uint32_t n_header_segs; char name[0xA0]; std::vector segments; @@ -106,6 +173,9 @@ private: struct segment { + static const int len = 65; + static const int size = len * len; + struct description { uint32_t offset; @@ -124,13 +194,8 @@ struct segment { uint16_t render_flags; uint16_t texture_index; - }; - struct color - { - uint8_t b; - uint8_t g; - uint8_t r; - uint8_t a; + + uint16_t getTexture() const { return texture_index & 0x0fff; } // first 4 bits are unk (flags?) }; struct shadow { @@ -151,11 +216,11 @@ struct segment uint32_t MagicNumber; old_data old; - float Heightmap[4225]; - info Infomap[4225]; - color Colormap[4225]; - shadow Shadowmap[4225]; - normal Normalmap[4225]; + float Heightmap[size]; + info Infomap[size]; + color Colormap[size]; + shadow Shadowmap[size]; + normal Normalmap[size]; }; description desc; @@ -169,5 +234,34 @@ struct mmp header h; std::vector segments; + // + std::string filename; + int xsegs; + int ysegs; + std::map textures; + std::map textures_map; + std::map> alpha_maps; + std::map textures_map_colored; + std::map textures_names; + float h_min; + float h_max; + float scale16 = 0; + mat heightmap; + mat texmap; + mat texmap_colored; + mat colormap; + void load(buffer &b); -}; \ No newline at end of file + void load(const std::string &filename); + void loadTextureNames(const std::string &filename); + + void process(); + + void writeFileInfo(); + void writeTexturesList(); + void writeHeightMap(); + void writeTextureMap(); + void writeTextureAlphaMaps(); + void writeTextureMapColored(); + void writeColorMap(); +}; diff --git a/src/mmp_extractor/mmp_extractor.bat b/src/mmp_extractor/mmp_extractor.bat index 8d0d700..4ecbced 100644 --- a/src/mmp_extractor/mmp_extractor.bat +++ b/src/mmp_extractor/mmp_extractor.bat @@ -1,2 +1,3 @@ -python mmp_extractor.py --dir "h:\Games\AIM\data\maps.pak.dir" -python mmp_extractor.py --dir "h:\Games\Steam\steamapps\common\AIM2\Data\mmp.pak\DATA\LOCS" \ No newline at end of file +python mmp_extractor.py --dir "h:\Games\AIM\data\maps.pak.dir" --tex mmp_tex_aim1.txt +python mmp_extractor.py --dir "h:\Games\Steam\steamapps\common\AIM2\Data\mmp.pak\DATA\LOCS" --tex mmp_tex_aim2.txt +python mmp_extractor.py --dir "h:\Games\Steam\steamapps\common\AIM2\Projects" --tex mmp_tex_aim2.txt diff --git a/src/mmp_extractor/mmp_extractor.cpp b/src/mmp_extractor/mmp_extractor.cpp index cb68fee..3f22054 100644 --- a/src/mmp_extractor/mmp_extractor.cpp +++ b/src/mmp_extractor/mmp_extractor.cpp @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -25,28 +26,26 @@ using namespace std; -mmp read_mmp(string fn) -{ - buffer b(readFile(fn)); - mmp m; - m.load(b); - return m; -} - -void process_mmp(mmp &m, string fn) -{ -} - int main(int argc, char *argv[]) try { - if (argc != 2) + if (argc < 2 || argc > 3) { - cout << "Usage:\n" << argv[0] << " file.mmp" << "\n"; + cout << "Usage:\n" << argv[0] << " file.mmp [texture_ids.txt]" << "\n"; return 1; } - auto m = read_mmp(argv[1]); - process_mmp(m, argv[1]); + mmp m; + if (argc > 2) + m.loadTextureNames(argv[2]); + m.load(argv[1]); + m.process(); + m.writeFileInfo(); + m.writeTexturesList(); + m.writeHeightMap(); + m.writeTextureMap(); + m.writeTextureAlphaMaps(); + m.writeTextureMapColored(); + m.writeColorMap(); return 0; } catch (std::exception &e) @@ -58,4 +57,4 @@ catch (...) { printf("error: unknown exception\n"); return 1; -} \ No newline at end of file +} diff --git a/src/mmp_extractor/mmp_extractor.py b/src/mmp_extractor/mmp_extractor.py index b1b9e3b..96d8e95 100644 --- a/src/mmp_extractor/mmp_extractor.py +++ b/src/mmp_extractor/mmp_extractor.py @@ -8,17 +8,18 @@ import subprocess def main(): parser = argparse.ArgumentParser(description='Batch MMP extractor') parser.add_argument('--dir', dest='dir', help='path to directory with maps') + parser.add_argument('--tex', dest='tex', help='path to textures ids') pargs = parser.parse_args() if pargs.dir: - run(pargs.dir) + run(pargs.dir, pargs.tex) -def run(dir): +def run(dir, tex): for file in sorted(os.listdir(dir)): if os.path.isdir(file) or os.path.splitext(file)[1].lower() != ".mmp": continue print('processing: ' + file) - p = subprocess.Popen(['mmp_extractor.exe', dir + '/' + file]) + p = subprocess.Popen(['mmp_extractor.exe', dir + '/' + file, tex]) p.communicate() if __name__ == '__main__': diff --git a/src/mmp_extractor/mmp_tex_aim1.txt b/src/mmp_extractor/mmp_tex_aim1.txt new file mode 100644 index 0000000..540cd95 --- /dev/null +++ b/src/mmp_extractor/mmp_tex_aim1.txt @@ -0,0 +1,328 @@ +276 TEX_VERT_12 +284 TEX_LAND108 +285 TEX_PESOK_8 +288 TEX_6_8-2 +289 TEX_VERT5 +291 TEX_VERT_1 +292 TEX_TRAVA-8 +293 TEX_16_8 +299 TEX_PLITA8 +314 TEX_SNOW2_8 +321 TEX_SNOW3_8 +321 TEX_SNOW3_8 +325 TEX_SNOW4_8 +345 TEX_SNOW_VERT_1 +352 TEX_SNOW_VERT2 +428 TEX_ROADS_8 +437 TEX_ICE_8 +455 TEX_MOH_BROUN_8 +493 TEX_BEREG +502 TEX_BEREG_2 +511 TEX_GLINA_8_2 +520 TEX_LAVA_8_2 +523 TEX_PESOK_V_8 +532 TEX_BASALT_8 +549 TEX_LAVA1_8 +558 TEX_LAND_S_8 +564 TEX_FUND8 +567 TEX_VERT_LAVA_1 +576 TEX_LAVA_2_8 +585 TEX_VERT_LAVA_2 +598 TEX_LAND_BLACK_8 +607 TEX_TRAVA-8 +616 TEX_SWAMP_8 +625 TEX_SWAMP_2_8 +634 TEX_LAND_3_8 +643 TEX_CRYSTALL_8 +652 TEX_ROAD_BROUNE_8 +661 TEX_CRYST_8 +670 TEX_16_8 +690 TEX_6_8-2 +699 TEX_LAND_V_8 +708 TEX_LAND_V_8 +736 TEX_PESOK_8 +745 TEX_KORDILYER +785 TEX_PESOK_8 +794 TEX_L3_ROAD_8 +797 TEX_ROCKLAND_2 +824 TEX_TRAVA-8 +833 TEX_ROCK_LAND +841 TEX_SWAMP_8 +844 TEX_IKRA-8 +847 TEX_SNOW_VERT_3 +850 TEX_VERT_SNOW_2 +853 TEX_VERT_SNOW_3 +856 TEX_L4_ROAD_8 +859 TEX_TRAVA-8 +862 TEX_TRAVA-8 +864 TEX_16_8 +868 TEX_PESOK_8 +908 TEX_VERT_1 +914 TEX_PESOK_8 +927 TEX_BEREG +933 TEX_GLINA_8_2 +943 TEX_L5_DUNA_81 +953 TEX_PESOK_8 +957 TEX_PESOK_8 +960 TEX_PESOK_8 +981 TEX_L5_DUNA_81 +984 TEX_VERTIKAL +987 TEX_L5_DUNA_81 +990 TEX_GLINA_8_2 +999 TEX_LAND108 +1002 TEX_L5_DUNA_8 +1005 TEX_L5_DUNA_81 +1014 TEX_L5_STONE_DUNA +1026 TEX_PESOK_8 +1034 TEX_L5_DUNA_81 +1037 TEX_L5_DUNA_81 +1049 TEX_PESOK_8 +1052 TEX_L5_ROAD_8 +1056 TEX_PESOK_8 +1067 TEX_PESOK_8 +1070 TEX_PESOK_8 +1079 TEX_LAND108 +1082 TEX_LAND108 +1089 TEX_PESOK_8 +1092 TEX_PESOK_8 +1095 TEX_BEREG_2 +1104 TEX_GLINA_8_2 +1110 TEX_LAVA_8_2 +1123 TEX_L6_SAND_1 +1129 TEX_LAND_V_8 +1149 TEX_SWAMP_2_8 +1153 TEX_SWAMP_2_8 +1159 TEX_SWAMP_2_8 +1166 TEX_SWAMP_2_8 +1168 TEX_L3_ROAD_8 +1171 TEX_SWAMP_2_8 +1174 TEX_SWAMP_2_8 +1180 TEX_BEREG +1183 TEX_SWAMP_2_8 +1186 TEX_GLINA_8_2 +1189 TEX_SWAMP_2_8 +1198 TEX_SWAMP_2_8 +1206 TEX_SWAMP_2_8 +1213 TEX_LAND_3_8 +1216 TEX_SWAMP_2_8 +1225 TEX_L6_SAND_1 +1229 TEX_VERTIKAL +1235 TEX_ROCKLAND_2 +1245 TEX_BEREG_2 +1248 TEX_VERTIKAL +1251 TEX_SWAMP_2_8 +1254 TEX_SWAMP_2_8 +1256 TEX_CRYST_8 +1259 TEX_PLITA_8 +1268 TEX_TRAVA +1279 TEX_L3_ROAD_8 +1286 TEX_L3_ROAD_8 +1292 TEX_SWAMP_2_8 +1295 TEX_TRAVA +1299 TEX_L6_SAND_1 +1308 TEX_L6_SAND_1 +1311 TEX_L6_SAND_1 +1316 TEX_L6_SAND_1 +1319 TEX_TRAVA +1326 TEX_16_8 +1337 TEX_PESOK_8 +1340 TEX_PLITA_BLD_8 +1343 TEX_L3_ROAD_8 +1346 TEX_PLITA_BETON +1355 TEX_PLITA_8 +1358 TEX_PESOK_8 +1363 TEX_SWAMP_2_8 +1371 TEX_SWAMP_2_8 +1382 TEX_SWAMP_2_8 +1385 TEX_SWAMP_2_8 +1400 TEX_SWAMP_2_8 +1410 TEX_SWAMP_2_8 +1420 TEX_SWAMP_2_8 +1423 TEX_SWAMP_2_8 +1432 TEX_MOH_BROUN_8 +1438 TEX_SWAMP_2_8 +1440 TEX_SWAMP_2_8 +1444 TEX_SWAMP_2_8 +1447 TEX_GLINA_8_2 +1458 TEX_SWAMP_2_8 +1469 TEX_SWAMP_2_8 +1472 TEX_SWAMP_2_8 +1475 TEX_GLINA_8_2 +1484 TEX_SWAMP_2_8 +1488 TEX_SWAMP_2_8 +1493 TEX_SWAMP_2_8 +1504 TEX_GLINA_8_2 +1510 TEX_SWAMP_2_8 +1513 TEX_MOH_BROUN_8 +1522 TEX_BASALT_8 +1528 TEX_BASALT_8 +1531 TEX_MAGMA_8 +1543 TEX_LAVA_2_8 +1552 TEX_LAVA1_8 +1558 TEX_LAND_S_8 +1569 TEX_PLITA_BETON +1575 TEX_CRYSTALL_8 +1584 TEX_SWAMP_2_8 +1589 TEX_SWAMP_2_8 +1598 TEX_SWAMP_2_8 +1601 TEX_LAVA_2_8 +1604 TEX_SWAMP_2_8 +1607 TEX_SWAMP_2_8 +1610 TEX_L4_PROVAL_8 +1613 TEX_L4_FLASH +1615 TEX_SWAMP_2_8 +1618 TEX_GLINA_8_2 +1621 TEX_SWAMP_2_8 +1626 TEX_SWAMP_2_8 +1632 TEX_SWAMP_2_8 +1643 TEX_L7_MOUTH +1646 TEX_SNOW_VERT_3 +1649 TEX_CRYSTALL_8 +1661 TEX_L4_LAVA_STONE_8 +1664 TEX_L8_KORNI_8 +1669 TEX_SWAMP_2_8 +1673 TEX_L8_PIMPLE_8 +1676 TEX_L8_PIMPLE_VIOLET_8 +1686 TEX_CRYSTALL_8 +1689 TEX_L8_PIMPLE_ORANGE_8 +1698 TEX_VERT_LAVA_1 +1701 TEX_L8_ROCKS +1704 TEX_L8_KORNI_8 +1713 TEX_L8_PIMPLE_8 +1719 TEX_L8_PIMPLE_ORANGE_8 +1721 TEX_L8_PIMPLE_ORANGE_8 +1724 TEX_L8_PIMPLE_VIOLET_8 +1727 TEX_L8_ROOTS_8 +1730 TEX_SWAMP_2_8 +1733 TEX_L8_FLESH_8 +1736 TEX_L8_MOULD_ROCK +1739 TEX_PESOK_8 +1742 TEX_L8_ROCKS_2 +1745 TEX_L8_BOWELS +1748 TEX_16_8 +1758 TEX_SWAMP_2_8 +1768 TEX_L6_ROAD_90_8 +1771 TEX_L6_ROAD_45_8 +1775 TEX_L6_ROAD_FD_8 +1782 TEX_L6_SAND_1 +1793 TEX_PESOK_8 +1801 TEX_PESOK_8 +1803 TEX_L6_SAND_1 +1806 TEX_SWAMP_2_8 +1809 TEX_L8_BOWELS_2 +1819 TEX_SWAMP_2_8 +1829 TEX_SWAMP_2_8 +1831 TEX_BEREG_2 +1836 TEX_SWAMP_2_8 +1839 TEX_TRAVA_8_ALT +1842 TEX_SWAMP_2_8 +1845 TEX_LAND_3_8 +1848 TEX_SWAMP_2_8 +1859 TEX_L3_ROCKS_V +1870 TEX_L5_STONE_DUNE_G_8 +1879 TEX_L6_SAND_1 +1885 TEX_L6_SAND_1 +1888 TEX_L6_SAND_CLIFF +1891 TEX_METAL_WALL +1894 TEX_METAL_WALL_2 +1903 TEX_METAL_GORIZ_8 +1906 TEX_METAL_RELS_8 +1909 TEX_METAL_RELS_2_8 +1920 TEX_L5_BIGWORM_V +1926 TEX_PLITA_8 +1937 TEX_PESOK_8 +1941 TEX_SWAMP_2_8 +1952 TEX_TRAVA +1955 TEX_SWAMP_2_8 +1959 TEX_SWAMP_2_8 +1967 TEX_SWAMP_2_8 +1974 TEX_SWAMP_2_8 +1980 TEX_SWAMP_2_8 +1987 TEX_SWAMP_2_8 +1991 TEX_L6_SAND_1 +1995 TEX_SWAMP_2_8 +1999 TEX_L6_SAND_1 +2010 TEX_L6_SAND_1 +2014 TEX_PLITA8 +2024 TEX_PESOK_8 +2029 TEX_SNOW3_8 +2034 TEX_ROADS_8 +2040 TEX_SNOW4_8 +2044 TEX_SNOW2_8 +2050 TEX_L3_ROCKS_V +2055 TEX_SNOW4_8 +2061 TEX_ICE_8 +2065 TEX_ICE_8 +2070 TEX_ICE_8 +2074 TEX_LAND_3_8 +2076 TEX_LAND_3_8 +2082 TEX_LAND_3_8 +2091 TEX_L3_ROCKS_V +2101 TEX_VERT_SNOW_3 +2108 TEX_LAND_3_8 +2113 TEX_L6_SAND_1 +2123 TEX_SWAMP_2_8 +2127 TEX_L6_SAND_1 +2133 TEX_L6_STONES +2140 TEX_L6_STONES +2151 TEX_PESOK_8 +2155 TEX_SNOW4_8 +2158 TEX_SWAMP_2_8 +2163 TEX_SNOW4_8 +2173 TEX_LAVA1_8 +2177 TEX_LAVA1_8 +2180 TEX_PLITA_BLD_8 +2189 TEX_METAL_WALL_2 +2195 TEX_METAL_WALL +2197 TEX_METAL_GORIZ_8 +2208 TEX_UG_LOW_WALL_GENERAL_8 +2214 TEX_UG_PIPE_8 +2224 TEX_UG_RAIL_8 +2234 TEX_UG_FLOOR_CONVEYOR_8_V2 +2238 TEX_METAL_GORIZ_8 +2244 TEX_UG_FLOOR_PANEL_VENT_8 +2251 TEX_UG_LOW_WALL_GENERAL_8 +2257 TEX_METAL_WALL_2 +2260 TEX_UG_FLOOR_CONVEYOR_8 +2263 TEX_ROCK_LAND +2272 TEX_MOH_BROUN_8 +2278 TEX_UG_LOW_WALL_GENERAL_8 +2286 TEX_ROCKLAND_2 +2288 TEX__TEST +2292 TEX_ROCKLAND_2 +2300 TEX_L6_SAND_CLIFF +2305 TEX_SWAMP_2_8 +2318 TEX_VERT_LAVA_2 +2321 TEX_LDM_SAND +2336 TEX_LDM_SAND +2345 TEX_L6_SAND_CLIFF +2351 TEX_LDM_SAND +2353 TEX_MAGMA_8 +2364 TEX_LDM_SAND +2370 TEX_LAND_3_8 +2380 TEX_LAND_3_8 +2383 TEX_L6_STONES +2386 TEX_SWAMP_2_8 +2389 TEX_SWAMP_2_8 +2393 TEX_L5_ROAD2_8 +2400 TEX_VERT_LAVA_2 +2407 TEX_L3_ROCKS_V +2412 TEX_L6_SAND_CLIFF +2414 TEX_SNOW2_8 +2422 TEX_SWAMP_2_8 +2422 TEX_SWAMP_2_8 +2425 TEX_SNOW_VERT2 +2428 TEX_L6_SAND_CLIFF +2428 TEX_L6_SAND_CLIFF +2434 TEX_CRYST_8 +2437 TEX_MOH_BROUN_8 +2437 TEX_MOH_BROUN_8 +2443 TEX_LAND108 +2443 TEX_LAND108 +2453 TEX_LAND108 +2456 TEX_L6_ROAD_90_8 +2456 TEX_L6_ROAD_90_8 +2464 TEX_MOH_BROUN_8 +2464 TEX_MOH_BROUN_8 +2467 TEX_METAL_GORIZ_8 +2467 TEX_METAL_GORIZ_8 \ No newline at end of file diff --git a/src/mmp_extractor/mmp_tex_aim2.txt b/src/mmp_extractor/mmp_tex_aim2.txt new file mode 100644 index 0000000..08c6b06 --- /dev/null +++ b/src/mmp_extractor/mmp_tex_aim2.txt @@ -0,0 +1,485 @@ +276 TEX_VERT_12 +284 TEX_LAND108 +285 TEX_PESOK_8 +288 TEX_6_8-2 +289 TEX_VERT5 +291 TEX_L1_CLIFF_SLICK +292 TEX_TRAVA-8 +293 TEX_16_8 +299 TEX_PLITA8 +314 TEX_SNOW2_8 +321 TEX_SNOW3_8 +321 TEX_SNOW3_8 +325 TEX_SNOW4_8 +345 TEX_SNOW_VERT_1 +352 TEX_SNOW_VERT2 +428 TEX_ROADS_8 +437 TEX_ICE_8 +455 TEX_MOH_BROUN_8 +493 TEX_BEREG +502 TEX_BEREG_2 +511 TEX_GLINA_8_2 +520 TEX_LAVA_8_2 +523 TEX_PESOK_V_8 +532 TEX_BASALT_8 +549 TEX_LAVA1_8 +558 TEX_LAND_S_8 +564 TEX_FUND8 +567 TEX_VERT_LAVA_1 +576 TEX_LAVA_2_8 +585 TEX_VERT_LAVA_2 +598 TEX_LAND_BLACK_8 +607 TEX_TRAVA-8 +616 TEX_SWAMP_8 +625 TEX_SWAMP_2_8 +634 TEX_LAND_3_8 +643 TEX_CRYSTALL_8 +652 TEX_ROAD_BROUNE_8 +661 TEX_CRYST_8 +670 TEX_16_8 +690 TEX_6_8-2 +699 TEX_LAND_V_8 +708 TEX_LAND_V_8 +736 TEX_PESOK_8 +745 TEX_KORDILYER +785 TEX_PESOK_8 +794 TEX_L3_ROAD_8 +797 TEX_ROCKLAND_2 +824 TEX_TRAVA-8 +833 TEX_ROCK_LAND +841 TEX_SWAMP_8 +844 TEX_IKRA-8 +847 TEX_SNOW_VERT_3 +850 TEX_VERT_SNOW_2 +853 TEX_VERT_SNOW_3 +856 TEX_L4_ROAD_8 +859 TEX_TRAVA-8 +862 TEX_TRAVA-8 +864 TEX_16_8 +868 TEX_PESOK_8 +908 TEX_VERT_1 +914 TEX_PESOK_8 +927 TEX_L2_RIVERBANK +933 TEX_GLINA_8_2 +943 TEX_L5_DUNA_81 +953 TEX_PESOK_8 +957 TEX_PESOK_8 +960 TEX_PESOK_8 +981 TEX_L5_DUNA_81 +984 TEX_VERTIKAL +987 TEX_L5_DUNA_81 +990 TEX_GLINA_8_2 +999 TEX_LAND108 +1002 TEX_L5_DUNA_8 +1005 TEX_L5_DUNA_81 +1014 TEX_L5_STONE_DUNA +1026 TEX_PESOK_8 +1034 TEX_L5_DUNA_81 +1037 TEX_L5_DUNA_81 +1049 TEX_PESOK_8 +1052 TEX_L5_ROAD_8 +1056 TEX_PESOK_8 +1067 TEX_PESOK_8 +1070 TEX_PESOK_8 +1079 TEX_LAND108 +1082 TEX_LAND108 +1089 TEX_PESOK_8 +1092 TEX_PESOK_8 +1095 TEX_L2_SAND_GULLY_02 +1104 TEX_GLINA_8_2 +1110 TEX_LAVA_8_2 +1123 TEX_L6_SAND_1 +1129 TEX_LAND_V_8 +1149 TEX_SWAMP_2_8 +1153 TEX_SWAMP_2_8 +1159 TEX_SWAMP_2_8 +1166 TEX_SWAMP_2_8 +1168 TEX_L3_ROAD_8 +1171 TEX_SWAMP_2_8 +1174 TEX_SWAMP_2_8 +1180 TEX_BEREG +1183 TEX_SWAMP_2_8 +1186 TEX_GLINA_8_2 +1189 TEX_SWAMP_2_8 +1198 TEX_SWAMP_2_8 +1206 TEX_SWAMP_2_8 +1213 TEX_LAND_3_8 +1216 TEX_SWAMP_2_8 +1225 TEX_L6_SAND_1 +1229 TEX_VERTIKAL +1235 TEX_ROCKLAND_2 +1245 TEX_L2_SAND_GULLY_01_2 +1248 TEX_VERTIKAL +1251 TEX_SWAMP_2_8 +1254 TEX_SWAMP_2_8 +1256 TEX_CRYST_8 +1259 TEX_PLITA_8 +1268 TEX_TRAVA +1279 TEX_L3_ROAD_8 +1286 TEX_L3_ROAD_8 +1292 TEX_SWAMP_2_8 +1295 TEX_TRAVA +1299 TEX_L6_SAND_1 +1308 TEX_L6_SAND_1 +1311 TEX_L6_SAND_1 +1316 TEX_L6_SAND_1 +1319 TEX_TRAVA +1326 TEX_16_8 +1337 TEX_PESOK_8 +1340 TEX_PLITA_BLD_8 +1343 TEX_L3_ROAD_8 +1346 TEX_PLITA_BETON +1355 TEX_PLITA_8 +1358 TEX_PESOK_8 +1363 TEX_SWAMP_2_8 +1371 TEX_SWAMP_2_8 +1382 TEX_SWAMP_2_8 +1385 TEX_SWAMP_2_8 +1400 TEX_SWAMP_2_8 +1410 TEX_SWAMP_2_8 +1420 TEX_SWAMP_2_8 +1423 TEX_SWAMP_2_8 +1432 TEX_MOH_BROUN_8 +1438 TEX_SWAMP_2_8 +1440 TEX_SWAMP_2_8 +1444 TEX_SWAMP_2_8 +1447 TEX_GLINA_8_2 +1458 TEX_SWAMP_2_8 +1469 TEX_SWAMP_2_8 +1472 TEX_SWAMP_2_8 +1475 TEX_GLINA_8_2 +1484 TEX_SWAMP_2_8 +1488 TEX_SWAMP_2_8 +1493 TEX_SWAMP_2_8 +1504 TEX_GLINA_8_2 +1510 TEX_SWAMP_2_8 +1513 TEX_MOH_BROUN_8 +1522 TEX_BASALT_8 +1528 TEX_BASALT_8 +1531 TEX_MAGMA_8 +1543 TEX_LAVA_2_8 +1552 TEX_LAVA1_8 +1558 TEX_LAND_S_8 +1569 TEX_PLITA_BETON +1575 TEX_CRYSTALL_8 +1584 TEX_SWAMP_2_8 +1589 TEX_SWAMP_2_8 +1598 TEX_SWAMP_2_8 +1601 TEX_LAVA_2_8 +1604 TEX_SWAMP_2_8 +1607 TEX_SWAMP_2_8 +1610 TEX_L4_PROVAL_8 +1613 TEX_L4_FLASH +1615 TEX_SWAMP_2_8 +1618 TEX_GLINA_8_2 +1621 TEX_SWAMP_2_8 +1626 TEX_SWAMP_2_8 +1632 TEX_SWAMP_2_8 +1643 TEX_L7_MOUTH +1646 TEX_SNOW_VERT_3 +1649 TEX_CRYSTALL_8 +1661 TEX_L4_LAVA_STONE_8 +1664 TEX_L8_KORNI_8 +1669 TEX_SWAMP_2_8 +1673 TEX_L8_PIMPLE_8 +1676 TEX_L8_PIMPLE_VIOLET_8 +1686 TEX_CRYSTALL_8 +1689 TEX_L8_PIMPLE_ORANGE_8 +1698 TEX_VERT_LAVA_1 +1701 TEX_L8_ROCKS +1704 TEX_L8_KORNI_8 +1713 TEX_L8_PIMPLE_8 +1719 TEX_L8_PIMPLE_ORANGE_8 +1721 TEX_L8_PIMPLE_ORANGE_8 +1724 TEX_L8_PIMPLE_VIOLET_8 +1727 TEX_L8_ROOTS_8 +1730 TEX_SWAMP_2_8 +1733 TEX_L8_FLESH_8 +1736 TEX_L8_MOULD_ROCK +1739 TEX_PESOK_8 +1742 TEX_L8_ROCKS_2 +1745 TEX_L8_BOWELS +1748 TEX_16_8 +1758 TEX_SWAMP_2_8 +1768 TEX_L6_ROAD_90_8 +1771 TEX_L6_ROAD_45_8 +1775 TEX_L6_ROAD_FD_8 +1782 TEX_L6_SAND_1 +1793 TEX_PESOK_8 +1801 TEX_PESOK_8 +1803 TEX_L6_SAND_1 +1806 TEX_SWAMP_2_8 +1809 TEX_L8_BOWELS_2 +1819 TEX_SWAMP_2_8 +1829 TEX_SWAMP_2_8 +1831 TEX_BEREG_2 +1836 TEX_SWAMP_2_8 +1839 TEX_TRAVA_8_ALT +1842 TEX_SWAMP_2_8 +1845 TEX_LAND_3_8 +1848 TEX_SWAMP_2_8 +1859 TEX_L3_ROCKS_V +1870 TEX_L5_STONE_DUNE_G_8 +1879 TEX_L6_SAND_1 +1885 TEX_L6_SAND_1 +1888 TEX_L6_SAND_CLIFF +1891 TEX_METAL_WALL +1894 TEX_METAL_WALL_2 +1903 TEX_METAL_GORIZ_8 +1906 TEX_METAL_RELS_8 +1909 TEX_METAL_RELS_2_8 +1920 TEX_L5_BIGWORM_V +1926 TEX_PLITA_8 +1937 TEX_PESOK_8 +1941 TEX_SWAMP_2_8 +1952 TEX_TRAVA +1955 TEX_SWAMP_2_8 +1959 TEX_SWAMP_2_8 +1967 TEX_SWAMP_2_8 +1974 TEX_SWAMP_2_8 +1980 TEX_SWAMP_2_8 +1987 TEX_SWAMP_2_8 +1991 TEX_L6_SAND_1 +1995 TEX_SWAMP_2_8 +1999 TEX_L6_SAND_1 +2010 TEX_L6_SAND_1 +2014 TEX_PLITA8 +2024 TEX_PESOK_8 +2029 TEX_SNOW3_8 +2034 TEX_ROADS_8 +2040 TEX_SNOW4_8 +2044 TEX_SNOW2_8 +2050 TEX_L3_ROCKS_V +2055 TEX_SNOW4_8 +2061 TEX_ICE_8 +2065 TEX_ICE_8 +2070 TEX_ICE_8 +2074 TEX_LAND_3_8 +2076 TEX_LAND_3_8 +2082 TEX_LAND_3_8 +2091 TEX_L3_ROCKS_V +2101 TEX_VERT_SNOW_3 +2108 TEX_LAND_3_8 +2113 TEX_L6_SAND_1 +2123 TEX_SWAMP_2_8 +2127 TEX_L6_SAND_1 +2133 TEX_L6_STONES +2140 TEX_L6_STONES +2151 TEX_PESOK_8 +2155 TEX_SNOW4_8 +2158 TEX_SWAMP_2_8 +2163 TEX_SNOW4_8 +2173 TEX_LAVA1_8 +2177 TEX_LAVA1_8 +2180 TEX_PLITA_BLD +2189 TEX_METAL_WALL_2 +2195 TEX_METAL_WALL +2197 TEX_METAL_GORIZ_8 +2208 TEX_UG_LOW_WALL_GENERAL +2214 TEX_UG_PIPE_8 +2224 TEX_UG_RAIL_8 +2234 TEX_UG_FLOOR_CONVEYOR_8_V2 +2238 TEX_METAL_GORIZ +2244 TEX_UG_FLOOR_PANEL_VENT_8 +2251 TEX_UG_LOW_WALL_GENERAL_8 +2257 TEX_METAL_WALL_2 +2260 TEX_UG_FLOOR_CONVEYOR_8 +2263 TEX_ROCK_LAND +2272 TEX_MOH_BROUN_8 +2278 TEX_UG_LOW_WALL_GENERAL_8 +2286 TEX_ROCKLAND_2 +2288 TEX__TEST +2292 TEX_ROCKLAND_2 +2300 TEX_L6_SAND_CLIFF +2305 TEX_SWAMP_2_8 +2318 TEX_VERT_LAVA_2 +2321 TEX_LDM_SAND +2336 TEX_LDM_SAND +2345 TEX_L6_SAND_CLIFF +2351 TEX_LDM_SAND +2353 TEX_MAGMA_8 +2364 TEX_LDM_SAND +2370 TEX_LAND_3_8 +2380 TEX_LAND_3_8 +2383 TEX_L6_STONES +2386 TEX_SWAMP_2_8 +2389 TEX_SWAMP_2_8 +2393 TEX_L5_ROAD2_8 +2400 TEX_VERT_LAVA_2 +2407 TEX_L3_ROCKS_V +2412 TEX_L6_SAND_CLIFF +2414 TEX_SNOW2_8 +2422 TEX_SWAMP_2_8 +2425 TEX_SNOW_VERT2 +2428 TEX_L6_SAND_CLIFF +2437 TEX_MOH_BROUN_8 +2443 TEX_LAND108 +2453 TEX_LAND108 +2456 TEX_L6_ROAD_90_8 +2464 TEX_MOH_BROUN_8 +2467 TEX_METAL_GORIZ_8 +2470 TEX_L9_GROUND_BROWN_8 +2473 TEX_L9_GROUND_STONES_2_8 +2482 TEX_L9_GROUND_8 +2488 TEX_L9_GROUND_STONES_8 +2490 TEX_L9_GROUND_STONES_2_8 +2501 TEX_L9_SAND_8 +2507 TEX_L9_SAND_2_8 +2517 TEX_L9_CLIFF_LAYERED +2520 TEX_L9_CLIFF_CRACKS +2529 TEX_L9_CLIFF_CRACKS_2 +2535 TEX_L9_CLIFF +2538 TEX_L10_GROUND_8 +2547 TEX_L10_ROCKS_8 +2553 TEX_L10_CLIFF_STRIPES +2555 TEX_L10_CLIFF +2558 TEX_L9_CLIFF +2567 TEX_L10_CLIFF_CANYON +2573 TEX_L10_LAVA_1 +2575 TEX_L9_SAND_8 +2586 TEX_L10_GRASS_8 +2592 TEX_L10_CLIFF_CANYON_2 +2598 TEX_L10_ROAD_1_S8 +2604 TEX_L9_GROUND_BROWN_8 +2609 TEX_L9_SAND_8 +2617 TEX_L9_SAND_2_8 +2620 TEX_L9_GROUND_8 +2627 TEX_L9_GROUND_8 +2632 TEX_L9_SAND_8 +2640 TEX_L9_SAND_8 +2651 TEX_L9_SAND_8 +2656 TEX_L9_SAND_8 +2658 TEX_L10_GROUND_8 +2662 TEX_L10_GROUND_8 +2673 TEX_L10_GRASS_8 +2678 TEX_L10_ROCKS_8 +2680 TEX_PLITA_BLD_8 +2683 TEX_U_FLOOR_BROWN_S1 +2692 TEX_U_FLOOR_CONCRETE_S4 +2698 TEX_U_FLOOR_CROSSING_S8 +2700 TEX_U_FLOOR_DARK_S8 +2711 TEX_U_FLOOR_GRATE_SIMPLE_S1 +2717 TEX_U_FLOOR_LIGHT_S8 +2720 TEX_U_FLOOR_METAL_SQUARED_S8 +2735 TEX_U_FLOOR_WARNING_S1 +2737 TEX_U_WALL_BLOCKS +2748 TEX_U_WALL_BLOCKS_STRIPE +2754 TEX_U_WALL_BLOCKS_WARN +2764 TEX_U_WALL_FRAMES +2774 TEX_U_WALL_FRAMES_CROSS +2778 TEX_U_WALL_HOLES +2784 TEX_U_WALL_METAL_EDGES +2791 TEX_U_WALL_METAL_EDGES_CORR +2798 TEX_U_WALL_METAL_PLATES +2801 TEX_U_WALL_PATCHY_1 +2810 TEX_U_WALL_PATCHY_2 +2813 TEX_U_WALL_PATCHY_3 +2816 TEX_U_WALL_PLATED_2 +2823 TEX_U_WALL_PLATED_SIMPLE +2827 TEX_U_WALL_SCALES +2836 TEX_U_WALL_STRIPS_PLASTIC +2844 TEX_U_WALL_STRIPS_PLASTIC_2 +2847 TEX_U_WALL_VENTS +2853 TEX_U_WALL_METAL_HOLES +2855 TEX_U_FLOOR_PATCHY_RAIL +2858 TEX_U_FLOOR_PANEL_VENT_RUST_S4 +2867 TEX_U_FLOOR_PATCHY_FRAME_S4 +2870 TEX_U_FLOOR_PATCHY_S8 +2873 TEX_U_FLOOR_METAL +2882 TEX_L11_LICHEN_S1 +2885 TEX_L11_LICHEN_2 +2894 TEX_L11_MOULD_S4 +2900 TEX_L11_PLATEU_2_S4 +2902 TEX_L11_PLATEU_3_S1 +2913 TEX_L11_PLATEU_4_S1 +2919 TEX_L11_PLATEU_GRASS_S4 +2929 TEX_L11_PLATEU_PL_S4 +2939 TEX_L11_ROCK +2943 TEX_L11_ROCK2 +2949 TEX_L11_ROCK3 +2956 TEX_L11_ROCK4 +2963 TEX_L11_MUSHROOM_BASE +2966 TEX_U_WALL_CONCRETE +2969 TEX_L12_CAVE_SLICK +2978 TEX_L12_CAVE_HARD +2984 TEX_L11_ROCK3 +2987 TEX_L10_GROUND_8 +2996 TEX_MOH_BROUN_8 +2998 TEX_U_WALL_CONCRETE +3001 TEX_U_LIGHT_WHITE +3010 TEX_U_BORDER_PIPES +3028 TEX_L9_GROUND_BROWN_8 +3034 TEX_L9_CLIFF +3042 TEX_L9_SAND_8 +3047 TEX_L9_SAND_8 +3057 TEX_L9_HIGHWAY_WALL +3060 TEX_L9_METAL_PLATES +3069 TEX_L9_WALL_RUSTY +3072 TEX_CANYON01 +3076 TEX_L10_CLIFF +3083 TEX_L10_LAVA_1 +3094 TEX_SWAMP_2_8 +3099 TEX_PESOK_8 +3110 TEX_GLINA_8_2 +3113 TEX_VERT5 +3122 TEX__TEST +3131 TEX_L10_GROUND_8 +3134 TEX_L10_CRATER +3140 TEX_U_FLOOR_CLIMB_90 +3143 TEX_VERT_LAVA_1 +3152 TEX_L4_PROVAL_8 +3160 TEX_L9_SAND_2_8 +3173 TEX_L10_CLIFF_MIX +3181 TEX_L1_CLIFF_CANYON +3189 TEX_L1_CLIFF_HARD +3197 TEX_L1_CLIFF_HARD_2 +3200 TEX_L10_ROAD_M2 +3208 TEX_L10_ROAD_M2 +3212 TEX_SNOW4_8 +3217 TEX_LD_ROAD +3221 TEX_PLITA_8 +3226 TEX_L9_SAND_8 +3233 TEX_SWAMP_2_8 +3238 TEX_L4_PROVAL_8 +3246 TEX_GLINA_8_2 +3252 TEX_L10_ROCKS_8 +3260 TEX_L10_ROCKS_8 +3262 TEX_L10_CLIFF_STRIPES +3270 TEX_L9_SAND_2_8 +3278 TEX_L9_SAND_8 +3281 TEX_L10_GROUND_8 +3292 TEX_L11_LICHEN_2 +3297 TEX_L11_PLATEU_4_S1 +3307 TEX_L10_LAVA_1 +3317 TEX_L10_CLIFF +3323 TEX_SWAMP_2_8 +3330 TEX_L11_VEINS_S4 +3341 TEX_L11_VEINS_S4 +3350 TEX_L11_VEINS_S4 +3361 TEX_L11_GROUND_SKIN_4 +3367 TEX_L4_LAVA_STONE_8 +3369 TEX_U_WALL_PLATED_SIMPLE +3379 TEX_U_WALL_PLATED_SIMPLE +3390 TEX_U_FLOOR_WARNING_S1 +3398 TEX_U_FLOOR_CLIMB_90 +3402 TEX_U_FLOOR_LIGHT_S8 +3412 TEX_L2_RIVERBANK_2 +3419 TEX_GLINA_8_2 +3424 TEX_SWAMP_2_8 +3434 TEX_SWAMP_2_8 +3437 TEX_SWAMP_2_8 +3445 TEX_L10_GRASS_8 +3454 TEX_L11_GROUND_MEAT_4 +3466 TEX_L11_GROUND_SPONGE_8 +3474 TEX_L11_VEINS_S4 +3489 TEX_L11_SOUP_4 +3500 TEX_L11_CLIFF_SKIN +3510 TEX_L11_TONGUE_S4 +3519 TEX_L11_PLATEU_3_S1 +3523 TEX_L11_ROCK4 +3532 TEX_L11_GROUND_SPONGE_8 +3543 TEX_U_FLOOR_PATCHY_RG +3552 TEX_SWAMP_2_8 +3562 TEX_U_WALL_PLATED_SNOW +3570 TEX_U_FLOOR_LIGHT_S8_SNOW +3576 TEX_L11_GROUND_SPONGE_8 \ No newline at end of file