/MCQuai/Memory.cs
C# | 543 lines | 475 code | 66 blank | 2 comment | 120 complexity | 7181cd22853acdc4cd52d64980a6b81a MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.IO.Compression;
- using System.Threading;
- namespace MCRevive
- {
- public class Memory
- {
- public static List<string> BlocksOpen = new List<string>();
- public static List<string> PortalsOpen = new List<string>();
- public const int BlockMemoryVersion = 2;
- public const int PortalMemoryVersion = 2;
- public static void ClearPortals(string level)
- {
- while (PortalsOpen.Contains(level))
- System.Threading.Thread.Sleep(10);
- if (File.Exists("memory/portals/" + level + ".txt"))
- File.Delete("memory/portals/" + level + ".txt");
- }
- public static void UpdatePortals(string levels = "")
- {
- //Does nothing yet - no newer portal memory
- //Add portal permissions?
- bool generate = false;
- if (!Directory.Exists("memory"))
- {
- Directory.CreateDirectory("memory");
- Directory.CreateDirectory("memory/portals");
- generate = true; ;
- }
- if (!Directory.Exists("memory/blocks"))
- {
- Directory.CreateDirectory("memory/portals");
- generate = true;
- }
- string[] files;
- if (levels == "")
- files = Directory.GetFiles("memory/portals");
- else
- {
- files = levels.Split(',');
- for (int i = 0; i < files.Length; i++)
- files[i] = "memory/portals/" + files[i] + ".txt";
- }
- if (!generate)
- for (int f = 0; f < files.Length; f++)
- {
- string name = files[f].Remove(files[f].LastIndexOf('.')).Substring(files[f].LastIndexOfAny(new char[] { '\\', '/' }) + 1);
- while (PortalsOpen.Contains(name))
- System.Threading.Thread.Sleep(10);
- if (File.Exists(files[f]))
- {
- PortalsOpen.Add(name);
- char[] getter = new char[1];
- StreamReader r = File.OpenText(files[f]);
- r.Read(getter, 0, 1);
- r.Close();
- r.Dispose();
- PortalsOpen.Remove(name);
- if (getter[0] == PortalMemoryVersion)
- continue;
- List<Level.PortalPos> list = new List<Level.PortalPos>();
- ushort[] dimensions = getDimensionsOfLevel(name);
- if (dimensions == null)
- continue;
- PortalsOpen.Add(name);
- string t = File.ReadAllText(files[f]);
- PortalsOpen.Remove(name);
- if (t.IndexOf((char)32002) == -1)
- continue;
- if (t[0] == (char)2)
- {
- t = t.Substring(1);
- int amn = t.Length;
- string endMap = "";
- for (int i = 0; i < amn; i += 2)
- {
- if (t[i] != (char)32001)
- {
- endMap = t.Substring(i, t.IndexOf((char)32001, i + 1));
- i += endMap.Length;
- }
- list.Add(new Level.PortalPos(t[++i] * 65336 + t[++i], t[++i] * 65336 + t[++i], endMap));
- }
- }
- int amount = list.Count;
- List<string> leNames = new List<string>();
- for (int i = 0; i < amount; i++)
- if (!leNames.Contains(list[i].end))
- leNames.Add(list[i].end);
- leNames.Sort();
- List<Level.PortalPos> finished = new List<Level.PortalPos>(amount);
- int amount2 = leNames.Count;
- for (int i = 0; i < amount2; i++)
- finished.AddRange(list.FindAll(li => li.end == leNames[i]));
- SavePortals(name, finished, true);
- }
- }
- else
- {
- for (int f = 0; f < files.Length; ++f)
- SaveBlocks(files[f], new List<Level.BlockPos>(), true);
- }
- }
- public static void SavePortals(string level, List<Level.PortalPos> list, bool resave = false)
- {
- while (PortalsOpen.Contains(level))
- System.Threading.Thread.Sleep(10);
- if (File.Exists("memory/portals/" + level + ".txt"))
- {
- if (new FileInfo("memory/portals/" + level + ".txt").Length < 10)
- resave = true;
- }
- else
- resave = true;
- PortalsOpen.Add(level);
- StreamWriter sw = new StreamWriter("memory/portals/" + level + ".txt", !resave, System.Text.Encoding.UTF8);
- try
- {
- if (resave)
- sw.Write((char)PortalMemoryVersion);
- string lastEnd = "";
- foreach (Level.PortalPos pP in list)
- {
- ushort pos11 = (ushort)(pP.pos / 65336);
- ushort pos12 = (ushort)(pP.pos % 65336);
- ushort pos21 = (ushort)(pP.pos2 / 65336);
- ushort pos22 = (ushort)(pP.pos2 % 65336);
- sw.Write((lastEnd == pP.end ? "" : pP.end) + (char)32001 + (char)pos11 + (char)pos12 + (char)pos21 + (char)pos22 + (char)32002);
- lastEnd = pP.end;
- }
- }
- catch (Exception ex) { Server.ErrorLog(ex); }
- finally
- {
- sw.Close();
- sw.Dispose();
- }
- PortalsOpen.Remove(level);
- }
- public static Level.PortalPos LoadPortal(string level, int pos)
- {
- while (PortalsOpen.Contains(level))
- System.Threading.Thread.Sleep(10);
- if (!Directory.Exists("memory") || !Directory.Exists("memory/portals") || !File.Exists("memory/portals/" + level + ".txt"))
- return null;
-
- PortalsOpen.Add(level);
- string t = File.ReadAllText("memory/portals/" + level + ".txt");
- PortalsOpen.Remove(level);
-
- if (t[0] == (char)PortalMemoryVersion)
- {
- t = t.Substring(1);
- int amn = t.Length;
- for (int i = 0; i < amn; ++i)
- {
- if (t[t.IndexOf((char)32001, i) + 1] * 65336 + (int)t[t.IndexOf((char)32001, i) + 2] != pos)
- {
- i = t.IndexOf((char)32001, i) + 5;
- continue;
- }
- string endMap = "";
- if (t[i] == (char)32001)
- {
- for (int ss = 6; ss < t.Length - 7; ss += 6)
- if (t[i - ss] == (char)32001 && t[i - ss - 1] != (char)32002)
- {
- if (t.IndexOf((char)32001) == i - ss)
- ss = i;
- else
- {
- while (t[i - ss] != (char)32002) ss++;
- ss--;
- }
- endMap = t.Substring(i - ss, t.IndexOf((char)32001, i - ss + 1) - i + ss);
- break;
- }
- }
- else
- {
- endMap = t.Substring(i, t.IndexOf((char)32001, i + 1) - i);
- i += endMap.Length;
- }
-
- ushort pos11 = t[++i];
- ushort pos12 = t[++i];
- ushort pos21 = t[++i];
- ushort pos22 = t[++i];
- return new Level.PortalPos(pos11 * 65336 + pos12, pos21 * 65336 + pos22, endMap);
- }
- }
- else
- {
- UpdatePortals(level);
- return LoadPortal(level, pos);
- }
- return null;
- }
- public static List<Level.PortalPos> LoadPortals(string level)
- {
- while (PortalsOpen.Contains(level))
- Thread.Sleep(10);
- if (!Directory.Exists("memory") || !Directory.Exists("memory/portals") || !File.Exists("memory/portals/" + level + ".txt"))
- return null;
- PortalsOpen.Add(level);
- string t = File.ReadAllText("memory/portals/" + level + ".txt");
- PortalsOpen.Remove(level);
- List<Level.PortalPos> list = new List<Level.PortalPos>();
- if (t[0] == (char)PortalMemoryVersion)
- {
- t = t.Substring(1);
- int amn = t.Length;
- string endMap = "";
- for (int i = 0; i < amn; i += 2)
- {
- if (t[i] != (char)32001)
- {
- endMap = t.Substring(i, t.IndexOf((char)32001, i + 1) - i);
- i += endMap.Length;
- }
- list.Add(new Level.PortalPos(t[++i] * 65336 + t[++i], t[++i] * 65336 + t[++i], endMap));
- }
- return list;
- }
- else
- {
- UpdatePortals(level);
- return LoadPortals(level);
- }
- }
- public static void ClearBlocks(string level)
- {
- while (BlocksOpen.Contains(level))
- System.Threading.Thread.Sleep(10);
- if (File.Exists("memory/blocks/" + level + ".txt"))
- File.Delete("memory/blocks/" + level + ".txt");
- }
- public static void UpdateBlocks(string ff = "")
- {
- bool generate = false;
- if (!Directory.Exists("memory"))
- {
- Directory.CreateDirectory("memory");
- Directory.CreateDirectory("memory/blocks");
- generate = true; ;
- }
- if (!Directory.Exists("memory/blocks"))
- {
- Directory.CreateDirectory("memory/blocks");
- generate = true;
- }
- string[] files;
- if (ff == "")
- files = Directory.GetFiles("memory/blocks");
- else
- {
- files = ff.Split(',');
- for (int i = 0; i < files.Length; i++)
- files[i] = "memory/blocks/" + files[i] + ".txt";
- }
- if (!generate)
- for (int f = 0; f < files.Length; f++)
- {
- string name = files[f].Remove(files[f].LastIndexOf('.')).Substring(files[f].LastIndexOfAny(new char[] { '\\', '/' }) + 1);
- while (BlocksOpen.Contains(name))
- System.Threading.Thread.Sleep(10);
- if (File.Exists(files[f]))
- {
- BlocksOpen.Add(name);
- char[] getter = new char[1];
- StreamReader r = File.OpenText(files[f]);
- r.Read(getter, 0, 1);
- r.Close();
- r.Dispose();
- BlocksOpen.Remove(name);
- if (getter[0] == BlockMemoryVersion)
- continue;
- List<Level.BlockPos> list = new List<Level.BlockPos>();
- ushort[] dimensions = getDimensionsOfLevel(name);
- if (dimensions == null)
- continue;
- BlocksOpen.Add(name);
- string t = File.ReadAllText(files[f]);
- BlocksOpen.Remove(name);
- if (t.IndexOf((char)32002) == -1)
- continue;
- if (t[1] == (char)32002)
- {
- if (t[0] == (char)2)
- {
- t = t.Substring(2);
- string NextName = "";
- int position = 0;
- DateTime when = new DateTime();
- bool deleted = false;
- int lastIndex = 0;
- for (int i = 0; i < t.Length; ++i)
- {
- if (t[i] != (char)32001)
- {
- NextName = t.Substring(i, t.IndexOf((char)32001, lastIndex));
- i += NextName.Length;
- }
- position = (int)t[++i] * 65336 + (int)t[++i];
- when = new DateTime(2000, 1, 1).AddSeconds((int)t[++i] * 65336 + (int)t[++i]);
- deleted = t[++i] != (char)32002;
- if (deleted) i++;
- list.Add(new Level.BlockPos(position, when, deleted, NextName));
- lastIndex = i;
- }
- }
- }
- else
- foreach (string s in t.Split((char)32002))
- if (s.Split((char)32001).Length > 2)
- list.Add(new Level.BlockPos((int)s.Split((char)32001)[1][0] + (int)s.Split((char)32001)[1][1] * dimensions[0] + (int)s.Split((char)32001)[1][2] * dimensions[0] * dimensions[1], DateTime.Parse(s.Split((char)32001)[2]), s.Split((char)32001).Length == 4, s.Split((char)32001)[0]));
-
- int amount = list.Count;
- List<string> leNames = new List<string>();
- for (int i = 0; i < amount; i++)
- if (!leNames.Contains(list[i].name))
- leNames.Add(list[i].name);
- leNames.Sort();
- List<Level.BlockPos> finished = new List<Level.BlockPos>(amount);
- int amount2 = leNames.Count;
- for (int i = 0; i < amount2; i++)
- finished.AddRange(list.FindAll(li => li.name == leNames[i]));
- SaveBlocks(name, finished, true);
- }
- else
- generate = true;
- }
- else
- {
- for (int f = 0; f < files.Length; ++f)
- SaveBlocks(files[f], new List<Level.BlockPos>(), true);
- }
- }
- public static void SaveBlocks(string level, List<Level.BlockPos> list, bool resave = false)
- {
- while (BlocksOpen.Contains(level))
- System.Threading.Thread.Sleep(10);
- if (File.Exists("memory/blocks/" + level + ".txt"))
- {
- if (new FileInfo("memory/blocks/" + level + ".txt").Length < 10)
- resave = true;
- }
- else
- resave = true;
- StreamWriter sw = new StreamWriter("memory/blocks/" + level + ".txt", !resave, System.Text.Encoding.UTF8);
- try
- {
- if (resave)
- sw.Write((char)BlockMemoryVersion + "" + (char)32002);
- string lastName = "";
- foreach (Level.BlockPos bP in list)
- {
- int a = (int)(bP.TimePerformed - new DateTime(2000, 1, 1)).TotalSeconds;
- ushort sec1 = (ushort)(a / 65336);
- ushort sec2 = (ushort)(a % 65336);
- ushort pos1 = (ushort)(bP.pos / 65336);
- ushort pos2 = (ushort)(bP.pos % 65336);
- sw.Write((lastName == bP.name ? "" : bP.name) + (char)32001 + (char)pos1 + (char)pos2 + (char)sec1 + (char)sec2 + (bP.deleted ? "a" : "") + (char)32002); //just need an extra char if deleted
- lastName = bP.name;
- }
- }
- catch (Exception ex) { Server.ErrorLog(ex); }
- finally
- {
- sw.Close();
- sw.Dispose();
- }
- }
- public static List<Level.BlockPos> LoadBlocks(string name)
- {
- while (BlocksOpen.Contains(name))
- System.Threading.Thread.Sleep(10);
-
- if (File.Exists("memory/blocks/" + name + ".txt"))
- {
- List<Level.BlockPos> list = new List<Level.BlockPos>();
- ushort[] dimensions = getDimensionsOfLevel(name);
- if (dimensions == null)
- return null;
- BlocksOpen.Add(name);
- string t = File.ReadAllText("memory/blocks/" + name + ".txt");
- BlocksOpen.Remove(name);
- if (t.IndexOf((char)32002) == -1)
- return null;
- if (t[0] == (char)BlockMemoryVersion && t[1] == (char)32002)
- {
- t = t.Substring(2);
- string NextName = "";
- int position = 0, amn = t.Length;
- DateTime when = new DateTime();
- bool deleted = false;
- for (int i = 0; i < amn; ++i)
- {
- if (t[i] != (char)32001)
- {
- NextName = t.Substring(i, t.IndexOf((char)32001, i) - i);
- i += NextName.Length;
- }
-
- position = (int)t[++i] * 65336 + (int)t[++i];
- when = new DateTime(2000, 1, 1).AddSeconds((int)t[++i] * 65336 + (int)t[++i]);
- deleted = t[++i] != (char)32002;
- if (deleted) i++;
- list.Add(new Level.BlockPos(position, when, deleted, NextName));
- }
- }
- else
- {
- UpdateBlocks();
- return LoadBlocks(name);
- }
-
- return list;
- }
- return null;
- }
- public static void AddBlock(Level l, ushort x, ushort y, ushort z, bool deleted, string name)
- {
- l.blockCache.Add(new Level.BlockPos(l.PosToInt(x, y, z), DateTime.Now, deleted, name));
- }
- public static void AddBlock(Level l, int pos, bool deleted, string name)
- {
- l.blockCache.Add(new Level.BlockPos(pos, DateTime.Now, deleted, name));
- }
- public static void AddBlock(Level l, Level.BlockPos bP)
- {
- l.blockCache.Add(bP);
- }
- public static void AddBlocks(Level l, List<Level.BlockPos> lBP)
- {
- l.blockCache.AddRange(lBP.ToArray());
- }
-
- public static void Done()
- {
- GC.Collect();
- GC.WaitForPendingFinalizers();
- }
- private static ushort[] getDimensionsOfLevel(string level)
- {
- ushort[] dimensions = new ushort[3];
- Level l = Level.Find(level);
- if (l != null)
- {
- dimensions[0] = l.width;
- dimensions[1] = l.height;
- dimensions[2] = l.depth;
- }
- else if (File.Exists("levels/" + level + ".mcqlvl")) // no .lvl support, as that should've been converted
- {
- FileStream fs = File.OpenRead("levels/" + level + ".mcqlvl");
- try
- {
- GZipStream gs = new GZipStream(fs, CompressionMode.Decompress);
- byte[] ver = new byte[2];
- gs.Read(ver, 0, ver.Length);
- ushort version = BitConverter.ToUInt16(ver, 0);
- if (version == 2)
- {
- byte[] header = new byte[6];
- gs.Read(header, 0, header.Length);
- dimensions[0] = BitConverter.ToUInt16(header, 0);
- dimensions[1] = BitConverter.ToUInt16(header, 2);
- dimensions[2] = BitConverter.ToUInt16(header, 4);
- }
- else
- throw new NotSupportedException("mcqlvl version not supported");
- gs.Close();
- }
- catch (Exception ex) { Server.ErrorLog(ex); }
- finally { fs.Close(); }
- }
- else
- return null;
- return dimensions;
- }
- }
- }