979 lines
40 KiB
C
979 lines
40 KiB
C
/*
|
|
* mtsedit/schemimp.c
|
|
*
|
|
* Copyright (C) 2019 bzt (bztsrc@gitlab)
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use, copy,
|
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
* of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* @brief Import various non-MTS schematic formats
|
|
*
|
|
*/
|
|
|
|
#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
|
|
*/
|
|
/* parse an integer, the only dynamic type we are interested in. */
|
|
#define SCHEM_GETINT(v,t) do{switch(t){case 1:v=d[0];d++;break;case 2:v=(d[0]<<8)|d[1];d+=2;break; \
|
|
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, l, x, y, z, g = 0, min_x = 0, min_y = 0, min_z = 0, tr[1024];
|
|
char name[256], rep[1024], rot[1024];
|
|
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, 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, "\000\009WEOffsetY", 11)) { d += 11; SCHEM_GETINT(g, d[-12]); d--; } else
|
|
if(!memcmp(d, "\007\000\004Data", 7)) { d += 7; SCHEM_GETINT(i, 3); blkd = d; d += i; d--; } else
|
|
if(!memcmp(d, "\007\000\006Blocks", 9)) { d += 9; SCHEM_GETINT(l, 3); blk = d; d += l; d--; } 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; d--; }
|
|
}
|
|
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, 0xff, sizeof(tr));
|
|
memset(rep, 0, sizeof(rep));
|
|
memset(rot, 0, sizeof(rot));
|
|
if(!blkp) {
|
|
tr[0] = 0;
|
|
for(i = 1; i < numblocks; i++)
|
|
for(j = 0; j < 4; j++)
|
|
if(blocks[i].blockids[j])
|
|
tr[blocks[i].blockids[j]] = i;
|
|
rot[0] = 0; rot[1] = 2; rot[2] = 1; rot[3] = 3;
|
|
} else {
|
|
for(d = blkp; *d > 0 && *d < 4;) {
|
|
j = *d++; d++; l = *d++; s = d; d += l;
|
|
memcpy(name, s, l); name[l] = 0;
|
|
SCHEM_GETINT(k, j);
|
|
for(l = 0; name[l]; l++) if(name[l] == '[') {
|
|
if(strstr(name + l, "=north")) rot[k] = 0; else
|
|
if(strstr(name + l, "=east")) rot[k] = 1; else
|
|
if(strstr(name + l, "=west")) rot[k] = 2; else
|
|
if(strstr(name + l, "=south")) rot[k] = 3;
|
|
name[l] = 0;
|
|
break;
|
|
}
|
|
for(i = l = 0; i < numblocks; i++)
|
|
if((blocks[i].name && (!strcmp(blocks[i].name, name) || (!strncmp(name, "minecraft:", 10) &&
|
|
strlen(blocks[i].name) > 11 && !strcasecmp(blocks[i].name + 10, 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;
|
|
/* 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; }
|
|
}
|
|
}
|
|
if(n < 1024 && tr[n] != -1) {
|
|
layerprob[y+min_y] = 127;
|
|
nodes[y+min_y][255-(x+min_x)][z+min_z].param0 = tr[n];
|
|
nodes[y+min_y][255-(x+min_x)][z+min_z].param1 = !tr[n] ? 0 : 127;
|
|
if(blkp)
|
|
nodes[y+min_y][255-(x+min_x)][z+min_z].param2 = rot[tr[n]];
|
|
else if(blkd)
|
|
nodes[y+min_y][255-(x+min_x)][z+min_z].param2 = rot[blkd[i] & 3];
|
|
blocks[tr[n]].numref++;
|
|
} else if(!blkp && !*d) {
|
|
if(n >= sizeof(rep) || !rep[n])
|
|
fprintf(stderr, "mtsedit: %s: %s %d\r\n", mtsfile, lang[ERR_NODE], n);
|
|
if(n < sizeof(rep))
|
|
rep[n] = 1;
|
|
}
|
|
}
|
|
mts_getbounds(0, NULL, NULL);
|
|
mts_x = max - mix + 1;
|
|
mts_y = may - miy + 1;
|
|
mts_z = maz - miz + 1;
|
|
gndlayer = miy - g;
|
|
status = lang[LOADED];
|
|
}
|
|
|
|
/**
|
|
* Load a blueprint from a PNG file (or voxelize any other PNG image)
|
|
*/
|
|
void bprint_load(unsigned char *data, unsigned int size)
|
|
{
|
|
stbi__context s;
|
|
stbi__result_info ri;
|
|
int w = 0, h = 0, xs = 1, ys = 0, yg = 0, min_x = 0, min_y = 0, min_z = 0, len, x, y, z;
|
|
uint32_t *d;
|
|
|
|
mts_y = mts_z = mts_x = gndlayer = 0;
|
|
s.read_from_callbacks = 0;
|
|
s.img_buffer = s.img_buffer_original = data;
|
|
s.img_buffer_end = s.img_buffer_original_end = data + size;
|
|
ri.bits_per_channel = 8;
|
|
d = (uint32_t*)stbi__png_load(&s, &w, &h, &len, 0, &ri);
|
|
if(!d || len != 4) return;
|
|
|
|
/* detect dimensions */
|
|
for(y = 0; y < h; y++) {
|
|
if(d[y*w] == 0xFF000000 || d[y*w] == 0xFF0000FF) {
|
|
if(!mts_y) {
|
|
ys = y;
|
|
for(mts_z=1; mts_z+1 < w-1 && d[y*w+mts_z+1] != 0xFF0000FF && d[y*w+mts_z+1] != theme[THEME_BP_BG]; mts_z++);
|
|
} else if(mts_y == 1) mts_x = y - ys - 1;
|
|
if(d[y*w] == 0xFF0000FF) yg = mts_y;
|
|
mts_y++;
|
|
}
|
|
}
|
|
if(!mts_x) mts_x = h - ys - 2;
|
|
if(!mts_y) { ys = yg = xs = 0; mts_y = 1; mts_z = w; mts_x = h; }
|
|
if(mts_x < 1 || mts_y < 1 || mts_z < 1) { mts_y = mts_z = mts_x = 0; return; }
|
|
if(mts_y > 255) mts_y = 255;
|
|
if(mts_z > 255) mts_z = 255;
|
|
if(mts_x > 255) mts_x = 255;
|
|
blocks[0].numref = mts_y * mts_z * mts_x;
|
|
min_x = 127 - mts_x / 2;
|
|
min_y = 127 + mts_y / 2;
|
|
min_z = 127 - mts_z / 2;
|
|
gndlayer = min_y - yg;
|
|
|
|
/* read in the layers */
|
|
for(y = 0; y < mts_y; y++)
|
|
for(x = 0; x < mts_x && (y*(mts_x+1)+ys+x) < h; x++)
|
|
for(z = 0; z < mts_z; z++) {
|
|
nodes[min_y-y][mts_z+min_z-z][x+min_x].param0 = color2blockid(d[(y*(mts_x+1)+ys+x)*w + z + xs]);
|
|
if(nodes[min_y-y][mts_z+min_z-z][x+min_x].param0) {
|
|
layerprob[min_y-y] = 127;
|
|
nodes[min_y-y][mts_z+min_z-z][x+min_x].param1 = 127;
|
|
blocks[nodes[min_y-y][mts_z+min_z-z][x+min_x].param0].numref++;
|
|
blocks[0].numref--;
|
|
}
|
|
}
|
|
status = lang[LOADED];
|
|
}
|
|
|
|
/**
|
|
* Load a Model 3D with voxel image
|
|
*/
|
|
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, 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, size, 4096, &l, 1);
|
|
if(!data || !l || memcmp(data, "HEAD", 4)) {
|
|
if(data) free(data);
|
|
return;
|
|
}
|
|
e = data + l;
|
|
}
|
|
strtbl = (char*)data + 16;
|
|
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 color and node palettes */
|
|
ch = data;
|
|
while(ch < e && memcmp(ch, "OMD3", 4)) {
|
|
s = ch;
|
|
l = *((uint32_t*)(ch + 4));
|
|
ch += l;
|
|
if(l < 8 || ch >= e) { ma_x = mi_x = nt = 0; break; }
|
|
l -= 8;
|
|
if(!memcmp(s, "CMAP", 4)) { cmap = (uint32_t*)(s + 8); } else
|
|
if(!memcmp(s, "VOXT", 4)) {
|
|
s += 8;
|
|
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));
|
|
if(!palref) error(lang[ERR_MEM]);
|
|
memset(palref, 0, numpalettes * sizeof(int));
|
|
/* get voxel types */
|
|
for(i = 0; i < nt; i++) {
|
|
c = 0;
|
|
switch(ci_s) {
|
|
case 1: c = cmap ? cmap[s[0]] : 0; s++; break;
|
|
case 2: c = cmap ? cmap[*((uint16_t*)s)] : 0; s += 2; break;
|
|
case 4: c = *((uint32_t*)s); s += 4; break;
|
|
}
|
|
j = 0;
|
|
switch(si_s) {
|
|
case 1: j = s[0]; s++; break;
|
|
case 2: j = *((uint16_t*)s); s += 2; break;
|
|
case 4: j = *((uint32_t*)s); s += 4; break;
|
|
}
|
|
/* if voxel type name given, match that */
|
|
if(j) {
|
|
n = strtbl + j;
|
|
tr[i] = numblocks;
|
|
for(k = 0; k < numblocks; k++)
|
|
for(m = 0; m < numpalettes + 3; m++)
|
|
if((!blocks[k].blocknames && !strcmp(blocks[k].name, n)) ||
|
|
(blocks[k].blocknames && namematch(n, blocks[k].blocknames[m]))) {
|
|
if(k)
|
|
switch(m) {
|
|
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) {
|
|
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;
|
|
/* 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++)
|
|
if(palref[i] > palref[savepal]) savepal = i;
|
|
free(palref);
|
|
} else
|
|
if(!memcmp(s, "VOXD", 4)) {
|
|
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; }
|
|
}
|
|
}
|
|
mts_x = ma_x - mi_x;
|
|
mts_y = ma_y - mi_y;
|
|
mts_z = ma_z - mi_z;
|
|
if(mts_y > 255) mts_y = 255;
|
|
if(mts_z > 255) mts_z = 255;
|
|
if(mts_x > 255) mts_x = 255;
|
|
if(!nt || mts_x < 1 || mts_y < 1 || mts_z < 1) {
|
|
mts_y = mts_z = mts_x = 0;
|
|
if(f) free(f);
|
|
if(tr) free(tr);
|
|
return;
|
|
}
|
|
blocks[0].numref = mts_y * mts_z * mts_x;
|
|
min_x = 127 - mts_x / 2;
|
|
min_y = 127 - mts_y / 2;
|
|
min_z = 127 - mts_z / 2;
|
|
gndlayer = min_y - mi_y;
|
|
|
|
/* read in the layers */
|
|
ch = data;
|
|
while(ch < e && memcmp(ch, "OMD3", 4)) {
|
|
s = ch;
|
|
l = *((uint32_t*)(ch + 4));
|
|
ch += l;
|
|
if(!memcmp(s, "VOXD", 4)) {
|
|
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; 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][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) & 0xFF;
|
|
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++) {
|
|
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][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) & 0xFF;
|
|
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++; } }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(f) free(f);
|
|
if(tr) free(tr);
|
|
status = lang[LOADED];
|
|
}
|
|
|
|
/**
|
|
* Load a Tiled TMX file
|
|
*/
|
|
void tmx_load(unsigned char *data, unsigned int size)
|
|
{
|
|
unsigned char *s, *e = data + size;
|
|
int i, j, k, min_x = 0, min_y = 0, min_z = 0, x, y, z;
|
|
|
|
/* detect dimensions */
|
|
for(s = data; *s && s < e; s++)
|
|
if(!memcmp(s, "<layer", 6)) {
|
|
if(!mts_y)
|
|
for(; *s && *s != '>'; s++) {
|
|
if(!memcmp(s, "width=", 6)) {
|
|
s += 6; if(*s == '\"') s++;
|
|
mts_x = atoi((char*)s);
|
|
}
|
|
if(!memcmp(s, "height=", 7)) {
|
|
s += 7; if(*s == '\"') s++;
|
|
mts_z = atoi((char*)s);
|
|
}
|
|
}
|
|
mts_y++;
|
|
}
|
|
if(mts_x < 1 || mts_y < 1 || mts_z < 1) { mts_y = mts_z = mts_x = 0; return; }
|
|
if(mts_y > 255) mts_y = 255;
|
|
if(mts_z > 255) mts_z = 255;
|
|
if(mts_x > 255) mts_x = 255;
|
|
blocks[0].numref = mts_y * mts_z * mts_x;
|
|
min_x = 127 - mts_x / 2;
|
|
min_y = 127 + mts_y / 2;
|
|
min_z = 127 - mts_z / 2;
|
|
gndlayer = min_y;
|
|
|
|
/* read in the layers */
|
|
for(s = data, y = 0; *s && y < 255; s++)
|
|
if(!memcmp(s, "<layer", 6)) {
|
|
for(; *s && memcmp(s, "<data", 5); s++);
|
|
for(; *s && *s != '>'; s++);
|
|
for(; *s && (*s == '>' || *s == ' ' || *s == '\t' || *s == '\r' || *s == '\n'); s++);
|
|
for(x = z = 0; *s && *s != '<'; s++) {
|
|
if(*s == '\r' || *s == '\t' || *s == ' ' || *s == ',') continue;
|
|
if(*s == '\n') { x = 0; z++; continue; }
|
|
j = atoi((char*)s);
|
|
for(; *s && *s >= '0' && *s <= '9'; s++);
|
|
for(i = 0, k = -1; i < numblocks; i++)
|
|
if(j == blocks[i].blockids[0]) { k = i; break; }
|
|
if(k != -1) {
|
|
if(k && x < 255 && z < 255) {
|
|
nodes[min_y-y][z+min_z][x+min_x].param0 = k;
|
|
layerprob[min_y-y] = 127;
|
|
nodes[min_y-y][z+min_z][x+min_x].param1 = 127;
|
|
blocks[nodes[min_y-y][z+min_z][x+min_x].param0].numref++;
|
|
blocks[0].numref--;
|
|
}
|
|
} else
|
|
fprintf(stderr, "mtsedit: %s: %s %d\r\n", mtsfile, lang[ERR_NODE], j);
|
|
}
|
|
y++;
|
|
}
|
|
status = lang[LOADED];
|
|
}
|
|
|
|
/**
|
|
* Load a Goxel GOX file
|
|
*/
|
|
void gox_load(unsigned char *data, unsigned int size)
|
|
{
|
|
stbi__context sc;
|
|
stbi__result_info ri;
|
|
int i, j, l, 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 k, nb = 0, px, py, pz;
|
|
unsigned char *s, *e = data + size, *c;
|
|
uint32_t p, **blks = NULL;
|
|
|
|
/* detect dimensions and uncompress blocks */
|
|
for(s = data + 8, nb = 0; s < e; s++) {
|
|
if(!memcmp(s, "BL16", 4)) {
|
|
blks = (uint32_t**)realloc(blks, (nb+1) * sizeof(uint32_t*));
|
|
if(!blks) error(lang[ERR_MEM]);
|
|
j = *((uint32_t*)(s + 4));
|
|
sc.read_from_callbacks = 0;
|
|
sc.img_buffer = sc.img_buffer_original = s + 8;
|
|
sc.img_buffer_end = sc.img_buffer_original_end = s + 8 + j;
|
|
ri.bits_per_channel = 8;
|
|
blks[nb] = (uint32_t*)stbi__png_load(&sc, &i, &j, &l, 0, &ri);
|
|
nb++;
|
|
} else
|
|
if(!memcmp(s, "LAYR", 4)) {
|
|
l = *((uint32_t*)(s + 8));
|
|
for(c = s + 12, i = 0; i < l; i++, c += 20) {
|
|
px = *((int*)(c + 4)); py = *((int*)(c + 8)); pz = *((int*)(c + 12));
|
|
if(px < mi_x) { mi_x = px; } if(px+16 > ma_x) { ma_x = px+16; }
|
|
if(py < mi_y) { mi_y = py; } if(py+16 > ma_y) { ma_y = py+16; }
|
|
if(pz < mi_z) { mi_z = pz; } if(pz+16 > ma_z) { ma_z = pz+16; }
|
|
}
|
|
}
|
|
s += *((uint32_t*)(s + 4)) + 11;
|
|
}
|
|
mts_x = ma_x - mi_x;
|
|
mts_y = ma_y - mi_y;
|
|
mts_z = ma_z - mi_z;
|
|
if(mts_y > 255) mts_y = 255;
|
|
if(mts_z > 255) mts_z = 255;
|
|
if(mts_x > 255) mts_x = 255;
|
|
if(!blks || mts_x < 1 || mts_y < 1 || mts_z < 1) { mts_y = mts_z = mts_x = 0; return; }
|
|
blocks[0].numref = mts_y * mts_z * mts_x;
|
|
min_x = 127 - mts_x / 2;
|
|
min_y = 127 - mts_y / 2;
|
|
min_z = 127 - mts_z / 2;
|
|
|
|
/* read in the layers (possibly from multiple chunks) */
|
|
for(s = data + 8; s < e; s++) {
|
|
if(!memcmp(s, "LAYR", 4)) {
|
|
l = *((uint32_t*)(s + 8));
|
|
for(c = s + 12, i = 0; i < l; i++, c += 20) {
|
|
j = *((int*)(c));
|
|
px = *((int*)(c+4)) - mi_x + min_x; py = *((int*)(c+8)) - mi_y + min_y; pz = *((int*)(c+12)) - mi_z + min_z;
|
|
for(k = z = 0; z < 16; z++)
|
|
for(y = 0; y < 16; y++)
|
|
for(x = 0; x < 16; x++, k++)
|
|
if(j >=0 && j < nb && blks[j][k] && px+x >= 0 && px+x < 256 && py+y >= 0 && py+y < 256 &&
|
|
pz+z >= 0 && pz+z < 256) {
|
|
p = color2blockid(blks[j][k]);
|
|
if(p) {
|
|
nodes[pz+z][py+y][px+x].param0 = p;
|
|
layerprob[pz+z] = 127;
|
|
nodes[pz+z][py+y][px+x].param1 = 127;
|
|
blocks[nodes[pz+z][py+y][pz+x].param0].numref++;
|
|
blocks[0].numref--;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
s += *((uint32_t*)(s + 4)) + 11;
|
|
}
|
|
|
|
for(i = 0; i < nb; i++)
|
|
if(blks[i]) free(blks[i]);
|
|
free(blks);
|
|
|
|
bound_valid = 0;
|
|
mts_getbounds(1, NULL, NULL);
|
|
mts_flip();
|
|
mts_x = max - mix + 1;
|
|
mts_y = may - miy + 1;
|
|
mts_z = maz - miz + 1;
|
|
gndlayer = miy;
|
|
status = lang[LOADED];
|
|
}
|
|
|
|
/**
|
|
* Load a Magicavoxel VOX file
|
|
*/
|
|
static uint32_t vox_default_palette[256] = {
|
|
0x00000000, 0xffffffff, 0xffccffff, 0xff99ffff, 0xff66ffff, 0xff33ffff, 0xff00ffff, 0xffffccff, 0xffccccff, 0xff99ccff, 0xff66ccff, 0xff33ccff, 0xff00ccff, 0xffff99ff, 0xffcc99ff, 0xff9999ff,
|
|
0xff6699ff, 0xff3399ff, 0xff0099ff, 0xffff66ff, 0xffcc66ff, 0xff9966ff, 0xff6666ff, 0xff3366ff, 0xff0066ff, 0xffff33ff, 0xffcc33ff, 0xff9933ff, 0xff6633ff, 0xff3333ff, 0xff0033ff, 0xffff00ff,
|
|
0xffcc00ff, 0xff9900ff, 0xff6600ff, 0xff3300ff, 0xff0000ff, 0xffffffcc, 0xffccffcc, 0xff99ffcc, 0xff66ffcc, 0xff33ffcc, 0xff00ffcc, 0xffffcccc, 0xffcccccc, 0xff99cccc, 0xff66cccc, 0xff33cccc,
|
|
0xff00cccc, 0xffff99cc, 0xffcc99cc, 0xff9999cc, 0xff6699cc, 0xff3399cc, 0xff0099cc, 0xffff66cc, 0xffcc66cc, 0xff9966cc, 0xff6666cc, 0xff3366cc, 0xff0066cc, 0xffff33cc, 0xffcc33cc, 0xff9933cc,
|
|
0xff6633cc, 0xff3333cc, 0xff0033cc, 0xffff00cc, 0xffcc00cc, 0xff9900cc, 0xff6600cc, 0xff3300cc, 0xff0000cc, 0xffffff99, 0xffccff99, 0xff99ff99, 0xff66ff99, 0xff33ff99, 0xff00ff99, 0xffffcc99,
|
|
0xffcccc99, 0xff99cc99, 0xff66cc99, 0xff33cc99, 0xff00cc99, 0xffff9999, 0xffcc9999, 0xff999999, 0xff669999, 0xff339999, 0xff009999, 0xffff6699, 0xffcc6699, 0xff996699, 0xff666699, 0xff336699,
|
|
0xff006699, 0xffff3399, 0xffcc3399, 0xff993399, 0xff663399, 0xff333399, 0xff003399, 0xffff0099, 0xffcc0099, 0xff990099, 0xff660099, 0xff330099, 0xff000099, 0xffffff66, 0xffccff66, 0xff99ff66,
|
|
0xff66ff66, 0xff33ff66, 0xff00ff66, 0xffffcc66, 0xffcccc66, 0xff99cc66, 0xff66cc66, 0xff33cc66, 0xff00cc66, 0xffff9966, 0xffcc9966, 0xff999966, 0xff669966, 0xff339966, 0xff009966, 0xffff6666,
|
|
0xffcc6666, 0xff996666, 0xff666666, 0xff336666, 0xff006666, 0xffff3366, 0xffcc3366, 0xff993366, 0xff663366, 0xff333366, 0xff003366, 0xffff0066, 0xffcc0066, 0xff990066, 0xff660066, 0xff330066,
|
|
0xff000066, 0xffffff33, 0xffccff33, 0xff99ff33, 0xff66ff33, 0xff33ff33, 0xff00ff33, 0xffffcc33, 0xffcccc33, 0xff99cc33, 0xff66cc33, 0xff33cc33, 0xff00cc33, 0xffff9933, 0xffcc9933, 0xff999933,
|
|
0xff669933, 0xff339933, 0xff009933, 0xffff6633, 0xffcc6633, 0xff996633, 0xff666633, 0xff336633, 0xff006633, 0xffff3333, 0xffcc3333, 0xff993333, 0xff663333, 0xff333333, 0xff003333, 0xffff0033,
|
|
0xffcc0033, 0xff990033, 0xff660033, 0xff330033, 0xff000033, 0xffffff00, 0xffccff00, 0xff99ff00, 0xff66ff00, 0xff33ff00, 0xff00ff00, 0xffffcc00, 0xffcccc00, 0xff99cc00, 0xff66cc00, 0xff33cc00,
|
|
0xff00cc00, 0xffff9900, 0xffcc9900, 0xff999900, 0xff669900, 0xff339900, 0xff009900, 0xffff6600, 0xffcc6600, 0xff996600, 0xff666600, 0xff336600, 0xff006600, 0xffff3300, 0xffcc3300, 0xff993300,
|
|
0xff663300, 0xff333300, 0xff003300, 0xffff0000, 0xffcc0000, 0xff990000, 0xff660000, 0xff330000, 0xff0000ee, 0xff0000dd, 0xff0000bb, 0xff0000aa, 0xff000088, 0xff000077, 0xff000055, 0xff000044,
|
|
0xff000022, 0xff000011, 0xff00ee00, 0xff00dd00, 0xff00bb00, 0xff00aa00, 0xff008800, 0xff007700, 0xff005500, 0xff004400, 0xff002200, 0xff001100, 0xffee0000, 0xffdd0000, 0xffbb0000, 0xffaa0000,
|
|
0xff880000, 0xff770000, 0xff550000, 0xff440000, 0xff220000, 0xff110000, 0xffeeeeee, 0xffdddddd, 0xffbbbbbb, 0xffaaaaaa, 0xff888888, 0xff777777, 0xff555555, 0xff444444, 0xff222222, 0xff111111,
|
|
};
|
|
void vox_load(unsigned char *data, unsigned int size)
|
|
{
|
|
unsigned char *s, *e = data + size;
|
|
uint32_t *pal = vox_default_palette;
|
|
int i, min_x = 0, min_y = 0, min_z = 0, mi_x = 255, mi_y = 255, mi_z = 255, ma_x = 0, ma_y = 0, ma_z = 0, x, y, z;
|
|
int psiz = 256, siz, tr[256];
|
|
|
|
/* detect dimensions and get palette */
|
|
for(s = data + 20; s < e; s++) {
|
|
if(!memcmp(s, "RGBA", 4)) {
|
|
pal = (uint32_t*)(s + 8); psiz = *((uint32_t*)(s + 4)) / 4;
|
|
/* use the children size field as the first (empty) color, and we don't have to mess with palette indices */
|
|
pal[0] = 0;
|
|
} else
|
|
if(!memcmp(s, "XYZI", 4)) {
|
|
siz = (*((uint32_t*)(s + 4)) / 4) - 1;
|
|
s += 16;
|
|
for(i = 0; i < siz; i++, s += 4) {
|
|
if(s[0] < mi_x) mi_x = s[0];
|
|
if(s[0] > ma_x) ma_x = s[0];
|
|
if(s[1] < mi_z) mi_z = s[1];
|
|
if(s[1] > ma_z) ma_z = s[1];
|
|
if(s[2] < mi_y) mi_y = s[2];
|
|
if(s[2] > ma_y) ma_y = s[2];
|
|
}
|
|
s--;
|
|
continue;
|
|
}
|
|
s += *((uint32_t*)(s + 4)) + 11;
|
|
}
|
|
mts_x = ma_x - mi_x + 1;
|
|
mts_y = ma_y - mi_y + 1;
|
|
mts_z = ma_z - mi_z + 1;
|
|
if(!pal || !psiz || mts_x < 1 || mts_y < 1 || mts_z < 1) { mts_y = mts_z = mts_x = 0; return; }
|
|
blocks[0].numref = mts_y * mts_z * mts_x;
|
|
min_x = 127 - mts_x / 2;
|
|
min_y = 127 - mts_y / 2;
|
|
min_z = 127 + mts_z / 2;
|
|
gndlayer = min_y;
|
|
|
|
/* get palette index translation */
|
|
memset(tr, 0, sizeof(tr));
|
|
for(i = 0; i < psiz; i++)
|
|
tr[i] = color2blockid(pal[i]);
|
|
|
|
/* read in the layers (possibly from multiple chunks) */
|
|
for(s = data + 20; s < e; s++) {
|
|
if(!memcmp(s, "XYZI", 4)) {
|
|
siz = (*((uint32_t*)(s + 4)) / 4) - 1;
|
|
s += 16;
|
|
for(i = 0; i < siz; i++, s += 4) {
|
|
x = s[0] - mi_x;
|
|
z = s[1] - mi_z;
|
|
y = s[2] - mi_y;
|
|
nodes[min_y+y][min_z-z][x+min_x].param0 = tr[s[3]];
|
|
if(nodes[min_y+y][min_z-z][x+min_x].param0) {
|
|
layerprob[min_y+y] = 127;
|
|
nodes[min_y+y][min_z-z][x+min_x].param1 = 127;
|
|
blocks[nodes[min_y+y][min_z-z][x+min_x].param0].numref++;
|
|
blocks[0].numref--;
|
|
}
|
|
}
|
|
s--;
|
|
continue;
|
|
}
|
|
s += *((uint32_t*)(s + 4)) + 11;
|
|
}
|
|
status = lang[LOADED];
|
|
}
|
|
|
|
/**
|
|
* Save a Magicavoxel VOX file (this is an exception to support bidirectional workflows)
|
|
*/
|
|
int vox_save()
|
|
{
|
|
char outfile[MAXPATHLEN], *c;
|
|
unsigned short *tr, *tr2;
|
|
unsigned char hdr[12 + 1024];
|
|
int i, j, n = 0, x, y, z;
|
|
FILE *f;
|
|
|
|
status = lang[ERR_SAVE];
|
|
tr = (unsigned short*)malloc(numblocks * sizeof(unsigned short));
|
|
if(!tr) error(lang[ERR_MEM]);
|
|
memset(tr, 0, numblocks * sizeof(unsigned short));
|
|
tr2 = (unsigned short*)malloc(numblocks * sizeof(unsigned short));
|
|
if(!tr2) error(lang[ERR_MEM]);
|
|
memset(tr2, 0, numblocks * sizeof(unsigned short));
|
|
|
|
j = mts_getbounds(1, tr, tr2);
|
|
if(mix > max) { free(tr); free(tr2); return 1; }
|
|
|
|
for(y = miy; y <= may; y++)
|
|
for(z = miz; z <= maz; z++)
|
|
for(x = mix; x <= max; x++)
|
|
if(nodes[y][z][x].param0) n++;
|
|
|
|
/* get filename, buffer and open file */
|
|
strcpy(outfile, mtsfile);
|
|
c = strrchr(outfile, '.');
|
|
if(!c) c = &outfile[strlen(outfile)];
|
|
strcpy(c, ".vox");
|
|
f = fopen(outfile,"wb");
|
|
if(!f) return 1;
|
|
|
|
/* write header */
|
|
memcpy(hdr, "VOX ", 4);
|
|
*((uint32_t*)(hdr+4)) = 150;
|
|
memcpy(hdr + 8, "MAIN", 4);
|
|
*((uint32_t*)(hdr+12)) = 0;
|
|
*((uint32_t*)(hdr+16)) = 40 + n*4 + 1036;
|
|
memcpy(hdr + 20, "SIZE", 4);
|
|
*((uint32_t*)(hdr+24)) = 12;
|
|
*((uint32_t*)(hdr+28)) = 0;
|
|
*((uint32_t*)(hdr+32)) = max-mix+1;
|
|
*((uint32_t*)(hdr+36)) = may-miy+1;
|
|
*((uint32_t*)(hdr+40)) = maz-miz+1;
|
|
memcpy(hdr + 44, "XYZI", 4);
|
|
*((uint32_t*)(hdr+48)) = n*4 + 4;
|
|
*((uint32_t*)(hdr+52)) = 0;
|
|
*((uint32_t*)(hdr+56)) = n;
|
|
fwrite(hdr, 60, 1, f);
|
|
|
|
/* write data */
|
|
for(y = miy; y <= may; y++)
|
|
for(z = miz; z <= maz; z++)
|
|
for(x = mix; x <= max; x++)
|
|
if(nodes[y][z][x].param0) {
|
|
hdr[0] = x - mix;
|
|
hdr[1] = maz - z;
|
|
hdr[2] = y - miy;
|
|
hdr[3] = tr2[nodes[y][z][x].param0];
|
|
fwrite(hdr, 4, 1, f);
|
|
}
|
|
|
|
/* write palette */
|
|
memset(hdr, 0, sizeof(hdr));
|
|
memcpy(hdr, "RGBA", 4);
|
|
for(i = 0; i < j; i++)
|
|
memcpy(hdr + 8 + i * 4, &blocks[tr[i]].color, 4);
|
|
*((uint32_t*)(hdr+4)) = 1024;
|
|
*((uint32_t*)(hdr+8)) = 0;
|
|
fwrite(hdr, 12+1024, 1, f);
|
|
|
|
status = lang[SAVED];
|
|
fclose(f);
|
|
free(tr);
|
|
free(tr2);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Load a Qubicle QB file
|
|
*/
|
|
void _qb_set(int cf, int x, int y, int z, unsigned char *s)
|
|
{
|
|
int i;
|
|
|
|
if(y < 0 || y > 255 || z < 0 || z > 255 || x < 0 || x > 255) return;
|
|
i = color2blockid(!s[3] ? 0 : 0xFF000000 | (cf ?
|
|
((uint32_t)s[0] << 16) | ((uint32_t)s[1] << 8) | (uint32_t)s[2] : *((uint32_t*)s)));
|
|
if(i) {
|
|
nodes[y][z][x].param0 = i;
|
|
layerprob[y] = 127;
|
|
nodes[y][z][x].param1 = 127;
|
|
blocks[nodes[y][z][x].param0].numref++;
|
|
blocks[0].numref--;
|
|
}
|
|
}
|
|
void qb_load(unsigned char *data, unsigned int size)
|
|
{
|
|
int cf = data[4], za = data[8], co = data[12], mc = *((int*)(data+20));
|
|
int i, j, l, 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;
|
|
unsigned char *s, *e = data + size;
|
|
uint32_t c;
|
|
|
|
/* detect dimensions */
|
|
for(s = data + 24, i = 0; i < mc && s < e; i++) {
|
|
s += s[0] + 1;
|
|
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(y = 0; y < sy; y++) {
|
|
while(1) {
|
|
c = *((uint32_t*)s); s += 4;
|
|
if(c == 6 || c == 0x60000) break;
|
|
if(c == 2 || c == 0x20000) s += 8;
|
|
}
|
|
}
|
|
} else
|
|
s += sx * sy * sz * 4;
|
|
}
|
|
mts_x = ma_x - mi_x;
|
|
mts_y = ma_y - mi_y;
|
|
mts_z = ma_z - mi_z;
|
|
if(mts_y > 255) mts_y = 255;
|
|
if(mts_z > 255) mts_z = 255;
|
|
if(mts_x > 255) mts_x = 255;
|
|
if(mts_x < 1 || mts_y < 1 || mts_z < 1) { mts_y = mts_z = mts_x = 0; return; }
|
|
blocks[0].numref = mts_y * mts_z * mts_x;
|
|
min_x = 127 - mts_x / 2;
|
|
min_y = 127 - mts_y / 2;
|
|
min_z = 127 - mts_z / 2;
|
|
gndlayer = min_y;
|
|
|
|
/* read in the layers */
|
|
for(s = data + 24, i = 0; i < mc && s < e; i++) {
|
|
s += s[0] + 1;
|
|
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(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; z = i / sx;
|
|
_qb_set(cf, px+x, pz + (za ? mts_z-z : z), py+y, (unsigned char*)&c);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
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, pz + (za ? mts_z-z : z), py+y, s);
|
|
}
|
|
}
|
|
status = lang[LOADED];
|
|
}
|
|
|
|
/**
|
|
* Load a WorldEdit .we file
|
|
*/
|
|
void we_load(unsigned char *data, unsigned int size)
|
|
{
|
|
unsigned char *s, *d, *e = data + size;
|
|
unsigned int idx;
|
|
int j, k, l, 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;
|
|
int x, y, z, b, p0, p1, p2, *palref;
|
|
|
|
/* detect dimensions */
|
|
while(data < e && *data != '{') data++;
|
|
if(*data != '{') return;
|
|
data++;
|
|
for(s = data, b = 0; b >= 0 && s < e; s++) {
|
|
if(b == 1 && *s == '[') {
|
|
if(!memcmp(s, "[\"x\"]", 5)) {
|
|
while(s < e && *s != '=') s++;
|
|
while(s < e && (*s == '=' || *s == ' ')) s++;
|
|
x = atoi((char*)s);
|
|
if(x < mi_x) mi_x = x;
|
|
if(x > ma_x) ma_x = x;
|
|
} else
|
|
if(!memcmp(s, "[\"y\"]", 5)) {
|
|
while(s < e && *s != '=') s++;
|
|
while(s < e && (*s == '=' || *s == ' ')) s++;
|
|
y = atoi((char*)s);
|
|
if(y < mi_y) mi_y = y;
|
|
if(y > ma_y) ma_y = y;
|
|
} else
|
|
if(!memcmp(s, "[\"z\"]", 5)) {
|
|
while(s < e && *s != '=') s++;
|
|
while(s < e && (*s == '=' || *s == ' ')) s++;
|
|
z = atoi((char*)s);
|
|
if(z < mi_z) mi_z = z;
|
|
if(z > ma_z) ma_z = z;
|
|
}
|
|
}
|
|
if(*s == '{') b++; else
|
|
if(*s == '}') b--;
|
|
}
|
|
mts_x = ma_x - mi_x + 1;
|
|
mts_y = ma_y - mi_y + 1;
|
|
mts_z = ma_z - mi_z + 1;
|
|
if(mts_y > 255) mts_y = 255;
|
|
if(mts_z > 255) mts_z = 255;
|
|
if(mts_x > 255) mts_x = 255;
|
|
if(mts_x < 1 || mts_y < 1 || mts_z < 1) { mts_y = mts_z = mts_x = 0; return; }
|
|
blocks[0].numref = mts_y * mts_z * mts_x;
|
|
min_x = 127 - mts_x / 2;
|
|
min_y = 127 - mts_y / 2;
|
|
min_z = 127 - mts_z / 2;
|
|
gndlayer = min_y;
|
|
|
|
palref = (int*)malloc(numpalettes * sizeof(int));
|
|
if(!palref) error(lang[ERR_MEM]);
|
|
|
|
p0 = p2 = 0; p1 = 127; x = y = z = -256;
|
|
for(s = data, b = 0; b >= 0 && s < e; s++) {
|
|
if(b == 1 && *s == '[') {
|
|
if(!memcmp(s, "[\"x\"]", 5)) {
|
|
while(s < e && *s != '=') s++;
|
|
while(s < e && (*s == '=' || *s == ' ')) s++;
|
|
x = atoi((char*)s);
|
|
} else
|
|
if(!memcmp(s, "[\"y\"]", 5)) {
|
|
while(s < e && *s != '=') s++;
|
|
while(s < e && (*s == '=' || *s == ' ')) s++;
|
|
y = atoi((char*)s);
|
|
} else
|
|
if(!memcmp(s, "[\"z\"]", 5)) {
|
|
while(s < e && *s != '=') s++;
|
|
while(s < e && (*s == '=' || *s == ' ')) s++;
|
|
z = atoi((char*)s);
|
|
} else
|
|
if(!memcmp(s, "[\"param1\"]", 10)) {
|
|
while(s < e && *s != '=') s++;
|
|
while(s < e && (*s == '=' || *s == ' ')) s++;
|
|
p1 = atoi((char*)s);
|
|
} else
|
|
if(!memcmp(s, "[\"param2\"]", 10)) {
|
|
while(s < e && *s != '=') s++;
|
|
while(s < e && (*s == '=' || *s == ' ')) s++;
|
|
p2 = atoi((char*)s);
|
|
} else
|
|
if(!memcmp(s, "[\"name\"]", 8)) {
|
|
while(s < e && *s != '=') s++;
|
|
while(s < e && (*s == '=' || *s == ' ' || *s == '\"')) s++;
|
|
for(d = s, j = 0; d < e && *d && *d != '\"'; d++, j++);
|
|
p0 = numblocks;
|
|
for(k = 0; k < numblocks; k++)
|
|
for(l = 0; l < numpalettes + 3; l++)
|
|
if((!blocks[k].blocknames && (int)strlen(blocks[k].name) == j &&
|
|
!memcmp(blocks[k].name, s, j)) || (blocks[k].blocknames && blocks[k].blocknames[l] &&
|
|
(int)strlen(blocks[k].blocknames[l]) == j && !memcmp(blocks[k].blocknames[l], s, j))) {
|
|
if(k)
|
|
switch(l) {
|
|
case 0: break;
|
|
case 1: blocks[k].dobiome = 1; savebiome = 1; break;
|
|
case 2: if(!memcmp(s, "mapgen", 6)) { savemapgen = 1; } break;
|
|
default: palref[l - 3]++; break;
|
|
}
|
|
p0 = k;
|
|
break;
|
|
}
|
|
if(p0 == numblocks) {
|
|
l = s[j]; s[j] = 0;
|
|
fprintf(stderr, "mtsedit: %s: %s %d '%s'\r\n", mtsfile, lang[ERR_NODE], p0, s);
|
|
s[j] = l;
|
|
idx = numblocks++;
|
|
blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t));
|
|
if(!blocks) error(lang[ERR_MEM]);
|
|
memset(&blocks[idx], 0, sizeof(mtsblock_t));
|
|
blocks[idx].name = (char*)malloc(j + 1);
|
|
if(!blocks[idx].name) error(lang[ERR_MEM]);
|
|
memcpy(blocks[idx].name, s, j);
|
|
blocks[idx].name[j] = 0;
|
|
}
|
|
s = d;
|
|
}
|
|
}
|
|
if(*s == '{') b++; else
|
|
if(*s == '}') {
|
|
b--;
|
|
if(!b) {
|
|
if(p0 && x != -256 && y != -256 && z != -256) {
|
|
layerprob[min_y+y] = 127;
|
|
nodes[min_y+y][mts_z+min_z-z][x+min_x].param0 = p0;
|
|
nodes[min_y+y][mts_z+min_z-z][x+min_x].param1 = p1;
|
|
nodes[min_y+y][mts_z+min_z-z][x+min_x].param2 = p2;
|
|
blocks[p0].numref++;
|
|
blocks[0].numref--;
|
|
}
|
|
p0 = p2 = 0; p1 = 127; x = y = z = -256;
|
|
}
|
|
}
|
|
}
|
|
/* pick the node palette which has the most node reference */
|
|
for(j = savepal = 0; j < numpalettes; j++)
|
|
if(palref[j] > palref[savepal]) savepal = j;
|
|
free(palref);
|
|
status = lang[LOADED];
|
|
}
|