mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-12 17:17:09 -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 "Utils.h"
|
||||
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;
|
||||
}
|
||||
|
||||
IMapImporter Map_FindImporter(const cc_string* path) {
|
||||
static const cc_string cw = String_FromConst(".cw"), lvl = String_FromConst(".lvl");
|
||||
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");
|
||||
void MapImporter_Register(struct MapImporter* imp) {
|
||||
LinkedList_Append(imp, imp_head, imp_tail);
|
||||
}
|
||||
|
||||
if (String_CaselessEnds(path, &cw)) return Cw_Load;
|
||||
if (String_CaselessEnds(path, &lvl)) return Lvl_Load;
|
||||
if (String_CaselessEnds(path, &fcm)) return Fcm_Load;
|
||||
if (String_CaselessEnds(path, &dat)) return Dat_Load;
|
||||
if (String_CaselessEnds(path, &mine)) return Dat_Load;
|
||||
if (String_CaselessEnds(path, &mclvl)) return MCLevel_Load;
|
||||
struct MapImporter* MapImporter_Find(const cc_string* path) {
|
||||
struct MapImporter* imp;
|
||||
cc_string ext;
|
||||
|
||||
for (imp = imp_head; imp; imp = imp->next)
|
||||
{
|
||||
ext = String_FromReadonly(imp->fileExt);
|
||||
if (String_CaselessEnds(path, &ext)) return imp;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cc_result Map_LoadFrom(const cc_string* path) {
|
||||
cc_string relPath, fileName, fileExt;
|
||||
IMapImporter importer;
|
||||
struct MapImporter* imp;
|
||||
struct Stream stream;
|
||||
cc_result res;
|
||||
Game_Reset();
|
||||
@ -68,10 +70,10 @@ cc_result Map_LoadFrom(const cc_string* path) {
|
||||
res = Stream_OpenFile(&stream, path);
|
||||
if (res) { Logger_SysWarn2(res, "opening", path); return res; }
|
||||
|
||||
importer = Map_FindImporter(path);
|
||||
if (!importer) {
|
||||
imp = MapImporter_Find(path);
|
||||
if (!imp) {
|
||||
res = ERR_NOT_SUPPORTED;
|
||||
} else if ((res = importer(&stream))) {
|
||||
} else if ((res = imp->import(&stream))) {
|
||||
World_Reset();
|
||||
}
|
||||
|
||||
@ -171,7 +173,9 @@ static cc_result Lvl_ReadCustomBlocks(struct Stream* stream) {
|
||||
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* blocks;
|
||||
cc_uint8 section;
|
||||
@ -258,7 +262,9 @@ static cc_result Fcm_ReadString(struct Stream* stream) {
|
||||
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_result res;
|
||||
int i, count;
|
||||
@ -863,7 +869,9 @@ static void Cw_Callback(struct NbtTag* tag) {
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1326,7 +1334,9 @@ static cc_result Dat_LoadFormat2(struct Stream* stream) {
|
||||
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_uint32 signature;
|
||||
cc_result res;
|
||||
@ -1417,6 +1427,7 @@ static void MCLevel_ParseEnvironment(struct NbtTag* tag) {
|
||||
} else if (IsTag(tag, "SurroundingWaterHeight")) {
|
||||
mcl_edgeHeight = NbtTag_U16(tag);
|
||||
}
|
||||
/* TODO: SkyBrightness */
|
||||
}
|
||||
|
||||
|
||||
@ -1455,7 +1466,9 @@ static void MCLevel_Callback(struct NbtTag* tag) {
|
||||
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);
|
||||
|
||||
Env.EdgeHeight = mcl_edgeHeight;
|
||||
@ -1835,4 +1848,33 @@ cc_result Dat_Save(struct Stream* stream) {
|
||||
}
|
||||
}
|
||||
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 */
|
||||
};
|
@ -5,31 +5,27 @@
|
||||
Copyright 2014-2022 ClassiCube | Licensed under BSD-3
|
||||
*/
|
||||
|
||||
struct Stream;
|
||||
/* Imports a world encoded in a particular map file format. */
|
||||
typedef cc_result (*IMapImporter)(struct Stream* stream);
|
||||
/* 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);
|
||||
struct Stream;
|
||||
struct IGameComponent;
|
||||
extern struct IGameComponent Formats_Component;
|
||||
|
||||
/* Imports a world from a .lvl MCSharp server map file. */
|
||||
/* Used by MCSharp/MCLawl/MCForge/MCDzienny/MCGalaxy. */
|
||||
cc_result Lvl_Load(struct Stream* stream);
|
||||
/* Imports a world from a .fcm fCraft server map file. (v3 only) */
|
||||
/* Used by fCraft/800Craft/LegendCraft/ProCraft. */
|
||||
cc_result Fcm_Load(struct Stream* stream);
|
||||
/* Imports a world from a .cw ClassicWorld map file. */
|
||||
/* Used by ClassiCube/ClassicalSharp. */
|
||||
cc_result Cw_Load(struct Stream* stream);
|
||||
/* Imports a world from a .dat classic map file. */
|
||||
/* Used by Minecraft Classic/WoM client. */
|
||||
cc_result Dat_Load(struct Stream* stream);
|
||||
/* Imports a world from a .mclevel NBT map file. */
|
||||
/* Used by Minecraft Indev client. */
|
||||
cc_result MCLevel_Load(struct Stream* stream);
|
||||
/* Imports a world encoded in a particular map file format */
|
||||
typedef cc_result (*MapImportFunc)(struct Stream* stream);
|
||||
struct MapImporter;
|
||||
/* Reads/Loads world data (and potentially metadata) encoded in a particular format */
|
||||
struct MapImporter {
|
||||
const char* fileExt; /* File extension of the map format */
|
||||
MapImportFunc import; /* Function that imports the encoded data */
|
||||
struct MapImporter* next; /* Next importer in linked-list of map importers */
|
||||
};
|
||||
|
||||
/* Adds the given importer to the list of map importers */
|
||||
CC_API void MapImporter_Register(struct MapImporter* imp);
|
||||
/* Attempts to find a suitable map importer based on filename */
|
||||
/* Returns NULL if no match found */
|
||||
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. */
|
||||
/* Compatible with ClassiCube/ClassicalSharp */
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "Picking.h"
|
||||
#include "Animations.h"
|
||||
#include "SystemFonts.h"
|
||||
#include "Formats.h"
|
||||
|
||||
struct _GameData Game;
|
||||
cc_uint64 Game_FrameStart;
|
||||
@ -414,6 +415,7 @@ static void Game_Load(void) {
|
||||
Game_AddComponent(&PickedPosRenderer_Component);
|
||||
Game_AddComponent(&Audio_Component);
|
||||
Game_AddComponent(&AxisLinesRenderer_Component);
|
||||
Game_AddComponent(&Formats_Component);
|
||||
|
||||
LoadPlugins();
|
||||
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) {
|
||||
IMapImporter importer = Map_FindImporter(path);
|
||||
struct MapImporter* imp = MapImporter_Find(path);
|
||||
cc_string relPath = *path;
|
||||
if (!importer) return;
|
||||
if (!imp) return;
|
||||
|
||||
Utils_UNSAFE_TrimFirstDirectory(&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 const char* const filters[] = {
|
||||
".cw", ".dat", ".lvl", ".mine", ".fcm", ".mclevel", NULL
|
||||
};
|
||||
}; /* TODO not hardcode list */
|
||||
static struct OpenFileDialogArgs args = {
|
||||
"Classic map files", filters,
|
||||
LoadLevelScreen_UploadCallback,
|
||||
|
Loading…
x
Reference in New Issue
Block a user