mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-13 01:26:50 -04:00
Redesign map importing to not be so hardcoded
This commit is contained in:
parent
7204116ad1
commit
e9ddb97f56
@ -17,6 +17,8 @@
|
|||||||
#include "TexturePack.h"
|
#include "TexturePack.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
static cc_bool calcDefaultSpawn;
|
static cc_bool calcDefaultSpawn;
|
||||||
|
static struct MapImporter* imp_head;
|
||||||
|
static struct MapImporter* imp_tail;
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
@ -41,25 +43,25 @@ static cc_result Map_SkipGZipHeader(struct Stream* stream) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMapImporter Map_FindImporter(const cc_string* path) {
|
void MapImporter_Register(struct MapImporter* imp) {
|
||||||
static const cc_string cw = String_FromConst(".cw"), lvl = String_FromConst(".lvl");
|
LinkedList_Append(imp, imp_head, imp_tail);
|
||||||
static const cc_string fcm = String_FromConst(".fcm"), dat = String_FromConst(".dat");
|
}
|
||||||
static const cc_string mine = String_FromConst(".mine");
|
|
||||||
static const cc_string mclvl = String_FromConst(".mclevel");
|
|
||||||
|
|
||||||
if (String_CaselessEnds(path, &cw)) return Cw_Load;
|
struct MapImporter* MapImporter_Find(const cc_string* path) {
|
||||||
if (String_CaselessEnds(path, &lvl)) return Lvl_Load;
|
struct MapImporter* imp;
|
||||||
if (String_CaselessEnds(path, &fcm)) return Fcm_Load;
|
cc_string ext;
|
||||||
if (String_CaselessEnds(path, &dat)) return Dat_Load;
|
|
||||||
if (String_CaselessEnds(path, &mine)) return Dat_Load;
|
|
||||||
if (String_CaselessEnds(path, &mclvl)) return MCLevel_Load;
|
|
||||||
|
|
||||||
|
for (imp = imp_head; imp; imp = imp->next)
|
||||||
|
{
|
||||||
|
ext = String_FromReadonly(imp->fileExt);
|
||||||
|
if (String_CaselessEnds(path, &ext)) return imp;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_result Map_LoadFrom(const cc_string* path) {
|
cc_result Map_LoadFrom(const cc_string* path) {
|
||||||
cc_string relPath, fileName, fileExt;
|
cc_string relPath, fileName, fileExt;
|
||||||
IMapImporter importer;
|
struct MapImporter* imp;
|
||||||
struct Stream stream;
|
struct Stream stream;
|
||||||
cc_result res;
|
cc_result res;
|
||||||
Game_Reset();
|
Game_Reset();
|
||||||
@ -68,10 +70,10 @@ cc_result Map_LoadFrom(const cc_string* path) {
|
|||||||
res = Stream_OpenFile(&stream, path);
|
res = Stream_OpenFile(&stream, path);
|
||||||
if (res) { Logger_SysWarn2(res, "opening", path); return res; }
|
if (res) { Logger_SysWarn2(res, "opening", path); return res; }
|
||||||
|
|
||||||
importer = Map_FindImporter(path);
|
imp = MapImporter_Find(path);
|
||||||
if (!importer) {
|
if (!imp) {
|
||||||
res = ERR_NOT_SUPPORTED;
|
res = ERR_NOT_SUPPORTED;
|
||||||
} else if ((res = importer(&stream))) {
|
} else if ((res = imp->import(&stream))) {
|
||||||
World_Reset();
|
World_Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +173,9 @@ static cc_result Lvl_ReadCustomBlocks(struct Stream* stream) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_result Lvl_Load(struct Stream* stream) {
|
/* Imports a world from a .lvl MCSharp server map file */
|
||||||
|
/* Used by MCSharp/MCLawl/MCForge/MCDzienny/MCGalaxy */
|
||||||
|
static cc_result Lvl_Load(struct Stream* stream) {
|
||||||
cc_uint8 header[18];
|
cc_uint8 header[18];
|
||||||
cc_uint8* blocks;
|
cc_uint8* blocks;
|
||||||
cc_uint8 section;
|
cc_uint8 section;
|
||||||
@ -258,7 +262,9 @@ static cc_result Fcm_ReadString(struct Stream* stream) {
|
|||||||
return stream->Skip(stream, len);
|
return stream->Skip(stream, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_result Fcm_Load(struct Stream* stream) {
|
/* Imports a world from a .fcm fCraft server map file (v3 only) */
|
||||||
|
/* Used by fCraft/800Craft/LegendCraft/ProCraft */
|
||||||
|
static cc_result Fcm_Load(struct Stream* stream) {
|
||||||
cc_uint8 header[79];
|
cc_uint8 header[79];
|
||||||
cc_result res;
|
cc_result res;
|
||||||
int i, count;
|
int i, count;
|
||||||
@ -863,7 +869,9 @@ static void Cw_Callback(struct NbtTag* tag) {
|
|||||||
0 1 2 3 4 */
|
0 1 2 3 4 */
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_result Cw_Load(struct Stream* stream) {
|
/* Imports a world from a .cw ClassicWorld map file */
|
||||||
|
/* Used by ClassiCube/ClassicalSharp */
|
||||||
|
static cc_result Cw_Load(struct Stream* stream) {
|
||||||
return Nbt_Read(stream, Cw_Callback);
|
return Nbt_Read(stream, Cw_Callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1326,7 +1334,9 @@ static cc_result Dat_LoadFormat2(struct Stream* stream) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_result Dat_Load(struct Stream* stream) {
|
/* Imports a world from a .dat classic map file */
|
||||||
|
/* Used by Minecraft Classic/WoM client */
|
||||||
|
static cc_result Dat_Load(struct Stream* stream) {
|
||||||
cc_uint8 header[4 + 1];
|
cc_uint8 header[4 + 1];
|
||||||
cc_uint32 signature;
|
cc_uint32 signature;
|
||||||
cc_result res;
|
cc_result res;
|
||||||
@ -1417,6 +1427,7 @@ static void MCLevel_ParseEnvironment(struct NbtTag* tag) {
|
|||||||
} else if (IsTag(tag, "SurroundingWaterHeight")) {
|
} else if (IsTag(tag, "SurroundingWaterHeight")) {
|
||||||
mcl_edgeHeight = NbtTag_U16(tag);
|
mcl_edgeHeight = NbtTag_U16(tag);
|
||||||
}
|
}
|
||||||
|
/* TODO: SkyBrightness */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1455,7 +1466,9 @@ static void MCLevel_Callback(struct NbtTag* tag) {
|
|||||||
0 1 2 */
|
0 1 2 */
|
||||||
}
|
}
|
||||||
|
|
||||||
cc_result MCLevel_Load(struct Stream* stream) {
|
/* Imports a world from a .mclevel NBT map file */
|
||||||
|
/* Used by Minecraft Indev client */
|
||||||
|
static cc_result MCLevel_Load(struct Stream* stream) {
|
||||||
cc_result res = Nbt_Read(stream, MCLevel_Callback);
|
cc_result res = Nbt_Read(stream, MCLevel_Callback);
|
||||||
|
|
||||||
Env.EdgeHeight = mcl_edgeHeight;
|
Env.EdgeHeight = mcl_edgeHeight;
|
||||||
@ -1836,3 +1849,32 @@ cc_result Dat_Save(struct Stream* stream) {
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*-------------------------------------------------------Formats component-------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
static struct MapImporter cw_imp = { ".cw", Cw_Load };
|
||||||
|
static struct MapImporter dat_imp = { ".dat", Dat_Load };
|
||||||
|
static struct MapImporter lvl_imp = { ".lvl", Lvl_Load };
|
||||||
|
static struct MapImporter mine_imp = { ".mine", Dat_Load };
|
||||||
|
static struct MapImporter fcm_imp = { ".fcm", Fcm_Load };
|
||||||
|
static struct MapImporter mclvl_imp = { ".mclevel", MCLevel_Load };
|
||||||
|
|
||||||
|
static void OnInit(void) {
|
||||||
|
MapImporter_Register(&cw_imp);
|
||||||
|
MapImporter_Register(&dat_imp);
|
||||||
|
MapImporter_Register(&lvl_imp);
|
||||||
|
MapImporter_Register(&mine_imp);
|
||||||
|
MapImporter_Register(&fcm_imp);
|
||||||
|
MapImporter_Register(&mclvl_imp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OnFree(void) {
|
||||||
|
imp_head = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IGameComponent Formats_Component = {
|
||||||
|
OnInit, /* Init */
|
||||||
|
OnFree /* Free */
|
||||||
|
};
|
@ -6,30 +6,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct Stream;
|
struct Stream;
|
||||||
/* Imports a world encoded in a particular map file format. */
|
struct IGameComponent;
|
||||||
typedef cc_result (*IMapImporter)(struct Stream* stream);
|
extern struct IGameComponent Formats_Component;
|
||||||
/* Attempts to find a suitable importer based on filename. */
|
|
||||||
/* Returns NULL if no match found. */
|
|
||||||
CC_API IMapImporter Map_FindImporter(const cc_string* path);
|
|
||||||
/* Attempts to import the map from the given file. */
|
|
||||||
/* NOTE: Uses Map_FindImporter to import based on filename. */
|
|
||||||
CC_API cc_result Map_LoadFrom(const cc_string* path);
|
|
||||||
|
|
||||||
/* Imports a world from a .lvl MCSharp server map file. */
|
/* Imports a world encoded in a particular map file format */
|
||||||
/* Used by MCSharp/MCLawl/MCForge/MCDzienny/MCGalaxy. */
|
typedef cc_result (*MapImportFunc)(struct Stream* stream);
|
||||||
cc_result Lvl_Load(struct Stream* stream);
|
struct MapImporter;
|
||||||
/* Imports a world from a .fcm fCraft server map file. (v3 only) */
|
/* Reads/Loads world data (and potentially metadata) encoded in a particular format */
|
||||||
/* Used by fCraft/800Craft/LegendCraft/ProCraft. */
|
struct MapImporter {
|
||||||
cc_result Fcm_Load(struct Stream* stream);
|
const char* fileExt; /* File extension of the map format */
|
||||||
/* Imports a world from a .cw ClassicWorld map file. */
|
MapImportFunc import; /* Function that imports the encoded data */
|
||||||
/* Used by ClassiCube/ClassicalSharp. */
|
struct MapImporter* next; /* Next importer in linked-list of map importers */
|
||||||
cc_result Cw_Load(struct Stream* stream);
|
};
|
||||||
/* Imports a world from a .dat classic map file. */
|
|
||||||
/* Used by Minecraft Classic/WoM client. */
|
/* Adds the given importer to the list of map importers */
|
||||||
cc_result Dat_Load(struct Stream* stream);
|
CC_API void MapImporter_Register(struct MapImporter* imp);
|
||||||
/* Imports a world from a .mclevel NBT map file. */
|
/* Attempts to find a suitable map importer based on filename */
|
||||||
/* Used by Minecraft Indev client. */
|
/* Returns NULL if no match found */
|
||||||
cc_result MCLevel_Load(struct Stream* stream);
|
CC_API struct MapImporter* MapImporter_Find(const cc_string* path);
|
||||||
|
/* Attempts to import a map from the given file */
|
||||||
|
CC_API cc_result Map_LoadFrom(const cc_string* path);
|
||||||
|
|
||||||
/* 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 */
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "Picking.h"
|
#include "Picking.h"
|
||||||
#include "Animations.h"
|
#include "Animations.h"
|
||||||
#include "SystemFonts.h"
|
#include "SystemFonts.h"
|
||||||
|
#include "Formats.h"
|
||||||
|
|
||||||
struct _GameData Game;
|
struct _GameData Game;
|
||||||
cc_uint64 Game_FrameStart;
|
cc_uint64 Game_FrameStart;
|
||||||
@ -414,6 +415,7 @@ static void Game_Load(void) {
|
|||||||
Game_AddComponent(&PickedPosRenderer_Component);
|
Game_AddComponent(&PickedPosRenderer_Component);
|
||||||
Game_AddComponent(&Audio_Component);
|
Game_AddComponent(&Audio_Component);
|
||||||
Game_AddComponent(&AxisLinesRenderer_Component);
|
Game_AddComponent(&AxisLinesRenderer_Component);
|
||||||
|
Game_AddComponent(&Formats_Component);
|
||||||
|
|
||||||
LoadPlugins();
|
LoadPlugins();
|
||||||
for (comp = comps_head; comp; comp = comp->next) {
|
for (comp = comps_head; comp; comp = comp->next) {
|
||||||
|
@ -1711,9 +1711,9 @@ static void LoadLevelScreen_EntryClick(void* screen, void* widget) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void LoadLevelScreen_FilterFiles(const cc_string* path, void* obj) {
|
static void LoadLevelScreen_FilterFiles(const cc_string* path, void* obj) {
|
||||||
IMapImporter importer = Map_FindImporter(path);
|
struct MapImporter* imp = MapImporter_Find(path);
|
||||||
cc_string relPath = *path;
|
cc_string relPath = *path;
|
||||||
if (!importer) return;
|
if (!imp) return;
|
||||||
|
|
||||||
Utils_UNSAFE_TrimFirstDirectory(&relPath);
|
Utils_UNSAFE_TrimFirstDirectory(&relPath);
|
||||||
StringsBuffer_Add((struct StringsBuffer*)obj, &relPath);
|
StringsBuffer_Add((struct StringsBuffer*)obj, &relPath);
|
||||||
@ -1729,7 +1729,7 @@ static void LoadLevelScreen_UploadCallback(const cc_string* path) { Map_LoadFrom
|
|||||||
static void LoadLevelScreen_UploadFunc(void* s, void* w) {
|
static void LoadLevelScreen_UploadFunc(void* s, void* w) {
|
||||||
static const char* const filters[] = {
|
static const char* const filters[] = {
|
||||||
".cw", ".dat", ".lvl", ".mine", ".fcm", ".mclevel", NULL
|
".cw", ".dat", ".lvl", ".mine", ".fcm", ".mclevel", NULL
|
||||||
};
|
}; /* TODO not hardcode list */
|
||||||
static struct OpenFileDialogArgs args = {
|
static struct OpenFileDialogArgs args = {
|
||||||
"Classic map files", filters,
|
"Classic map files", filters,
|
||||||
LoadLevelScreen_UploadCallback,
|
LoadLevelScreen_UploadCallback,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user