Code cleanup
parent
94e9271337
commit
7f3383ee28
|
@ -0,0 +1,322 @@
|
|||
/*
|
||||
* mtsedit/blocks.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 Dealing with the data directory and blocks.csv
|
||||
*
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include <dirent.h>
|
||||
|
||||
char *path = NULL, *fn = NULL;
|
||||
|
||||
int fncmp(const void *a, const void *b) { return strcmp(*((const char**)a), *((const char**)b)); }
|
||||
|
||||
/**
|
||||
* Get blocks.csv's absolute path
|
||||
*/
|
||||
void getblocksdir(char **argv, char **envp)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
char **env = envp;
|
||||
#ifndef __WIN32__
|
||||
char *home = NULL;
|
||||
#endif
|
||||
/* find our data directory. Environment variable takes preference */
|
||||
for(env = envp; env && *env; env++) {
|
||||
if(!memcmp(*env, "MTSDATA=", 8)) {
|
||||
path = (char*)malloc(strlen(*env)+256);
|
||||
if(!path) error(lang[ERR_MEM]);
|
||||
i = strlen(*env)-9;
|
||||
memcpy(path, *env + 8, i+1);
|
||||
if(path[i] != DIRSEP) { path[++i] = DIRSEP; i++; }
|
||||
strcpy(path + i, "blocks.csv");
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[i] = 0; fclose(f); }
|
||||
else { free(path); path = NULL; }
|
||||
}
|
||||
#ifndef __WIN32__
|
||||
if(!memcmp(*env, "HOME=", 5))
|
||||
home = *env + 5;
|
||||
#endif
|
||||
}
|
||||
#ifndef __WIN32__
|
||||
/* in user's home */
|
||||
if(!path && home) {
|
||||
path = (char*)malloc(strlen(home)+256);
|
||||
if(!path) error(lang[ERR_MEM]);
|
||||
i = strlen(home)-1;
|
||||
memcpy(path, home, i + 1);
|
||||
if(path[i] != DIRSEP) { path[++i] = DIRSEP; i++; }
|
||||
/* Linux and BSDs */
|
||||
strcpy(path + i, ".config/mtsedit/blocks.csv");
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else {
|
||||
strcpy(path + i, "Library/Application Support/MTSEdit/blocks.csv");
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else { free(path); path = NULL; }
|
||||
}
|
||||
}
|
||||
/* system wide */
|
||||
if(!path) {
|
||||
path = (char*)malloc(26+256);
|
||||
if(!path) error(lang[ERR_MEM]);
|
||||
strcpy(path, "/usr/share/mtsedit/blocks.csv");
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else {
|
||||
strcpy(path, "/usr/local/share/mtsedit/blocks.csv");
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else { free(path); path = NULL; }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* same directory as the executable */
|
||||
if(!path) {
|
||||
path = (char*)malloc(strlen(argv[0])+256);
|
||||
if(!path) error(lang[ERR_MEM]);
|
||||
strcpy(path, argv[0]);
|
||||
home = strrchr(path, DIRSEP);
|
||||
if(home) home++; else { sprintf(path, ".%c", DIRSEP); home = path + 2; }
|
||||
sprintf(home, "data%cblocks.csv", DIRSEP);
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else {
|
||||
/* last resort, development repository or /opt/mtsedit/bin, data in parent directory */
|
||||
sprintf(home, "..%cdata%cblocks.csv", DIRSEP, DIRSEP);
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else { free(path); path = NULL; }
|
||||
}
|
||||
}
|
||||
if(!path) error(lang[ERR_DATADIR]);
|
||||
fn = path + strlen(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the blocks.csv
|
||||
*/
|
||||
void parseblocks()
|
||||
{
|
||||
stbi__context sc;
|
||||
stbi__result_info ri;
|
||||
int w, h, l;
|
||||
unsigned int numfiles = 0, i, j, k;
|
||||
char **files = NULL, c, *s, *e;
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
unsigned int size;
|
||||
unsigned char *img;
|
||||
char *data = (char*)readfile("blocks.csv", &size);
|
||||
|
||||
if(!data || !size) error(lang[ERR_CSV]);
|
||||
|
||||
/* get block images */
|
||||
*fn = 0;
|
||||
dir = opendir(path);
|
||||
if(dir) {
|
||||
while((de = readdir(dir))) {
|
||||
i = strlen(de->d_name);
|
||||
if(i > 8 && !strcmp(de->d_name + i - 4, ".png") && de->d_name[i-7] == '_') {
|
||||
j = numfiles++;
|
||||
files = (char**)realloc(files, numfiles * sizeof(char*));
|
||||
if(!files) error(lang[ERR_MEM]);
|
||||
files[j] = (char*)malloc(i + 1);
|
||||
if(!files[j]) error(lang[ERR_MEM]);
|
||||
memcpy(files[j], de->d_name, i + 1);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
qsort(files, numfiles, sizeof(char*), fncmp);
|
||||
|
||||
/* parse header */
|
||||
for(e = data, i = j = 0; *e && *e != '\r' && *e != '\n' && i < 3; e++) {
|
||||
if(*e == '\"') j ^= 1;
|
||||
if(!j && (*e == ',' || *e == ';' || *e == '\t')) i++;
|
||||
}
|
||||
if(i != 3 || !*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 = ',';
|
||||
for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++)
|
||||
if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; }
|
||||
while(*s <= ' ') s++;
|
||||
while(*(e-1) <= ' ') e--;
|
||||
j = numpalettes++;
|
||||
palettes = (char**)realloc(palettes, numpalettes * sizeof(char*));
|
||||
if(!palettes) error(lang[ERR_MEM]);
|
||||
palettes[j] = (char*)malloc(e - s + 1);
|
||||
if(!palettes[j]) error(lang[ERR_MEM]);
|
||||
memcpy(palettes[j], s, e - s + 1);
|
||||
palettes[j][e - s] = 0;
|
||||
if((int)(e - s) > lenpalettes) lenpalettes = e - s;
|
||||
while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++;
|
||||
}
|
||||
/* add Air as first block */
|
||||
numblocks++;
|
||||
blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t));
|
||||
if(!blocks) error(lang[ERR_MEM]);
|
||||
memset(&blocks[0], 0, sizeof(mtsblock_t));
|
||||
blocks[0].name = (char*)malloc(4);
|
||||
if(!blocks[0].name) error(lang[ERR_MEM]);
|
||||
memcpy(blocks[0].name, "Air", 4);
|
||||
blocks[0].blocknames = (char**)malloc((numpalettes + 1) * sizeof(char*));
|
||||
if(!blocks[0].blocknames) error(lang[ERR_MEM]);
|
||||
blocks[0].blocknames[0] = NULL;
|
||||
for(i = 1; i < (unsigned int)numpalettes + 1; i++) {
|
||||
blocks[0].blocknames[i] = (char*)malloc(4);
|
||||
if(!blocks[0].blocknames[i]) error(lang[ERR_MEM]);
|
||||
memcpy(blocks[0].blocknames[i], "air", 4);
|
||||
}
|
||||
|
||||
/* parse rows */
|
||||
while(*e) {
|
||||
if(*e == '\r' || *e == '\n') {
|
||||
while(*e == '\r' || *e == '\n') e++;
|
||||
if(!*e) break;
|
||||
/* get canonical name */
|
||||
if(*e == '\"') { e++; c = '\"'; } else c = ',';
|
||||
for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++)
|
||||
if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; }
|
||||
while(*s <= ' ') s++;
|
||||
while(*(e-1) <= ' ') e--;
|
||||
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(e - s + 1);
|
||||
if(!blocks[j].name) error(lang[ERR_MEM]);
|
||||
blocks[j].blocknames = (char**)malloc((numpalettes + 1) * sizeof(char*));
|
||||
if(!blocks[j].blocknames) error(lang[ERR_MEM]);
|
||||
memset(blocks[j].blocknames, 0, (numpalettes + 1) * sizeof(char*));
|
||||
for(i = 0; s + i < e; i++) {
|
||||
blocks[j].name[i] = s[i] == '_' ? ' ' : s[i];
|
||||
if(s[i] == ' ') s[i] = '_';
|
||||
}
|
||||
blocks[j].name[i] = 0;
|
||||
/* get block images and possible param2 values */
|
||||
for(i = 0, l = 0; i < numfiles; i++) {
|
||||
if((int)strlen(files[i]) == (int)(e - s + 7) && !memcmp(files[i], s, e - s)) {
|
||||
img = readfile(files[i], &size);
|
||||
if(img && size) {
|
||||
k = ahtoi(strrchr(files[i], '_') + 1) & 0x1F;
|
||||
sc.read_from_callbacks = 0;
|
||||
sc.img_buffer = sc.img_buffer_original = img;
|
||||
sc.img_buffer_end = sc.img_buffer_original_end = img + size;
|
||||
ri.bits_per_channel = 8;
|
||||
blocks[j].img[k] = (unsigned char*)stbi__png_load(&sc, &w, &h, &l, 0, &ri);
|
||||
if(blocks[j].img[k]) {
|
||||
l++;
|
||||
if(!dx || !dz) {
|
||||
detcube(32, 32, blocks[j].img[k]);
|
||||
printf("x %d z %d\n",x1-x0,y1-y0);
|
||||
dx = x1 - x0;
|
||||
dz = y1 - y0;
|
||||
}
|
||||
}
|
||||
free(img);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!l)
|
||||
fprintf(stderr, "mtsedit: blocks.csv(%d): %s '%s'\r\n", j+1, lang[ERR_IMG], blocks[j].name);
|
||||
while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++;
|
||||
while(*e == ' ') e++;
|
||||
if(*e != ',' && *e != ';' && *e != '\t') errorcsv(j+1);
|
||||
e++;
|
||||
while(*e == ' ') e++;
|
||||
/* get Block IDs */
|
||||
if(*e == '\"') { e++; c = '\"'; } else c = ',';
|
||||
for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++)
|
||||
if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; }
|
||||
while(*s <= ' ') s++;
|
||||
for(i = 0; s < e && i < 8;) {
|
||||
blocks[j].blockids[i] = atoi(s);
|
||||
if(blocks[j].blockids[i]) i++;
|
||||
while(*s >= '0' && *s <= '9') s++;
|
||||
if(*s == '/') s++;
|
||||
}
|
||||
while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++;
|
||||
k = 0;
|
||||
}
|
||||
/* get palette specific names */
|
||||
while(*e == ' ') e++;
|
||||
if(*e != ',' && *e != ';' && *e != '\t') errorcsv(j+1);
|
||||
e++;
|
||||
while(*e == ' ') e++;
|
||||
if(!*e) errorcsv(j+1);
|
||||
if(*e == '\"') { e++; c = '\"'; } else c = ',';
|
||||
for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++)
|
||||
if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; }
|
||||
while(*s <= ' ') s++;
|
||||
while(*(e-1) <= ' ') e--;
|
||||
if(e != s) {
|
||||
blocks[j].blocknames[k] = (char*)malloc(e - s + 1);
|
||||
if(!blocks[j].blocknames[k]) error(lang[ERR_MEM]);
|
||||
memcpy(blocks[j].blocknames[k], s, e - s + 1);
|
||||
blocks[j].blocknames[k][e - s] = 0;
|
||||
}
|
||||
k++; if(k > (unsigned int)numpalettes + 1) errorcsv(j+2);
|
||||
while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++;
|
||||
}
|
||||
if(!numblocks || numblocks > 65535) error(lang[ERR_CSV]);
|
||||
|
||||
/* free temp resources */
|
||||
for(i = 0; i < numfiles; i++) free(files[i]);
|
||||
free(files);
|
||||
free(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free resources
|
||||
*/
|
||||
void freeblocks()
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for(i = 0; i < numpalettes; i++) free(palettes[i]);
|
||||
free(palettes);
|
||||
|
||||
for(i = 0; i < numblocks; i++) {
|
||||
free(blocks[i].name);
|
||||
if(blocks[i].blocknames) {
|
||||
for(j = 0; j < numpalettes; j++)
|
||||
if(blocks[i].blocknames[j]) free(blocks[i].blocknames[j]);
|
||||
free(blocks[i].blocknames);
|
||||
}
|
||||
for(j = 0; j < 32; j++) {
|
||||
if(blocks[i].img[j]) free(blocks[i].img[j]);
|
||||
if(blocks[i].dr[j]) free(blocks[i].dr[j]);
|
||||
if(blocks[i].tr[j]) free(blocks[i].tr[j]);
|
||||
}
|
||||
}
|
||||
free(results);
|
||||
free(blocks);
|
||||
}
|
106
src/edit.c
106
src/edit.c
|
@ -29,7 +29,19 @@
|
|||
|
||||
#include "main.h"
|
||||
|
||||
int dx = 13, dz = 8, cx = 127, cz = 127, ox = 0, oy = 0, up = 0;
|
||||
int dx = 0, dz = 0, cx = 0, cz = 0, ox = 0, oy = 0, up = 0;
|
||||
|
||||
/**
|
||||
* Place a node
|
||||
*/
|
||||
void edit_placenode(int y, int z, int x, int i)
|
||||
{
|
||||
blocks[nodes[y][z][x].param0].numref--;
|
||||
blocks[i].numref++;
|
||||
nodes[y][z][x].param0 = i;
|
||||
nodes[y][z][x].param1 = i ? 127 : 0;
|
||||
status = i ? blocks[i].name : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redraw the Edit Area
|
||||
|
@ -325,6 +337,7 @@ void edit_mouseover(SDL_Event *event)
|
|||
{
|
||||
int l, k;
|
||||
|
||||
edit_hidecursor();
|
||||
l = (int)(event->motion.y - (bg->h / 2));
|
||||
if(l < 0) l -= dz;
|
||||
l /= dz; l--;
|
||||
|
@ -344,6 +357,7 @@ void edit_mouseover(SDL_Event *event)
|
|||
nodes[currlayer][cz][cx].param1 = k ? 127 : 0;
|
||||
}
|
||||
status = nodes[currlayer][cz][cx].param0 ? blocks[nodes[currlayer][cz][cx].param0].name : NULL;
|
||||
edit_showcursor(event->button.button == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -351,17 +365,91 @@ void edit_mouseover(SDL_Event *event)
|
|||
*/
|
||||
void edit_mousedown(_unused SDL_Event *event)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(event->button.button != 1)
|
||||
edit_rotate(currlayer, cz, cx, 1 - shift);
|
||||
else {
|
||||
blocks[nodes[currlayer][cz][cx].param0].numref--;
|
||||
i = palette[activeblock];
|
||||
blocks[i].numref++;
|
||||
nodes[currlayer][cz][cx].param0 = i;
|
||||
nodes[currlayer][cz][cx].param1 = i ? 127 : 0;
|
||||
status = i ? blocks[i].name : NULL;
|
||||
edit_placenode(currlayer, cz, cx, palette[activeblock]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit Area key event handler
|
||||
*/
|
||||
void edit_key(SDL_Event *event)
|
||||
{
|
||||
char str[32];
|
||||
|
||||
switch (event->key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
case SDLK_q: quitting = 1; break;
|
||||
case SDLK_s: if(!shift) sdldosave(); break;
|
||||
case SDLK_l: sdldoload(); break;
|
||||
case SDLK_p: sdldopreview(); break;
|
||||
case SDLK_r: sdldorotate(1 - shift); break;
|
||||
case SDLK_g: gndlayer = currlayer; break;
|
||||
case SDLK_PLUS: case SDLK_EQUALS: mts_layerprob(+1); break;
|
||||
case SDLK_MINUS: mts_layerprob(-1); break;
|
||||
case SDLK_PAGEUP: if(currlayer < 255) currlayer++; break;
|
||||
case SDLK_PAGEDOWN: if(currlayer > 0) currlayer--; break;
|
||||
case SDLK_BACKQUOTE: case SDLK_0: activeblock = 0; break;
|
||||
case SDLK_1: case SDLK_2: case SDLK_3: case SDLK_4: case SDLK_5:
|
||||
case SDLK_6: case SDLK_7: case SDLK_8: case SDLK_9:
|
||||
if(palette[event->key.keysym.sym - SDLK_0])
|
||||
activeblock = event->key.keysym.sym - SDLK_0;
|
||||
break;
|
||||
case SDLK_h: dx--; sprintf(str, "dx %d dz %d", dx, dz); status = str; break;
|
||||
case SDLK_k: dx++; sprintf(str, "dx %d dz %d", dx, dz); status = str; break;
|
||||
case SDLK_u: dz--; sprintf(str, "dx %d dz %d", dx, dz); status = str; break;
|
||||
case SDLK_j: dz++; sprintf(str, "dx %d dz %d", dx, dz); status = str; break;
|
||||
case SDLK_UP:
|
||||
if(ctrl) {
|
||||
if(oy < 127) oy++;
|
||||
} else if(shift) {
|
||||
if(up > -128) up--;
|
||||
} else {
|
||||
if(cz > 0) cz--;
|
||||
status = nodes[currlayer][cz][cx].param0 ?
|
||||
blocks[nodes[currlayer][cz][cx].param0].name : NULL;
|
||||
}
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
if(ctrl) {
|
||||
if(oy > -128) oy--;
|
||||
} else if(shift) {
|
||||
if(up < 127) up++;
|
||||
} else {
|
||||
if(cz < 255) cz++;
|
||||
status = nodes[currlayer][cz][cx].param0 ?
|
||||
blocks[nodes[currlayer][cz][cx].param0].name : NULL;
|
||||
}
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
if(ctrl) {
|
||||
if(ox < 127) ox++;
|
||||
} else if(shift) {
|
||||
edit_rotate(currlayer, cz, cx, 1);
|
||||
} else {
|
||||
if(cx > 0) cx--;
|
||||
status = nodes[currlayer][cz][cx].param0 ?
|
||||
blocks[nodes[currlayer][cz][cx].param0].name : NULL;
|
||||
}
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
if(ctrl) {
|
||||
if(ox > -128) ox--;
|
||||
} else if(shift) {
|
||||
edit_rotate(currlayer, cz, cx, 0);
|
||||
} else {
|
||||
if(cx < 255) cx++;
|
||||
status = nodes[currlayer][cz][cx].param0 ?
|
||||
blocks[nodes[currlayer][cz][cx].param0].name : NULL;
|
||||
}
|
||||
break;
|
||||
case SDLK_BACKSPACE:
|
||||
case SDLK_DELETE:
|
||||
case SDLK_SPACE:
|
||||
edit_placenode(currlayer, cz, cx, event->key.keysym.sym == SDLK_SPACE && !shift ? palette[activeblock] : 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
98
src/main.c
98
src/main.c
|
@ -157,30 +157,14 @@ int APIENTRY WinMain(__attribute__((unused)) HINSTANCE hInstance, __attribute__(
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Common error handler
|
||||
*/
|
||||
void error(char *msg)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
MessageBox(NULL, msg, "MTSEdit", MB_ICONEXCLAMATION | MB_OK);
|
||||
#else
|
||||
fprintf(stderr, "mtsedit: %s\r\n", msg);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* The real main procedure
|
||||
*/
|
||||
int main(int argc, char** argv, char** envp)
|
||||
{
|
||||
FILE *f;
|
||||
int i, j, opt = 0, ret = 0;
|
||||
char **env = envp, *newmap = NULL;
|
||||
#ifndef __WIN32__
|
||||
char *home = NULL;
|
||||
#endif
|
||||
char **env, *newmap = NULL;
|
||||
|
||||
/* detect the language and load dictionary for it */
|
||||
for(env = envp; env && *env; env++)
|
||||
if(!memcmp(*env, "LANG=", 5)) {
|
||||
|
@ -192,79 +176,9 @@ int main(int argc, char** argv, char** envp)
|
|||
}
|
||||
break;
|
||||
}
|
||||
/* get blocks data */
|
||||
getblocksdir(argv, envp);
|
||||
|
||||
/* find our data directory. Environment variable takes preference */
|
||||
for(env = envp; env && *env; env++) {
|
||||
if(!memcmp(*env, "MTSDATA=", 8)) {
|
||||
path = (char*)malloc(strlen(*env)+256);
|
||||
if(!path) error(lang[ERR_MEM]);
|
||||
i = strlen(*env)-9;
|
||||
memcpy(path, *env + 8, i+1);
|
||||
if(path[i] != DIRSEP) { path[++i] = DIRSEP; i++; }
|
||||
strcpy(path + i, "blocks.csv");
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[i] = 0; fclose(f); }
|
||||
else { free(path); path = NULL; }
|
||||
}
|
||||
#ifndef __WIN32__
|
||||
if(!memcmp(*env, "HOME=", 5))
|
||||
home = *env + 5;
|
||||
#endif
|
||||
}
|
||||
#ifndef __WIN32__
|
||||
/* in user's home */
|
||||
if(!path && home) {
|
||||
path = (char*)malloc(strlen(home)+256);
|
||||
if(!path) error(lang[ERR_MEM]);
|
||||
i = strlen(home)-1;
|
||||
memcpy(path, home, i + 1);
|
||||
if(path[i] != DIRSEP) { path[++i] = DIRSEP; i++; }
|
||||
/* Linux and BSDs */
|
||||
strcpy(path + i, ".config/mtsedit/blocks.csv");
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else {
|
||||
strcpy(path + i, "Library/Application Support/MTSEdit/blocks.csv");
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else { free(path); path = NULL; }
|
||||
}
|
||||
}
|
||||
/* system wide */
|
||||
if(!path) {
|
||||
path = (char*)malloc(26+256);
|
||||
if(!path) error(lang[ERR_MEM]);
|
||||
strcpy(path, "/usr/share/mtsedit/blocks.csv");
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else {
|
||||
strcpy(path, "/usr/local/share/mtsedit/blocks.csv");
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else { free(path); path = NULL; }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* same directory as the executable */
|
||||
if(!path) {
|
||||
path = (char*)malloc(strlen(argv[0])+256);
|
||||
if(!path) error(lang[ERR_MEM]);
|
||||
strcpy(path, argv[0]);
|
||||
home = strrchr(path, DIRSEP);
|
||||
if(home) home++; else { sprintf(path, ".%c", DIRSEP); home = path + 2; }
|
||||
sprintf(home, "data%cblocks.csv", DIRSEP);
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else {
|
||||
/* last resort, development repository or /opt/mtsedit/bin, data in parent directory */
|
||||
sprintf(home, "..%cdata%cblocks.csv", DIRSEP, DIRSEP);
|
||||
f = fopen(path, "r");
|
||||
if(f) { path[strlen(path)-10] = 0; fclose(f); }
|
||||
else { free(path); path = NULL; }
|
||||
}
|
||||
}
|
||||
if(!path) error(lang[ERR_DATADIR]);
|
||||
fn = path + strlen(path);
|
||||
if(argc < 2) {
|
||||
printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license\r\n\r\n"
|
||||
"./mtsedit [-d|-p|-P|-g] [-m map] <.mts|.schematic> [out.mts]\r\n\r\n -d: %s\r\n -p: %s\r\n -P: %s\r\n"
|
||||
|
@ -294,7 +208,7 @@ int main(int argc, char** argv, char** envp)
|
|||
if(argv[i+1] && !opt) opt = 5;
|
||||
if(opt && opt != 4) {
|
||||
parseblocks();
|
||||
mts_load(mtsfile);
|
||||
readschem();
|
||||
if(newmap) {
|
||||
j = atoi(newmap);
|
||||
if(j) savepal = j - 1;
|
||||
|
@ -312,7 +226,7 @@ int main(int argc, char** argv, char** envp)
|
|||
case 1: ret = mts_dump(); break;
|
||||
case 2:
|
||||
case 3: ret = mts_view(opt-2); break;
|
||||
case 4: ret = mts_stairgen(); break;
|
||||
case 4: ret = stairgen(); break;
|
||||
case 5: break;
|
||||
default:
|
||||
/* start the main user interface */
|
||||
|
|
34
src/main.h
34
src/main.h
|
@ -99,7 +99,7 @@ typedef struct {
|
|||
|
||||
extern int numpalettes, lenpalettes, palette[16], strmaxw, savelen, savepos, savepal, savebiome, numresults, *results;
|
||||
extern int currlayer, gndlayer, mts_x, mts_y, mts_z, min_x, min_y, min_z, dx, dz, cx, cz, ox, oy, up;
|
||||
extern int shift, ctrl, activeblock;
|
||||
extern int shift, ctrl, activeblock, quitting, x0, x1, y0, y1;
|
||||
extern char **palettes, layerprob[256];
|
||||
extern int numblocks;
|
||||
extern mtsblock_t *blocks;
|
||||
|
@ -131,37 +131,57 @@ extern unsigned char *tmpblk;
|
|||
extern SDL_Window *window;
|
||||
extern SDL_Surface *screen, *icons, *blk, *fg, *bg, *cursor;
|
||||
|
||||
/* util.c */
|
||||
unsigned char *readfile(char *file, unsigned int *size);
|
||||
void readschem();
|
||||
void error(char *msg);
|
||||
void errorcsv(int line);
|
||||
unsigned char ahtoi(char *s);
|
||||
void detcube(int w, int h, unsigned char *block);
|
||||
int stairgen();
|
||||
|
||||
void mts_load();
|
||||
/* blocks.c */
|
||||
void getblocksdir(char **argv, char **envp);
|
||||
void parseblocks();
|
||||
void freeblocks();
|
||||
|
||||
/* schem.c */
|
||||
void schem_load(unsigned char *data, unsigned int size);
|
||||
|
||||
/* mts.c */
|
||||
void mts_load(unsigned char *data, unsigned int size);
|
||||
int mts_save();
|
||||
int mts_view(int type);
|
||||
int mts_dump();
|
||||
void mts_layerprob(int diff);
|
||||
void mts_rotate(int ccw);
|
||||
int mts_stairgen();
|
||||
|
||||
void parseblocks();
|
||||
void freeblocks();
|
||||
|
||||
/* sdl.c */
|
||||
void sdlprint(int x, int y, int fg, int bg, char *s);
|
||||
void sdldosave();
|
||||
void sdlredraw();
|
||||
void sdldosave();
|
||||
void sdldoload();
|
||||
void sdldopreview();
|
||||
void sdldorotate(int ccw);
|
||||
void sdlmain();
|
||||
|
||||
/* edit.c */
|
||||
void edit_redraw();
|
||||
void edit_hidecursor();
|
||||
void edit_showcursor(int painting);
|
||||
void edit_scroll(SDL_Event *event);
|
||||
void edit_mouseover(SDL_Event *event);
|
||||
void edit_mousedown(_unused SDL_Event *event);
|
||||
void edit_key(SDL_Event *event);
|
||||
void edit_rotate(int y, int z, int x, int ccw);
|
||||
|
||||
/* save.c */
|
||||
void save_redraw();
|
||||
void save_scroll(SDL_Event *event);
|
||||
void save_mousedown(SDL_Event *event);
|
||||
void save_key(SDL_Event *event);
|
||||
|
||||
/* search.c */
|
||||
void search_redraw();
|
||||
void search_scroll(SDL_Event *event);
|
||||
void search_mousedown(SDL_Event *event);
|
||||
|
|
570
src/mts.c
570
src/mts.c
|
@ -43,194 +43,132 @@ int currlayer = 127, gndlayer = 0;
|
|||
char layerprob[256];
|
||||
node_t nodes[256][256][256];
|
||||
|
||||
/**
|
||||
* Load a Minecraft NBT Schematic file
|
||||
*/
|
||||
#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, x, y, z, min_x = 0, min_y = 0, min_z = 0;
|
||||
unsigned char *d, *end = data + size;
|
||||
/* generated properties */
|
||||
int mix = 255, max = 0, miy = 255, may = 0, miz = 255, maz = 0;
|
||||
|
||||
/* we don't care about that overcomplicated NBT mess */
|
||||
mts_y = mts_z = mts_x = 0;
|
||||
for(d = data; d < end && (!mts_y || !mts_z || !mts_x); 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--; }
|
||||
}
|
||||
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;
|
||||
min_x = 127 - mts_x / 2;
|
||||
min_y = 127 - mts_y / 2;
|
||||
min_z = 127 - mts_z / 2;
|
||||
/* now that we know the dimensions, find the blocks data */
|
||||
for(d = data; d < end; d++) {
|
||||
if(!memcmp(d, "\007\000\006Blocks", 9)) {
|
||||
d += 9;
|
||||
SCHEM_GETINT(i, 3);
|
||||
if(i != mts_y * mts_z * mts_x) return;
|
||||
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;
|
||||
nodes[y+min_y][z+min_z][x+min_x].param1 = 127;
|
||||
for(i = 1, k = 0; i < numblocks; i++)
|
||||
for(j = 0; j < 8; j++)
|
||||
if(blocks[i].blockids[j] == *d) { k = i; i = numblocks; break; }
|
||||
if(k) {
|
||||
nodes[y+min_y][z+min_z][x+min_x].param0 = k;
|
||||
blocks[k].numref++;
|
||||
} else
|
||||
fprintf(stderr, "mtsedit: %s: %s %d\r\n", mtsfile, lang[ERR_NODE], *d);
|
||||
/**
|
||||
* Get schematic bounding cube and node id translation tables
|
||||
*/
|
||||
int mts_getbounds(int sanitize, unsigned short *tr, unsigned short *tr2)
|
||||
{
|
||||
int x, y, z, j, k;
|
||||
|
||||
/* get boundind box and block ID translation tables, sanitize probability values */
|
||||
j = 1; mix = 255; max = 0; miy = 255; may = 0; miz = 255; maz = 0;
|
||||
for(y = 0; y < 256; y++) {
|
||||
for(z = k = 0; z < 256; z++)
|
||||
for(x = 0; x < 256; x++) {
|
||||
if(nodes[y][z][x].param0) {
|
||||
if(tr && tr2 && !tr2[nodes[y][z][x].param0]) {
|
||||
tr2[nodes[y][z][x].param0] = j;
|
||||
tr[j++] = nodes[y][z][x].param0;
|
||||
}
|
||||
status = lang[LOADED];
|
||||
break;
|
||||
}
|
||||
if(x < mix) mix = x;
|
||||
if(x > max) max = x;
|
||||
if(y < miy) miy = y;
|
||||
if(y > may) may = y;
|
||||
if(z < miz) miz = z;
|
||||
if(z > maz) maz = z;
|
||||
if(sanitize) {
|
||||
if(!nodes[y][z][x].param1) nodes[y][z][x].param1 = 127;
|
||||
if(!layerprob[y]) layerprob[y] = 127;
|
||||
k = 1;
|
||||
}
|
||||
} else if(sanitize)
|
||||
nodes[y][z][x].param1 = 0;
|
||||
}
|
||||
if(sanitize && !k) layerprob[y] = 0;
|
||||
}
|
||||
return j;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load an MTS file
|
||||
*/
|
||||
void mts_load()
|
||||
void mts_load(unsigned char *data, unsigned int size)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned char *data = NULL, *buff = NULL, *un = NULL, *b;
|
||||
unsigned int size = 0, idx;
|
||||
unsigned char *buff = NULL, *un = NULL, *b;
|
||||
unsigned int idx;
|
||||
int i, j, k, l, n, x, y, z, min_x = 0, min_y = 0, min_z = 0;
|
||||
unsigned short *tr;
|
||||
unsigned short *tr = NULL;
|
||||
|
||||
status = lang[ERR_LOAD];
|
||||
mts_x = mts_y = mts_z = 0; currlayer = 127;
|
||||
memset(layerprob, 127, sizeof(layerprob));
|
||||
memset(nodes, 0, sizeof(nodes));
|
||||
for(i = 0; i < numblocks; i++) {
|
||||
blocks[i].dobiome = 0;
|
||||
blocks[i].numref = 0;
|
||||
}
|
||||
blocks[0].numref = 256 * 256 * 256;
|
||||
savepal = savebiome = 0;
|
||||
|
||||
f = fopen(mtsfile, "rb");
|
||||
if(f) {
|
||||
fseek(f, 0L, SEEK_END);
|
||||
size = (unsigned int)ftell(f);
|
||||
fseek(f, 0L, SEEK_SET);
|
||||
data = (unsigned char*)malloc(size);
|
||||
if(!data) error(lang[ERR_MEM]);
|
||||
fread(data, size, 1, f);
|
||||
fclose(f);
|
||||
status = lang[ERR_BADFILE];
|
||||
/* if it's an MTS file */
|
||||
if(!memcmp(data, "MTSM", 4)) {
|
||||
if(!data[4] && (data[5] == 3 || data[5] == 4) && !data[6] && data[7] && !data[8] && data[9] &&
|
||||
!data[10] && data[11]) {
|
||||
mts_x = data[7]; mts_y = data[9]; mts_z = data[11];
|
||||
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;
|
||||
buff = data + 12;
|
||||
if(data[5] == 4) {
|
||||
memcpy(layerprob + min_y, buff, mts_y);
|
||||
buff += mts_y;
|
||||
}
|
||||
n = (buff[0] << 8) | buff[1];
|
||||
if(n > 0 && n < 1024) {
|
||||
buff += 2;
|
||||
tr = (unsigned short*)malloc(n * sizeof(unsigned short));
|
||||
if(!tr) error(lang[ERR_MEM]);
|
||||
for(i = 0; i < n; i++) {
|
||||
tr[i] = numblocks;
|
||||
j = buff[1];
|
||||
buff += 2;
|
||||
for(k = 0; k < numblocks; k++)
|
||||
for(l = 0; l < numpalettes + 1; l++)
|
||||
if((!blocks[k].blocknames && l && (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(!l && k) { blocks[k].dobiome = 1; savebiome = 1; }
|
||||
if(l && l - 1 > savepal) savepal = l - 1;
|
||||
tr[i] = k;
|
||||
break;
|
||||
}
|
||||
if(tr[i] == numblocks) {
|
||||
x = buff[j]; buff[j] = 0;
|
||||
fprintf(stderr, "mtsedit: %s: %s %d '%s'\r\n", mtsfile, lang[ERR_NODE], i, buff);
|
||||
buff[j] = x;
|
||||
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, buff, j);
|
||||
blocks[idx].name[j] = 0;
|
||||
}
|
||||
buff += j;
|
||||
}
|
||||
size -= (int)(buff - data);
|
||||
un = (uint8_t*)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)buff, size, 4096, &i, 1);
|
||||
if(un) { buff = un; size = (unsigned int)i; }
|
||||
if(4 * mts_x * mts_y * mts_z <= (int)size) {
|
||||
for(z = 0, b = buff; z < mts_z; z++)
|
||||
for(y = 0; y < mts_y; y++)
|
||||
for(x = 0; x < mts_x; x++, b += 2) {
|
||||
nodes[y+min_y][z+min_z][x+min_x].param0 = tr[(b[0] << 8) | b[1]];
|
||||
blocks[nodes[y+min_y][z+min_z][x+min_x].param0].numref++;
|
||||
}
|
||||
for(z = 0; z < mts_z; z++)
|
||||
for(y = 0; y < mts_y; y++)
|
||||
for(x = 0; x < mts_x; x++, b++)
|
||||
nodes[y+min_y][z+min_z][x+min_x].param1 = data[5] == 3 ? b[0] >> 1 : b[0];
|
||||
for(z = 0; z < mts_z; z++)
|
||||
for(y = 0; y < mts_y; y++)
|
||||
for(x = 0; x < mts_x; x++, b++)
|
||||
nodes[y+min_y][z+min_z][x+min_x].param2 = b[0];
|
||||
gndlayer = currlayer = min_y;
|
||||
for(y = 0; y < mts_y; y++)
|
||||
for(z = 0; z < mts_z; z++)
|
||||
for(x = 0; x < mts_x; x++)
|
||||
if(nodes[y+min_y][z+min_z][x+min_x].param2 == 0x20) {
|
||||
gndlayer = currlayer = y+min_y;
|
||||
nodes[y+min_y][z+min_z][x+min_x].param2 = 0;
|
||||
}
|
||||
status = lang[LOADED];
|
||||
} else mts_x = mts_y = mts_z = 0;
|
||||
free(tr);
|
||||
if(un) free(un);
|
||||
} else mts_x = mts_y = mts_z = 0;
|
||||
buff = NULL;
|
||||
}
|
||||
} else {
|
||||
/* Could be a Minecraft NBT */
|
||||
if(data[0] == 0x1f && data[1] == 0x8b) {
|
||||
/* skip over gzip header */
|
||||
buff = data + 3;
|
||||
i = *buff++; buff += 6;
|
||||
if(i & 4) { j = *buff++; j += (*buff++ << 8); buff += j; }
|
||||
if(i & 8) { while(*buff++ != 0); }
|
||||
if(i & 16) { while(*buff++ != 0); }
|
||||
if(i & 2) buff += 2;
|
||||
size -= (int)(buff - data);
|
||||
} else buff = data;
|
||||
buff = (uint8_t*)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)buff, size, 4096, &i, 0);
|
||||
if(buff) { free(data); data = buff; buff = NULL; size = (unsigned int)i; }
|
||||
if(!memcmp(data + 3, "Schematic", 9)) schem_load(data, size);
|
||||
if(!data[4] && (data[5] == 3 || data[5] == 4) && !data[6] && data[7] && !data[8] && data[9] && !data[10] && data[11]) {
|
||||
mts_x = data[7]; mts_y = data[9]; mts_z = data[11];
|
||||
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;
|
||||
buff = data + 12;
|
||||
if(data[5] == 4) {
|
||||
memcpy(layerprob + min_y, buff, mts_y);
|
||||
buff += mts_y;
|
||||
}
|
||||
if(!mts_y || !mts_y || !mts_x)
|
||||
fprintf(stderr, "mtsedit: %s: %s\r\n", mtsfile, lang[ERR_LOAD]);
|
||||
/* make sure that all non-air blocks have their probability set */
|
||||
for(y = 0; y < mts_y; y++)
|
||||
for(z = 0; z < mts_z; z++)
|
||||
for(x = 0; x < mts_x; x++, b++)
|
||||
if(nodes[y+min_y][z+min_z][x+min_x].param0 && !nodes[y+min_y][z+min_z][x+min_x].param1)
|
||||
nodes[y+min_y][z+min_z][x+min_x].param1 = 127;
|
||||
n = (buff[0] << 8) | buff[1];
|
||||
if(n > 0 && n < 1024) {
|
||||
buff += 2;
|
||||
tr = (unsigned short*)malloc(n * sizeof(unsigned short));
|
||||
if(!tr) error(lang[ERR_MEM]);
|
||||
for(i = 0; i < n; i++) {
|
||||
tr[i] = numblocks;
|
||||
j = buff[1];
|
||||
buff += 2;
|
||||
for(k = 0; k < numblocks; k++)
|
||||
for(l = 0; l < numpalettes + 1; l++)
|
||||
if((!blocks[k].blocknames && l && (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(!l && k) { blocks[k].dobiome = 1; savebiome = 1; }
|
||||
if(l && l - 1 > savepal) savepal = l - 1;
|
||||
tr[i] = k;
|
||||
break;
|
||||
}
|
||||
if(tr[i] == numblocks) {
|
||||
x = buff[j]; buff[j] = 0;
|
||||
fprintf(stderr, "mtsedit: %s: %s %d '%s'\r\n", mtsfile, lang[ERR_NODE], i, buff);
|
||||
buff[j] = x;
|
||||
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, buff, j);
|
||||
blocks[idx].name[j] = 0;
|
||||
}
|
||||
buff += j;
|
||||
}
|
||||
size -= (int)(buff - data);
|
||||
un = (uint8_t*)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)buff, size, 4096, &i, 1);
|
||||
if(un) { buff = un; size = (unsigned int)i; }
|
||||
if(4 * mts_x * mts_y * mts_z <= (int)size) {
|
||||
for(z = 0, b = buff; z < mts_z; z++)
|
||||
for(y = 0; y < mts_y; y++)
|
||||
for(x = 0; x < mts_x; x++, b += 2) {
|
||||
nodes[y+min_y][z+min_z][x+min_x].param0 = tr[(b[0] << 8) | b[1]];
|
||||
blocks[nodes[y+min_y][z+min_z][x+min_x].param0].numref++;
|
||||
}
|
||||
for(z = 0; z < mts_z; z++)
|
||||
for(y = 0; y < mts_y; y++)
|
||||
for(x = 0; x < mts_x; x++, b++)
|
||||
nodes[y+min_y][z+min_z][x+min_x].param1 = data[5] == 3 ? b[0] >> 1 : b[0];
|
||||
for(z = 0; z < mts_z; z++)
|
||||
for(y = 0; y < mts_y; y++)
|
||||
for(x = 0; x < mts_x; x++, b++)
|
||||
nodes[y+min_y][z+min_z][x+min_x].param2 = b[0];
|
||||
gndlayer = currlayer = min_y;
|
||||
for(y = 0; y < mts_y; y++)
|
||||
for(z = 0; z < mts_z; z++)
|
||||
for(x = 0; x < mts_x; x++)
|
||||
if(nodes[y+min_y][z+min_z][x+min_x].param2 == 0x20) {
|
||||
gndlayer = currlayer = y+min_y;
|
||||
nodes[y+min_y][z+min_z][x+min_x].param2 = 0;
|
||||
}
|
||||
status = lang[LOADED];
|
||||
} else mts_x = mts_y = mts_z = 0;
|
||||
free(tr);
|
||||
if(un) free(un);
|
||||
} else mts_x = mts_y = mts_z = 0;
|
||||
}
|
||||
if(data) free(data);
|
||||
if(buff) free(buff);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,7 +179,7 @@ int mts_save()
|
|||
char outfile[MAXPATHLEN], *c;
|
||||
unsigned short *tr, *tr2;
|
||||
unsigned char *b, *b2, hdr[12];
|
||||
int i, j, k, x, y, z, mix = 255, max = 0, miy = 255, may = 0, miz = 255, maz = 0;
|
||||
int i, j, k, x, y, z;
|
||||
FILE *f;
|
||||
|
||||
status = lang[ERR_SAVE];
|
||||
|
@ -251,30 +189,8 @@ int mts_save()
|
|||
tr2 = (unsigned short*)malloc(numblocks * sizeof(unsigned short));
|
||||
if(!tr2) error(lang[ERR_MEM]);
|
||||
memset(tr2, 0, numblocks * sizeof(unsigned short));
|
||||
/* get boundind box and block ID translation tables, sanitize probability values */
|
||||
j = 1;
|
||||
for(y = 0; y < 256; y++) {
|
||||
for(z = k = 0; z < 256; z++)
|
||||
for(x = 0; x < 256; x++) {
|
||||
if(nodes[y][z][x].param0) {
|
||||
if(!tr2[nodes[y][z][x].param0]) {
|
||||
tr2[nodes[y][z][x].param0] = j;
|
||||
tr[j++] = nodes[y][z][x].param0;
|
||||
}
|
||||
if(x < mix) mix = x;
|
||||
if(x > max) max = x;
|
||||
if(y < miy) miy = y;
|
||||
if(y > may) may = y;
|
||||
if(z < miz) miz = z;
|
||||
if(z > maz) maz = z;
|
||||
if(!nodes[y][z][x].param1) nodes[y][z][x].param1 = 127;
|
||||
if(!layerprob[y]) layerprob[y] = 127;
|
||||
k = 1;
|
||||
} else
|
||||
nodes[y][z][x].param1 = 0;
|
||||
}
|
||||
if(!k) layerprob[y] = 0;
|
||||
}
|
||||
|
||||
j = mts_getbounds(1, tr, tr2);
|
||||
if(mix > max) { free(tr); free(tr2); return 1; }
|
||||
|
||||
for(y = miy; y <= may; y++) {
|
||||
|
@ -386,7 +302,7 @@ int mts_save()
|
|||
*/
|
||||
int mts_view(int type)
|
||||
{
|
||||
int i, j, w, h, x, y, z, mix = 255, max = 0, miy = 255, may = 0, miz = 255, maz = 0, lh = 0;
|
||||
int i, j, w, h, x, y, z, lh = 0;
|
||||
int r = 0, k, n;
|
||||
char pngfile[MAXPATHLEN], *c;
|
||||
unsigned char *buff = NULL;
|
||||
|
@ -395,19 +311,10 @@ int mts_view(int type)
|
|||
FILE *f;
|
||||
|
||||
status = lang[ERR_PREVIEW];
|
||||
for(y = 0; y < 256; y++)
|
||||
for(z = 0; z < 256; z++)
|
||||
for(x = 0; x < 256; x++) {
|
||||
if(nodes[y][z][x].param0) {
|
||||
if(x < mix) mix = x;
|
||||
if(x > max) max = x;
|
||||
if(y < miy) miy = y;
|
||||
if(y > may) may = y;
|
||||
if(z < miz) miz = z;
|
||||
if(z > maz) maz = z;
|
||||
}
|
||||
}
|
||||
mts_getbounds(0, NULL, NULL);
|
||||
if(mix > max) return 1;
|
||||
|
||||
/* calculate dimensions and create images */
|
||||
n = (max - mix) + (maz - miz) + 1;
|
||||
w = n * dx + 16;
|
||||
lh = n * dz + 32 - dz;
|
||||
|
@ -416,6 +323,8 @@ int mts_view(int type)
|
|||
preview = SDL_CreateRGBSurface(0, w, h, 32, 0xFF, 0xFF00, 0xFF0000, 0xFF000000);
|
||||
src.x = src.y = 0; src.w = src.h = dst.w = dst.h = 32;
|
||||
n = ((max-mix)+(maz-miz))/2;
|
||||
|
||||
/* generate preview into surface */
|
||||
for(y = miy; y <= may; y++)
|
||||
for(z = miz; z <= maz; z++) {
|
||||
if(type) r = ((z-miz+1)*(max-mix+1)*(y-miy)/(maz-miz+1))/(may-miy);
|
||||
|
@ -443,6 +352,8 @@ int mts_view(int type)
|
|||
}
|
||||
}
|
||||
SDL_FreeSurface(blk);
|
||||
|
||||
/* crop the result */
|
||||
buff = preview->pixels;
|
||||
for(i = miy = 0; i < preview->pitch * h; i += 4)
|
||||
if(buff[i + 3]) { miy = i / preview->pitch; break; }
|
||||
|
@ -463,6 +374,7 @@ int mts_view(int type)
|
|||
SDL_BlitSurface(preview, &src, blk, &dst);
|
||||
SDL_FreeSurface(preview);
|
||||
|
||||
/* write result to PNG file */
|
||||
buff = (unsigned char *)stbi_write_png_to_mem(blk->pixels, blk->pitch, blk->w, blk->h, 4, &i);
|
||||
SDL_FreeSurface(blk);
|
||||
if(buff) {
|
||||
|
@ -499,22 +411,12 @@ void mts_layerprob(int diff)
|
|||
*/
|
||||
void mts_rotate(int ccw)
|
||||
{
|
||||
int nx, nz, x, y, z, mix = 255, max = 0, miy = 255, may = 0, miz = 255, maz = 0;
|
||||
int nx, nz, x, y, z;
|
||||
node_t layer[256][256];
|
||||
|
||||
for(y = 0; y < 256; y++)
|
||||
for(z = 0; z < 256; z++)
|
||||
for(x = 0; x < 256; x++) {
|
||||
if(nodes[y][z][x].param0 || nodes[y][z][x].param1) {
|
||||
if(x < mix) mix = x;
|
||||
if(x > max) max = x;
|
||||
if(y < miy) miy = y;
|
||||
if(y > may) may = y;
|
||||
if(z < miz) miz = z;
|
||||
if(z > maz) maz = z;
|
||||
}
|
||||
}
|
||||
mts_getbounds(0, NULL, NULL);
|
||||
if(mix > max) return;
|
||||
|
||||
for(y = miy; y <= may; y++) {
|
||||
memcpy(layer, nodes[y], sizeof(node_t)*256*256);
|
||||
memset(nodes[y], 0, sizeof(node_t)*256*256);
|
||||
|
@ -534,7 +436,7 @@ void mts_rotate(int ccw)
|
|||
int mts_dump()
|
||||
{
|
||||
unsigned short *tr, *tr2;
|
||||
int i, j, x, y, z, mix = 255, max = 0, miy = 255, may = 0, miz = 255, maz = 0;
|
||||
int i, j, x, y, z;
|
||||
|
||||
tr = (unsigned short*)malloc(numblocks * sizeof(unsigned short));
|
||||
if(!tr) error(lang[ERR_MEM]);
|
||||
|
@ -542,24 +444,10 @@ int mts_dump()
|
|||
tr2 = (unsigned short*)malloc(numblocks * sizeof(unsigned short));
|
||||
if(!tr2) error(lang[ERR_MEM]);
|
||||
memset(tr2, 0, numblocks * sizeof(unsigned short));
|
||||
j = 1;
|
||||
for(y = 0; y < 256; y++)
|
||||
for(z = 0; z < 256; z++)
|
||||
for(x = 0; x < 256; x++) {
|
||||
if(nodes[y][z][x].param0) {
|
||||
if(!tr2[nodes[y][z][x].param0]) {
|
||||
tr2[nodes[y][z][x].param0] = j;
|
||||
tr[j++] = nodes[y][z][x].param0;
|
||||
}
|
||||
if(x < mix) mix = x;
|
||||
if(x > max) max = x;
|
||||
if(y < miy) miy = y;
|
||||
if(y > may) may = y;
|
||||
if(z < miz) miz = z;
|
||||
if(z > maz) maz = z;
|
||||
}
|
||||
}
|
||||
|
||||
j = mts_getbounds(0, tr, tr2);
|
||||
if(mix > max) { free(tr); free(tr2); return 1; }
|
||||
|
||||
printf("-------------------------------- %s --------------------------------\r\n", mtsfile);
|
||||
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;
|
||||
|
@ -573,9 +461,9 @@ int mts_dump()
|
|||
if(j < 15) printf(" ");
|
||||
for(x = mix; x <= max; x++) {
|
||||
if(nodes[y][z][x].param0) {
|
||||
if(j < 15) printf("%x", tr2[nodes[y][z][x].param0]);
|
||||
if(j < 16) printf("%x", tr2[nodes[y][z][x].param0]);
|
||||
else printf(" %02x", tr2[nodes[y][z][x].param0]);
|
||||
} else printf(j < 15 ? "." : " ..");
|
||||
} else printf(j < 16 ? "." : " ..");
|
||||
}
|
||||
printf(" ");
|
||||
for(x = mix; x <= max; x++)
|
||||
|
@ -591,193 +479,3 @@ int mts_dump()
|
|||
free(tr2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate slab and stair pictures from block image
|
||||
*/
|
||||
int mts_stairgen()
|
||||
{
|
||||
FILE *f;
|
||||
stbi__context sc;
|
||||
stbi__result_info ri;
|
||||
int i, j, w, h, l, x0,x1,x2, y0,y1,y2,y3,y4;
|
||||
unsigned int size;
|
||||
unsigned char *d, *data, *block, *slab, *stair;
|
||||
char *c;
|
||||
|
||||
f = fopen(mtsfile, "rb");
|
||||
if(f) {
|
||||
fseek(f, 0L, SEEK_END);
|
||||
size = (unsigned int)ftell(f);
|
||||
fseek(f, 0L, SEEK_SET);
|
||||
data = (unsigned char*)malloc(size);
|
||||
if(!data) error(lang[ERR_MEM]);
|
||||
fread(data, size, 1, f);
|
||||
fclose(f);
|
||||
c = strrchr(mtsfile, '_');
|
||||
if(!c) c = strrchr(mtsfile, '.');
|
||||
if(!c) c = &mtsfile[strlen(mtsfile)];
|
||||
sc.read_from_callbacks = 0;
|
||||
sc.img_buffer = sc.img_buffer_original = data;
|
||||
sc.img_buffer_end = sc.img_buffer_original_end = data + size;
|
||||
ri.bits_per_channel = 8;
|
||||
block = (unsigned char*)stbi__png_load(&sc, &w, &h, &l, 0, &ri);
|
||||
free(data);
|
||||
if(!block) return 1;
|
||||
slab = (unsigned char *)malloc(w * h * 4);
|
||||
if(!slab) error(lang[ERR_MEM]);
|
||||
memset(slab, 0, w * h * 4);
|
||||
stair = (unsigned char *)malloc(w * h * 4);
|
||||
if(!stair) error(lang[ERR_MEM]);
|
||||
/* detect cube edges */
|
||||
for(d = block; d[3] < 128; d += 4);
|
||||
x1 = ((int)(d - block) % (w * 4)) / 4;
|
||||
y0 = (int)(d - block) / (w * 4);
|
||||
for(i = 0, d = block; i < w/2 && d[3] < 128; i++)
|
||||
for(j = 0, d = block + i*4; j < h/2 && d[3] < 128; j++, d += w*4);
|
||||
x0 = ((int)(d - block) % (w * 4)) / 4 - 1;
|
||||
y1 = (int)(d - block) / (w * 4);
|
||||
x2 = x1 + (x1 - x0) + 1;
|
||||
y2 = y1 + (y1 - y0);
|
||||
for(; d[3] > 128; d += w*4);
|
||||
d -= w*4;
|
||||
y3 = (int)(d - block) / (w * 4);
|
||||
y4 = y3 + (y1 - y0);
|
||||
#if DEBUG
|
||||
*((uint32_t*)(slab + y0*w*4 + x1*4)) = 0xFF0000FF;
|
||||
*((uint32_t*)(slab + y1*w*4 + x0*4)) = 0xFF0000FF;
|
||||
*((uint32_t*)(slab + y1*w*4 + x2*4)) = 0xFF00FF00;
|
||||
*((uint32_t*)(slab + y2*w*4 + x1*4)) = 0xFF00FF00;
|
||||
*((uint32_t*)(slab + y3*w*4 + x0*4)) = 0xFF0000FF;
|
||||
*((uint32_t*)(slab + y3*w*4 + x2*4)) = 0xFF00FF00;
|
||||
*((uint32_t*)(slab + y4*w*4 + x1*4)) = 0xFF00FF00;
|
||||
#endif
|
||||
|
||||
/* rotated block */
|
||||
for(i = x0; i <= x2+1; i++) {
|
||||
for(j = y0; j <= y4; j++)
|
||||
*((uint32_t*)(slab + j*w*4 + (x2 - i + x0 + (x0 & 1))*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
data = (unsigned char *)stbi_write_png_to_mem(slab, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_01.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
/* slab */
|
||||
memset(slab, 0, w * h * 4);
|
||||
for(i = x0; i <= x1; i++) {
|
||||
l = (y1 - y0) * (i - x0) / (x1 - x0);
|
||||
for(j = y0; j < y1 + (y3 - y1)/2 + l; j++)
|
||||
*((uint32_t*)(slab + (j+(y3 - y1)/2+1)*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
for(j = y3 + l; j < h; j++)
|
||||
*((uint32_t*)(slab + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(i = x1+1; i <= x2; i++) {
|
||||
l = (y1 - y0) * ((x2-i+1) - x1) / (x2 - x1);
|
||||
for(j = y0; j < y2 + (y3 - y1)/2 + l; j++)
|
||||
*((uint32_t*)(slab + (j+(y3 - y1)/2+1)*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
for(j = y4 + l; j < h; j++)
|
||||
*((uint32_t*)(slab + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
|
||||
data = (unsigned char *)stbi_write_png_to_mem(slab, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_Slab_00.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
/* rotated stairs */
|
||||
memcpy(stair, slab, w * h * 4);
|
||||
for(i = x0; i <= x1 + (x2 - x1)/2; i++) {
|
||||
l = (y1 - y0) * (i - x0) / (x1 - x0);
|
||||
for(j = y0 + l; j < y4; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(i = x1; i <= x2; i++) {
|
||||
l = (y1 - y0) * (i - x1) / (x1 - x0);
|
||||
for(j = y0 + l; j <= y0 + l + 1; j++)
|
||||
*((uint32_t*)(stair + (j+(y1-y0)/2)*w*4 + (i - (x1 - x0)/2)*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
data = (unsigned char *)stbi_write_png_to_mem(stair, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_Stair_00.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
memcpy(stair, slab, w * h * 4);
|
||||
for(i = x0 + (x1 - x0)/2; i <= x2; i++) {
|
||||
l = (y1 - y0) * ((x2-i+1) - x1) / (x2 - x1);
|
||||
for(j = y1 + l; j < y4; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(i = x0; i <= x1; i++) {
|
||||
l = (y1 - y0) * ((x1-i+1) - x1) / (x1 - x0);
|
||||
for(j = y1 + l; j <= y2 + l; j++)
|
||||
*((uint32_t*)(stair + (j+(y1-y0)/2)*w*4 + (i+(x1 - x0)/2)*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
data = (unsigned char *)stbi_write_png_to_mem(stair, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_Stair_01.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
memcpy(stair, slab, w * h * 4);
|
||||
for(i = x0 + (x1 - x0)/2; i <= x1 + (x2 - x1)/2; i++) {
|
||||
l = (y1 - y0) * (i - x0) / (x1 - x0);
|
||||
for(j = y0; j <= y0 + l; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(; i <= x2; i++) {
|
||||
for(j = y0; j <= y4; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(i = x0; i < x1; i++) {
|
||||
l = (y1 - y0) * (i - x0) / (x1 - x0);
|
||||
for(j = y1 + l - 1; j <= y1 + (y3 - y1)/2 + l; j++)
|
||||
*((uint32_t*)(stair + (j-(y1-y0)/2)*w*4 + (i + (x1 - x0)/2)*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
data = (unsigned char *)stbi_write_png_to_mem(stair, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_Stair_02.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
memcpy(stair, slab, w * h * 4);
|
||||
for(i = x0; i <= x0 + (x1 - x0)/2 +1; i++) {
|
||||
for(j = y0; j <= y4; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(; i <= x2; i++) {
|
||||
l = (y1 - y0) * (i - (x0 + (x1 - x0)/2)) / (x2 - x1);
|
||||
for(j = y0; j <= y1 + (y2 - y1)/2 - l; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(i = x1+1; i <= x2; i++) {
|
||||
l = (y1 - y0) * ((x2-i+1) - x1) / (x2 - x1);
|
||||
for(j = y2 + l - 1; j <= y2 + (y3 - y1)/2 + l; j++)
|
||||
*((uint32_t*)(stair + (j-(y1-y0)/2)*w*4 + (i-(x1-x0)/2)*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
data = (unsigned char *)stbi_write_png_to_mem(stair, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_Stair_03.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
fprintf(stderr, "mtsedit: %s\r\n", lang[IMGSGEN]);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* mtsedit/schem.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 a Minecraft NBT .schematic file
|
||||
*
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
|
||||
/* parse an integer, the only type we are interested */
|
||||
#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)
|
||||
|
||||
/**
|
||||
* Load a Minecraft NBT Schematic file
|
||||
*/
|
||||
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, *end = data + size;
|
||||
|
||||
/* we don't care about that overcomplicated NBT mess */
|
||||
mts_y = mts_z = mts_x = 0;
|
||||
for(d = data; d < end && (!mts_y || !mts_z || !mts_x); 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--; }
|
||||
}
|
||||
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;
|
||||
min_x = 127 - mts_x / 2;
|
||||
min_y = 127 - mts_y / 2;
|
||||
min_z = 127 - mts_z / 2;
|
||||
/* 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;
|
||||
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;
|
||||
nodes[y+min_y][z+min_z][x+min_x].param1 = 127;
|
||||
for(i = 1, k = 0; i < numblocks; i++)
|
||||
for(j = 0; j < 8; j++)
|
||||
if(blocks[i].blockids[j] == *d) { k = i; i = numblocks; break; }
|
||||
if(k) {
|
||||
nodes[y+min_y][z+min_z][x+min_x].param0 = k;
|
||||
blocks[k].numref++;
|
||||
} else
|
||||
fprintf(stderr, "mtsedit: %s: %s %d\r\n", mtsfile, lang[ERR_NODE], *d);
|
||||
}
|
||||
status = lang[LOADED];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
155
src/sdl.c
155
src/sdl.c
|
@ -154,9 +154,11 @@ void sdlredraw()
|
|||
strmaxw = screen->w;
|
||||
rect.x = 36; rect.y = 0; rect.w = screen->w - 36; rect.h = screen->h - font->height;
|
||||
SDL_FillRect(screen, &rect, theme[activetool == 1 || activetool == 4 ? THEME_BG : THEME_TABBG]);
|
||||
if(activetool == 1) save_redraw(); else
|
||||
if(activetool == 4) search_redraw(); else
|
||||
edit_redraw();
|
||||
switch(activetool) {
|
||||
case 1: save_redraw(); break;
|
||||
case 4: search_redraw(); break;
|
||||
default: if(dx && dz) edit_redraw(); break;
|
||||
}
|
||||
|
||||
/* toolbar and status bar */
|
||||
sdltoolbar();
|
||||
|
@ -167,7 +169,8 @@ void sdlredraw()
|
|||
/**
|
||||
* UI for saving
|
||||
*/
|
||||
void sdldosave() {
|
||||
void sdldosave()
|
||||
{
|
||||
SDL_SetCursor(working);
|
||||
mts_save();
|
||||
SDL_SetCursor(pointer);
|
||||
|
@ -178,9 +181,10 @@ void sdldosave() {
|
|||
/**
|
||||
* UI for loading
|
||||
*/
|
||||
void sdldoload() {
|
||||
void sdldoload()
|
||||
{
|
||||
SDL_SetCursor(working);
|
||||
mts_load();
|
||||
readschem();
|
||||
SDL_SetCursor(pointer);
|
||||
activetool = -1; activeblock = 0;
|
||||
sdlredraw();
|
||||
|
@ -189,7 +193,8 @@ void sdldoload() {
|
|||
/**
|
||||
* UI for preview
|
||||
*/
|
||||
void sdldopreview() {
|
||||
void sdldopreview()
|
||||
{
|
||||
SDL_SetCursor(working);
|
||||
mts_view(shift);
|
||||
SDL_SetCursor(pointer);
|
||||
|
@ -199,7 +204,8 @@ void sdldopreview() {
|
|||
/**
|
||||
* UI for rotating
|
||||
*/
|
||||
void sdldorotate(int ccw) {
|
||||
void sdldorotate(int ccw)
|
||||
{
|
||||
int i;
|
||||
|
||||
SDL_SetCursor(working);
|
||||
|
@ -217,7 +223,7 @@ void sdlmain()
|
|||
stbi__context s;
|
||||
stbi__result_info ri;
|
||||
unsigned char *icondata;
|
||||
char *fn, *title, str[32];
|
||||
char *fn, *title;
|
||||
int iw = 0, ih = 0, len, i, j, k;
|
||||
SDL_Event event;
|
||||
SDL_Rect dst;
|
||||
|
@ -263,8 +269,8 @@ void sdlmain()
|
|||
|
||||
/* parse blocks.csv */
|
||||
parseblocks();
|
||||
/* load MTS */
|
||||
mts_load(mtsfile);
|
||||
/* load schematics from file */
|
||||
readschem();
|
||||
|
||||
/* populate search window with default results (may include unknown blocks from the MTS) */
|
||||
numresults = numblocks - 1;
|
||||
|
@ -322,19 +328,13 @@ void sdlmain()
|
|||
/* toolbar */
|
||||
if(event.motion.y < 4 + 5 * 36) {
|
||||
i = (event.motion.y > 3 ? event.motion.y - 4 : event.motion.y) / 36;
|
||||
} else if(event.motion.y >= (int)(screen->h - font->height)) {
|
||||
i = -3;
|
||||
} else if(event.motion.y >= (int)(screen->h - 2*font->height)) {
|
||||
i = -4;
|
||||
} else if(event.motion.y >= (int)(screen->h - 3*font->height)) {
|
||||
i = -2;
|
||||
} else if(event.motion.y >= (int)(screen->h - 3*font->height - 36)) {
|
||||
i = 6;
|
||||
} else if(event.motion.y >= (int)(screen->h - 3*font->height - 2*36)) {
|
||||
i = 5;
|
||||
} else if(event.motion.y < (int)(screen->h - 3*font->height - 2*36)) {
|
||||
j = (event.motion.y - (4 + 5 * 36)) / 32;
|
||||
}
|
||||
} else
|
||||
if(event.motion.y >= (int)(screen->h - font->height)) i = -3; else
|
||||
if(event.motion.y >= (int)(screen->h - 2*font->height)) i = -4; else
|
||||
if(event.motion.y >= (int)(screen->h - 3*font->height)) i = -2; else
|
||||
if(event.motion.y >= (int)(screen->h - 3*font->height - 36)) i = 6; else
|
||||
if(event.motion.y >= (int)(screen->h - 3*font->height - 2*36)) i = 5; else
|
||||
if(event.motion.y < (int)(screen->h - 3*font->height - 2*36)) j = (event.motion.y - (4 + 5 * 36)) / 32;
|
||||
} else
|
||||
if(activetool == 4) search_mouseover(&event); else
|
||||
if(activetool == -1) {
|
||||
|
@ -342,9 +342,7 @@ void sdlmain()
|
|||
status = NULL;
|
||||
dst.x = 36; dst.y = screen->h - font->height; dst.w = screen->w - 36; dst.h = font->height;
|
||||
SDL_FillRect(screen, &dst, theme[THEME_BG]);
|
||||
edit_hidecursor();
|
||||
edit_mouseover(&event);
|
||||
edit_showcursor(event.button.button == 1);
|
||||
sdltoolbar();
|
||||
SDL_UpdateWindowSurface(window);
|
||||
}
|
||||
|
@ -358,7 +356,7 @@ void sdlmain()
|
|||
case SDL_MOUSEBUTTONDOWN:
|
||||
if(activetool == -1 && overtool == -1 && event.motion.x > 36) edit_mousedown(&event); else
|
||||
if(overtool == -3) mts_layerprob(event.button.button == 1 ? +1 : -1); else
|
||||
if(overtool == -2) gndlayer = currlayer;
|
||||
if(overtool == -2) gndlayer = currlayer; else
|
||||
if(overtool >= 0 || overblock != -1) {
|
||||
if(overtool >= 0 && activetool != overtool) activetool = overtool;
|
||||
else { activetool = -1; if(overblock != -1) activeblock = overblock; }
|
||||
|
@ -370,20 +368,24 @@ void sdlmain()
|
|||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if(activetool != -1 && activetool == overtool) {
|
||||
if(activetool == 0) sdldoload();
|
||||
if(activetool == 2) sdldopreview();
|
||||
if(activetool == 3) sdldorotate(shift || event.button.button != 1 ? 0 : 1);
|
||||
if(activetool == 5 && currlayer < 255) currlayer++;
|
||||
if(activetool == 6 && currlayer > 0) currlayer--;
|
||||
if(activetool != 1 && activetool != 4) activetool = -1;
|
||||
switch(activetool) {
|
||||
case 0: sdldoload(); break;
|
||||
case 2: sdldopreview(); break;
|
||||
case 3: sdldorotate(shift || event.button.button != 1 ? 0 : 1); break;
|
||||
case 5: if(currlayer < 255) currlayer++; break;
|
||||
case 6: if(currlayer > 0) currlayer--; break;
|
||||
default: if(activetool != 1 && activetool != 4) activetool = -1; break;
|
||||
}
|
||||
}
|
||||
sdlredraw();
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
if(overtool == -3) mts_layerprob(event.wheel.y); else
|
||||
if(activetool == 1) save_scroll(&event); else
|
||||
if(activetool == 4) search_scroll(&event); else
|
||||
if(activetool == -1) edit_scroll(&event);
|
||||
switch(activetool) {
|
||||
case 1: save_scroll(&event); break;
|
||||
case 4: search_scroll(&event); break;
|
||||
case -1: edit_scroll(&event); break;
|
||||
}
|
||||
sdlredraw();
|
||||
break;
|
||||
|
||||
|
@ -396,85 +398,8 @@ void sdlmain()
|
|||
SDL_ShowCursor(0);
|
||||
systemcursor = 0;
|
||||
activetool = -1;
|
||||
} else if(activetool != 1 && activetool != 4) {
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_ESCAPE:
|
||||
case SDLK_q: quitting = 1; break;
|
||||
case SDLK_s: if(!shift) sdldosave(); break;
|
||||
case SDLK_l: sdldoload(); break;
|
||||
case SDLK_p: sdldopreview(); break;
|
||||
case SDLK_r: sdldorotate(1 - shift); break;
|
||||
case SDLK_g: gndlayer = currlayer; break;
|
||||
case SDLK_PLUS: case SDLK_EQUALS: mts_layerprob(+1); break;
|
||||
case SDLK_MINUS: mts_layerprob(-1); break;
|
||||
case SDLK_PAGEUP: if(currlayer < 255) currlayer++; break;
|
||||
case SDLK_PAGEDOWN: if(currlayer > 0) currlayer--; break;
|
||||
case SDLK_BACKQUOTE: case SDLK_0: activeblock = 0; break;
|
||||
case SDLK_1: case SDLK_2: case SDLK_3: case SDLK_4: case SDLK_5:
|
||||
case SDLK_6: case SDLK_7: case SDLK_8: case SDLK_9:
|
||||
if(palette[event.key.keysym.sym - SDLK_0])
|
||||
activeblock = event.key.keysym.sym - SDLK_0;
|
||||
break;
|
||||
case SDLK_h: dx--; sprintf(str, "dx %d dz %d", dx, dz); status = str; break;
|
||||
case SDLK_k: dx++; sprintf(str, "dx %d dz %d", dx, dz); status = str; break;
|
||||
case SDLK_u: dz--; sprintf(str, "dx %d dz %d", dx, dz); status = str; break;
|
||||
case SDLK_j: dz++; sprintf(str, "dx %d dz %d", dx, dz); status = str; break;
|
||||
case SDLK_UP:
|
||||
if(ctrl) {
|
||||
if(oy < 127) oy++;
|
||||
} else if(shift) {
|
||||
if(up > -128) up--;
|
||||
} else {
|
||||
if(cz > 0) cz--;
|
||||
status = nodes[currlayer][cz][cx].param0 ?
|
||||
blocks[nodes[currlayer][cz][cx].param0].name : NULL;
|
||||
}
|
||||
break;
|
||||
case SDLK_DOWN:
|
||||
if(ctrl) {
|
||||
if(oy > -128) oy--;
|
||||
} else if(shift) {
|
||||
if(up < 127) up++;
|
||||
} else {
|
||||
if(cz < 255) cz++;
|
||||
status = nodes[currlayer][cz][cx].param0 ?
|
||||
blocks[nodes[currlayer][cz][cx].param0].name : NULL;
|
||||
}
|
||||
break;
|
||||
case SDLK_LEFT:
|
||||
if(ctrl) {
|
||||
if(ox < 127) ox++;
|
||||
} else if(shift) {
|
||||
edit_rotate(currlayer, cz, cx, 1);
|
||||
} else {
|
||||
if(cx > 0) cx--;
|
||||
status = nodes[currlayer][cz][cx].param0 ?
|
||||
blocks[nodes[currlayer][cz][cx].param0].name : NULL;
|
||||
}
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
if(ctrl) {
|
||||
if(ox > -128) ox--;
|
||||
} else if(shift) {
|
||||
edit_rotate(currlayer, cz, cx, 0);
|
||||
} else {
|
||||
if(cx < 255) cx++;
|
||||
status = nodes[currlayer][cz][cx].param0 ?
|
||||
blocks[nodes[currlayer][cz][cx].param0].name : NULL;
|
||||
}
|
||||
break;
|
||||
case SDLK_BACKSPACE:
|
||||
case SDLK_DELETE:
|
||||
case SDLK_SPACE:
|
||||
blocks[nodes[currlayer][cz][cx].param0].numref--;
|
||||
i = event.key.keysym.sym == SDLK_SPACE && !shift ? palette[activeblock] : 0;
|
||||
blocks[i].numref++;
|
||||
nodes[currlayer][cz][cx].param0 = i;
|
||||
nodes[currlayer][cz][cx].param1 = i ? 127 : 0;
|
||||
status = i ? blocks[i].name : NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
if(activetool != 1 && activetool != 4) edit_key(&event);
|
||||
sdlredraw();
|
||||
break;
|
||||
case SDL_TEXTINPUT:
|
||||
|
|
446
src/util.c
446
src/util.c
|
@ -28,11 +28,9 @@
|
|||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include <dirent.h>
|
||||
|
||||
char *path = NULL, *fn = NULL;
|
||||
|
||||
int fncmp(const void *a, const void *b) { return strcmp(*((const char**)a), *((const char**)b)); }
|
||||
/* cube coordinates */
|
||||
int x0,x1,x2, y0,y1,y2,y3,y4;
|
||||
|
||||
/**
|
||||
* Read a file into memory from the data directory
|
||||
|
@ -61,6 +59,83 @@ unsigned char *readfile(char *file, unsigned int *size)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read schematics from file
|
||||
*/
|
||||
void readschem()
|
||||
{
|
||||
FILE *f;
|
||||
unsigned char *data = NULL, *buff = NULL;
|
||||
unsigned int size = 0;
|
||||
int x, y, z;
|
||||
|
||||
status = lang[ERR_LOAD];
|
||||
mts_x = mts_y = mts_z = 0; currlayer = 127;
|
||||
memset(layerprob, 127, sizeof(layerprob));
|
||||
memset(nodes, 0, sizeof(nodes));
|
||||
for(x = 0; x < numblocks; x++) {
|
||||
blocks[x].dobiome = 0;
|
||||
blocks[x].numref = 0;
|
||||
}
|
||||
blocks[0].numref = 256 * 256 * 256;
|
||||
savepal = savebiome = 0;
|
||||
currlayer = cx = cz = 127;
|
||||
|
||||
f = fopen(mtsfile, "rb");
|
||||
if(f) {
|
||||
fseek(f, 0L, SEEK_END);
|
||||
size = (unsigned int)ftell(f);
|
||||
fseek(f, 0L, SEEK_SET);
|
||||
data = (unsigned char*)malloc(size);
|
||||
if(!data) error(lang[ERR_MEM]);
|
||||
fread(data, size, 1, f);
|
||||
fclose(f);
|
||||
status = lang[ERR_BADFILE];
|
||||
|
||||
/* if it's gzip compressed, uncompress it first */
|
||||
if(data[0] == 0x1f && data[1] == 0x8b) {
|
||||
/* skip over gzip header */
|
||||
buff = data + 3;
|
||||
x = *buff++; buff += 6;
|
||||
if(x & 4) { y = *buff++; y += (*buff++ << 8); buff += y; }
|
||||
if(x & 8) { while(*buff++ != 0); }
|
||||
if(x & 16) { while(*buff++ != 0); }
|
||||
if(x & 2) buff += 2;
|
||||
size -= (int)(buff - data);
|
||||
buff = (uint8_t*)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)buff, size, 4096, &x, 0);
|
||||
if(buff) { free(data); data = buff; buff = NULL; size = (unsigned int)x; }
|
||||
} else buff = data;
|
||||
|
||||
/* if it's an MTS file */
|
||||
if(!memcmp(data, "MTSM", 4)) mts_load(data, size); else
|
||||
/* Could be a Minecraft NBT */
|
||||
if(!memcmp(data + 3, "Schematic", 9)) schem_load(data, size);
|
||||
|
||||
/* make sure that all non-air blocks have their probability set */
|
||||
if(!mts_y || !mts_y || !mts_x)
|
||||
fprintf(stderr, "mtsedit: %s: %s\r\n", mtsfile, lang[ERR_LOAD]);
|
||||
for(y = 0; y < 256; y++)
|
||||
for(z = 0; z < 256; z++)
|
||||
for(x = 0; x < 256; x++)
|
||||
if(nodes[y][z][x].param0 && !nodes[y][z][x].param1)
|
||||
nodes[y][z][x].param1 = 127;
|
||||
}
|
||||
if(data) free(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Common error handler
|
||||
*/
|
||||
void error(char *msg)
|
||||
{
|
||||
#ifdef __WIN32__
|
||||
MessageBox(NULL, msg, "MTSEdit", MB_ICONEXCLAMATION | MB_OK);
|
||||
#else
|
||||
fprintf(stderr, "mtsedit: %s\r\n", msg);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* CSV error
|
||||
*/
|
||||
|
@ -86,195 +161,202 @@ unsigned char ahtoi(char *s)
|
|||
}
|
||||
|
||||
/**
|
||||
* Parse the blocks.csv
|
||||
* Deetect cube edges
|
||||
*/
|
||||
void parseblocks()
|
||||
void detcube(int w, int h, unsigned char *block)
|
||||
{
|
||||
stbi__context sc;
|
||||
stbi__result_info ri;
|
||||
int w, h, l;
|
||||
unsigned int numfiles = 0, i, j, k;
|
||||
char **files = NULL, c, *s, *e;
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
unsigned int size;
|
||||
unsigned char *img;
|
||||
char *data = (char*)readfile("blocks.csv", &size);
|
||||
unsigned char *d;
|
||||
int i, j;
|
||||
|
||||
if(!data || !size) error(lang[ERR_CSV]);
|
||||
|
||||
/* get block images */
|
||||
*fn = 0;
|
||||
dir = opendir(path);
|
||||
if(dir) {
|
||||
while((de = readdir(dir))) {
|
||||
i = strlen(de->d_name);
|
||||
if(i > 8 && !strcmp(de->d_name + i - 4, ".png") && de->d_name[i-7] == '_') {
|
||||
j = numfiles++;
|
||||
files = (char**)realloc(files, numfiles * sizeof(char*));
|
||||
if(!files) error(lang[ERR_MEM]);
|
||||
files[j] = (char*)malloc(i + 1);
|
||||
if(!files[j]) error(lang[ERR_MEM]);
|
||||
memcpy(files[j], de->d_name, i + 1);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
qsort(files, numfiles, sizeof(char*), fncmp);
|
||||
|
||||
/* parse header */
|
||||
for(e = data, i = j = 0; *e && *e != '\r' && *e != '\n' && i < 3; e++) {
|
||||
if(*e == '\"') j ^= 1;
|
||||
if(!j && (*e == ',' || *e == ';' || *e == '\t')) i++;
|
||||
}
|
||||
if(i != 3 || !*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 = ',';
|
||||
for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++)
|
||||
if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; }
|
||||
while(*s <= ' ') s++;
|
||||
while(*(e-1) <= ' ') e--;
|
||||
j = numpalettes++;
|
||||
palettes = (char**)realloc(palettes, numpalettes * sizeof(char*));
|
||||
if(!palettes) error(lang[ERR_MEM]);
|
||||
palettes[j] = (char*)malloc(e - s + 1);
|
||||
if(!palettes[j]) error(lang[ERR_MEM]);
|
||||
memcpy(palettes[j], s, e - s + 1);
|
||||
palettes[j][e - s] = 0;
|
||||
if((int)(e - s) > lenpalettes) lenpalettes = e - s;
|
||||
while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++;
|
||||
}
|
||||
/* add Air as first block */
|
||||
numblocks++;
|
||||
blocks = (mtsblock_t*)realloc(blocks, numblocks * sizeof(mtsblock_t));
|
||||
if(!blocks) error(lang[ERR_MEM]);
|
||||
memset(&blocks[0], 0, sizeof(mtsblock_t));
|
||||
blocks[0].name = (char*)malloc(4);
|
||||
if(!blocks[0].name) error(lang[ERR_MEM]);
|
||||
memcpy(blocks[0].name, "Air", 4);
|
||||
blocks[0].blocknames = (char**)malloc((numpalettes + 1) * sizeof(char*));
|
||||
if(!blocks[0].blocknames) error(lang[ERR_MEM]);
|
||||
blocks[0].blocknames[0] = NULL;
|
||||
for(i = 1; i < (unsigned int)numpalettes + 1; i++) {
|
||||
blocks[0].blocknames[i] = (char*)malloc(4);
|
||||
if(!blocks[0].blocknames[i]) error(lang[ERR_MEM]);
|
||||
memcpy(blocks[0].blocknames[i], "air", 4);
|
||||
}
|
||||
|
||||
/* parse rows */
|
||||
while(*e) {
|
||||
if(*e == '\r' || *e == '\n') {
|
||||
while(*e == '\r' || *e == '\n') e++;
|
||||
if(!*e) break;
|
||||
/* get canonical name */
|
||||
if(*e == '\"') { e++; c = '\"'; } else c = ',';
|
||||
for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++)
|
||||
if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; }
|
||||
while(*s <= ' ') s++;
|
||||
while(*(e-1) <= ' ') e--;
|
||||
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(e - s + 1);
|
||||
if(!blocks[j].name) error(lang[ERR_MEM]);
|
||||
blocks[j].blocknames = (char**)malloc((numpalettes + 1) * sizeof(char*));
|
||||
if(!blocks[j].blocknames) error(lang[ERR_MEM]);
|
||||
memset(blocks[j].blocknames, 0, (numpalettes + 1) * sizeof(char*));
|
||||
for(i = 0; s + i < e; i++) {
|
||||
blocks[j].name[i] = s[i] == '_' ? ' ' : s[i];
|
||||
if(s[i] == ' ') s[i] = '_';
|
||||
}
|
||||
blocks[j].name[i] = 0;
|
||||
/* get block images and possible param2 values */
|
||||
for(i = 0, l = 0; i < numfiles; i++) {
|
||||
if((int)strlen(files[i]) == (int)(e - s + 7) && !memcmp(files[i], s, e - s)) {
|
||||
img = readfile(files[i], &size);
|
||||
if(img && size) {
|
||||
k = ahtoi(strrchr(files[i], '_') + 1) & 0x1F;
|
||||
sc.read_from_callbacks = 0;
|
||||
sc.img_buffer = sc.img_buffer_original = img;
|
||||
sc.img_buffer_end = sc.img_buffer_original_end = img + size;
|
||||
ri.bits_per_channel = 8;
|
||||
blocks[j].img[k] = (unsigned char*)stbi__png_load(&sc, &w, &h, &l, 0, &ri);
|
||||
if(blocks[j].img[k]) l++;
|
||||
free(img);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!l)
|
||||
fprintf(stderr, "mtsedit: blocks.csv(%d): %s '%s'\r\n", j+1, lang[ERR_IMG], blocks[j].name);
|
||||
while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++;
|
||||
while(*e == ' ') e++;
|
||||
if(*e != ',' && *e != ';' && *e != '\t') errorcsv(j+1);
|
||||
e++;
|
||||
while(*e == ' ') e++;
|
||||
/* get Block IDs */
|
||||
if(*e == '\"') { e++; c = '\"'; } else c = ',';
|
||||
for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++)
|
||||
if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; }
|
||||
while(*s <= ' ') s++;
|
||||
for(i = 0; s < e && i < 8;) {
|
||||
blocks[j].blockids[i] = atoi(s);
|
||||
if(blocks[j].blockids[i]) i++;
|
||||
while(*s >= '0' && *s <= '9') s++;
|
||||
if(*s == '/') s++;
|
||||
}
|
||||
while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++;
|
||||
k = 0;
|
||||
}
|
||||
/* get palette specific names */
|
||||
while(*e == ' ') e++;
|
||||
if(*e != ',' && *e != ';' && *e != '\t') errorcsv(j+1);
|
||||
e++;
|
||||
while(*e == ' ') e++;
|
||||
if(!*e) errorcsv(j+1);
|
||||
if(*e == '\"') { e++; c = '\"'; } else c = ',';
|
||||
for(s = e; *e && *e != '\r' && *e != '\n' && *e != c; e++)
|
||||
if(*e == '\\' || (*e == '\"' && e[1] == '\"')) { e++; continue; }
|
||||
while(*s <= ' ') s++;
|
||||
while(*(e-1) <= ' ') e--;
|
||||
if(e != s) {
|
||||
blocks[j].blocknames[k] = (char*)malloc(e - s + 1);
|
||||
if(!blocks[j].blocknames[k]) error(lang[ERR_MEM]);
|
||||
memcpy(blocks[j].blocknames[k], s, e - s + 1);
|
||||
blocks[j].blocknames[k][e - s] = 0;
|
||||
}
|
||||
k++; if(k > (unsigned int)numpalettes + 1) errorcsv(j+2);
|
||||
while(*e && *e != ',' && *e != ';' && *e != '\t' && *e != '\r' && *e != '\n') e++;
|
||||
}
|
||||
if(!numblocks || numblocks > 65535) error(lang[ERR_CSV]);
|
||||
|
||||
/* free temp resources */
|
||||
for(i = 0; i < numfiles; i++) free(files[i]);
|
||||
free(files);
|
||||
free(data);
|
||||
for(d = block; d[3] < 128; d += 4);
|
||||
x1 = ((int)(d - block) % (w * 4)) / 4;
|
||||
y0 = (int)(d - block) / (w * 4);
|
||||
for(i = 0, d = block; i < w/2 && d[3] < 128; i++)
|
||||
for(j = 0, d = block + i*4; j < h/2 && d[3] < 128; j++, d += w*4);
|
||||
x0 = ((int)(d - block) % (w * 4)) / 4 - 1;
|
||||
y1 = (int)(d - block) / (w * 4);
|
||||
x2 = x1 + (x1 - x0) + 1;
|
||||
y2 = y1 + (y1 - y0);
|
||||
for(; d[3] > 128; d += w*4);
|
||||
d -= w*4;
|
||||
y3 = (int)(d - block) / (w * 4);
|
||||
y4 = y3 + (y1 - y0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Free resources
|
||||
* Generate slab and stair pictures from block image
|
||||
*/
|
||||
void freeblocks()
|
||||
int stairgen()
|
||||
{
|
||||
int i, j;
|
||||
FILE *f;
|
||||
stbi__context sc;
|
||||
stbi__result_info ri;
|
||||
int i, j, w, h, l;
|
||||
unsigned int size;
|
||||
unsigned char *data, *block, *slab, *stair;
|
||||
char *c;
|
||||
|
||||
for(i = 0; i < numpalettes; i++) free(palettes[i]);
|
||||
free(palettes);
|
||||
f = fopen(mtsfile, "rb");
|
||||
if(f) {
|
||||
fseek(f, 0L, SEEK_END);
|
||||
size = (unsigned int)ftell(f);
|
||||
fseek(f, 0L, SEEK_SET);
|
||||
data = (unsigned char*)malloc(size);
|
||||
if(!data) error(lang[ERR_MEM]);
|
||||
fread(data, size, 1, f);
|
||||
fclose(f);
|
||||
c = strrchr(mtsfile, '_');
|
||||
if(!c) c = strrchr(mtsfile, '.');
|
||||
if(!c) c = &mtsfile[strlen(mtsfile)];
|
||||
sc.read_from_callbacks = 0;
|
||||
sc.img_buffer = sc.img_buffer_original = data;
|
||||
sc.img_buffer_end = sc.img_buffer_original_end = data + size;
|
||||
ri.bits_per_channel = 8;
|
||||
block = (unsigned char*)stbi__png_load(&sc, &w, &h, &l, 0, &ri);
|
||||
free(data);
|
||||
if(!block) return 1;
|
||||
slab = (unsigned char *)malloc(w * h * 4);
|
||||
if(!slab) error(lang[ERR_MEM]);
|
||||
memset(slab, 0, w * h * 4);
|
||||
stair = (unsigned char *)malloc(w * h * 4);
|
||||
if(!stair) error(lang[ERR_MEM]);
|
||||
/* detect cube edges */
|
||||
detcube(w, h, block);
|
||||
#if DEBUG
|
||||
*((uint32_t*)(slab + y0*w*4 + x1*4)) = 0xFF0000FF;
|
||||
*((uint32_t*)(slab + y1*w*4 + x0*4)) = 0xFF0000FF;
|
||||
*((uint32_t*)(slab + y1*w*4 + x2*4)) = 0xFF00FF00;
|
||||
*((uint32_t*)(slab + y2*w*4 + x1*4)) = 0xFF00FF00;
|
||||
*((uint32_t*)(slab + y3*w*4 + x0*4)) = 0xFF0000FF;
|
||||
*((uint32_t*)(slab + y3*w*4 + x2*4)) = 0xFF00FF00;
|
||||
*((uint32_t*)(slab + y4*w*4 + x1*4)) = 0xFF00FF00;
|
||||
#endif
|
||||
|
||||
for(i = 0; i < numblocks; i++) {
|
||||
free(blocks[i].name);
|
||||
if(blocks[i].blocknames) {
|
||||
for(j = 0; j < numpalettes; j++)
|
||||
if(blocks[i].blocknames[j]) free(blocks[i].blocknames[j]);
|
||||
free(blocks[i].blocknames);
|
||||
/* rotated block */
|
||||
for(i = x0; i <= x2+1; i++) {
|
||||
for(j = y0; j <= y4; j++)
|
||||
*((uint32_t*)(slab + j*w*4 + (x2 - i + x0 + (x0 & 1))*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(j = 0; j < 32; j++) {
|
||||
if(blocks[i].img[j]) free(blocks[i].img[j]);
|
||||
if(blocks[i].dr[j]) free(blocks[i].dr[j]);
|
||||
if(blocks[i].tr[j]) free(blocks[i].tr[j]);
|
||||
data = (unsigned char *)stbi_write_png_to_mem(slab, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_01.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
/* slab */
|
||||
memset(slab, 0, w * h * 4);
|
||||
for(i = x0; i <= x1; i++) {
|
||||
l = (y1 - y0) * (i - x0) / (x1 - x0);
|
||||
for(j = y0; j < y1 + (y3 - y1)/2 + l; j++)
|
||||
*((uint32_t*)(slab + (j+(y3 - y1)/2+1)*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
for(j = y3 + l; j < h; j++)
|
||||
*((uint32_t*)(slab + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(i = x1+1; i <= x2; i++) {
|
||||
l = (y1 - y0) * ((x2-i+1) - x1) / (x2 - x1);
|
||||
for(j = y0; j < y2 + (y3 - y1)/2 + l; j++)
|
||||
*((uint32_t*)(slab + (j+(y3 - y1)/2+1)*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
for(j = y4 + l; j < h; j++)
|
||||
*((uint32_t*)(slab + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
|
||||
data = (unsigned char *)stbi_write_png_to_mem(slab, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_Slab_00.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
/* rotated stairs */
|
||||
memcpy(stair, slab, w * h * 4);
|
||||
for(i = x0; i <= x1 + (x2 - x1)/2; i++) {
|
||||
l = (y1 - y0) * (i - x0) / (x1 - x0);
|
||||
for(j = y0 + l; j < y4; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(i = x1; i <= x2; i++) {
|
||||
l = (y1 - y0) * (i - x1) / (x1 - x0);
|
||||
for(j = y0 + l; j <= y0 + l + 1; j++)
|
||||
*((uint32_t*)(stair + (j+(y1-y0)/2)*w*4 + (i - (x1 - x0)/2)*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
data = (unsigned char *)stbi_write_png_to_mem(stair, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_Stair_00.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
memcpy(stair, slab, w * h * 4);
|
||||
for(i = x0 + (x1 - x0)/2; i <= x2; i++) {
|
||||
l = (y1 - y0) * ((x2-i+1) - x1) / (x2 - x1);
|
||||
for(j = y1 + l; j < y4; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(i = x0; i <= x1; i++) {
|
||||
l = (y1 - y0) * ((x1-i+1) - x1) / (x1 - x0);
|
||||
for(j = y1 + l; j <= y2 + l; j++)
|
||||
*((uint32_t*)(stair + (j+(y1-y0)/2)*w*4 + (i+(x1 - x0)/2)*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
data = (unsigned char *)stbi_write_png_to_mem(stair, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_Stair_01.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
memcpy(stair, slab, w * h * 4);
|
||||
for(i = x0 + (x1 - x0)/2; i <= x1 + (x2 - x1)/2; i++) {
|
||||
l = (y1 - y0) * (i - x0) / (x1 - x0);
|
||||
for(j = y0; j <= y0 + l; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(; i <= x2; i++) {
|
||||
for(j = y0; j <= y4; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(i = x0; i < x1; i++) {
|
||||
l = (y1 - y0) * (i - x0) / (x1 - x0);
|
||||
for(j = y1 + l - 1; j <= y1 + (y3 - y1)/2 + l; j++)
|
||||
*((uint32_t*)(stair + (j-(y1-y0)/2)*w*4 + (i + (x1 - x0)/2)*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
data = (unsigned char *)stbi_write_png_to_mem(stair, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_Stair_02.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
memcpy(stair, slab, w * h * 4);
|
||||
for(i = x0; i <= x0 + (x1 - x0)/2 +1; i++) {
|
||||
for(j = y0; j <= y4; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(; i <= x2; i++) {
|
||||
l = (y1 - y0) * (i - (x0 + (x1 - x0)/2)) / (x2 - x1);
|
||||
for(j = y0; j <= y1 + (y2 - y1)/2 - l; j++)
|
||||
*((uint32_t*)(stair + j*w*4 + i*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
for(i = x1+1; i <= x2; i++) {
|
||||
l = (y1 - y0) * ((x2-i+1) - x1) / (x2 - x1);
|
||||
for(j = y2 + l - 1; j <= y2 + (y3 - y1)/2 + l; j++)
|
||||
*((uint32_t*)(stair + (j-(y1-y0)/2)*w*4 + (i-(x1-x0)/2)*4)) = *((uint32_t*)(block + j*w*4 + i*4));
|
||||
}
|
||||
data = (unsigned char *)stbi_write_png_to_mem(stair, w*4, w, h, 4, &l);
|
||||
if(data) {
|
||||
strcpy(c, "_Stair_03.png");
|
||||
f = fopen(mtsfile,"wb");
|
||||
if(f) { fwrite(data, l, 1, f); fclose(f); }
|
||||
free(data);
|
||||
}
|
||||
|
||||
fprintf(stderr, "mtsedit: %s\r\n", lang[IMGSGEN]);
|
||||
return 0;
|
||||
}
|
||||
free(results);
|
||||
free(blocks);
|
||||
return 1;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue