mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-10 16:03:15 -04:00
Also allow saving maps as .mine that can be imported by minecraft classic, still a WIP though
This commit is contained in:
parent
70258163f1
commit
6aec5e83f2
@ -1587,3 +1587,97 @@ cc_result Schematic_Save(struct Stream* stream) {
|
|||||||
}
|
}
|
||||||
return Stream_Write(stream, sc_end, sizeof(sc_end));
|
return Stream_Write(stream, sc_end, sizeof(sc_end));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int spawn_value = 8;
|
||||||
|
static const struct JField {
|
||||||
|
cc_uint8 type;
|
||||||
|
const char* name;
|
||||||
|
void* value;
|
||||||
|
} level_fields[] = {
|
||||||
|
{ JFIELD_I32, "width", &World.Width },
|
||||||
|
{ JFIELD_I32, "depth", &World.Height },
|
||||||
|
{ JFIELD_I32, "height", &World.Length },
|
||||||
|
{ JFIELD_I32, "xSpawn", &spawn_value },
|
||||||
|
{ JFIELD_I32, "ySpawn", &spawn_value },
|
||||||
|
{ JFIELD_I32, "zSpawn", &spawn_value },
|
||||||
|
/*{JFIELD_I32, "skyColor", &Env.SkyCol},
|
||||||
|
{ JFIELD_I32, "fogColor", &Env.FogCol},
|
||||||
|
{ JFIELD_I32, "cloudColor", &Env.CloudsCol},*/
|
||||||
|
{ JFIELD_ARRAY, "blocks", &World.Blocks }
|
||||||
|
/* TODO spawn, classic only blocks */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int WriteJavaString(cc_uint8* dst, const char* value) {
|
||||||
|
int length = String_Length(value);
|
||||||
|
dst[0] = 0;
|
||||||
|
dst[1] = length;
|
||||||
|
Mem_Copy(dst + 2, value, length);
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cc_result WriteClassDesc(struct Stream* stream, cc_uint8 typecode, const char* klass,
|
||||||
|
int numFields, const struct JField* fields) {
|
||||||
|
cc_uint8 header[256] = { 0 };
|
||||||
|
static const cc_uint8 footer[] = {
|
||||||
|
TC_ENDBLOCKDATA, /* classAnnotations */
|
||||||
|
TC_NULL /* superClassDesc */
|
||||||
|
};
|
||||||
|
int i, length;
|
||||||
|
cc_result res;
|
||||||
|
|
||||||
|
header[0] = typecode;
|
||||||
|
header[1] = TC_CLASSDESC;
|
||||||
|
length = WriteJavaString(header + 2, klass);
|
||||||
|
header[4 + length + 8] = SC_SERIALIZABLE;
|
||||||
|
header[4 + length + 9] = 0;
|
||||||
|
header[4 + length + 10] = numFields;
|
||||||
|
|
||||||
|
if ((res = Stream_Write(stream, header, 15 + length))) return res;
|
||||||
|
|
||||||
|
for (i = 0; i < numFields; i++)
|
||||||
|
{
|
||||||
|
header[0] = fields[i].type;
|
||||||
|
length = WriteJavaString(header + 1, fields[i].name);
|
||||||
|
|
||||||
|
if (fields[i].type == JFIELD_ARRAY) {
|
||||||
|
header[3 + length + 0] = TC_STRING;
|
||||||
|
WriteJavaString(&header[3 + length + 1], "[B");
|
||||||
|
length += 5;
|
||||||
|
}
|
||||||
|
if ((res = Stream_Write(stream, header, 3 + length))) return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((res = Stream_Write(stream, footer, sizeof(footer)))) return res;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cc_result Dat_Save(struct Stream* stream) {
|
||||||
|
static const cc_uint8 header[] = {
|
||||||
|
/* DAT signature + version */
|
||||||
|
0x27,0x1B,0xB7,0x88, 0x02,
|
||||||
|
/* JSF signature + version */
|
||||||
|
0xAC,0xED, 0x00,0x05
|
||||||
|
};
|
||||||
|
cc_uint8 tmp[4];
|
||||||
|
cc_result res;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ((res = Stream_Write(stream, header, sizeof(header)))) return res;
|
||||||
|
if ((res = WriteClassDesc(stream, TC_OBJECT, "com.mojang.minecraft.level.Level",
|
||||||
|
Array_Elems(level_fields), level_fields))) return res;
|
||||||
|
|
||||||
|
/* Write field values */
|
||||||
|
for (i = 0; i < Array_Elems(level_fields); i++)
|
||||||
|
{
|
||||||
|
if (level_fields[i].type == JFIELD_I32) {
|
||||||
|
Stream_SetU32_BE(tmp, *((int*)level_fields[i].value));
|
||||||
|
if ((res = Stream_Write(stream, tmp, 4))) return res;
|
||||||
|
} else {
|
||||||
|
if ((res = WriteClassDesc(stream, TC_ARRAY, "[B", 0, NULL))) return res;
|
||||||
|
Stream_SetU32_BE(tmp, World.Volume);
|
||||||
|
if ((res = Stream_Write(stream, tmp, 4))) return res;
|
||||||
|
if ((res = Stream_Write(stream, World.Blocks, World.Volume))) return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@ -29,9 +29,12 @@ cc_result Cw_Load(struct Stream* stream);
|
|||||||
cc_result Dat_Load(struct Stream* stream);
|
cc_result Dat_Load(struct Stream* stream);
|
||||||
|
|
||||||
/* Exports a world to a .cw ClassicWorld map file. */
|
/* Exports a world to a .cw ClassicWorld map file. */
|
||||||
/* Compatible with ClassiCube/ClassicalSharp. */
|
/* Compatible with ClassiCube/ClassicalSharp */
|
||||||
cc_result Cw_Save(struct Stream* stream);
|
cc_result Cw_Save(struct Stream* stream);
|
||||||
/* Exports a world to a .schematic Schematic map file. */
|
/* Exports a world to a .schematic Schematic map file */
|
||||||
/* Used by MCEdit and other tools. */
|
/* Used by MCEdit and other tools */
|
||||||
cc_result Schematic_Save(struct Stream* stream);
|
cc_result Schematic_Save(struct Stream* stream);
|
||||||
|
/* Exports a world to a .dat Classic map file */
|
||||||
|
/* Used by MineCraft Classic */
|
||||||
|
cc_result Dat_Save(struct Stream* stream);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1324,6 +1324,7 @@ static void DownloadMap(const cc_string* path) {
|
|||||||
|
|
||||||
static cc_result SaveLevelScreen_SaveMap(struct SaveLevelScreen* s, const cc_string* path) {
|
static cc_result SaveLevelScreen_SaveMap(struct SaveLevelScreen* s, const cc_string* path) {
|
||||||
static const cc_string schematic = String_FromConst(".schematic");
|
static const cc_string schematic = String_FromConst(".schematic");
|
||||||
|
static const cc_string mine = String_FromConst(".mine");
|
||||||
struct Stream stream, compStream;
|
struct Stream stream, compStream;
|
||||||
struct GZipState state;
|
struct GZipState state;
|
||||||
cc_result res;
|
cc_result res;
|
||||||
@ -1337,6 +1338,8 @@ static cc_result SaveLevelScreen_SaveMap(struct SaveLevelScreen* s, const cc_str
|
|||||||
#else
|
#else
|
||||||
if (String_CaselessEnds(path, &schematic)) {
|
if (String_CaselessEnds(path, &schematic)) {
|
||||||
res = Schematic_Save(&compStream);
|
res = Schematic_Save(&compStream);
|
||||||
|
} else if (String_CaselessEnds(path, &mine)) {
|
||||||
|
res = Dat_Save(&compStream);
|
||||||
} else {
|
} else {
|
||||||
res = Cw_Save(&compStream);
|
res = Cw_Save(&compStream);
|
||||||
}
|
}
|
||||||
@ -1411,10 +1414,10 @@ static void SaveLevelScreen_UploadCallback(const cc_string* path) {
|
|||||||
|
|
||||||
static void SaveLevelScreen_File(void* a, void* b) {
|
static void SaveLevelScreen_File(void* a, void* b) {
|
||||||
static const char* const titles[] = {
|
static const char* const titles[] = {
|
||||||
"ClassiCube map", "MineCraft schematic", NULL
|
"ClassiCube map", "MineCraft schematic", "MineCraft classic map", NULL
|
||||||
};
|
};
|
||||||
static const char* const filters[] = {
|
static const char* const filters[] = {
|
||||||
".cw", ".schematic", NULL
|
".cw", ".schematic", ".mine", NULL
|
||||||
};
|
};
|
||||||
static struct SaveFileDialogArgs args = {
|
static struct SaveFileDialogArgs args = {
|
||||||
filters, titles, SaveLevelScreen_UploadCallback
|
filters, titles, SaveLevelScreen_UploadCallback
|
||||||
|
Loading…
x
Reference in New Issue
Block a user