PageRenderTime 51ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/MCQuai/Memory.cs

https://bitbucket.org/realquaisaq/mcrevive
C# | 543 lines | 475 code | 66 blank | 2 comment | 120 complexity | 7181cd22853acdc4cd52d64980a6b81a MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.IO.Compression;
  5. using System.Threading;
  6. namespace MCRevive
  7. {
  8. public class Memory
  9. {
  10. public static List<string> BlocksOpen = new List<string>();
  11. public static List<string> PortalsOpen = new List<string>();
  12. public const int BlockMemoryVersion = 2;
  13. public const int PortalMemoryVersion = 2;
  14. public static void ClearPortals(string level)
  15. {
  16. while (PortalsOpen.Contains(level))
  17. System.Threading.Thread.Sleep(10);
  18. if (File.Exists("memory/portals/" + level + ".txt"))
  19. File.Delete("memory/portals/" + level + ".txt");
  20. }
  21. public static void UpdatePortals(string levels = "")
  22. {
  23. //Does nothing yet - no newer portal memory
  24. //Add portal permissions?
  25. bool generate = false;
  26. if (!Directory.Exists("memory"))
  27. {
  28. Directory.CreateDirectory("memory");
  29. Directory.CreateDirectory("memory/portals");
  30. generate = true; ;
  31. }
  32. if (!Directory.Exists("memory/blocks"))
  33. {
  34. Directory.CreateDirectory("memory/portals");
  35. generate = true;
  36. }
  37. string[] files;
  38. if (levels == "")
  39. files = Directory.GetFiles("memory/portals");
  40. else
  41. {
  42. files = levels.Split(',');
  43. for (int i = 0; i < files.Length; i++)
  44. files[i] = "memory/portals/" + files[i] + ".txt";
  45. }
  46. if (!generate)
  47. for (int f = 0; f < files.Length; f++)
  48. {
  49. string name = files[f].Remove(files[f].LastIndexOf('.')).Substring(files[f].LastIndexOfAny(new char[] { '\\', '/' }) + 1);
  50. while (PortalsOpen.Contains(name))
  51. System.Threading.Thread.Sleep(10);
  52. if (File.Exists(files[f]))
  53. {
  54. PortalsOpen.Add(name);
  55. char[] getter = new char[1];
  56. StreamReader r = File.OpenText(files[f]);
  57. r.Read(getter, 0, 1);
  58. r.Close();
  59. r.Dispose();
  60. PortalsOpen.Remove(name);
  61. if (getter[0] == PortalMemoryVersion)
  62. continue;
  63. List<Level.PortalPos> list = new List<Level.PortalPos>();
  64. ushort[] dimensions = getDimensionsOfLevel(name);
  65. if (dimensions == null)
  66. continue;
  67. PortalsOpen.Add(name);
  68. string t = File.ReadAllText(files[f]);
  69. PortalsOpen.Remove(name);
  70. if (t.IndexOf((char)32002) == -1)
  71. continue;
  72. if (t[0] == (char)2)
  73. {
  74. t = t.Substring(1);
  75. int amn = t.Length;
  76. string endMap = "";
  77. for (int i = 0; i < amn; i += 2)
  78. {
  79. if (t[i] != (char)32001)
  80. {
  81. endMap = t.Substring(i, t.IndexOf((char)32001, i + 1));
  82. i += endMap.Length;
  83. }
  84. list.Add(new Level.PortalPos(t[++i] * 65336 + t[++i], t[++i] * 65336 + t[++i], endMap));
  85. }
  86. }
  87. int amount = list.Count;
  88. List<string> leNames = new List<string>();
  89. for (int i = 0; i < amount; i++)
  90. if (!leNames.Contains(list[i].end))
  91. leNames.Add(list[i].end);
  92. leNames.Sort();
  93. List<Level.PortalPos> finished = new List<Level.PortalPos>(amount);
  94. int amount2 = leNames.Count;
  95. for (int i = 0; i < amount2; i++)
  96. finished.AddRange(list.FindAll(li => li.end == leNames[i]));
  97. SavePortals(name, finished, true);
  98. }
  99. }
  100. else
  101. {
  102. for (int f = 0; f < files.Length; ++f)
  103. SaveBlocks(files[f], new List<Level.BlockPos>(), true);
  104. }
  105. }
  106. public static void SavePortals(string level, List<Level.PortalPos> list, bool resave = false)
  107. {
  108. while (PortalsOpen.Contains(level))
  109. System.Threading.Thread.Sleep(10);
  110. if (File.Exists("memory/portals/" + level + ".txt"))
  111. {
  112. if (new FileInfo("memory/portals/" + level + ".txt").Length < 10)
  113. resave = true;
  114. }
  115. else
  116. resave = true;
  117. PortalsOpen.Add(level);
  118. StreamWriter sw = new StreamWriter("memory/portals/" + level + ".txt", !resave, System.Text.Encoding.UTF8);
  119. try
  120. {
  121. if (resave)
  122. sw.Write((char)PortalMemoryVersion);
  123. string lastEnd = "";
  124. foreach (Level.PortalPos pP in list)
  125. {
  126. ushort pos11 = (ushort)(pP.pos / 65336);
  127. ushort pos12 = (ushort)(pP.pos % 65336);
  128. ushort pos21 = (ushort)(pP.pos2 / 65336);
  129. ushort pos22 = (ushort)(pP.pos2 % 65336);
  130. sw.Write((lastEnd == pP.end ? "" : pP.end) + (char)32001 + (char)pos11 + (char)pos12 + (char)pos21 + (char)pos22 + (char)32002);
  131. lastEnd = pP.end;
  132. }
  133. }
  134. catch (Exception ex) { Server.ErrorLog(ex); }
  135. finally
  136. {
  137. sw.Close();
  138. sw.Dispose();
  139. }
  140. PortalsOpen.Remove(level);
  141. }
  142. public static Level.PortalPos LoadPortal(string level, int pos)
  143. {
  144. while (PortalsOpen.Contains(level))
  145. System.Threading.Thread.Sleep(10);
  146. if (!Directory.Exists("memory") || !Directory.Exists("memory/portals") || !File.Exists("memory/portals/" + level + ".txt"))
  147. return null;
  148. PortalsOpen.Add(level);
  149. string t = File.ReadAllText("memory/portals/" + level + ".txt");
  150. PortalsOpen.Remove(level);
  151. if (t[0] == (char)PortalMemoryVersion)
  152. {
  153. t = t.Substring(1);
  154. int amn = t.Length;
  155. for (int i = 0; i < amn; ++i)
  156. {
  157. if (t[t.IndexOf((char)32001, i) + 1] * 65336 + (int)t[t.IndexOf((char)32001, i) + 2] != pos)
  158. {
  159. i = t.IndexOf((char)32001, i) + 5;
  160. continue;
  161. }
  162. string endMap = "";
  163. if (t[i] == (char)32001)
  164. {
  165. for (int ss = 6; ss < t.Length - 7; ss += 6)
  166. if (t[i - ss] == (char)32001 && t[i - ss - 1] != (char)32002)
  167. {
  168. if (t.IndexOf((char)32001) == i - ss)
  169. ss = i;
  170. else
  171. {
  172. while (t[i - ss] != (char)32002) ss++;
  173. ss--;
  174. }
  175. endMap = t.Substring(i - ss, t.IndexOf((char)32001, i - ss + 1) - i + ss);
  176. break;
  177. }
  178. }
  179. else
  180. {
  181. endMap = t.Substring(i, t.IndexOf((char)32001, i + 1) - i);
  182. i += endMap.Length;
  183. }
  184. ushort pos11 = t[++i];
  185. ushort pos12 = t[++i];
  186. ushort pos21 = t[++i];
  187. ushort pos22 = t[++i];
  188. return new Level.PortalPos(pos11 * 65336 + pos12, pos21 * 65336 + pos22, endMap);
  189. }
  190. }
  191. else
  192. {
  193. UpdatePortals(level);
  194. return LoadPortal(level, pos);
  195. }
  196. return null;
  197. }
  198. public static List<Level.PortalPos> LoadPortals(string level)
  199. {
  200. while (PortalsOpen.Contains(level))
  201. Thread.Sleep(10);
  202. if (!Directory.Exists("memory") || !Directory.Exists("memory/portals") || !File.Exists("memory/portals/" + level + ".txt"))
  203. return null;
  204. PortalsOpen.Add(level);
  205. string t = File.ReadAllText("memory/portals/" + level + ".txt");
  206. PortalsOpen.Remove(level);
  207. List<Level.PortalPos> list = new List<Level.PortalPos>();
  208. if (t[0] == (char)PortalMemoryVersion)
  209. {
  210. t = t.Substring(1);
  211. int amn = t.Length;
  212. string endMap = "";
  213. for (int i = 0; i < amn; i += 2)
  214. {
  215. if (t[i] != (char)32001)
  216. {
  217. endMap = t.Substring(i, t.IndexOf((char)32001, i + 1) - i);
  218. i += endMap.Length;
  219. }
  220. list.Add(new Level.PortalPos(t[++i] * 65336 + t[++i], t[++i] * 65336 + t[++i], endMap));
  221. }
  222. return list;
  223. }
  224. else
  225. {
  226. UpdatePortals(level);
  227. return LoadPortals(level);
  228. }
  229. }
  230. public static void ClearBlocks(string level)
  231. {
  232. while (BlocksOpen.Contains(level))
  233. System.Threading.Thread.Sleep(10);
  234. if (File.Exists("memory/blocks/" + level + ".txt"))
  235. File.Delete("memory/blocks/" + level + ".txt");
  236. }
  237. public static void UpdateBlocks(string ff = "")
  238. {
  239. bool generate = false;
  240. if (!Directory.Exists("memory"))
  241. {
  242. Directory.CreateDirectory("memory");
  243. Directory.CreateDirectory("memory/blocks");
  244. generate = true; ;
  245. }
  246. if (!Directory.Exists("memory/blocks"))
  247. {
  248. Directory.CreateDirectory("memory/blocks");
  249. generate = true;
  250. }
  251. string[] files;
  252. if (ff == "")
  253. files = Directory.GetFiles("memory/blocks");
  254. else
  255. {
  256. files = ff.Split(',');
  257. for (int i = 0; i < files.Length; i++)
  258. files[i] = "memory/blocks/" + files[i] + ".txt";
  259. }
  260. if (!generate)
  261. for (int f = 0; f < files.Length; f++)
  262. {
  263. string name = files[f].Remove(files[f].LastIndexOf('.')).Substring(files[f].LastIndexOfAny(new char[] { '\\', '/' }) + 1);
  264. while (BlocksOpen.Contains(name))
  265. System.Threading.Thread.Sleep(10);
  266. if (File.Exists(files[f]))
  267. {
  268. BlocksOpen.Add(name);
  269. char[] getter = new char[1];
  270. StreamReader r = File.OpenText(files[f]);
  271. r.Read(getter, 0, 1);
  272. r.Close();
  273. r.Dispose();
  274. BlocksOpen.Remove(name);
  275. if (getter[0] == BlockMemoryVersion)
  276. continue;
  277. List<Level.BlockPos> list = new List<Level.BlockPos>();
  278. ushort[] dimensions = getDimensionsOfLevel(name);
  279. if (dimensions == null)
  280. continue;
  281. BlocksOpen.Add(name);
  282. string t = File.ReadAllText(files[f]);
  283. BlocksOpen.Remove(name);
  284. if (t.IndexOf((char)32002) == -1)
  285. continue;
  286. if (t[1] == (char)32002)
  287. {
  288. if (t[0] == (char)2)
  289. {
  290. t = t.Substring(2);
  291. string NextName = "";
  292. int position = 0;
  293. DateTime when = new DateTime();
  294. bool deleted = false;
  295. int lastIndex = 0;
  296. for (int i = 0; i < t.Length; ++i)
  297. {
  298. if (t[i] != (char)32001)
  299. {
  300. NextName = t.Substring(i, t.IndexOf((char)32001, lastIndex));
  301. i += NextName.Length;
  302. }
  303. position = (int)t[++i] * 65336 + (int)t[++i];
  304. when = new DateTime(2000, 1, 1).AddSeconds((int)t[++i] * 65336 + (int)t[++i]);
  305. deleted = t[++i] != (char)32002;
  306. if (deleted) i++;
  307. list.Add(new Level.BlockPos(position, when, deleted, NextName));
  308. lastIndex = i;
  309. }
  310. }
  311. }
  312. else
  313. foreach (string s in t.Split((char)32002))
  314. if (s.Split((char)32001).Length > 2)
  315. 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]));
  316. int amount = list.Count;
  317. List<string> leNames = new List<string>();
  318. for (int i = 0; i < amount; i++)
  319. if (!leNames.Contains(list[i].name))
  320. leNames.Add(list[i].name);
  321. leNames.Sort();
  322. List<Level.BlockPos> finished = new List<Level.BlockPos>(amount);
  323. int amount2 = leNames.Count;
  324. for (int i = 0; i < amount2; i++)
  325. finished.AddRange(list.FindAll(li => li.name == leNames[i]));
  326. SaveBlocks(name, finished, true);
  327. }
  328. else
  329. generate = true;
  330. }
  331. else
  332. {
  333. for (int f = 0; f < files.Length; ++f)
  334. SaveBlocks(files[f], new List<Level.BlockPos>(), true);
  335. }
  336. }
  337. public static void SaveBlocks(string level, List<Level.BlockPos> list, bool resave = false)
  338. {
  339. while (BlocksOpen.Contains(level))
  340. System.Threading.Thread.Sleep(10);
  341. if (File.Exists("memory/blocks/" + level + ".txt"))
  342. {
  343. if (new FileInfo("memory/blocks/" + level + ".txt").Length < 10)
  344. resave = true;
  345. }
  346. else
  347. resave = true;
  348. StreamWriter sw = new StreamWriter("memory/blocks/" + level + ".txt", !resave, System.Text.Encoding.UTF8);
  349. try
  350. {
  351. if (resave)
  352. sw.Write((char)BlockMemoryVersion + "" + (char)32002);
  353. string lastName = "";
  354. foreach (Level.BlockPos bP in list)
  355. {
  356. int a = (int)(bP.TimePerformed - new DateTime(2000, 1, 1)).TotalSeconds;
  357. ushort sec1 = (ushort)(a / 65336);
  358. ushort sec2 = (ushort)(a % 65336);
  359. ushort pos1 = (ushort)(bP.pos / 65336);
  360. ushort pos2 = (ushort)(bP.pos % 65336);
  361. 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
  362. lastName = bP.name;
  363. }
  364. }
  365. catch (Exception ex) { Server.ErrorLog(ex); }
  366. finally
  367. {
  368. sw.Close();
  369. sw.Dispose();
  370. }
  371. }
  372. public static List<Level.BlockPos> LoadBlocks(string name)
  373. {
  374. while (BlocksOpen.Contains(name))
  375. System.Threading.Thread.Sleep(10);
  376. if (File.Exists("memory/blocks/" + name + ".txt"))
  377. {
  378. List<Level.BlockPos> list = new List<Level.BlockPos>();
  379. ushort[] dimensions = getDimensionsOfLevel(name);
  380. if (dimensions == null)
  381. return null;
  382. BlocksOpen.Add(name);
  383. string t = File.ReadAllText("memory/blocks/" + name + ".txt");
  384. BlocksOpen.Remove(name);
  385. if (t.IndexOf((char)32002) == -1)
  386. return null;
  387. if (t[0] == (char)BlockMemoryVersion && t[1] == (char)32002)
  388. {
  389. t = t.Substring(2);
  390. string NextName = "";
  391. int position = 0, amn = t.Length;
  392. DateTime when = new DateTime();
  393. bool deleted = false;
  394. for (int i = 0; i < amn; ++i)
  395. {
  396. if (t[i] != (char)32001)
  397. {
  398. NextName = t.Substring(i, t.IndexOf((char)32001, i) - i);
  399. i += NextName.Length;
  400. }
  401. position = (int)t[++i] * 65336 + (int)t[++i];
  402. when = new DateTime(2000, 1, 1).AddSeconds((int)t[++i] * 65336 + (int)t[++i]);
  403. deleted = t[++i] != (char)32002;
  404. if (deleted) i++;
  405. list.Add(new Level.BlockPos(position, when, deleted, NextName));
  406. }
  407. }
  408. else
  409. {
  410. UpdateBlocks();
  411. return LoadBlocks(name);
  412. }
  413. return list;
  414. }
  415. return null;
  416. }
  417. public static void AddBlock(Level l, ushort x, ushort y, ushort z, bool deleted, string name)
  418. {
  419. l.blockCache.Add(new Level.BlockPos(l.PosToInt(x, y, z), DateTime.Now, deleted, name));
  420. }
  421. public static void AddBlock(Level l, int pos, bool deleted, string name)
  422. {
  423. l.blockCache.Add(new Level.BlockPos(pos, DateTime.Now, deleted, name));
  424. }
  425. public static void AddBlock(Level l, Level.BlockPos bP)
  426. {
  427. l.blockCache.Add(bP);
  428. }
  429. public static void AddBlocks(Level l, List<Level.BlockPos> lBP)
  430. {
  431. l.blockCache.AddRange(lBP.ToArray());
  432. }
  433. public static void Done()
  434. {
  435. GC.Collect();
  436. GC.WaitForPendingFinalizers();
  437. }
  438. private static ushort[] getDimensionsOfLevel(string level)
  439. {
  440. ushort[] dimensions = new ushort[3];
  441. Level l = Level.Find(level);
  442. if (l != null)
  443. {
  444. dimensions[0] = l.width;
  445. dimensions[1] = l.height;
  446. dimensions[2] = l.depth;
  447. }
  448. else if (File.Exists("levels/" + level + ".mcqlvl")) // no .lvl support, as that should've been converted
  449. {
  450. FileStream fs = File.OpenRead("levels/" + level + ".mcqlvl");
  451. try
  452. {
  453. GZipStream gs = new GZipStream(fs, CompressionMode.Decompress);
  454. byte[] ver = new byte[2];
  455. gs.Read(ver, 0, ver.Length);
  456. ushort version = BitConverter.ToUInt16(ver, 0);
  457. if (version == 2)
  458. {
  459. byte[] header = new byte[6];
  460. gs.Read(header, 0, header.Length);
  461. dimensions[0] = BitConverter.ToUInt16(header, 0);
  462. dimensions[1] = BitConverter.ToUInt16(header, 2);
  463. dimensions[2] = BitConverter.ToUInt16(header, 4);
  464. }
  465. else
  466. throw new NotSupportedException("mcqlvl version not supported");
  467. gs.Close();
  468. }
  469. catch (Exception ex) { Server.ErrorLog(ex); }
  470. finally { fs.Close(); }
  471. }
  472. else
  473. return null;
  474. return dimensions;
  475. }
  476. }
  477. }