diff --git a/src/Errors.h b/src/Errors.h index c9f595a50..b5e8e0045 100644 --- a/src/Errors.h +++ b/src/Errors.h @@ -19,12 +19,11 @@ enum CC_ERRORS { WAV_ERR_STREAM_HDR = 0xCCDED007UL, /* Bytes #1-#4 aren't "RIFF" */ WAV_ERR_STREAM_TYPE = 0xCCDED008UL, /* Bytes #9-#12 aren't "WAV " */ WAV_ERR_DATA_TYPE = 0xCCDED009UL, /* Audio data type isn't 1 (PCM) */ - /*WAV_ERR_NO_DATA = 0xCCDED00AUL, repurposed for AUDIO_ERR_MP3_SIG */ + AUDIO_ERR_MP3_SIG = 0xCCDED00AUL, /* Signature bytes are "ID3" */ WAV_ERR_SAMPLE_BITS = 0xCCDED00BUL, /* Bits per sample isn't 16 */ - AUDIO_ERR_MP3_SIG = 0xCCDED00AUL, /* Signature bytes are "ID3" (repurposed WAV_ERR_NO_DATA) */ + SFD_ERR_NEED_DEFAULT_NAME = 0xCCDED00CUL, - /*VORBIS_ERR_HEADER = 0xCCDED00CUL, no longer used */ VORBIS_ERR_WRONG_HEADER = 0xCCDED00DUL, /* Packet header doesn't match expected type */ VORBIS_ERR_FRAMING = 0xCCDED00EUL, /* Framing flag doesn't match expected value */ VORBIS_ERR_VERSION = 0xCCDED00FUL, /* Vorbis version isn't 0 */ diff --git a/src/Formats.c b/src/Formats.c index 2c6aa9423..3dc90003e 100644 --- a/src/Formats.c +++ b/src/Formats.c @@ -1588,23 +1588,19 @@ cc_result Schematic_Save(struct Stream* stream) { return Stream_Write(stream, sc_end, sizeof(sc_end)); } -const int spawn_value = 8; static const struct JField { - cc_uint8 type; + cc_uint8 type, isFloat; 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 */ + { JFIELD_I32, false, "width", &World.Width }, + { JFIELD_I32, false, "depth", &World.Height }, + { JFIELD_I32, false, "height", &World.Length }, + { JFIELD_I32, true, "xSpawn", &LocalPlayer_Instance.Base.Position.X }, + { JFIELD_I32, true, "ySpawn", &LocalPlayer_Instance.Base.Position.Y }, + { JFIELD_I32, true, "zSpawn", &LocalPlayer_Instance.Base.Position.Z }, + { JFIELD_ARRAY,0, "blocks" } + /* TODO classic only blocks */ }; static int WriteJavaString(cc_uint8* dst, const char* value) { @@ -1658,9 +1654,10 @@ cc_result Dat_Save(struct Stream* stream) { /* JSF signature + version */ 0xAC,0xED, 0x00,0x05 }; + const struct JField* field; cc_uint8 tmp[4]; cc_result res; - int i; + int i, value; if ((res = Stream_Write(stream, header, sizeof(header)))) return res; if ((res = WriteClassDesc(stream, TC_OBJECT, "com.mojang.minecraft.level.Level", @@ -1669,8 +1666,11 @@ cc_result Dat_Save(struct Stream* stream) { /* 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)); + field = &level_fields[i]; + + if (field->type == JFIELD_I32) { + value = field->isFloat ? *((float*)field->value) : *((int*)field->value); + Stream_SetU32_BE(tmp, value); if ((res = Stream_Write(stream, tmp, 4))) return res; } else { if ((res = WriteClassDesc(stream, TC_ARRAY, "[B", 0, NULL))) return res; diff --git a/src/Menus.c b/src/Menus.c index 34ca192c6..b9102bc40 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -31,6 +31,7 @@ #include "Options.h" #include "Input.h" #include "Utils.h" +#include "Errors.h" /* Describes a menu option button */ struct MenuOptionDesc { @@ -1301,28 +1302,7 @@ static void SaveLevelScreen_RemoveOverwrites(struct SaveLevelScreen* s) { } } -#ifdef CC_BUILD_WEB -extern int interop_DownloadMap(const char* path, const char* filename); -static void DownloadMap(const cc_string* path) { - char strPath[NATIVE_STR_LEN]; - char strFile[NATIVE_STR_LEN]; - cc_string file; - cc_result res; - - Platform_EncodeUtf8(strPath, path); - file = *path; Utils_UNSAFE_GetFilename(&file); - latform_EncodeUtf8(strFile, file); - - res = interop_DownloadMap(strPath, strFile); - if (res) { - Logger_SysWarn2(res, "Downloading map", &file); - } else { - Chat_Add1("&eDownloaded map: %s", &file); - } -} -#endif - -static cc_result SaveLevelScreen_SaveMap(struct SaveLevelScreen* s, const cc_string* path) { +static cc_result SaveLevelScreen_SaveMap(const cc_string* path) { static const cc_string schematic = String_FromConst(".schematic"); static const cc_string mine = String_FromConst(".mine"); struct Stream stream, compStream; @@ -1363,10 +1343,10 @@ static cc_result SaveLevelScreen_SaveMap(struct SaveLevelScreen* s, const cc_str return 0; } -static void SaveLevelScreen_DoSave(void* screen, void* widget, const char* fmt) { - cc_string path; char pathBuffer[FILENAME_SIZE]; +static void SaveLevelScreen_Save(void* screen, void* widget) { struct SaveLevelScreen* s = (struct SaveLevelScreen*)screen; struct ButtonWidget* btn = (struct ButtonWidget*)widget; + cc_string path; char pathBuffer[FILENAME_SIZE]; cc_string file = s->input.base.text; cc_result res; @@ -1374,9 +1354,10 @@ static void SaveLevelScreen_DoSave(void* screen, void* widget, const char* fmt) TextWidget_SetConst(&s->desc, "&ePlease enter a filename", &s->textFont); return; } + String_InitArray(path, pathBuffer); - String_Format1(&path, fmt, &file); - String_Copy(&World.Name, &file); + String_Format1(&path, "maps/%s.cw", &file); + String_Copy(&World.Name, &file); if (File_Exists(&path) && !btn->optName) { btn->optName = ""; @@ -1385,48 +1366,38 @@ static void SaveLevelScreen_DoSave(void* screen, void* widget, const char* fmt) } SaveLevelScreen_RemoveOverwrites(s); - if ((res = SaveLevelScreen_SaveMap(s, &path))) return; - -#ifdef CC_BUILD_WEB - if (btn == &s->save) { - Chat_Add1("&eSaved map to: %s", &path); - } else { - DownloadMap(&path); - } -#else + if ((res = SaveLevelScreen_SaveMap(&path))) return; Chat_Add1("&eSaved map to: %s", &path); -#endif } -static void SaveLevelScreen_Save(void* a, void* b) { - SaveLevelScreen_DoSave(a, b, "maps/%s.cw"); -} - -#ifdef CC_BUILD_WEB -static void SaveLevelScreen_File(void* a, void* b) { - SaveLevelScreen_DoSave(a, b, "/tmpmaps/%s.cw"); -} -#else static void SaveLevelScreen_UploadCallback(const cc_string* path) { - cc_result res = SaveLevelScreen_SaveMap(NULL, path); + cc_result res = SaveLevelScreen_SaveMap(path); if (!res) Chat_Add1("&eSaved map to: %s", path); } -static void SaveLevelScreen_File(void* a, void* b) { +static void SaveLevelScreen_File(void* screen, void* b) { static const char* const titles[] = { "ClassiCube map", "MineCraft schematic", "MineCraft classic map", NULL }; static const char* const filters[] = { ".cw", ".schematic", ".mine", NULL }; - static struct SaveFileDialogArgs args = { - filters, titles, SaveLevelScreen_UploadCallback - }; + struct SaveLevelScreen* s = (struct SaveLevelScreen*)screen; + struct SaveFileDialogArgs args; + cc_result res; - cc_result res = Window_SaveFileDialog(&args); - if (res) Logger_SimpleWarn(res, "showing save file dialog"); + args.filters = filters; + args.titles = titles; + args.defaultName = s->input.base.text; + args.Callback = SaveLevelScreen_UploadCallback; + + res = Window_SaveFileDialog(&args); + if (res == SFD_ERR_NEED_DEFAULT_NAME) { + TextWidget_SetConst(&s->desc, "&ePlease enter a filename", &s->textFont); + } else if (res) { + Logger_SimpleWarn(res, "showing save file dialog"); + } } -#endif static int SaveLevelScreen_KeyPress(void* screen, char keyChar) { struct SaveLevelScreen* s = (struct SaveLevelScreen*)screen; diff --git a/src/Window.h b/src/Window.h index 05134fdb2..f85d2438a 100644 --- a/src/Window.h +++ b/src/Window.h @@ -136,6 +136,7 @@ typedef void (*FileDialogCallback)(const cc_string* path); struct SaveFileDialogArgs { const char* const* filters; /* File extensions to limit dialog to showing (e.g. ".zip", NULL) */ const char* const* titles; /* Descriptions to show for each file extension */ + cc_string defaultName; /* Default filename (without extension), required by some backends */ FileDialogCallback Callback; }; struct OpenFileDialogArgs { diff --git a/src/Window_Web.c b/src/Window_Web.c index 386e82966..87b32534b 100644 --- a/src/Window_Web.c +++ b/src/Window_Web.c @@ -573,6 +573,24 @@ cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { return 0; } +extern int interop_DownloadFile(const char* path, const char* filename); +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + cc_string path; char pathBuffer[FILENAME_SIZE]; + cc_string file; char fileBuffer[FILENAME_SIZE]; + + if (!args->defaultName.length) return SFD_ERR_NEED_DEFAULT_NAME; + + String_InitArray(file, fileBuffer); + String_InitArray(path, pathBuffer); + String_Format2(&file, "%s%c", &args->defaultName, args->filters[0]); + String_Format1(&path, "Downloads/%s", &file); + + args->Callback(&path); + pathBuffer[path.length] = '\0'; + fileBuffer[file.length] = '\0'; + return interop_DownloadFile(pathBuffer, fileBuffer); +} + void Window_AllocFramebuffer(struct Bitmap* bmp) { } void Window_DrawFramebuffer(Rect2D r) { } void Window_FreeFramebuffer(struct Bitmap* bmp) { } diff --git a/src/interop_web.js b/src/interop_web.js index e9bccd9ba..ea16794f4 100644 --- a/src/interop_web.js +++ b/src/interop_web.js @@ -93,7 +93,7 @@ mergeInto(LibraryManager.library, { //######################################################################################################################## //-----------------------------------------------------------Menu--------------------------------------------------------- //######################################################################################################################## - interop_DownloadMap: function(path, filename) { + interop_DownloadFile: function(path, filename) { try { var name = UTF8ToString(path); var data = CCFS.readFile(name);