/// <summary> /// Saves a TeddyBear map. If you are not really well versed in how JCR6 works, you may only need the first two paramters, I only added the others so more advanced users can benefit from the true power of JCR6 ;) /// </summary> /// <param name="map"></param> /// <param name="jcr"></param> /// <param name="Entry"></param> /// <param name="Storage"></param> /// <param name="FileTableStorage"></param> static public string Save(TeddyMap map, string filename, string EntryPref = "", string Storage = "Store", string FileTableStorage = "Store") { var bt = new TJCRCreate(filename, FileTableStorage); var r = Save(map, bt, EntryPref, Storage); bt.Close(); return(r); }
static public void DrawLayer(TeddyMap map, string Layer, int x = 0, int y = 0, int scrollx = 0, int scrolly = 0, bool[,] visibilityMap = null) { d_DrawItem DrawItem = DrawTileItem; if (qstr.Prefixed(Layer.ToUpper(), "ZONE_")) { DrawItem = DrawZoneItem; } for (int iy = 0; iy < map.Layers[Layer].H; iy++) { for (int ix = 0; ix < map.Layers[Layer].W; ix++) { try { DrawItem(map, Layer, x, y, scrollx, scrolly, ix, iy); } catch (Exception e) { Debug.WriteLine($"DrawLayer error! {e.Message} >> Layer: {Layer}({x},{y})"); } } } }
/// <summary> /// Saves the TeddyBear map inside a JCR6 resouce currently in creation. Returns "Ok" if succesful and otherwise an error message. /// </summary> /// <param name="map"></param> /// <param name="jcr"></param> /// <param name="Entry"></param> /// <param name="Storage"></param> public static string Save(TeddyMap map, TJCRCreate jcr, string EntryPref, string Storage = "Store") { try { Init(); //Local MP$ = Replace(MapFile, "\"," / ") TJCRCreate BT = jcr; TJCRCreateStream BTE; // var K = ""; // Local Ak, X, Y // TeddyObject Obj; // Local Obj: TeddyObject //'If Right(MP,1)<>"/" MP:+"/" //'If Not CreateDir(MP,1) Return "Required path could not be created!" // BT = JCR_Create(MapFile) Log("Gonna save a Teddy Bear map"); if (BT == null) { return("Save file could not be created or null sent to saveJCR request!"); } // DEFS Log("Saving Defs"); BTE = BT.NewEntry($"{EntryPref}Defs", Storage); if (BTE == null) { return($"Entry creation failed: {JCR6.JERROR}"); } BTE.WriteByte(0); BTE.WriteInt(map.GridX); BTE.WriteInt(map.GridY); BTE.WriteByte(1); if (map.TexResize) { BTE.WriteByte(1); } else { BTE.WriteByte(0); } BTE.WriteByte(2); BTE.WriteInt(map.SizeX); BTE.WriteInt(map.SizeY); Log("\tWriting Textures"); for (byte Ak = 255; Ak > 0; Ak--) { // Log($"\tWriting texture {Ak}"); // Needless to log all the time, but I used this line for debugging purposes. if (map.Texture[Ak] != null && map.Texture[Ak] != "") { BTE.WriteByte(3); BTE.WriteByte(Ak); BTE.WriteString(map.Texture[Ak]); } } Log("\tWriting Layers"); foreach (string K in map.Layers.Keys) { Log($"\tWriting Layer: {K}"); BTE.WriteByte(4); BTE.WriteString(K); if (qstr.Left(K, 5) == "Zone_") { for (byte Ak = 255; Ak > 0; Ak--) // Zone Names (if the specific layer is a zone) { if (map.ZName(K).Name[Ak] == null) { map.ZName(K).Name[Ak] = ""; } BTE.WriteByte(5); BTE.WriteByte(Ak); BTE.WriteString(map.ZName(K).Name[Ak]); } } } BTE.Close(); // Layers Log("Saving Layers"); foreach (string K in map.Layers.Keys) { Log($"Saving Layer {K}"); var Prefix = "Layer_"; var lay = map.Layers[K]; if (qstr.Left(K, 5) == "Zone_") { Prefix = ""; } BTE = BT.NewEntry($"{EntryPref}{Prefix}{K}", Storage); // Layer Type (should in this version be 0 always) BTE.WriteByte(0); BTE.WriteByte(map.Layers[K].T); // Format BTE.WriteByte(1); BTE.WriteInt(lay.W); BTE.WriteInt(lay.H); // Hot Spots BTE.WriteByte(2); BTE.WriteString(qstr.Left($"{lay.Hot} ", 2), true); // Saving the map itself. No compression is used in saving the data, as TeddyBear has been designed to be used in combination with JCR6 which already compresses everything by itself. // Also note, the map itself tagged with $ff will cause the loader to end loading as soon as the map itself is read. In other words it must always come last in the file. // This is simply a security measure as some tags above can cause the loaded level to be unloaded immediatly, when this comes last, this simply can't happen. // A level without a $ff tagged map will also result into an error when loading. // $fe is also reserved in case 32 bit maps may be added in the future, which is in the current state of things, not likely to happen, but just in case :) // and for that reason $fd is reserved in case of the very small chance 64bit is used. // Must I really reserve $fc for 128bit (which is not even supported by BlitzMax yet)? Nah.... :-P BTE.WriteByte(0xff); for (int X = 0; X <= lay.W; X++) { for (int Y = 0; Y <= lay.H; Y++) { BTE.WriteByte(lay.Get(X, Y)); } } BTE.Close(); } // Objects Log("Saving Objects"); BTE = BT.NewEntry($"{EntryPref}Objects", Storage); BTE.WriteInt(map.OWidth); BTE.WriteInt(map.OHeight); for (int X = 0; X <= map.OWidth; X++) { for (int Y = 0; Y <= map.OHeight; Y++) { foreach (TeddyObject Obj in map.ObjectList(X, Y)) { BTE.WriteByte(0); // New Object on the next coordinates BTE.WriteInt(X); BTE.WriteInt(Y); BTE.WriteByte(2); BTE.WriteString(Obj.ObjType); foreach (string K in Obj.Keys) // New field, with the next data { BTE.WriteByte(1); BTE.WriteString(K); BTE.WriteString(Obj.Cl(K)); } } } } BTE.Close(); // General Data Log("Saving General Data"); BT.NewStringMap(map.MetaData, $"{EntryPref}Data", Storage); // All done Log("Closing"); BT.Close(); Log("Map saved"); return("Ok"); } catch (System.Exception err) { return($"System Error: {err.Message}"); } }