Sponge Schematic import

master
bzt 2020-01-23 15:09:40 +01:00
parent b30c551334
commit c19ac61e8c
16 changed files with 903 additions and 802 deletions

View File

@ -21,7 +21,7 @@ for more details.
<img src="https://gitlab.com/bztsrc/mtsedit/raw/master/docs/mtsedit.png">
The User Interface is translatable. Supported languages: English, Magyar, Español, Français, Deutch, Polski, Русский, Português
and Italiana.
and Italiano.
The other component is a Minetest mod, under the [mt-mod](https://gitlab.com/bztsrc/mtsedit/tree/master/mt-mod) directory. This
small Lua script runs inside the game, and can import your edited MTS files into the game's world. It can also save MTS files

File diff suppressed because it is too large Load Diff

View File

@ -66,7 +66,7 @@ You can also convert MTS files using different block type mappings:
./mtsedit -m "Minetest Game" mcl2.mts mtg.mts
```
Where the parameter to "-m" is a coloumn name in [blocks.csv](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/blocks.md) file,
from the 5th coloumn and upwards. You can also use numbers, starting from 1 (which means the 5th coloumn, as the first four are
from the 6th coloumn and upwards. You can also use numbers, starting from 1 (which means the 6th coloumn, as the first five are
reserved for special use).
```
./mtsedit -m 1 mtg.mts mcl2.mts

View File

@ -26,7 +26,7 @@ from within the game (with all your desired mods enabled).
### Header
The first row is special, it defines the coloumn names. The first 4 coloumns are irrelevant and not parsed, others
The first row is special, it defines the coloumn names. The first 5 coloumns are irrelevant and not parsed, others
define the name of the block mappings (each coloumn is one mapping). These are the names used by the "/mtsedit export"
chat command, and they are also shown on the Save As window.
@ -36,9 +36,10 @@ chat command, and they are also shown on the Save As window.
|-------:|---------|---------------------------------------------------------------------------------------|
| 1st | string | block id, canonical name of the block (also used to identify block images) |
| 2nd | intlist | list of slash '/' separated integer numbers, the Minecraft BlockID in schematic files |
| 3rd | string | an optional biome specific name for the block (like "biome:node_stone") |
| 4th | string | an optional mapgen alias name for the block (like "mapgen_stone") |
| 5th+ | string | block's name in the mapping (this coloumn may be repated as many times as you like) |
| 3rd | string | list of slash '/' spearated strings, the Sponge BlockName in schematic files |
| 4th | string | an optional biome specific name for the block (like "biome:node_stone") |
| 5th | string | an optional mapgen alias name for the block (like "mapgen_stone") |
| 6th+ | string | block's name in the mapping (this coloumn may be repated as many times as you like) |
Block mappings are sometimes referenced as node palette. The repository ships a default blocks.csv with two coloumns,
mappings for "Mineclone2" and "Minetest Game", but feel free to add as many more mappings as you wish.
@ -46,6 +47,15 @@ mappings for "Mineclone2" and "Minetest Game", but feel free to add as many more
For file formats that rely on numeric IDs, the values in the 2nd coloumn are used. These can be however overriden on a
per schematic file basis using the `-r` flag.
An example line (with Mineclone2 in 6th and MineTest Game in 7th coloumn) would look like this:
```
Stone,1,minecraft:stone,biome:node_stone,mapgen_stone,mcl_core:stone,default:stone
```
The 2nd and 3rd coloumns may have more values, like
```
Leaves,18,minecraft:leaves/minecraft:oak_leaves,,,mcl_core:leaves,default:leaves
```
Block Images
------------

View File

@ -24,11 +24,20 @@ Minecraft Schematic Files
-------------------------
These are [Minecraft NBT](https://minecraft.gamepedia.com/Schematic_file_format) files, used by many Minecraft-compatible
editors. Typical extension is `.schematic`. Only the [blocks](https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening/Block_IDs)
section is parsed, and only used to import schematics. MTSEdit does not save .schematic files.
editors. Typical extension is `.schematic`. Only the [Blocks](https://minecraft.gamepedia.com/Java_Edition_data_values/Pre-flattening/Block_IDs)
and Data chunks are parsed, and only used to import schematics. MTSEdit does not save .schematic files.
Limitations: rotation info are not imported properly, but works for basic nodes most of the time.
Sponge Schematic Files
----------------------
These are [Minecraft NBT](https://minecraft.gamepedia.com/Schematic_file_format) files too, used by WorldEdit. Typical extension
is `.schematic` too. Instead of Blocks and Data chunks, these have [BlockData](https://github.com/SpongePowered/Schematic-Specification/blob/master/versions/schematic-2.md)
and Palette chunks. Although BlockData is a byte array, it contains bigger than 255 values using some messed up "varint" encoding.
Limitations: rotation info are not imported at all.
Model 3D Files
--------------

View File

@ -28,7 +28,7 @@ environment variable, or add `-l` to command line (useful in .desktop and .lnk f
- "pl" Polski
- "ru" Русский
- "pt" Português
- "it" Italiana
- "it" Italiano
```
LANG=hu ./mtsedit monkeyisland.mts

View File

@ -136,7 +136,7 @@ function mtsedit.export(param)
end
local fn = minetest.get_worldpath() .. "/blocks.csv"
local defpalettes = { "_Name", "BlockID", "Biome Specific", "MapGen Alias", param }
local defpalettes = { "_Name", "BlockID", "BlockName", "Biome Specific", "MapGen Alias", param }
local palettes, nodes, known, s = {}, {}, {}, {}
local line, node, i, cnt, idx = 0, "", 0, 1, 0
@ -151,7 +151,7 @@ function mtsedit.export(param)
palettes = defpalettes
end
end
for i,t in ipairs(palettes) do if (cnt > 4 and t == param) then idx = i end cnt = cnt + 1 end
for i,t in ipairs(palettes) do if (cnt > 5 and t == param) then idx = i end cnt = cnt + 1 end
if (idx == 0) then
table.insert(palettes, param)
idx = cnt
@ -181,34 +181,34 @@ function mtsedit.export(param)
if (blockid ~= nil and blockid ~= "") then
-- if new node
if (nodes[blockid] == nil) then
i = 4
nodes[blockid] = { "", "", "" }
i = 5
nodes[blockid] = { "", "", "", "" }
while (i < cnt) do table.insert(nodes[blockid], node) i = i + 1 end
end
-- if no biome specific name given already check if there's one
if (node ~= "air" and node ~= "ignore" and t["drawtype"] ~= "airlike" and
(nodes[blockid][2] == nil or nodes[blockid][2] == "")) then
(nodes[blockid][3] == nil or nodes[blockid][3] == "")) then
for name,biome in pairs(minetest.registered_biomes) do
for propname,propval in pairs(biome) do
if (string.sub(propname,1,5) == "node_" and propval == node) then
nodes[blockid][2] = "biome:"..propname
nodes[blockid][3] = "biome:"..propname
break
end
end
end
end
-- mapgen specific name
if (nodes[blockid][3] == nil) then nodes[blockid][3] = "" end
if (nodes[blockid][3] == "") then
if (nodes[blockid][4] == nil) then nodes[blockid][4] = "" end
if (nodes[blockid][4] == "") then
for mapgen,oname in pairs(minetest.registered_aliases) do
if (oname == node) then
nodes[blockid][3] = mapgen
nodes[blockid][4] = mapgen
break
end
end
end
-- replace block names
i = 4
i = 5
while (i < cnt) do
if (i == idx or nodes[blockid][i] == nil or nodes[blockid][i] == "") then nodes[blockid][i] = node end
i = i + 1

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -191,11 +191,11 @@ void blocks_parse()
}
/* parse header */
for(e = data, i = j = 0; *e && *e != '\r' && *e != '\n' && i < 4; e++) {
for(e = data, i = j = 0; *e && *e != '\r' && *e != '\n' && i < 5; e++) {
if(*e == '\"') j ^= 1;
if(!j && (*e == ',' || *e == ';' || *e == '\t')) i++;
}
if(i != 4 || !*e || *e == '\r' || *e == '\n') errorcsv(1);
if(i != 5 || !*e || *e == '\r' || *e == '\n') errorcsv(1);
while(*e && *e != '\r' && *e != '\n') {
while(*e == ',' || *e == ';' || *e == '\t' || *e == ' ') e++;
if(*e == '\"') { e++; c = '\"'; } else c = ',';
@ -224,13 +224,15 @@ void blocks_parse()
blocks[0].name = (char*)malloc(strlen(t)+1);
if(!blocks[0].name) error(lang[ERR_MEM]);
strcpy(blocks[0].name, t);
blocks[0].blocknames = (char**)malloc((numpalettes + 2) * sizeof(char*));
blocks[0].blocknames = (char**)malloc((numpalettes + 3) * sizeof(char*));
if(!blocks[0].blocknames) error(lang[ERR_MEM]);
blocks[0].blocknames[0] = NULL;
for(i = 1; i < (unsigned int)numpalettes + 2; i++) {
blocks[0].blocknames[i] = (char*)malloc(4);
for(i = 0; i < (unsigned int)numpalettes + 3; i++) {
blocks[0].blocknames[i] = (char*)malloc(!i ? 33 : 4);
if(!blocks[0].blocknames[i]) error(lang[ERR_MEM]);
memcpy(blocks[0].blocknames[i], "air", 4);
if(!i)
memcpy(blocks[0].blocknames[i], "minecraft:air/minecraft:cave_air", 33);
else
memcpy(blocks[0].blocknames[i], "air", 4);
}
for(i = 0; i < numbids; i++)
if(!strcmp(bids[i], "Air")) { blocks[0].blockids[0] = i; break; }
@ -250,9 +252,9 @@ void blocks_parse()
blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t));
if(!blocks) error(lang[ERR_MEM]);
memset(&blocks[j], 0, sizeof(mtsblock_t));
blocks[j].blocknames = (char**)malloc((numpalettes + 2) * sizeof(char*));
blocks[j].blocknames = (char**)malloc((numpalettes + 3) * sizeof(char*));
if(!blocks[j].blocknames) error(lang[ERR_MEM]);
memset(blocks[j].blocknames, 0, (numpalettes + 2) * sizeof(char*));
memset(blocks[j].blocknames, 0, (numpalettes + 3) * sizeof(char*));
for(k = 0; s + k < e; k++)
if(s[k] == ' ' || s[k] == '\'') s[k] = '_';
/* translate block name */
@ -366,7 +368,7 @@ void blocks_parse()
memcpy(blocks[j].blocknames[k], s, e - s + 1);
blocks[j].blocknames[k][e - s] = 0;
}
k++; if(k > (unsigned int)numpalettes + 2) errorcsv(j+2);
k++; if(k > (unsigned int)numpalettes + 3) errorcsv(j+2);
while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++;
}
if(!numblocks || numblocks > 65535) error(lang[ERR_CSV]);
@ -399,7 +401,7 @@ void blocks_free()
for(i = 0; i < numblocks; i++) {
free(blocks[i].name);
if(blocks[i].blocknames) {
for(j = 0; j < numpalettes + 2; j++)
for(j = 0; j < numpalettes + 3; j++)
if(blocks[i].blocknames[j]) free(blocks[i].blocknames[j]);
free(blocks[i].blocknames);
}

View File

@ -100,7 +100,7 @@ typedef struct {
char numpar2;
char dobiome;
uint32_t color;
unsigned char blockids[4];
unsigned short blockids[4];
unsigned char *img;
unsigned char *dr;
unsigned char *tr;

View File

@ -118,15 +118,16 @@ void mts_load(unsigned char *data, unsigned int size)
j = buff[1];
buff += 2;
for(k = 0; k < numblocks; k++)
for(l = 0; l < numpalettes + 2; l++)
for(l = 0; l < numpalettes + 3; l++)
if((!blocks[k].blocknames && (int)strlen(blocks[k].name) == j &&
!memcmp(blocks[k].name, buff, j)) || (blocks[k].blocknames && blocks[k].blocknames[l] &&
(int)strlen(blocks[k].blocknames[l]) == j && !memcmp(blocks[k].blocknames[l], buff, j))) {
if(k)
switch(l) {
case 0: blocks[k].dobiome = 1; savebiome = 1; break;
case 1: if(!memcmp(buff, "mapgen", 6)) { savemapgen = 1; } break;
default: palref[l - 2]++; break;
case 0: break;
case 1: blocks[k].dobiome = 1; savebiome = 1; break;
case 2: if(!memcmp(buff, "mapgen", 6)) { savemapgen = 1; } break;
default: palref[l - 3]++; break;
}
tr[i] = k;
break;
@ -269,10 +270,10 @@ int mts_save()
fwrite(hdr, 2, 1, f);
if(savepal < 0 || savepal >= numpalettes) savepal = 0;
for(i = 0; i < j; i++) {
c = !blocks[tr[i]].blocknames ? blocks[tr[i]].name : (savebiome && blocks[tr[i]].blocknames[0] &&
blocks[tr[i]].dobiome ? blocks[tr[i]].blocknames[0] : (savemapgen && blocks[tr[i]].blocknames[1] &&
blocks[tr[i]].blocknames[1][0] ? blocks[tr[i]].blocknames[1] : (blocks[tr[i]].blocknames[savepal+2] &&
blocks[tr[i]].blocknames[savepal+2][0] ? blocks[tr[i]].blocknames[savepal+2] : blocks[tr[i]].name)));
c = !blocks[tr[i]].blocknames ? blocks[tr[i]].name : (savebiome && blocks[tr[i]].blocknames[1] &&
blocks[tr[i]].dobiome ? blocks[tr[i]].blocknames[1] : (savemapgen && blocks[tr[i]].blocknames[2] &&
blocks[tr[i]].blocknames[2][0] ? blocks[tr[i]].blocknames[2] : (blocks[tr[i]].blocknames[savepal+3] &&
blocks[tr[i]].blocknames[savepal+3][0] ? blocks[tr[i]].blocknames[savepal+3] : blocks[tr[i]].name)));
hdr[1] = strlen(c);
fwrite(hdr, 2, 1, f);
fwrite(c, hdr[1], 1, f);
@ -530,8 +531,8 @@ int mts_dump()
printf("Map (x: %d y: %d z: %d):\r\n", max-mix+1, may-miy+1, maz-miz+1);
if(savepal < 0 || savepal >= numpalettes) savepal = 0;
for(i = 0; i < j; i++)
printf("%4x: %s\r\n", i, blocks[tr[i]].blocknames && blocks[tr[i]].blocknames[savepal+1] ?
blocks[tr[i]].blocknames[savepal+1] : blocks[tr[i]].name);
printf("%4x: %s\r\n", i, blocks[tr[i]].blocknames && blocks[tr[i]].blocknames[savepal+3] ?
blocks[tr[i]].blocknames[savepal+3] : blocks[tr[i]].name);
for(y = miy; y <= may; y++) {
printf("\r\nLayer %d (probability %d%s):\r\n", y - miy, layerprob[y], y == gndlayer ? ", Ground level" : "");

View File

@ -96,8 +96,8 @@ void save_redraw()
sdlprint(44,rect.y, savefld == 5 && biomepos == k ? THEME_INPUT : THEME_INACT, THEME_INPBG, blocks[i].name);
strmaxw = screen->w - 5;
sdlprint(screen->w/2,rect.y, savefld == 5 && biomepos == k ? THEME_INPUT : THEME_INACT, THEME_INPBG,
blocks[i].blocknames[blocks[i].dobiome ? 0 : (savemapgen && blocks[i].blocknames[1] &&
blocks[i].blocknames[1][0] ? 1 : savepal + 2)]);
blocks[i].blocknames[blocks[i].dobiome ? 1 : (savemapgen && blocks[i].blocknames[2] &&
blocks[i].blocknames[2][0] ? 2 : savepal + 3)]);
rect.y += font->height;
}
k++;

View File

@ -29,6 +29,22 @@
#include "main.h"
/**
* match name
*/
int namematch(char *a, char *b)
{
int la, lb, i;
if(!a || !*a || !b || !*b) return 0;
if(!strcmp(a, b)) return 1;
la = strlen(a); lb = strlen(b);
for(i = 0; i < lb - la + 1; i++) {
if((!i || b[i-1] == '/') && !memcmp(a, b + i, la) && (!b[i + la] || b[i + la] == '/'))
return 1;
}
return 0;
}
/**
* Load a Minecraft NBT Schematic file
*/
@ -37,51 +53,83 @@
case 3:v=(d[0]<<24)|(d[1]<<16)|(d[2]<<8)|d[3];d+=4;break;}}while(0)
void schem_load(unsigned char *data, unsigned int size)
{
int i, j, k, x, y, z, min_x = 0, min_y = 0, min_z = 0;
unsigned char *d, *blk, *blkd = NULL, *end = data + size;
int i, j, k, l, x, y, z, g = 0, min_x = 0, min_y = 0, min_z = 0, tr[1024];
char name[256];
unsigned char *d, *s, *blk, *blkd = NULL, *blkp = NULL, *end = data + size;
unsigned int n;
/* we don't care about that overcomplicated NBT mess */
for(d = data; d < end && (!mts_y || !mts_z || !mts_x); d++) {
for(d = data, blk = NULL; d + 12 < end; d++) {
if(!memcmp(d, "\000\006Height", 8)) { d += 8; SCHEM_GETINT(mts_y, d[-9]); d--; } else
if(!memcmp(d, "\000\006Length", 8)) { d += 8; SCHEM_GETINT(mts_z, d[-9]); d--; } else
if(!memcmp(d, "\000\005Width", 7)) { d += 7; SCHEM_GETINT(mts_x, d[-8]); d--; } else
if(!memcmp(d, "\007\000\004Data", 7)) { d += 7; blkd = d + 4; SCHEM_GETINT(i, 3); d += i; }
if(!memcmp(d, "\000\009WEOffsetY", 11)) { d += 11; SCHEM_GETINT(g, d[-12]); d--; } else
if(!memcmp(d, "\007\000\004Data", 7)) { d += 7; blkd = d + 4; SCHEM_GETINT(i, 3); d += i; } else
if(!memcmp(d, "\007\000\006Blocks", 9)) { d += 9; SCHEM_GETINT(l, 3); blk = d; d += l; } else
if(!memcmp(d, "\012\000\007Palette", 10)) { d += 10; blkp = d; } else
if(!memcmp(d, "\007\000\011BlockData", 12)) { d += 12; SCHEM_GETINT(l, 3); blk = d; d += l; }
}
if(!mts_y || !mts_z || !mts_x || mts_y > 255 || mts_z > 255 || mts_x > 255) { mts_y = mts_z = mts_x = 0; return; }
blocks[0].numref = mts_y * mts_z * mts_x;
if(!blk || !mts_y || !mts_z || !mts_x || mts_y > 255 || mts_z > 255 || mts_x > 255 || l < mts_y * mts_z * mts_x) {
mts_y = mts_z = mts_x = 0;
return;
}
memset(tr, 0, sizeof(tr));
if(!blkp) {
for(i = 1; i < numblocks; i++)
for(j = 0; j < 4; j++)
if(blocks[i].blockids[j])
tr[blocks[i].blockids[j]] = i;
} else {
for(d = blkp; *d > 0 && *d < 4;) {
j = *d++; d++; l = *d++; s = d; d += l;
memcpy(name, s, l); name[l] = 0;
for(l = 0; name[l]; l++) if(name[l] == '[') { name[l] = 0; break; }
SCHEM_GETINT(k, j);
for(i = l = 0; i < numblocks; i++)
if((blocks[i].name && !strcmp(blocks[i].name, name)) ||
(blocks[i].blocknames && namematch(name, blocks[i].blocknames[0]))) { tr[k] = i; l = 1; break; }
if(!l) {
fprintf(stderr, "mtsedit: %s: %s '%s'\r\n", mtsfile, lang[ERR_NODE], name);
j = numblocks++;
blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t));
if(!blocks) error(lang[ERR_MEM]);
memset(&blocks[j], 0, sizeof(mtsblock_t));
blocks[j].name = (char*)malloc(strlen(name) + 1);
if(!blocks[j].name) error(lang[ERR_MEM]);
strcpy(blocks[j].name, name);
}
}
}
blocks[0].numref = l;
min_x = 127 - mts_x / 2;
min_y = 127 - mts_y / 2;
min_z = 127 - mts_z / 2;
gndlayer = min_y;
/* now that we know the dimensions, find the blocks data */
for(d = data; d < end; d++) {
/* it must be type of byte array */
if(!memcmp(d, "\007\000\006Blocks", 9)) {
d += 9;
SCHEM_GETINT(i, 3);
if(i != mts_y * mts_z * mts_x) return;
blk = d;
for(y = 0; y < mts_y; y++)
for(z = 0; z < mts_z; z++)
for(x = 0; x < mts_x; x++, d++) {
if(!*d) continue;
for(i = 1, k = 0; i < numblocks; i++)
for(j = 0; j < 4; j++)
if(blocks[i].blockids[j] == *d) { k = i; i = numblocks; break; }
if(k) {
layerprob[y+min_y] = 127;
nodes[y+min_y][z+min_z][x+min_x].param0 = k;
nodes[y+min_y][z+min_z][x+min_x].param1 = 127;
if(blkd)
nodes[y+min_y][z+min_z][x+min_x].param2 = blkd[d - blk] & 3;
blocks[k].numref++;
} else
fprintf(stderr, "mtsedit: %s: %s %d\r\n", mtsfile, lang[ERR_NODE], *d);
gndlayer = min_y - g;
/* now that we know the dimensions, and the blocks data, we can parse */
for(d = blk, i = y = 0; y < mts_y; y++)
for(z = 0; z < mts_z; z++)
for(x = 0; x < mts_x; x++, i++) {
if(!blkp)
n = *d++;
else {
/* this is a f*cked up non-documented varint encoding...
* see https://github.com/EngineHub/WorldEdit/blob/master/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java#L259 */
for(n = 0, j = 0; j < 21; d++, j += 7) {
n |= (*d & 0x7F) << j;
if(!(*d & 0x80)) { d++; break; }
}
status = lang[LOADED];
break;
}
}
}
if(n < 1024 && tr[n]) {
layerprob[y+min_y] = 127;
nodes[y+min_y][z+min_z][x+min_x].param0 = tr[n];
nodes[y+min_y][z+min_z][x+min_x].param1 = 127;
if(blkd)
nodes[y+min_y][z+min_z][x+min_x].param2 = blkd[i] & 3;
blocks[tr[n]].numref++;
} else if(!blkp && !*d)
fprintf(stderr, "mtsedit: %s: %s %d\r\n", mtsfile, lang[ERR_NODE], n);
}
status = lang[LOADED];
}
/**
@ -147,14 +195,19 @@ void m3d_load(unsigned char *data, unsigned int size)
{
unsigned char *f = NULL, *ch, *s, *e = data + size;
char *strtbl, *n;
int i, j, k, l, m, g = 0, ci_s, si_s, sk_s, nt = 0, *palref;
int i, j, k, l, m, ci_s, si_s, sk_s, vd_s, vp_s, nt = 0, *palref;
int min_x = 0, min_y = 0, min_z = 0, mi_x = 65536, mi_y = 65536, mi_z = 65536, ma_x = 0, ma_y = 0, ma_z = 0, x, y, z;
int sx, sy, sz, px, py, pz;
uint32_t c, *cmap = NULL, *tr = NULL;
data += 8;
size -= 8;
if(!memcmp(data, "PRVW", 4)) {
size -= *((uint32_t*)(data + 4));
data += *((uint32_t*)(data + 4));
}
if(memcmp(data, "HEAD", 4)) {
data = f = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)data+8, size-8, 4096, &l, 1);
data = f = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)data, size, 4096, &l, 1);
if(!data || !l || memcmp(data, "HEAD", 4)) {
if(data) free(data);
return;
@ -165,10 +218,13 @@ void m3d_load(unsigned char *data, unsigned int size)
si_s = 1 << ((data[12] >> 4) & 3);
ci_s = 1 << ((data[12] >> 6) & 3);
sk_s = 1 << ((data[13] >> 6) & 3);
vd_s = 1 << ((data[14] >> 6) & 3);
vp_s = 1 << ((data[15] >> 0) & 3);
if(ci_s == 8) ci_s = 0;
if(sk_s == 8) sk_s = 0;
if(vd_s == 8 || vp_s > 2) return;
/* detect dimensions and get palette */
/* detect dimensions and get color and node palettes */
ch = data;
while(ch < e && memcmp(ch, "OMD3", 4)) {
s = ch;
@ -179,8 +235,7 @@ void m3d_load(unsigned char *data, unsigned int size)
if(!memcmp(s, "CMAP", 4)) { cmap = (uint32_t*)(s + 8); } else
if(!memcmp(s, "VOXT", 4)) {
s += 8;
g = *((uint16_t*)s); s += 2;
nt = (l-2) / (ci_s + si_s + 1);
nt = l / (ci_s + si_s + 3 + sk_s);
tr = (uint32_t*)malloc(nt * sizeof(uint32_t));
if(!tr) error(lang[ERR_MEM]);
palref = (int*)malloc(numpalettes * sizeof(int));
@ -205,34 +260,41 @@ void m3d_load(unsigned char *data, unsigned int size)
n = strtbl + j;
tr[i] = numblocks;
for(k = 0; k < numblocks; k++)
for(m = 0; m < numpalettes + 2; m++)
for(m = 0; m < numpalettes + 3; m++)
if((!blocks[k].blocknames && !strcmp(blocks[k].name, n)) ||
(blocks[k].blocknames && blocks[k].blocknames[m] && !strcmp(blocks[k].blocknames[m], n))) {
(blocks[k].blocknames && namematch(n, blocks[k].blocknames[m]))) {
if(k)
switch(m) {
case 0: blocks[k].dobiome = 1; savebiome = 1; break;
case 1: if(!memcmp(n, "mapgen", 6)) { savemapgen = 1; } break;
default: palref[m - 2]++; break;
case 0: break;
case 1: blocks[k].dobiome = 1; savebiome = 1; break;
case 2: if(!memcmp(n, "mapgen", 6)) { savemapgen = 1; } break;
default: palref[m - 3]++; break;
}
tr[i] = k;
break;
}
if(tr[i] == (uint32_t)numblocks) {
fprintf(stderr, "mtsedit: %s: %s %d '%s'\r\n", mtsfile, lang[ERR_NODE], i, n);
j = numblocks++;
blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t));
if(!blocks) error(lang[ERR_MEM]);
memset(&blocks[j], 0, sizeof(mtsblock_t));
blocks[j].name = (char*)malloc(strlen(n) + 1);
if(!blocks[j].name) error(lang[ERR_MEM]);
strcpy(blocks[j].name, n);
if(c) tr[i] = color2blockid(c);
else {
fprintf(stderr, "mtsedit: %s: %s %d '%s'\r\n", mtsfile, lang[ERR_NODE], i, n);
j = numblocks++;
blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t));
if(!blocks) error(lang[ERR_MEM]);
memset(&blocks[j], 0, sizeof(mtsblock_t));
blocks[j].name = (char*)malloc(strlen(n) + 1);
if(!blocks[j].name) error(lang[ERR_MEM]);
strcpy(blocks[j].name, n);
}
}
} else
/* fallback to best color match */
if(c) tr[i] = color2blockid(c);
else tr[i] = 0;
tr[i] |= s[0] << 24;
s += 2 + sk_s;
/* skip over additional attributes */
s += 2;
j = *s;
s += 1 + sk_s + j * (2 + si_s);
}
/* pick the node palette which has the most node reference */
for(i = savepal = 0; i < numpalettes; i++)
@ -240,9 +302,19 @@ void m3d_load(unsigned char *data, unsigned int size)
free(palref);
} else
if(!memcmp(s, "VOXD", 4)) {
s += 8;
py = *((uint16_t*)(s + 0)); pz = *((uint16_t*)(s + 2)); px = *((uint16_t*)(s + 4));
sy = *((uint16_t*)(s + 6)); sz = *((uint16_t*)(s + 8)); sx = *((uint16_t*)(s + 10));
s += 8 + si_s;
px = py = pz = sx = sy = sz = 0;
switch(vd_s) {
case 1:
px = (int8_t)s[0]; py = (int8_t)s[1]; pz = (int8_t)s[2];
sx = (int8_t)s[3]; sy = (int8_t)s[4]; sz = (int8_t)s[5];
break;
case 2:
px = *((int16_t*)(s+0)); py = *((int16_t*)(s+2)); pz = *((int16_t*)(s+4));
sx = *((int16_t*)(s+6)); sy = *((int16_t*)(s+8)); sz = *((int16_t*)(s+10));
break;
default: return; break;
}
if(px < mi_x) { mi_x = px; } if(px+sx > ma_x) { ma_x = px+sx; }
if(py < mi_y) { mi_y = py; } if(py+sy > ma_y) { ma_y = py+sy; }
if(pz < mi_z) { mi_z = pz; } if(pz+sz > ma_z) { ma_z = pz+sz; }
@ -264,7 +336,7 @@ void m3d_load(unsigned char *data, unsigned int size)
min_x = 127 - mts_x / 2;
min_y = 127 - mts_y / 2;
min_z = 127 - mts_z / 2;
gndlayer = min_y + g;
gndlayer = min_y - mi_y;
/* read in the layers */
ch = data;
@ -273,45 +345,51 @@ void m3d_load(unsigned char *data, unsigned int size)
l = *((uint32_t*)(ch + 4));
ch += l;
if(!memcmp(s, "VOXD", 4)) {
s += 8;
py = *((uint16_t*)(s + 0))-mi_y+min_y; pz = *((uint16_t*)(s + 2))-mi_z+min_z; px = *((uint16_t*)(s + 4))-mi_x+min_x;
sy = *((uint16_t*)(s + 6)); sz = *((uint16_t*)(s + 8)); sx = *((uint16_t*)(s + 10));
s += 12;
s += 8 + si_s;
px = py = pz = sx = sy = sz = 0;
switch(vd_s) {
case 1:
px = (int8_t)s[0]; py = (int8_t)s[1]; pz = (int8_t)s[2];
sx = (int8_t)s[3]; sy = (int8_t)s[4]; sz = (int8_t)s[5];
s += 6;
break;
case 2:
px = *((int16_t*)(s+0)); py = *((int16_t*)(s+2)); pz = *((int16_t*)(s+4));
sx = *((int16_t*)(s+6)); sy = *((int16_t*)(s+8)); sz = *((int16_t*)(s+10));
s += 12;
break;
}
px += min_x-mi_x; py += min_y-mi_y; pz += min_z-mi_z;
k = (255 - *s) >> 1;
for(y = 0; y < sy; y++)
if(py+y >= 0 && py+y < 256)
layerprob[py+y] = k;
k = sx * sz;
for(s += si_s + 2, i = 0; s < ch;) {
l = *s; s++;
if(!l) { s += si_s; } else
if(l < 0) {
if(nt < 256) { m = *s; s++; } else { m = *((uint16_t*)s); s += 2; }
for(j = 0; j < -l; j++, i++) {
y = i / k;
z = (i % k) / sx;
x = i % sx;
k = sx * sz; x = y = z = 0;
for(s += 2, i = 0; s < ch;) {
l = ((*s++) & 0x7F) + 1;
if(s[-1] & 0x80) {
if(vp_s == 1) { m = *s++; } else { m = *((uint16_t*)s); s += 2; }
for(j = 0; j < l; j++, i++) {
if(m >= 0 && m < nt && py+y >= 0 && py+y < 256 && pz+z >= 0 && pz+z < 256 && px+x >= 0 && px+x < 256) {
nodes[py+y][py+z][px+x].param0 = tr[m] & 0xFFFFFF;
nodes[py+y][py+z][px+x].param1 = tr[m] ? 127 : 0;
nodes[py+y][py+z][px+x].param2 = (tr[m] >> 24) & PARAM2_MAX;
nodes[py+y][pz+z][px+x].param0 = tr[m] & 0xFFFFFF;
nodes[py+y][pz+z][px+x].param1 = tr[m] ? 127 : 0;
nodes[py+y][pz+z][px+x].param2 = (tr[m] >> 24) & PARAM2_MAX;
blocks[nodes[py+y][py+z][px+x].param0].numref++;
blocks[0].numref--;
}
x++; if(x >= sx) { x = 0; z++; if(z >= sz) { z = 0; y++; } }
}
} else {
for(j = 0; j < l; j++, i++) {
y = i / k;
z = (i % k) / sx;
x = i % sx;
if(nt < 256) { m = *s; s++; } else { m = *((uint16_t*)s); s += 2; }
if(vp_s == 1) { m = *s++; } else { m = *((uint16_t*)s); s += 2; }
if(m >= 0 && m < nt && py+y >= 0 && py+y < 256 && pz+z >= 0 && pz+z < 256 && px+x >= 0 && px+x < 256) {
nodes[py+y][py+z][px+x].param0 = tr[m] & 0xFFFFFF;
nodes[py+y][py+z][px+x].param1 = tr[m] ? 127 : 0;
nodes[py+y][py+z][px+x].param2 = (tr[m] >> 24) & PARAM2_MAX;
nodes[py+y][pz+z][px+x].param0 = tr[m] & 0xFFFFFF;
nodes[py+y][pz+z][px+x].param1 = tr[m] ? 127 : 0;
nodes[py+y][pz+z][px+x].param2 = (tr[m] >> 24) & PARAM2_MAX;
blocks[nodes[py+y][py+z][px+x].param0].numref++;
blocks[0].numref--;
}
x++; if(x >= sx) { x = 0; z++; if(z >= sz) { z = 0; y++; } }
}
}
}
@ -594,14 +672,14 @@ void qb_load(unsigned char *data, unsigned int size)
/* detect dimensions */
for(s = data + 24, i = 0; i < mc && s < e; i++) {
s += s[0] + 1;
sx = *((int*)(s + 0)); sy = *((int*)(s + 4)); sz = *((int*)(s + 8));
px = *((int*)(s + 12)); py = *((int*)(s + 16)); pz = *((int*)(s + 20));
sx = *((int*)(s + 0)); sz = *((int*)(s + 4)); sy = *((int*)(s + 8));
px = *((int*)(s + 12)); pz = *((int*)(s + 16)); py = *((int*)(s + 20));
if(px < mi_x) { mi_x = px; } if(px+sx > ma_x) { ma_x = px+sx; }
if(py < mi_y) { mi_y = py; } if(py+sy > ma_y) { ma_y = py+sy; }
if(pz < mi_z) { mi_z = pz; } if(pz+sz > ma_z) { ma_z = pz+sz; }
s += 24;
if(co) {
for(z = 0; z < sz; z++) {
for(y = 0; y < sy; y++) {
while(1) {
c = *((uint32_t*)s); s += 4;
if(c == 6 || c == 0x60000) break;
@ -627,26 +705,26 @@ void qb_load(unsigned char *data, unsigned int size)
/* read in the layers */
for(s = data + 24, i = 0; i < mc && s < e; i++) {
s += s[0] + 1;
sx = *((int*)(s + 0)); sy = *((int*)(s + 4)); sz = *((int*)(s + 8));
px = *((int*)(s + 12)) - mi_x + min_x; py = *((int*)(s + 16)) - mi_y + min_y; pz = *((int*)(s + 20)) - mi_z + min_z;
sx = *((int*)(s + 0)); sz = *((int*)(s + 4)); sy = *((int*)(s + 8));
px = *((int*)(s + 12)) - mi_x + min_x; pz = *((int*)(s + 16)) - mi_z + min_z; py = *((int*)(s + 20)) - mi_y + min_y;
s += 24;
if(co) {
for(z = 0; z < sz; z++) {
for(y = 0; y < sy; y++) {
for(i = 0; 1;) {
c = *((uint32_t*)s); s += 4;
if(c == 6 || c == 0x60000) break;
if(c == 2 || c == 0x20000) { l = *((int32_t*)s); s += 4; c = *((uint32_t*)s); s += 4; } else l = 1;
for(j = 0; j < l; j++, i++) {
x = i % sx; y = i / sx;
_qb_set(cf, px+x, py+y, pz + (za ? mts_z-z : z), (unsigned char*)&c);
x = i % sx; z = i / sx;
_qb_set(cf, px+x, pz + (za ? mts_z-z : z), py+y, (unsigned char*)&c);
}
}
}
} else {
for(z = 0; z < sz; z++)
for(y = 0; y < sy; y++)
for(y = 0; y < sy; y++)
for(z = 0; z < sz; z++)
for(x = 0; x < sx; x++, s += 4)
_qb_set(cf, px+x, py+y, pz + (za ? mts_z-z : z), s);
_qb_set(cf, px+x, pz + (za ? mts_z-z : z), py+y, s);
}
}
status = lang[LOADED];

View File

@ -1354,10 +1354,11 @@ void tileremap()
blocks_parse();
for(j = 0; j < 256; j++)
for(i = 0; i < numblocks; i++)
if(blocks[i].blockids[0] == j) {
if(blocks[i].blockids[0] == j || (j && blocks[i].blockids[1] == j)) {
for(k = 0; k < (int)strlen(blocks[i].name); k++)
if(blocks[i].name[k] == ' ') blocks[i].name[k] = '_';
printf("%s\r\n", blocks[i].name);
/* printf("0x%08x\n",blocks[i].color);*/
break;
}
}