Force placement and mod installer

master
bzt 2019-12-06 09:18:22 +01:00
parent c0b0fffd9c
commit 1b8b6fe704
17 changed files with 273 additions and 48 deletions

View File

@ -7,17 +7,20 @@ This is a simple editor for [Minetest](https://www.minetest.net) Schematic files
```
MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
./mtsedit [-v] [-d|-p|-P|-g|-i] [-m map] [-f] <.mts|.schematic> [out.mts]
./mtsedit [-v] [-d|-p|-P] [-m map] <.mts|.schematic> [out.mts]
./mtsedit -g <block.png>
./mtsedit -t <blockimgs.csv>
./mtsedit -i [Minetest mods dir]
-v: verbose output
-d: dump layers to output
-p: save preview
-P: save preview, cut structure in half
-g: generate slab and stairs from block image
-i: generate block images from texture data
-m map: replace block type mapping
-g: generate slab and stairs from block image
-t: generate block images from texture data
-i: install Minetest mod
out.mts: output to file
```
Batch Mode
@ -43,6 +46,11 @@ and capable of generating the blocks.csv for you.
<img src="https://gitlab.com/bztsrc/mtsedit/raw/master/docs/mtseditmod.png">
You can install this Minetest mod by running
```
./mtsedit -i ~/.minetest/mods
```
Compilation
-----------

View File

@ -18,14 +18,21 @@ You can use this tool from scripts to bulk convert schematic files or generate p
### Conversion (or Remap)
You can convert Minecraft NBT Schematics with this tool.
```
./mtsedit from.schematic structure.mts
```
You can convert Minecraft Schematics with this tool. You can also convert MTS files using different block types:
You can also convert MTS files using different block types:
```
./mtsedit -m "Minetest Game" mcl2.mts mtg.mts
```
Where the parameter to "-m" is a coloumn name in [blocks.csv](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/usage.md) file.
You can also use numbers, starting from 1 (which means the 4th coloumn, as the first three are reserved for special use).
```
./mtsedit -m 1 mtg.mts mcl2.mts
```
### Generate Preview
@ -41,13 +48,24 @@ With uppercase "P", you can cut the structure in half to peek inside.
### Generate Pictures for Slab and Stairs
This wasn't a planned feature, but I needed it to generate differently rotated block images from block node images.
This wasn't a planned feature, but I needed quick and dirty tool to generate differently rotated and cut block images from
a block node image.
```
./mtsedit -g Gold_Block_00.png
```
This will save "Gold_Block_Slab_00.png", "Double_Gold_Block_Slab_00.png", "Gold_Block_Stair_00.png", "Gold_Block_Stair_01.png",
"Gold_Block_Stair_02.png" and "Gold_Block_Stair_03.png". Also saves a mirrored image by the name "Gold_Block_01.png". If you
dont' need this, just delete it. It does not look good because of the wrong direction of the shadow, but better than nothing
for nodes like furnace.
dont' need this, just delete it. Mirroring does not look good because of the wrong direction of the shadow, but better than nothing
for nodes like furnace. For a proper solution, generate block images from textures.
### Generate Block Images from Textures
This one was intended. With the [MTSEdit Minetest Mod](https://gitlab.com/bztsrc/mtsedit/tree/master/mt-mod) you can save
`blockimgs.csv` with the node's texture data. To import that data, use
```
./mtsedit -t ~/.minetest/worlds/MyWorld/blockimgs.csv
```
This will generate the block images as well as the slab and stair images into the CURRENT WORKING directory. You can then select
what you need and copy those to the `data` directory on your system.

View File

@ -1,8 +1,8 @@
MTSEdit User Manual
===================
This little tool can be compiled on any system easily. It's only dependency is SDL2. Without an argument, the Windows version
will ask the user for a file name. All the others print a usage to stdout.
This little tool can be compiled on any system easily. It's only dependency is SDL2. Without an argument, or with `-h` it prints
an usage to stdout.
See also [batch mode usage](https://gitlab.com/bztsrc/mtsedit/blob/master/docs/batch.md).
@ -117,6 +117,7 @@ Main editor window:
| <kbd>0</kbd>, <kbd>Backquote</kbd> | select Air block (erase mode) |
| <kbd>1</kbd> - <kbd>9</kbd> | quickly access one of the blocks from the palette |
| <kbd>G</kbd> | set current layer as ground level |
| <kbd>D</kbd> | toggle force placement flag |
| <kbd>Q</kbd> / <kbd>Esc</kbd> | quit MTSEdit |
Add blocks to palette window:

Binary file not shown.

View File

@ -10,7 +10,12 @@ You can also save and MTS files from your world, but most importantly, you can l
Installation
------------
Just copy this directory to your Minetest mod directory, for example "~/.minetest/mods".
Just copy this "mtsedit" directory to your Minetest mods directory, for example "~/.minetest/mods".
If you don't have the source, only the installed executable, you can run
```
./mtsedit -i ~/.minetest/mods
```
### Dependencies
@ -36,6 +41,7 @@ or
/mtsedit help
```
to get help. When you first run this command, it will give you a "MTSEdit Magic Placement Wand Tool" (TM) :-)
<img src="https://gitlab.com/bztsrc/raw/master/mt-mod/mtsedit/texture/mtsedit_place.png">
### Exporting node data for MTSEdit
@ -58,7 +64,7 @@ which also contains the Minecraft NBT .schematic files' Block IDs.
For that, enter chat and run
```
/mtsedit load (file name)
/mtsedit load (file name without .mts)
```
Exit chat (with <kbd>Esc</kbd>) and use the MTSEdit Wand with right clicking on a node where you want to build the structure.
That's all. Depending on which direction you're looking at your punched node, the structure's orientation will change. You can
@ -76,8 +82,8 @@ will list the available MTS files in your world directory's "schems" sub-dir.
First, select one corner of the area that you want to save: left click on a node with the MTSEdit Wand. Then go to the opposite
corner of the area (you probably want to get fly priv), and left click on the air (without selecting any particular node). A
green selection cube will appear arround the area. You can modify this as many times as you'd like. If by any chance you can't
reach the exact edges of the desired area, then you can grow (or with negative values, shrink) it using chat commands:
green selection cube will appear arround the area. You can modify this as many times as you want. If by any chance you can't
reach the exact edges of the desired area, then you can grow (or with negative values, shrink) it using the following chat command:
```
/mtsedit grow (delta)
@ -86,7 +92,7 @@ reach the exact edges of the desired area, then you can grow (or with negative v
When you're satisfied with the selection, go to the chat window, and
```
/mtsedit save (file name)
/mtsedit save (file name without .mts)
```
will save that area into an MTS file into the "schems" directory. After that you can open it with MTSEdit outside of the game.

View File

@ -6,7 +6,7 @@ MACSDL = ~/Library/Frameworks/SDL.framework/Versions/A/Headers
TARGET = mtsedit
SRCS = $(filter-out bin2h.c,$(wildcard *.c))
CFLAGS = -Wall -Wextra -ansi -pedantic -g
CFLAGS = -Wall -Wextra -ansi -pedantic
# MacOSX
ifneq ("$(wildcard $(MACSDL)/SDL.h)","")
@ -54,7 +54,7 @@ endif
data.h: bin2h.c icons.png font.psf.gz
@$(CC) bin2h.c -o bin2h
./bin2h icons.png font.psf.gz >data.h
./bin2h icons.png font.psf.gz ../mt-mod/mtsedit >data.h
@rm bin2h
%: %.c main.h lang.h data.h

View File

@ -30,12 +30,78 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <stdint.h>
#ifndef _MSC_VER
#define _inline __inline__
#define _pack __attribute__((packed))
#define _unused __attribute__((unused))
#else
#define _inline
#define _pack
#define _unused
#endif
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
char tmp[1024];
unsigned char *getdir(char *path, char *prefix, unsigned char *buff, long *size)
{
FILE *f;
DIR *dir, *dir2;
struct dirent *de;
char *fn;
int i;
long s;
strcpy(tmp, path);
i = strlen(tmp);
if(tmp[i-1] != '/') { tmp[i++] = '/'; tmp[i] = 0; }
fn = &tmp[i];
if(!prefix) prefix = &tmp[i];
dir = opendir(path);
if(dir) {
while((de = readdir(dir))) {
i = strlen(de->d_name);
if(de->d_name[0] == '.') continue;
strcpy(fn, de->d_name);
dir2 = opendir(tmp);
if(dir2) {
closedir(dir2);
buff = getdir(tmp, prefix, buff, size);
} else {
f = fopen(tmp,"rb");
if(f) {
fseek(f, 0, SEEK_END);
s = ftell(f);
fseek(f, 0, SEEK_SET);
i = strlen(prefix) + 1;
buff = (unsigned char*)realloc(buff, *size + i + 2 + s);
if(!buff) {
fprintf(stderr, "memory allocation error +%d\r\n", i);
exit(2);
}
memcpy(buff + *size, prefix, i);
*size += i;
memcpy(buff + *size, &s, 2);
*size += 2;
fread(buff + *size, s, 1, f);
*size += s;
fclose(f);
}
}
}
closedir(dir);
}
return buff;
}
int main(int argc, char **argv)
{
FILE *f;
long size;
unsigned char *buff = NULL;
unsigned char *buff = NULL, *buff2 = NULL;
char *fn, name[255];
int i, file;
@ -45,18 +111,27 @@ int main(int argc, char **argv)
}
for(file = 1; file < argc; file++){
f = fopen(argv[file],"r");
if(f) {
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
buff = (unsigned char*)realloc(buff, size);
if(!buff) {
fprintf(stderr, "memory allocation error\r\n");
exit(2);
size = 0;
buff = getdir(argv[file], NULL, NULL, &size);
if(buff) {
buff2 = stbi_zlib_compress(buff, (int)size, &i, 9);
if(buff2) { free(buff); buff = buff2; size = i; }
} else {
f = fopen(argv[file],"rb");
if(f) {
fseek(f, 0, SEEK_END);
size = ftell(f);
fseek(f, 0, SEEK_SET);
buff = (unsigned char*)malloc(size);
if(!buff) {
fprintf(stderr, "memory allocation error\r\n");
exit(2);
}
fread(buff, size, 1, f);
fclose(f);
}
fread(buff, size, 1, f);
fclose(f);
}
if(buff) {
fn = strrchr(argv[file], '/');
if(!fn) fn = strrchr(argv[file], '\\');
if(!fn) fn = argv[file]; else fn++;
@ -69,6 +144,8 @@ int main(int argc, char **argv)
printf("0x%02x", buff[i]);
}
printf(" };\n");
free(buff);
buff = NULL;
} else
fprintf(stderr, "Unable to open input file: %s\n", argv[file]);
}

View File

@ -30,6 +30,9 @@
#include "main.h"
char *path = NULL, *fn = NULL;
#ifndef __WIN32__
char *home = NULL;
#endif
/**
* Get blocks.csv's absolute path
@ -39,9 +42,7 @@ void blocks_getdir(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)) {

View File

@ -130,8 +130,8 @@ void edit_redraw(int full)
(uint8_t*)icons->pixels + 32 * icons->pitch), 32 * 32 * 4);
for(l = 0; l < 32 * 32 * 4; l += 4) {
blocks[i].dr[j][l+0] = (b[0]*k + (256 - k)*blocks[i].dr[j][l+0])>>8;
blocks[i].dr[j][l+1] = (b[0]*k + (256 - k)*blocks[i].dr[j][l+1])>>8;
blocks[i].dr[j][l+2] = (b[0]*k + (256 - k)*blocks[i].dr[j][l+2])>>8;
blocks[i].dr[j][l+1] = (b[1]*k + (256 - k)*blocks[i].dr[j][l+1])>>8;
blocks[i].dr[j][l+2] = (b[2]*k + (256 - k)*blocks[i].dr[j][l+2])>>8;
}
}
blk->pixels = blocks[i].dr[j];
@ -198,8 +198,17 @@ void edit_redraw(int full)
SDL_BlitScaled(blk, &src, cl, &dst);
}
if(i) {
blk->pixels = blocks[i].img[j] ? blocks[i].img[j] : (blocks[i].img[0] ? blocks[i].img[0] :
(uint8_t*)icons->pixels + 32 * icons->pitch);
if(nodes[currlayer][Z][X].param1 & 0x80) {
memcpy(tmpblk, blocks[i].img[j] ? blocks[i].img[j] : (blocks[i].img[0] ? blocks[i].img[0] :
(uint8_t*)icons->pixels + 32 * icons->pitch), 32 * 32 * 4);
for(k = 0; k < 32 * 32 * 4; k += 4)
if(tmpblk[k + 3])
tmpblk[k] = (255*64 + (256 - 64)*tmpblk[k])>>8;
blk->pixels = tmpblk;
} else {
blk->pixels = blocks[i].img[j] ? blocks[i].img[j] : (blocks[i].img[0] ? blocks[i].img[0] :
(uint8_t*)icons->pixels + 32 * icons->pitch);
}
if(dst.w == src.w)
SDL_BlitSurface(blk, &src, cl, &dst);
else
@ -298,6 +307,12 @@ void edit_key(SDL_Event *event)
case SDLK_p: sdldo(2); break;
case SDLK_r: sdldo(4 - shift); break;
case SDLK_g: gndlayer = currlayer; break;
case SDLK_d:
if(nodes[currlayer][cz][cx].param0) {
nodes[currlayer][cz][cx].param1 ^= 0x80;
status = blocks[nodes[currlayer][cz][cx].param0].name;
}
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;

Binary file not shown.

View File

@ -42,9 +42,11 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"generate slab and stairs from block image",
"generate block images from texture data",
"replace block type mapping",
"install Minetest mod",
"output to file",
"Loading...",
"Memory allocation error",
"Unable to unpack mod",
"Unable to locate data directory. Set MTSDATA environment variable.",
"Unable to parse blocks.csv",
"Unable to parse blockimgs.csv",
@ -114,9 +116,11 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"palló és lépcső generálás blokk képből",
"blokk képek generálása textúra adatokból",
"lecseréli a palettát",
"Minetest mod telepítése",
"kimenet lementése",
"Betöltés...",
"Memória foglalási hiba",
"Nem tudtom kicsomagolni a mod-ot",
"Nem találom az adatkönyvtárat. Álltsd be az MTSDATA környezeti változót.",
"Nem sikerült betölteni a blocks.csv-t",
"Nem sikerült betölteni a blockimgs.csv-t",
@ -186,9 +190,11 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"generar losas y escaleras desde la imagen de bloque",
"generar imágenes de bloque a partir de datos de textura",
"reemplazar el mapeo de tipo de bloque",
"install Minetest mod",
"salida a archivo",
"Cargando...",
"Error de asignación de memoria",
"Unable to create directory",
"No se puede ubicar el directorio de datos. Establecer variable de entorno MTSDATA.",
"No se puede analizar blocks.csv",
"No se puede analizar blockimgs.csv",
@ -258,9 +264,11 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"générer une dalle et des escaliers à partir d'une image de bloc",
"générer des images de bloc à partir de données de texture",
"remplacer la correspondance de type de bloc",
"install Minetest mod",
"sortie dans un fichier",
"Chargement...",
"Erreur d'allocation de mémoire",
"Unable to create directory",
"Impossible de localiser le répertoire de données. Définissez la variable denvironnement MTSDATA.",
"Impossible d'analyser blocks.csv",
"Impossible d'analyser blockimgs.csv",
@ -330,9 +338,11 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"Erzeugen von Platten und Treppen aus dem Blockbild",
"Blockbilder aus Texturdaten erzeugen",
"Blocktypzuordnung ersetzen",
"install Minetest mod",
"speichern Datei",
"Wird geladen...",
"Speicherzuordnungsfehler",
"Unable to create directory",
"Datenverzeichnis konnte nicht gefunden werden. Setzen Sie die Umgebungsvariable MTSDATA.",
"blocks.csv kann nicht analysiert werden",
"blockimgs.csv kann nicht analysiert werden",
@ -402,9 +412,11 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"generuj płytę i schody z obrazu bloku",
"generować obrazy bloków z danych tekstury",
"zastąpić mapowanie typów bloków",
"install Minetest mod",
"wyjście do pliku",
"Ładuję...",
"Błąd przydziału pamięci",
"Unable to create directory",
"Nie można znaleźć katalogu danych. Ustaw zmienną środowiskową MTSDATA.",
"Nie można przeanalizować blocks.csv",
"Nie można przeanalizować blockimgs.csv",
@ -474,9 +486,11 @@ char *dict[NUMLANGS][NUMTEXTS + 1] = {
"генерировать плиты и лестницы из изображения блока",
"генерировать блочные изображения из данных текстуры",
"заменить отображение типа блока",
"install Minetest mod",
"вывод в файл",
"Загрузка ...",
"Ошибка выделения памяти",
"Unable to unpack mod",
"Невозможно найти каталог данных. Установите переменную среды MTSDATA.",
"Невозможно проанализировать blocks.csv",
"Невозможно проанализировать blockimgs.csv",

View File

@ -35,9 +35,11 @@ enum {
INF_GEN,
INF_BLK,
INF_MAP,
INF_MOD,
INF_OUT,
LOADING,
ERR_MEM,
ERR_MOD,
ERR_DATADIR,
ERR_CSV,
ERR_IMGCSV,

View File

@ -171,10 +171,14 @@ int main(int argc, char** argv, char** envp)
if(argc < 2) {
usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license\r\n\r\n"
"./mtsedit [-v] [-d|-p|-P|-g|-i] [-m map] <.mts|.schematic> [out.mts]\r\n\r\n -v: %s\r\n -d: %s"
"\r\n -p: %s\r\n -P: %s\r\n -g: %s\r\n -i: %s\r\n -m map: %s\r\n out.mts: %s\r\n",
lang[INF_VERB], lang[INF_DUMP], lang[INF_PRE1], lang[INF_PRE2], lang[INF_GEN], lang[INF_BLK],
lang[INF_MAP], lang[INF_OUT]);
"./mtsedit [-v] [-d|-p|-P] [-m map] <.mts|.schematic> [out.mts]\r\n"
"./mtsedit -g <block.png>\r\n"
"./mtsedit -t <blockimgs.csv>\r\n"
"./mtsedit -i [Minetest mods dir]\r\n"
"\r\n -v: %s\r\n -d: %s\r\n -p: %s\r\n -P: %s\r\n -m map: %s\r\n -g: %s\r\n -t: %s\r\n"
" -i: %s\r\n out.mts: %s\r\n",
lang[INF_VERB], lang[INF_DUMP], lang[INF_PRE1], lang[INF_PRE2], lang[INF_MAP], lang[INF_GEN], lang[INF_BLK],
lang[INF_MOD], lang[INF_OUT]);
exit(0);
}
i = 1;
@ -186,7 +190,8 @@ usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
case 'p': opt = 2; break;
case 'P': opt = 3; break;
case 'g': opt = 4; break;
case 'i': opt = 5; break;
case 't': opt = 5; break;
case 'i': opt = 6; break;
case 'm': if(!opt) { opt = 7; } newmap = argv[++j]; break;
default: goto usage; break;
}
@ -203,7 +208,7 @@ usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
mts_x = mts_y = mts_z = 0;
if(i+1 <= argc && argv[i+1] && !opt) opt = 7;
if(opt && opt != 4) {
if(opt && opt != 4 && opt != 6) {
blocks_parse();
readschem();
if(!mts_y || !mts_y || !mts_x)
@ -227,9 +232,10 @@ usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license
case 3: ret = mts_view(opt-2); break;
case 4: ret = stairgen(); break;
case 5: ret = blockgen(); break;
case 6:
case 0:
/* start the main user interface */
sdlmain();
ret = sdlmain(opt);
break;
}

View File

@ -78,6 +78,7 @@
#define DIRSEP '\\'
#else
#define DIRSEP '/'
extern char *home;
#endif
typedef struct {
@ -175,6 +176,7 @@ int isdir(char *path);
int listdir(char *path, char ***files, int type);
void freedir(int n, char ***files);
void detcube(int w, int h, unsigned char *block);
int instmod(unsigned char *data, int size);
int stairgen();
int blockgen();
@ -206,7 +208,7 @@ void mts_delx(int x);
void sdlprint(int x, int y, int fg, int bg, char *s);
void sdlredraw();
void sdldo(int opt);
void sdlmain();
int sdlmain(int opt);
/* edit.c */
void edit_placenode(int y, int z, int x, int i);

View File

@ -71,7 +71,7 @@ int mts_getbounds(int sanitize, unsigned short *tr, unsigned short *tr2)
if(y > may) may = y;
if(z < miz) miz = z;
if(z > maz) maz = z;
if(sanitize && !nodes[y][z][x].param1) nodes[y][z][x].param1 = 127;
if(sanitize && !(nodes[y][z][x].param1 && 0x7F)) nodes[y][z][x].param1 |= 127;
} else
if(sanitize) nodes[y][z][x].param1 = 0;
}

View File

@ -222,7 +222,13 @@ void sdltoolbar()
sprintf(str, "%3d%%", layerprob[currlayer] * 100 / 127);
sdlprint(2, screen->h - font->height, THEME_INACT, THEME_BG, str);
/* status bar */
src.x = 16; src.y = 8 * 32 + 80; dst.x = screen->w - 9 * font->width - 9 - 52; dst.y = screen->h - font->height / 2 - 8;
src.x = 16; src.y = 8 * 32 + 80; dst.x = screen->w - 11 * font->width - 9 - 56; dst.y = screen->h - font->height / 2 - 8;
if(nodes[currlayer][cz][cx].param1 & 0x80) {
strsep = 0;
sdlprint(dst.x, screen->h - font->height, THEME_FG, THEME_BG, "\004\005");
strsep = 1;
}
dst.x += 2*font->width + 4;
src.w = src.h = dst.w = dst.h = 16;
SDL_BlitSurface(icons, &src, screen, &dst);
dst.x += 20;
@ -308,7 +314,7 @@ void sdldo(int opt)
/**
* The main SDL loop
*/
void sdlmain()
int sdlmain(int opt)
{
stbi__context s;
stbi__result_info ri;
@ -317,6 +323,9 @@ void sdlmain()
int iw = 0, ih = 0, len, i, j, k, l;
SDL_Event event;
/* this is tricky, because extern wouldn't know sizeof() */
if(opt) return instmod(binary_mtsedit, sizeof(binary_mtsedit));
/* get our font */
font = (psf_t*)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)binary_font_psf_gz + 10,
sizeof(binary_font_psf_gz) - 10, 32768, &len, 0);
@ -595,4 +604,5 @@ void sdlmain()
free(icondata);
free(font);
blocks_free();
return 0;
}

View File

@ -28,6 +28,8 @@
*/
#include "main.h"
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
/* cube coordinates */
@ -196,7 +198,7 @@ int listdir(char *path, char ***files, int type)
dir = opendir(tmp);
} else
fn = tmp + strlen(tmp);
if(tmp[strlen(tmp)-1] != DIRSEP) { *fn++ = DIRSEP; *fn = 0; }
if(fn[-1] != DIRSEP) { *fn++ = DIRSEP; *fn = 0; }
if(dir) {
while((de = readdir(dir))) {
i = strlen(de->d_name);
@ -268,6 +270,69 @@ void detcube(int w, int h, unsigned char *block)
y4 = y3 + (y1 - y0);
}
/**
* Install Minetest mod
*/
int instmod(unsigned char *data, int size)
{
FILE *f;
char tmp[MAXPATHLEN], msg[MAXPATHLEN + 128], *fn, *d;
unsigned char *un, *b, *end;
int i, j, s;
/* get the data */
b = un = (unsigned char*)stbi_zlib_decode_malloc_guesssize_headerflag((const char*)data, size, 32768, &s, 1);
if(!un) error(lang[ERR_MEM]);
end = b + s;
#ifdef __WIN32__
if(mtsfile[0] == '~') {
strcpy(tmp, home);
strcat(tmp, mtsfile + 1);
} else
#endif
strcpy(tmp, mtsfile);
fn = tmp + strlen(tmp);
if(fn[-1] != DIRSEP) { *fn++ = DIRSEP; *fn = 0; }
strcpy(fn, "mtsedit");
fn += 7; *fn++ = DIRSEP; *fn = 0;
mkdir(tmp
#ifndef __WIN32__
, 0755
#endif
);
if(!isdir(tmp)) {
sprintf(msg, "%s: %s", lang[ERR_MOD], tmp);
error(msg);
}
while(b < end) {
i = strlen((char*)b) + 1;
j = (b[i + 1] << 8) | b[i];
strcpy(fn, (char*)b);
d = strrchr(fn, DIRSEP);
if(d > fn) {
*d = 0;
mkdir(tmp
#ifndef __WIN32__
, 0755
#endif
);
*d = DIRSEP;
}
f = fopen(tmp, "wb");
if(f) {
fwrite(b + i + 2, j, 1, f);
fclose(f);
} else {
sprintf(msg, "%s: %s", lang[ERR_MOD], tmp);
error(msg);
}
b += i + 2 + j;
}
free(un);
return 0;
}
/**
* Generate slab and stair pictures from block image
*/