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"> <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 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 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 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 ./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, 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). reserved for special use).
``` ```
./mtsedit -m 1 mtg.mts mcl2.mts ./mtsedit -m 1 mtg.mts mcl2.mts

View File

@ -26,7 +26,7 @@ from within the game (with all your desired mods enabled).
### Header ### 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" 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. 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) | | 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 | | 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") | | 3rd | string | list of slash '/' spearated strings, the Sponge BlockName in schematic files |
| 4th | string | an optional mapgen alias name for the block (like "mapgen_stone") | | 4th | string | an optional biome specific name for the block (like "biome:node_stone") |
| 5th+ | string | block's name in the mapping (this coloumn may be repated as many times as you like) | | 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, 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. 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 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. 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 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 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) 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. 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. 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 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 - "pl" Polski
- "ru" Русский - "ru" Русский
- "pt" Português - "pt" Português
- "it" Italiana - "it" Italiano
``` ```
LANG=hu ./mtsedit monkeyisland.mts LANG=hu ./mtsedit monkeyisland.mts

View File

@ -136,7 +136,7 @@ function mtsedit.export(param)
end end
local fn = minetest.get_worldpath() .. "/blocks.csv" 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 palettes, nodes, known, s = {}, {}, {}, {}
local line, node, i, cnt, idx = 0, "", 0, 1, 0 local line, node, i, cnt, idx = 0, "", 0, 1, 0
@ -151,7 +151,7 @@ function mtsedit.export(param)
palettes = defpalettes palettes = defpalettes
end end
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 if (idx == 0) then
table.insert(palettes, param) table.insert(palettes, param)
idx = cnt idx = cnt
@ -181,34 +181,34 @@ function mtsedit.export(param)
if (blockid ~= nil and blockid ~= "") then if (blockid ~= nil and blockid ~= "") then
-- if new node -- if new node
if (nodes[blockid] == nil) then if (nodes[blockid] == nil) then
i = 4 i = 5
nodes[blockid] = { "", "", "" } nodes[blockid] = { "", "", "", "" }
while (i < cnt) do table.insert(nodes[blockid], node) i = i + 1 end while (i < cnt) do table.insert(nodes[blockid], node) i = i + 1 end
end end
-- if no biome specific name given already check if there's one -- if no biome specific name given already check if there's one
if (node ~= "air" and node ~= "ignore" and t["drawtype"] ~= "airlike" and 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 name,biome in pairs(minetest.registered_biomes) do
for propname,propval in pairs(biome) do for propname,propval in pairs(biome) do
if (string.sub(propname,1,5) == "node_" and propval == node) then if (string.sub(propname,1,5) == "node_" and propval == node) then
nodes[blockid][2] = "biome:"..propname nodes[blockid][3] = "biome:"..propname
break break
end end
end end
end end
end end
-- mapgen specific name -- mapgen specific name
if (nodes[blockid][3] == nil) then nodes[blockid][3] = "" end if (nodes[blockid][4] == nil) then nodes[blockid][4] = "" end
if (nodes[blockid][3] == "") then if (nodes[blockid][4] == "") then
for mapgen,oname in pairs(minetest.registered_aliases) do for mapgen,oname in pairs(minetest.registered_aliases) do
if (oname == node) then if (oname == node) then
nodes[blockid][3] = mapgen nodes[blockid][4] = mapgen
break break
end end
end end
end end
-- replace block names -- replace block names
i = 4 i = 5
while (i < cnt) do while (i < cnt) do
if (i == idx or nodes[blockid][i] == nil or nodes[blockid][i] == "") then nodes[blockid][i] = node end if (i == idx or nodes[blockid][i] == nil or nodes[blockid][i] == "") then nodes[blockid][i] = node end
i = i + 1 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 */ /* 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(*e == '\"') j ^= 1;
if(!j && (*e == ',' || *e == ';' || *e == '\t')) i++; 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 != '\r' && *e != '\n') {
while(*e == ',' || *e == ';' || *e == '\t' || *e == ' ') e++; while(*e == ',' || *e == ';' || *e == '\t' || *e == ' ') e++;
if(*e == '\"') { e++; c = '\"'; } else c = ','; if(*e == '\"') { e++; c = '\"'; } else c = ',';
@ -224,13 +224,15 @@ void blocks_parse()
blocks[0].name = (char*)malloc(strlen(t)+1); blocks[0].name = (char*)malloc(strlen(t)+1);
if(!blocks[0].name) error(lang[ERR_MEM]); if(!blocks[0].name) error(lang[ERR_MEM]);
strcpy(blocks[0].name, t); 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]); if(!blocks[0].blocknames) error(lang[ERR_MEM]);
blocks[0].blocknames[0] = NULL; for(i = 0; i < (unsigned int)numpalettes + 3; i++) {
for(i = 1; i < (unsigned int)numpalettes + 2; i++) { blocks[0].blocknames[i] = (char*)malloc(!i ? 33 : 4);
blocks[0].blocknames[i] = (char*)malloc(4);
if(!blocks[0].blocknames[i]) error(lang[ERR_MEM]); 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++) for(i = 0; i < numbids; i++)
if(!strcmp(bids[i], "Air")) { blocks[0].blockids[0] = i; break; } 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)); blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t));
if(!blocks) error(lang[ERR_MEM]); if(!blocks) error(lang[ERR_MEM]);
memset(&blocks[j], 0, sizeof(mtsblock_t)); 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]); 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++) for(k = 0; s + k < e; k++)
if(s[k] == ' ' || s[k] == '\'') s[k] = '_'; if(s[k] == ' ' || s[k] == '\'') s[k] = '_';
/* translate block name */ /* translate block name */
@ -366,7 +368,7 @@ void blocks_parse()
memcpy(blocks[j].blocknames[k], s, e - s + 1); memcpy(blocks[j].blocknames[k], s, e - s + 1);
blocks[j].blocknames[k][e - s] = 0; 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++; while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++;
} }
if(!numblocks || numblocks > 65535) error(lang[ERR_CSV]); if(!numblocks || numblocks > 65535) error(lang[ERR_CSV]);
@ -399,7 +401,7 @@ void blocks_free()
for(i = 0; i < numblocks; i++) { for(i = 0; i < numblocks; i++) {
free(blocks[i].name); free(blocks[i].name);
if(blocks[i].blocknames) { 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]); if(blocks[i].blocknames[j]) free(blocks[i].blocknames[j]);
free(blocks[i].blocknames); free(blocks[i].blocknames);
} }

View File

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

View File

@ -118,15 +118,16 @@ void mts_load(unsigned char *data, unsigned int size)
j = buff[1]; j = buff[1];
buff += 2; buff += 2;
for(k = 0; k < numblocks; k++) 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 && if((!blocks[k].blocknames && (int)strlen(blocks[k].name) == j &&
!memcmp(blocks[k].name, buff, j)) || (blocks[k].blocknames && blocks[k].blocknames[l] && !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))) { (int)strlen(blocks[k].blocknames[l]) == j && !memcmp(blocks[k].blocknames[l], buff, j))) {
if(k) if(k)
switch(l) { switch(l) {
case 0: blocks[k].dobiome = 1; savebiome = 1; break; case 0: break;
case 1: if(!memcmp(buff, "mapgen", 6)) { savemapgen = 1; } break; case 1: blocks[k].dobiome = 1; savebiome = 1; break;
default: palref[l - 2]++; break; case 2: if(!memcmp(buff, "mapgen", 6)) { savemapgen = 1; } break;
default: palref[l - 3]++; break;
} }
tr[i] = k; tr[i] = k;
break; break;
@ -269,10 +270,10 @@ int mts_save()
fwrite(hdr, 2, 1, f); fwrite(hdr, 2, 1, f);
if(savepal < 0 || savepal >= numpalettes) savepal = 0; if(savepal < 0 || savepal >= numpalettes) savepal = 0;
for(i = 0; i < j; i++) { for(i = 0; i < j; i++) {
c = !blocks[tr[i]].blocknames ? blocks[tr[i]].name : (savebiome && blocks[tr[i]].blocknames[0] && c = !blocks[tr[i]].blocknames ? blocks[tr[i]].name : (savebiome && blocks[tr[i]].blocknames[1] &&
blocks[tr[i]].dobiome ? blocks[tr[i]].blocknames[0] : (savemapgen && blocks[tr[i]].blocknames[1] && blocks[tr[i]].dobiome ? blocks[tr[i]].blocknames[1] : (savemapgen && blocks[tr[i]].blocknames[2] &&
blocks[tr[i]].blocknames[1][0] ? blocks[tr[i]].blocknames[1] : (blocks[tr[i]].blocknames[savepal+2] && blocks[tr[i]].blocknames[2][0] ? blocks[tr[i]].blocknames[2] : (blocks[tr[i]].blocknames[savepal+3] &&
blocks[tr[i]].blocknames[savepal+2][0] ? blocks[tr[i]].blocknames[savepal+2] : blocks[tr[i]].name))); blocks[tr[i]].blocknames[savepal+3][0] ? blocks[tr[i]].blocknames[savepal+3] : blocks[tr[i]].name)));
hdr[1] = strlen(c); hdr[1] = strlen(c);
fwrite(hdr, 2, 1, f); fwrite(hdr, 2, 1, f);
fwrite(c, hdr[1], 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); 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; if(savepal < 0 || savepal >= numpalettes) savepal = 0;
for(i = 0; i < j; i++) for(i = 0; i < j; i++)
printf("%4x: %s\r\n", i, blocks[tr[i]].blocknames && blocks[tr[i]].blocknames[savepal+1] ? printf("%4x: %s\r\n", i, blocks[tr[i]].blocknames && blocks[tr[i]].blocknames[savepal+3] ?
blocks[tr[i]].blocknames[savepal+1] : blocks[tr[i]].name); blocks[tr[i]].blocknames[savepal+3] : blocks[tr[i]].name);
for(y = miy; y <= may; y++) { for(y = miy; y <= may; y++) {
printf("\r\nLayer %d (probability %d%s):\r\n", y - miy, layerprob[y], y == gndlayer ? ", Ground level" : ""); 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); sdlprint(44,rect.y, savefld == 5 && biomepos == k ? THEME_INPUT : THEME_INACT, THEME_INPBG, blocks[i].name);
strmaxw = screen->w - 5; strmaxw = screen->w - 5;
sdlprint(screen->w/2,rect.y, savefld == 5 && biomepos == k ? THEME_INPUT : THEME_INACT, THEME_INPBG, 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[blocks[i].dobiome ? 1 : (savemapgen && blocks[i].blocknames[2] &&
blocks[i].blocknames[1][0] ? 1 : savepal + 2)]); blocks[i].blocknames[2][0] ? 2 : savepal + 3)]);
rect.y += font->height; rect.y += font->height;
} }
k++; k++;

View File

@ -29,6 +29,22 @@
#include "main.h" #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 * 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) 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) 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; int i, j, k, l, x, y, z, g = 0, min_x = 0, min_y = 0, min_z = 0, tr[1024];
unsigned char *d, *blk, *blkd = NULL, *end = data + size; 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 */ /* 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\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\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, "\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; } if(!blk || !mts_y || !mts_z || !mts_x || mts_y > 255 || mts_z > 255 || mts_x > 255 || l < mts_y * mts_z * mts_x) {
blocks[0].numref = 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_x = 127 - mts_x / 2;
min_y = 127 - mts_y / 2; min_y = 127 - mts_y / 2;
min_z = 127 - mts_z / 2; min_z = 127 - mts_z / 2;
gndlayer = min_y; gndlayer = min_y - g;
/* now that we know the dimensions, find the blocks data */ /* now that we know the dimensions, and the blocks data, we can parse */
for(d = data; d < end; d++) { for(d = blk, i = y = 0; y < mts_y; y++)
/* it must be type of byte array */ for(z = 0; z < mts_z; z++)
if(!memcmp(d, "\007\000\006Blocks", 9)) { for(x = 0; x < mts_x; x++, i++) {
d += 9; if(!blkp)
SCHEM_GETINT(i, 3); n = *d++;
if(i != mts_y * mts_z * mts_x) return; else {
blk = d; /* this is a f*cked up non-documented varint encoding...
for(y = 0; y < mts_y; y++) * see https://github.com/EngineHub/WorldEdit/blob/master/worldedit-core/src/main/java/com/sk89q/worldedit/extent/clipboard/io/SpongeSchematicReader.java#L259 */
for(z = 0; z < mts_z; z++) for(n = 0, j = 0; j < 21; d++, j += 7) {
for(x = 0; x < mts_x; x++, d++) { n |= (*d & 0x7F) << j;
if(!*d) continue; if(!(*d & 0x80)) { d++; break; }
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);
} }
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; unsigned char *f = NULL, *ch, *s, *e = data + size;
char *strtbl, *n; 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 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; int sx, sy, sz, px, py, pz;
uint32_t c, *cmap = NULL, *tr = NULL; uint32_t c, *cmap = NULL, *tr = NULL;
data += 8; data += 8;
size -= 8;
if(!memcmp(data, "PRVW", 4)) {
size -= *((uint32_t*)(data + 4));
data += *((uint32_t*)(data + 4));
}
if(memcmp(data, "HEAD", 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 || !l || memcmp(data, "HEAD", 4)) {
if(data) free(data); if(data) free(data);
return; return;
@ -165,10 +218,13 @@ void m3d_load(unsigned char *data, unsigned int size)
si_s = 1 << ((data[12] >> 4) & 3); si_s = 1 << ((data[12] >> 4) & 3);
ci_s = 1 << ((data[12] >> 6) & 3); ci_s = 1 << ((data[12] >> 6) & 3);
sk_s = 1 << ((data[13] >> 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(ci_s == 8) ci_s = 0;
if(sk_s == 8) sk_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; ch = data;
while(ch < e && memcmp(ch, "OMD3", 4)) { while(ch < e && memcmp(ch, "OMD3", 4)) {
s = ch; 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, "CMAP", 4)) { cmap = (uint32_t*)(s + 8); } else
if(!memcmp(s, "VOXT", 4)) { if(!memcmp(s, "VOXT", 4)) {
s += 8; s += 8;
g = *((uint16_t*)s); s += 2; nt = l / (ci_s + si_s + 3 + sk_s);
nt = (l-2) / (ci_s + si_s + 1);
tr = (uint32_t*)malloc(nt * sizeof(uint32_t)); tr = (uint32_t*)malloc(nt * sizeof(uint32_t));
if(!tr) error(lang[ERR_MEM]); if(!tr) error(lang[ERR_MEM]);
palref = (int*)malloc(numpalettes * sizeof(int)); palref = (int*)malloc(numpalettes * sizeof(int));
@ -205,34 +260,41 @@ void m3d_load(unsigned char *data, unsigned int size)
n = strtbl + j; n = strtbl + j;
tr[i] = numblocks; tr[i] = numblocks;
for(k = 0; k < numblocks; k++) 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)) || 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) if(k)
switch(m) { switch(m) {
case 0: blocks[k].dobiome = 1; savebiome = 1; break; case 0: break;
case 1: if(!memcmp(n, "mapgen", 6)) { savemapgen = 1; } break; case 1: blocks[k].dobiome = 1; savebiome = 1; break;
default: palref[m - 2]++; break; case 2: if(!memcmp(n, "mapgen", 6)) { savemapgen = 1; } break;
default: palref[m - 3]++; break;
} }
tr[i] = k; tr[i] = k;
break; break;
} }
if(tr[i] == (uint32_t)numblocks) { if(tr[i] == (uint32_t)numblocks) {
fprintf(stderr, "mtsedit: %s: %s %d '%s'\r\n", mtsfile, lang[ERR_NODE], i, n); if(c) tr[i] = color2blockid(c);
j = numblocks++; else {
blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t)); fprintf(stderr, "mtsedit: %s: %s %d '%s'\r\n", mtsfile, lang[ERR_NODE], i, n);
if(!blocks) error(lang[ERR_MEM]); j = numblocks++;
memset(&blocks[j], 0, sizeof(mtsblock_t)); blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t));
blocks[j].name = (char*)malloc(strlen(n) + 1); if(!blocks) error(lang[ERR_MEM]);
if(!blocks[j].name) error(lang[ERR_MEM]); memset(&blocks[j], 0, sizeof(mtsblock_t));
strcpy(blocks[j].name, n); blocks[j].name = (char*)malloc(strlen(n) + 1);
if(!blocks[j].name) error(lang[ERR_MEM]);
strcpy(blocks[j].name, n);
}
} }
} else } else
/* fallback to best color match */ /* fallback to best color match */
if(c) tr[i] = color2blockid(c); if(c) tr[i] = color2blockid(c);
else tr[i] = 0; else tr[i] = 0;
tr[i] |= s[0] << 24; 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 */ /* pick the node palette which has the most node reference */
for(i = savepal = 0; i < numpalettes; i++) for(i = savepal = 0; i < numpalettes; i++)
@ -240,9 +302,19 @@ void m3d_load(unsigned char *data, unsigned int size)
free(palref); free(palref);
} else } else
if(!memcmp(s, "VOXD", 4)) { if(!memcmp(s, "VOXD", 4)) {
s += 8; s += 8 + si_s;
py = *((uint16_t*)(s + 0)); pz = *((uint16_t*)(s + 2)); px = *((uint16_t*)(s + 4)); px = py = pz = sx = sy = sz = 0;
sy = *((uint16_t*)(s + 6)); sz = *((uint16_t*)(s + 8)); sx = *((uint16_t*)(s + 10)); 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(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(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; } 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_x = 127 - mts_x / 2;
min_y = 127 - mts_y / 2; min_y = 127 - mts_y / 2;
min_z = 127 - mts_z / 2; min_z = 127 - mts_z / 2;
gndlayer = min_y + g; gndlayer = min_y - mi_y;
/* read in the layers */ /* read in the layers */
ch = data; ch = data;
@ -273,45 +345,51 @@ void m3d_load(unsigned char *data, unsigned int size)
l = *((uint32_t*)(ch + 4)); l = *((uint32_t*)(ch + 4));
ch += l; ch += l;
if(!memcmp(s, "VOXD", 4)) { if(!memcmp(s, "VOXD", 4)) {
s += 8; s += 8 + si_s;
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; px = py = pz = sx = sy = sz = 0;
sy = *((uint16_t*)(s + 6)); sz = *((uint16_t*)(s + 8)); sx = *((uint16_t*)(s + 10)); switch(vd_s) {
s += 12; 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; k = (255 - *s) >> 1;
for(y = 0; y < sy; y++) for(y = 0; y < sy; y++)
if(py+y >= 0 && py+y < 256) if(py+y >= 0 && py+y < 256)
layerprob[py+y] = k; layerprob[py+y] = k;
k = sx * sz; k = sx * sz; x = y = z = 0;
for(s += si_s + 2, i = 0; s < ch;) { for(s += 2, i = 0; s < ch;) {
l = *s; s++; l = ((*s++) & 0x7F) + 1;
if(!l) { s += si_s; } else if(s[-1] & 0x80) {
if(l < 0) { if(vp_s == 1) { m = *s++; } else { m = *((uint16_t*)s); s += 2; }
if(nt < 256) { m = *s; s++; } else { m = *((uint16_t*)s); s += 2; } for(j = 0; j < l; j++, i++) {
for(j = 0; j < -l; j++, i++) {
y = i / k;
z = (i % k) / sx;
x = i % sx;
if(m >= 0 && m < nt && py+y >= 0 && py+y < 256 && pz+z >= 0 && pz+z < 256 && px+x >= 0 && px+x < 256) { 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][pz+z][px+x].param0 = tr[m] & 0xFFFFFF;
nodes[py+y][py+z][px+x].param1 = tr[m] ? 127 : 0; nodes[py+y][pz+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].param2 = (tr[m] >> 24) & PARAM2_MAX;
blocks[nodes[py+y][py+z][px+x].param0].numref++; blocks[nodes[py+y][py+z][px+x].param0].numref++;
blocks[0].numref--; blocks[0].numref--;
} }
x++; if(x >= sx) { x = 0; z++; if(z >= sz) { z = 0; y++; } }
} }
} else { } else {
for(j = 0; j < l; j++, i++) { for(j = 0; j < l; j++, i++) {
y = i / k; if(vp_s == 1) { m = *s++; } else { m = *((uint16_t*)s); s += 2; }
z = (i % k) / sx;
x = i % sx;
if(nt < 256) { m = *s; 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) { 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][pz+z][px+x].param0 = tr[m] & 0xFFFFFF;
nodes[py+y][py+z][px+x].param1 = tr[m] ? 127 : 0; nodes[py+y][pz+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].param2 = (tr[m] >> 24) & PARAM2_MAX;
blocks[nodes[py+y][py+z][px+x].param0].numref++; blocks[nodes[py+y][py+z][px+x].param0].numref++;
blocks[0].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 */ /* detect dimensions */
for(s = data + 24, i = 0; i < mc && s < e; i++) { for(s = data + 24, i = 0; i < mc && s < e; i++) {
s += s[0] + 1; s += s[0] + 1;
sx = *((int*)(s + 0)); sy = *((int*)(s + 4)); sz = *((int*)(s + 8)); sx = *((int*)(s + 0)); sz = *((int*)(s + 4)); sy = *((int*)(s + 8));
px = *((int*)(s + 12)); py = *((int*)(s + 16)); pz = *((int*)(s + 20)); 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(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(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; } if(pz < mi_z) { mi_z = pz; } if(pz+sz > ma_z) { ma_z = pz+sz; }
s += 24; s += 24;
if(co) { if(co) {
for(z = 0; z < sz; z++) { for(y = 0; y < sy; y++) {
while(1) { while(1) {
c = *((uint32_t*)s); s += 4; c = *((uint32_t*)s); s += 4;
if(c == 6 || c == 0x60000) break; if(c == 6 || c == 0x60000) break;
@ -627,26 +705,26 @@ void qb_load(unsigned char *data, unsigned int size)
/* read in the layers */ /* read in the layers */
for(s = data + 24, i = 0; i < mc && s < e; i++) { for(s = data + 24, i = 0; i < mc && s < e; i++) {
s += s[0] + 1; s += s[0] + 1;
sx = *((int*)(s + 0)); sy = *((int*)(s + 4)); sz = *((int*)(s + 8)); sx = *((int*)(s + 0)); sz = *((int*)(s + 4)); sy = *((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; 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; s += 24;
if(co) { if(co) {
for(z = 0; z < sz; z++) { for(y = 0; y < sy; y++) {
for(i = 0; 1;) { for(i = 0; 1;) {
c = *((uint32_t*)s); s += 4; c = *((uint32_t*)s); s += 4;
if(c == 6 || c == 0x60000) break; 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; 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++) { for(j = 0; j < l; j++, i++) {
x = i % sx; y = i / sx; x = i % sx; z = i / sx;
_qb_set(cf, px+x, py+y, pz + (za ? mts_z-z : z), (unsigned char*)&c); _qb_set(cf, px+x, pz + (za ? mts_z-z : z), py+y, (unsigned char*)&c);
} }
} }
} }
} else { } 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) 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]; status = lang[LOADED];

View File

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