PageRenderTime 58ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/TEditXna/Terraria/World.cs

https://github.com/Surfpup/Terraria-Map-Editor
C# | 1535 lines | 1218 code | 160 blank | 157 comment | 172 complexity | 52b2a256d43a0185905eb8843becf985 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. using System.ComponentModel;
  2. using System.Windows;
  3. using BCCL.Geometry;
  4. using BCCL.MvvmLight;
  5. using BCCL.Utility;
  6. using Microsoft.Xna.Framework;
  7. using TEditXNA.Terraria.Objects;
  8. using BCCL.Geometry.Primitives;
  9. using Vector2 = BCCL.Geometry.Primitives.Vector2;
  10. using Ionic.Zip;
  11. using System.Web.Script.Serialization;
  12. using System.Text.RegularExpressions;
  13. using System.Collections;
  14. using TEditXna.Terraria;
  15. using Gajatko.IniFiles;
  16. namespace TEditXNA.Terraria
  17. {
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Collections.ObjectModel;
  21. using System.IO;
  22. using System.Linq;
  23. public partial class World : ObservableObject
  24. {
  25. private static object _fileLock = new object();
  26. /// <summary>
  27. /// Triggered when an operation reports progress.
  28. /// </summary>
  29. public static event ProgressChangedEventHandler ProgressChanged;
  30. private static void OnProgressChanged(object sender, ProgressChangedEventArgs e)
  31. {
  32. if (ProgressChanged != null)
  33. ProgressChanged(sender, e);
  34. }
  35. public World()
  36. {
  37. NPCs.Clear();
  38. Signs.Clear();
  39. Chests.Clear();
  40. CharacterNames.Clear();
  41. }
  42. public World(int height, int width, string title, int seed = -1)
  43. : this()
  44. {
  45. TilesWide = width;
  46. TilesHigh = height;
  47. Title = title;
  48. var r = seed <= 0 ? new Random((int)DateTime.Now.Ticks) : new Random(seed);
  49. WorldId = r.Next(int.MaxValue);
  50. _npcs.Clear();
  51. _signs.Clear();
  52. _chests.Clear();
  53. _charNames.Clear();
  54. }
  55. public Tile[,] Tiles;
  56. private readonly ObservableCollection<NPC> _npcs = new ObservableCollection<NPC>();
  57. public ObservableCollection<NPC> NPCs
  58. {
  59. get { return _npcs; }
  60. }
  61. private readonly ObservableCollection<Sign> _signs = new ObservableCollection<Sign>();
  62. public ObservableCollection<Sign> Signs
  63. {
  64. get { return _signs; }
  65. }
  66. private readonly ObservableCollection<Chest> _chests = new ObservableCollection<Chest>();
  67. public ObservableCollection<Chest> Chests
  68. {
  69. get { return _chests; }
  70. }
  71. private readonly ObservableCollection<NpcName> _charNames = new ObservableCollection<NpcName>();
  72. public ObservableCollection<NpcName> CharacterNames
  73. {
  74. get { return _charNames; }
  75. }
  76. public uint Version;
  77. private string _title;
  78. private int _spawnX;
  79. private int _spawnY;
  80. private double _groundLevel;
  81. private double _rockLevel;
  82. private double _time;
  83. private bool _dayTime;
  84. private int _moonPhase;
  85. private bool _bloodMoon;
  86. private int _dungeonX;
  87. private int _dungeonY;
  88. private bool _downedBoss1;
  89. private bool _downedBoss2;
  90. private bool _downedBoss3;
  91. private bool _savedGoblin;
  92. private bool _savedWizard;
  93. private bool _downedGoblins;
  94. private bool _savedMech;
  95. private bool _downedClown;
  96. private bool _downedFrost;
  97. private bool _shadowOrbSmashed;
  98. private bool _spawnMeteor;
  99. private int _shadowOrbCount;
  100. private int _altarCount;
  101. private bool _hardMode;
  102. private double _invasionX;
  103. private int _invasionType;
  104. private int _invasionSize;
  105. private int _invasionDelay;
  106. private int _worldId;
  107. private float _leftWorld;
  108. private float _rightWorld;
  109. private float _topWorld;
  110. private float _bottomWorld;
  111. private int _tilesHigh;
  112. private int _tilesWide;
  113. private DateTime _lastSave;
  114. #region Properties
  115. public int TilesWide
  116. {
  117. get { return _tilesWide; }
  118. set { Set("TilesWide", ref _tilesWide, value); }
  119. }
  120. public int TilesHigh
  121. {
  122. get { return _tilesHigh; }
  123. set { Set("TilesHigh", ref _tilesHigh, value); }
  124. }
  125. public float BottomWorld
  126. {
  127. get { return _bottomWorld; }
  128. set { Set("BottomWorld", ref _bottomWorld, value); }
  129. }
  130. public float TopWorld
  131. {
  132. get { return _topWorld; }
  133. set { Set("TopWorld", ref _topWorld, value); }
  134. }
  135. public float RightWorld
  136. {
  137. get { return _rightWorld; }
  138. set { Set("RightWorld", ref _rightWorld, value); }
  139. }
  140. public float LeftWorld
  141. {
  142. get { return _leftWorld; }
  143. set { Set("LeftWorld", ref _leftWorld, value); }
  144. }
  145. public int WorldId
  146. {
  147. get { return _worldId; }
  148. set { Set("WorldId", ref _worldId, value); }
  149. }
  150. public bool DownedFrost
  151. {
  152. get { return _downedFrost; }
  153. set { Set("DownedFrost", ref _downedFrost, value); }
  154. }
  155. public string Title
  156. {
  157. get { return _title; }
  158. set { Set("Title", ref _title, value); }
  159. }
  160. public int SpawnX
  161. {
  162. get { return _spawnX; }
  163. set { Set("SpawnX", ref _spawnX, value); }
  164. }
  165. public int SpawnY
  166. {
  167. get { return _spawnY; }
  168. set { Set("SpawnY", ref _spawnY, value); }
  169. }
  170. public double GroundLevel
  171. {
  172. get { return _groundLevel; }
  173. set
  174. {
  175. Set("GroundLevel", ref _groundLevel, value);
  176. if (_groundLevel > _rockLevel)
  177. RockLevel = _groundLevel;
  178. }
  179. }
  180. public double RockLevel
  181. {
  182. get { return _rockLevel; }
  183. set
  184. {
  185. Set("RockLevel", ref _rockLevel, value);
  186. if (_groundLevel > _rockLevel)
  187. GroundLevel = _rockLevel;
  188. }
  189. }
  190. public double Time
  191. {
  192. get { return _time; }
  193. set { Set("Time", ref _time, value); }
  194. }
  195. public bool DayTime
  196. {
  197. get { return _dayTime; }
  198. set { Set("DayTime", ref _dayTime, value); }
  199. }
  200. public int MoonPhase
  201. {
  202. get { return _moonPhase; }
  203. set { Set("MoonPhase", ref _moonPhase, value); }
  204. }
  205. public bool BloodMoon
  206. {
  207. get { return _bloodMoon; }
  208. set { Set("BloodMoon", ref _bloodMoon, value); }
  209. }
  210. public int DungeonX
  211. {
  212. get { return _dungeonX; }
  213. set { Set("DungeonX", ref _dungeonX, value); }
  214. }
  215. public int DungeonY
  216. {
  217. get { return _dungeonY; }
  218. set { Set("DungeonY", ref _dungeonY, value); }
  219. }
  220. public bool DownedBoss1
  221. {
  222. get { return _downedBoss1; }
  223. set { Set("DownedBoss1", ref _downedBoss1, value); }
  224. }
  225. public bool DownedBoss2
  226. {
  227. get { return _downedBoss2; }
  228. set { Set("DownedBoss2", ref _downedBoss2, value); }
  229. }
  230. public bool DownedBoss3
  231. {
  232. get { return _downedBoss3; }
  233. set { Set("DownedBoss3", ref _downedBoss3, value); }
  234. }
  235. public bool SavedGoblin
  236. {
  237. get { return _savedGoblin; }
  238. set { Set("SavedGoblin", ref _savedGoblin, value); }
  239. }
  240. public bool SavedWizard
  241. {
  242. get { return _savedWizard; }
  243. set { Set("SavedWizard", ref _savedWizard, value); }
  244. }
  245. public bool DownedGoblins
  246. {
  247. get { return _downedGoblins; }
  248. set { Set("DownedGoblins", ref _downedGoblins, value); }
  249. }
  250. public bool SavedMech
  251. {
  252. get { return _savedMech; }
  253. set { Set("SavedMech", ref _savedMech, value); }
  254. }
  255. public bool DownedClown
  256. {
  257. get { return _downedClown; }
  258. set { Set("DownedClown", ref _downedClown, value); }
  259. }
  260. public bool ShadowOrbSmashed
  261. {
  262. get { return _shadowOrbSmashed; }
  263. set { Set("ShadowOrbSmashed", ref _shadowOrbSmashed, value); }
  264. }
  265. public bool SpawnMeteor
  266. {
  267. get { return _spawnMeteor; }
  268. set { Set("SpawnMeteor", ref _spawnMeteor, value); }
  269. }
  270. public int ShadowOrbCount
  271. {
  272. get { return _shadowOrbCount; }
  273. set
  274. {
  275. Set("ShadowOrbCount", ref _shadowOrbCount, value);
  276. ShadowOrbSmashed = _shadowOrbCount > 0;
  277. }
  278. }
  279. public int AltarCount
  280. {
  281. get { return _altarCount; }
  282. set { Set("AltarCount", ref _altarCount, value); }
  283. }
  284. public bool HardMode
  285. {
  286. get { return _hardMode; }
  287. set { Set("HardMode", ref _hardMode, value); }
  288. }
  289. public double InvasionX
  290. {
  291. get { return _invasionX; }
  292. set { Set("InvasionX", ref _invasionX, value); }
  293. }
  294. public int InvasionType
  295. {
  296. get { return _invasionType; }
  297. set { Set("InvasionType", ref _invasionType, value); }
  298. }
  299. public int InvasionSize
  300. {
  301. get { return _invasionSize; }
  302. set { Set("InvasionSize", ref _invasionSize, value); }
  303. }
  304. public int InvasionDelay
  305. {
  306. get { return _invasionDelay; }
  307. set { Set("InvasionDelay", ref _invasionDelay, value); }
  308. }
  309. internal DateTime LastSave
  310. {
  311. get { return _lastSave; }
  312. set { Set("LastSave", ref _lastSave, value); }
  313. }
  314. #endregion
  315. public bool ValidTileLocation(Vector2Int32 point)
  316. {
  317. if (point.X < 0)
  318. return false;
  319. if (point.Y < 0)
  320. return false;
  321. if (point.Y >= _tilesHigh)
  322. return false;
  323. if (point.X >= _tilesWide)
  324. return false;
  325. return true;
  326. }
  327. public Chest GetChestAtTile(int x, int y)
  328. {
  329. return Chests.FirstOrDefault(c => (c.X == x || c.X == x - 1) && (c.Y == y || c.Y == y - 1));
  330. }
  331. public Sign GetSignAtTile(int x, int y)
  332. {
  333. return Signs.FirstOrDefault(c => (c.X == x || c.X == x - 1) && (c.Y == y || c.Y == y - 1));
  334. }
  335. public void Save(string filename, bool resetTime = false)
  336. {
  337. lock (_fileLock)
  338. {
  339. if (resetTime)
  340. {
  341. OnProgressChanged(this, new ProgressChangedEventArgs(0, "Resetting Time..."));
  342. ResetTime();
  343. }
  344. if (filename == null)
  345. return;
  346. string temp = filename + ".tmp";
  347. using (var fs = new FileStream(temp, FileMode.Create))
  348. {
  349. using (var bw = new BinaryWriter(fs))
  350. {
  351. bw.Write(World.CompatibleVersion);
  352. bw.Write(Title);
  353. bw.Write(WorldId);
  354. bw.Write((int)LeftWorld);
  355. bw.Write((int)RightWorld);
  356. bw.Write((int)TopWorld);
  357. bw.Write((int)BottomWorld);
  358. bw.Write(TilesHigh);
  359. bw.Write(TilesWide);
  360. bw.Write(SpawnX);
  361. bw.Write(SpawnY);
  362. bw.Write(GroundLevel);
  363. bw.Write(RockLevel);
  364. bw.Write(Time);
  365. bw.Write(DayTime);
  366. bw.Write(MoonPhase);
  367. bw.Write(BloodMoon);
  368. bw.Write(DungeonX);
  369. bw.Write(DungeonY);
  370. bw.Write(DownedBoss1);
  371. bw.Write(DownedBoss2);
  372. bw.Write(DownedBoss3);
  373. bw.Write(SavedGoblin);
  374. bw.Write(SavedWizard);
  375. bw.Write(SavedMech);
  376. bw.Write(DownedGoblins);
  377. bw.Write(DownedClown);
  378. bw.Write(DownedFrost);
  379. bw.Write(ShadowOrbSmashed);
  380. bw.Write(SpawnMeteor);
  381. bw.Write((byte)ShadowOrbCount);
  382. bw.Write(AltarCount);
  383. bw.Write(HardMode);
  384. bw.Write(InvasionDelay);
  385. bw.Write(InvasionSize);
  386. bw.Write(InvasionType);
  387. bw.Write(InvasionX);
  388. for (int x = 0; x < TilesWide; ++x)
  389. {
  390. OnProgressChanged(this, new ProgressChangedEventArgs(x.ProgressPercentage(TilesWide), "Saving Tiles..."));
  391. int rle = 0;
  392. for (int y = 0; y < TilesHigh; y = y + rle + 1)
  393. {
  394. var curTile = Tiles[x, y];
  395. bw.Write(curTile.IsActive);
  396. if (curTile.IsActive)
  397. {
  398. bw.Write(curTile.Type);
  399. if (TileProperties[curTile.Type].IsFramed)
  400. {
  401. bw.Write(curTile.U);
  402. bw.Write(curTile.V);
  403. // TODO: Let Validate handle these
  404. //validate chest entry exists
  405. if (curTile.Type == 21)
  406. {
  407. if (GetChestAtTile(x, y) == null)
  408. {
  409. Chests.Add(new Chest(x, y));
  410. }
  411. }
  412. //validate sign entry exists
  413. else if (curTile.Type == 55 || curTile.Type == 85)
  414. {
  415. if (GetSignAtTile(x, y) == null)
  416. {
  417. Signs.Add(new Sign(x, y, string.Empty));
  418. }
  419. }
  420. }
  421. }
  422. if ((int)curTile.Wall > 0)
  423. {
  424. bw.Write(true);
  425. bw.Write(curTile.Wall);
  426. }
  427. else
  428. bw.Write(false);
  429. if ((int)curTile.Liquid > 0)
  430. {
  431. bw.Write(true);
  432. bw.Write(curTile.Liquid);
  433. bw.Write(curTile.IsLava);
  434. }
  435. else
  436. bw.Write(false);
  437. bw.Write(curTile.HasWire);
  438. int rleTemp = 1;
  439. while (y + rleTemp < TilesHigh && curTile.Equals(Tiles[x, (y + rleTemp)]))
  440. ++rleTemp;
  441. rle = rleTemp - 1;
  442. bw.Write((short)rle);
  443. }
  444. }
  445. OnProgressChanged(null, new ProgressChangedEventArgs(100, "Saving Chests..."));
  446. for (int i = 0; i < 1000; ++i)
  447. {
  448. if (i >= Chests.Count)
  449. {
  450. bw.Write(false);
  451. }
  452. else
  453. {
  454. Chest curChest = Chests[i];
  455. bw.Write(true);
  456. bw.Write(curChest.X);
  457. bw.Write(curChest.Y);
  458. for (int j = 0; j < Chest.MaxItems; ++j)
  459. {
  460. if (curChest.Items.Count > j)
  461. {
  462. bw.Write((byte)curChest.Items[j].StackSize);
  463. if (curChest.Items[j].StackSize > 0)
  464. {
  465. bw.Write(curChest.Items[j].NetId); // TODO Verify
  466. bw.Write(curChest.Items[j].Prefix);
  467. }
  468. }
  469. else
  470. bw.Write((byte)0);
  471. }
  472. }
  473. }
  474. OnProgressChanged(null, new ProgressChangedEventArgs(100, "Saving Signs..."));
  475. for (int i = 0; i < 1000; ++i)
  476. {
  477. if (i >= Signs.Count || string.IsNullOrWhiteSpace(Signs[i].Text))
  478. {
  479. bw.Write(false);
  480. }
  481. else
  482. {
  483. var curSign = Signs[i];
  484. bw.Write(true);
  485. bw.Write(curSign.Text);
  486. bw.Write(curSign.X);
  487. bw.Write(curSign.Y);
  488. }
  489. }
  490. OnProgressChanged(null, new ProgressChangedEventArgs(100, "Saving NPC Data..."));
  491. foreach (NPC curNpc in NPCs)
  492. {
  493. bw.Write(true);
  494. bw.Write(curNpc.Name);
  495. bw.Write(curNpc.Position.X);
  496. bw.Write(curNpc.Position.Y);
  497. bw.Write(curNpc.IsHomeless);
  498. bw.Write(curNpc.Home.X);
  499. bw.Write(curNpc.Home.Y);
  500. }
  501. bw.Write(false);
  502. OnProgressChanged(null, new ProgressChangedEventArgs(100, "Saving NPC Names..."));
  503. bw.Write(CharacterNames.FirstOrDefault(c => c.Id == 17).Name);
  504. bw.Write(CharacterNames.FirstOrDefault(c => c.Id == 18).Name);
  505. bw.Write(CharacterNames.FirstOrDefault(c => c.Id == 19).Name);
  506. bw.Write(CharacterNames.FirstOrDefault(c => c.Id == 20).Name);
  507. bw.Write(CharacterNames.FirstOrDefault(c => c.Id == 22).Name);
  508. bw.Write(CharacterNames.FirstOrDefault(c => c.Id == 54).Name);
  509. bw.Write(CharacterNames.FirstOrDefault(c => c.Id == 38).Name);
  510. bw.Write(CharacterNames.FirstOrDefault(c => c.Id == 107).Name);
  511. bw.Write(CharacterNames.FirstOrDefault(c => c.Id == 108).Name);
  512. bw.Write(CharacterNames.FirstOrDefault(c => c.Id == 124).Name);
  513. OnProgressChanged(null, new ProgressChangedEventArgs(100, "Saving Validation Data..."));
  514. bw.Write(true);
  515. bw.Write(Title);
  516. bw.Write(WorldId);
  517. bw.Close();
  518. fs.Close();
  519. // make a backup of current file if it exists
  520. if (File.Exists(filename))
  521. {
  522. string backup = filename + ".TEdit";
  523. File.Copy(filename, backup, true);
  524. }
  525. // replace actual file with temp save file
  526. File.Copy(temp, filename, true);
  527. // delete temp save file
  528. File.Delete(temp);
  529. OnProgressChanged(null, new ProgressChangedEventArgs(0, "World Save Complete."));
  530. }
  531. }
  532. _lastSave = File.GetLastWriteTimeUtc(filename);
  533. }
  534. }
  535. public void ResetTime()
  536. {
  537. DayTime = true;
  538. Time = 13500.0;
  539. MoonPhase = 0;
  540. BloodMoon = false;
  541. }
  542. public static World LoadWorldTC(string filename)
  543. {
  544. World w = new World();
  545. try
  546. {
  547. MemoryStream data = new MemoryStream();
  548. MemoryStream tiles = new MemoryStream();
  549. MemoryStream NPCs = new MemoryStream();
  550. MemoryStream NPCNames = new MemoryStream();
  551. MemoryStream signs = new MemoryStream();
  552. MemoryStream tileData = new MemoryStream();
  553. MemoryStream globalData = new MemoryStream();
  554. MemoryStream chests = new MemoryStream();
  555. MemoryStream chestData = new MemoryStream();
  556. using (ZipFile zip = ZipFile.Read(filename))
  557. {
  558. foreach (ZipEntry e in zip)
  559. {
  560. string name = e.FileName.ToLower();
  561. if (name == "world.txt") e.Extract(data);
  562. else if (name == "world.tiles") e.Extract(tiles);
  563. else if (name == "world.npcs") e.Extract(NPCs);
  564. else if (name == "world.npcnames") e.Extract(NPCNames);
  565. else if (name == "world.signs") e.Extract(signs);
  566. else if (name == "world.tiles.moddata") e.Extract(tileData);
  567. else if (name == "world.global.moddata") e.Extract(globalData);
  568. else if (name == "world.chests") e.Extract(chests);
  569. else if (name == "world.chests.moddata") e.Extract(chestData);
  570. }
  571. //zip.Dispose();
  572. }
  573. data.Position = 0;
  574. tiles.Position = 0;
  575. NPCs.Position = 0;
  576. NPCNames.Position = 0;
  577. signs.Position = 0;
  578. tileData.Position = 0;
  579. globalData.Position = 0;
  580. chests.Position = 0;
  581. chestData.Position = 0;
  582. //Load version number (from somewhere)
  583. int release = 39;
  584. int version = 4;
  585. int[] versions = loadWorldData(w, data);
  586. release = versions[0];
  587. version = versions[1];
  588. loadWorldTiles(w, release, tiles);
  589. loadWorldChests(w, release, chests, chestData);
  590. loadWorldNPCs(w, release, NPCs);
  591. loadWorldNPCNames(w, release, NPCNames);
  592. loadWorldSigns(w, release, signs);
  593. /*Config.LoadGlobalModData(globalData, "ModWorld");
  594. Config.LoadCustomTileData(tileData, version);
  595. */
  596. OnProgressChanged(null, new ProgressChangedEventArgs(0, "World Load Complete."));
  597. w.LastSave = File.GetLastWriteTimeUtc(filename);
  598. }
  599. catch (Exception err)
  600. {
  601. string msg = "There was an error reading the world file, do you wish to force it to load anyway?\r\n\r\n" +
  602. "WARNING: This may have unexpected results including corrupt world files and program crashes.\r\n\r\n" +
  603. "The error is :\r\n";
  604. if (MessageBox.Show(msg + err, "World File Error", MessageBoxButton.YesNo, MessageBoxImage.Error) != MessageBoxResult.Yes)
  605. return null;
  606. }
  607. return w;
  608. }
  609. public static int[] loadWorldData(World w, MemoryStream stream)
  610. {
  611. //string savePath = Path.Combine(Main.worldTempPath, "world.txt");
  612. //stream.Position = 0;
  613. StreamReader reader = new StreamReader(stream);
  614. string data = reader.ReadToEnd();
  615. //Debug.WriteLine("stream:\n" + data);
  616. Regex.Replace(data, @"\s", "");
  617. Dictionary<string, object> dict = new Dictionary<string, object>();
  618. JavaScriptSerializer ser = new JavaScriptSerializer();
  619. dict = ser.Deserialize<Dictionary<string, object>>(data);
  620. int tConfigRelease = (int)dict["tConfig save version"];
  621. Dictionary<string, object> header = (Dictionary<string, object>)dict["header"];
  622. int baseVersion = (int)header["baseversion"];
  623. w.Version = (uint) baseVersion; //now we care about the version
  624. w.Title = header["name"].ToString();
  625. ArrayList rect = (ArrayList)header["worldrect"];
  626. w.WorldId = (int)header["ID"];
  627. w.LeftWorld = (float)(int)rect[0];
  628. w.RightWorld = (float)(int)rect[1];
  629. w.TopWorld = (float)(int)rect[2];
  630. w.BottomWorld = (float)(int)rect[3];
  631. w.TilesHigh = (int)header["height"];
  632. w.TilesWide = (int)header["width"];
  633. if (w.TilesHigh > 10000 || w.TilesWide > 10000 || w.TilesHigh <= 0 || w.TilesWide <= 0)
  634. throw new FileLoadException(string.Format("Invalid File: {0}", "File!?"));
  635. ArrayList spawn = (ArrayList)header["spawn"];
  636. w.SpawnX = (int)spawn[0];
  637. w.SpawnY = (int)spawn[1];
  638. w.GroundLevel = (int)header["groundlevel"];
  639. w.RockLevel = (int)header["rocklevel"];
  640. // read world flags
  641. w.Time = Convert.ToSingle(header["time"], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  642. w.DayTime = Convert.ToBoolean((int)header["is_day"]);
  643. w.MoonPhase = (int)header["moonphase"];
  644. w.BloodMoon = Convert.ToBoolean((int)header["is_bloodmoon"]);
  645. ArrayList dung = (ArrayList)header["dungeon_xy"];
  646. w.DungeonX = (int)dung[0];
  647. w.DungeonY = (int)dung[1];
  648. ArrayList slainBoss = (ArrayList)header["bosses_slain"];
  649. w.DownedBoss1 = Convert.ToBoolean((int)slainBoss[0]);
  650. w.DownedBoss2 = Convert.ToBoolean((int)slainBoss[1]);
  651. w.DownedBoss3 = Convert.ToBoolean((int)slainBoss[2]);
  652. ArrayList savedNPCs = (ArrayList)header["npcs_saved"];
  653. w.SavedGoblin = Convert.ToBoolean((int)savedNPCs[0]);
  654. w.SavedWizard = Convert.ToBoolean((int)savedNPCs[1]);
  655. if (w.Version >= 34)
  656. w.SavedMech = Convert.ToBoolean((int)savedNPCs[2]);
  657. ArrayList downed = (ArrayList)header["special_slain"];
  658. w.DownedGoblins = Convert.ToBoolean((int)downed[0]);
  659. w.DownedClown = Convert.ToBoolean((int)downed[1]);
  660. w.DownedFrost = Convert.ToBoolean((int)downed[2]);
  661. w.ShadowOrbSmashed = Convert.ToBoolean((int)header["is_a_shadow_orb_broken"]);
  662. w.SpawnMeteor = Convert.ToBoolean((int)header["is_meteor_spawned"]);
  663. w.ShadowOrbCount = (int)header["shadow_orbs_broken"];
  664. w.AltarCount = (int)header["altars_broken"];
  665. w.HardMode = Convert.ToBoolean((int)header["hardmode"]);
  666. w.InvasionDelay = (int)header["gob_inv_time"];
  667. w.InvasionSize = (int)header["gob_inv_size"];
  668. w.InvasionType = (int)header["gob_inv_type"];
  669. w.InvasionX = Convert.ToSingle(header["gob_inv_x"], System.Globalization.CultureInfo.InvariantCulture.NumberFormat);
  670. //Custom tConfig info comes next...
  671. Config.tileDefs = new DefHandler();
  672. Config.wallDefs = new DefHandler();
  673. ArrayList tiles = (ArrayList)dict["tiles"];
  674. for (int i = 0; i < tiles.Count; i++)
  675. {
  676. ArrayList thetile = (ArrayList)tiles[i];
  677. int id = (int)thetile[0];
  678. string name = thetile[1].ToString();
  679. Config.tileDefs.load[id] = name;
  680. Config.tileDefs.color[id] = (ArrayList)thetile[4];
  681. // p.IsFramed = Convert.ToBoolean((int)thetile[2]);
  682. // p.IsSolid = Convert.ToBoolean((int)thetile[3]);
  683. //
  684. }
  685. ArrayList walls = (ArrayList)dict["walls"];
  686. for (int i = 0; i < walls.Count; i++)
  687. {
  688. ArrayList thewall = (ArrayList)walls[i];
  689. int id = (int)thewall[0];
  690. string name = thewall[1].ToString();
  691. //Debug.WriteLine("Wall load:" + id + "=" + name);
  692. Config.wallDefs.load[id] = name;
  693. WallProperty p = new WallProperty();
  694. p.Id = id;
  695. p.Name = name;
  696. ArrayList colors;
  697. try
  698. {
  699. colors = (ArrayList)thewall[2];
  700. p.Color = System.Windows.Media.Color.FromArgb((byte) 255, (byte)colors[0], (byte)colors[1], (byte)colors[2]);
  701. }
  702. catch (Exception e)
  703. {
  704. //colors = new ArrayList(new int[]{0,0,0});
  705. p.Color = System.Windows.Media.Color.FromArgb(255, 255, 0, 255);
  706. }
  707. _wallProperties[id] = p;
  708. }
  709. // Config.tileDefs.loadModname = new Dictionary<int, string>();
  710. Dictionary<string, object> modtiles = (Dictionary<string, object>)dict["modtiles"];
  711. foreach (string str in modtiles.Keys)
  712. {
  713. ArrayList arr = (ArrayList)modtiles[str];
  714. foreach (int id in arr)
  715. {
  716. Config.tileDefs.loadModname[id] = str;
  717. }
  718. }
  719. foreach (int id in Config.tileDefs.loadModname.Keys)
  720. {
  721. Console.WriteLine("Loading tile " + Config.tileDefs.load[id] + " (" + id + ") from mod " + Config.tileDefs.loadModname[id]);
  722. string iniPath = string.Concat(new object[]
  723. {
  724. Environment.GetFolderPath(Environment.SpecialFolder.Personal),
  725. Path.DirectorySeparatorChar,
  726. "My Games",
  727. Path.DirectorySeparatorChar,
  728. "Terraria",
  729. Path.DirectorySeparatorChar,
  730. "ModPacks",
  731. Path.DirectorySeparatorChar,
  732. Config.tileDefs.loadModname[id],
  733. Path.DirectorySeparatorChar,
  734. "Tile",
  735. Path.DirectorySeparatorChar,
  736. Config.tileDefs.load[id]+".ini"
  737. });
  738. TileProperty p = new TileProperty();
  739. p.Id = id;
  740. p.Name = Config.tileDefs.load[id];
  741. // p.IsFramed = Convert.ToBoolean((int)thetile[2]);
  742. // p.IsSolid = Convert.ToBoolean((int)thetile[3]);
  743. IniFile ini = IniFile.FromFile(iniPath);
  744. p.IsFramed = Convert.ToBoolean(ini["Stats"]["FrameImportant"]);
  745. p.IsSolid = Convert.ToBoolean(ini["Stats"]["Solid"]);
  746. p.IsSolidTop = Convert.ToBoolean(ini["Stats"]["SolidTop"]);
  747. p.IsLight = Convert.ToBoolean(ini["Stats"]["BlockLight"]);
  748. p.FrameSize = new Vector2Short((short)Convert.ToInt32(ini["Stats"]["Width"]), (short)Convert.ToInt32(ini["Stats"]["Height"]));
  749. p.IsLight = Convert.ToBoolean(ini["Stats"]["BlockLight"]);
  750. p.TextureGrid = new Vector2Short(16, 16);
  751. p.IsStone = Convert.ToBoolean(ini["Stats"]["Stone"]);
  752. p.CanBlend = Convert.ToBoolean(ini["Stats"]["MergeDirt"]);
  753. //curTile.Placement = InLineEnumTryParse<FramePlacement>((string)xElement.Attribute("Placement"));
  754. //curTile.TextureGrid = StringToVector2Short((string)xElement.Attribute("TextureGrid"), 16, 16);
  755. //curTile.IsGrass = "Grass".Equals((string)xElement.Attribute("Special")); /* Heathtech */
  756. //curTile.IsPlatform = "Platform".Equals((string)xElement.Attribute("Special")); /* Heathtech */
  757. //curTile.IsCactus = "Cactus".Equals((string)xElement.Attribute("Special")); /* Heathtech */
  758. //curTile.IsStone = (bool?)xElement.Attribute("Stone") ?? false; /* Heathtech */
  759. //curTile.CanBlend = (bool?)xElement.Attribute("Blends") ?? false; /* Heathtech */
  760. //curTile.MergeWith = (int?)xElement.Attribute("MergeWith") ?? null; /* Heathtech */
  761. ArrayList colors = Config.tileDefs.color[id];
  762. p.Color = System.Windows.Media.Color.FromArgb(255, (byte)(int)colors[0], (byte)(int)colors[1], (byte)(int)colors[2]);
  763. _tileProperties[id] = p;
  764. Config.world._textureDictionary.LoadCustom(id, Config.tileDefs.loadModname[id], Config.tileDefs.load[id], "tile");
  765. }
  766. //
  767. // Config.wallDefs.loadModname = new Dictionary<int, string>();
  768. Dictionary<string, object> modwalls = (Dictionary<string, object>)dict["modwalls"];
  769. foreach (string str in modwalls.Keys)
  770. {
  771. ArrayList arr = (ArrayList)modwalls[str];
  772. foreach (int id in arr)
  773. {
  774. Config.wallDefs.loadModname[id] = str;
  775. Config.world._textureDictionary.LoadCustom(id, str, Config.wallDefs.load[id], "wall");
  776. }
  777. }
  778. /*ArrayList modVersions = (ArrayList)dict["mods"];
  779. for (int i = 0; i < modVersions.Count; i++)
  780. {
  781. ArrayList theversion = (ArrayList)modVersions[i];
  782. string name = theversion[0].ToString();
  783. int v = (int)theversion[1];
  784. Config.loadedVersion[name] = v;
  785. }*/
  786. /*ArrayList items = (ArrayList)dict["items"];
  787. for (int i = 0; i < items.Count; i++)
  788. {
  789. ArrayList theitem = (ArrayList)items[i];
  790. int id = (int)theitem[0];
  791. string name = theitem[1].ToString();
  792. Config.itemDefs.load[id] = name;
  793. }*/
  794. Dictionary<string, object> npcnames = (Dictionary<string, object>)dict["npcnames"];
  795. foreach (string key in npcnames.Keys)
  796. {
  797. string name = npcnames[key].ToString();
  798. //Debug.WriteLine("Assigning NPC name for " + key + " to " + name);
  799. try
  800. {
  801. w.CharacterNames.Add(new NpcName(Config.npcDefs[key], name));
  802. }
  803. catch (Exception e)
  804. {
  805. throw new Exception("Error: NPC " + key + " is unknown, are you missing a mod?");
  806. }
  807. }
  808. // Main.chrName[Main.npc[num7].type] = newReader.ReadString()
  809. return new int[] { baseVersion, tConfigRelease };
  810. }
  811. public static bool loadWorldTiles(World w, int num, MemoryStream fileStream)
  812. {
  813. //Tile.activeArr = new byte[1000];
  814. //string savePath = Path.Combine(Main.worldTempPath, "world.tiles");
  815. //using (FileStream fileStream = new FileStream(savePath, FileMode.Open))
  816. //{
  817. // Main.tile.Init();
  818. using (BinaryReader b = new BinaryReader(fileStream))
  819. {
  820. try
  821. {
  822. w.Tiles = new Tile[w.TilesWide, w.TilesHigh];
  823. for (int x = 0; x < w.TilesWide; ++x)
  824. {
  825. OnProgressChanged(null, new ProgressChangedEventArgs(x.ProgressPercentage(w.TilesWide), "Loading Tiles..."));
  826. Tile prevtype = new Tile();
  827. for (int y = 0; y < w.TilesHigh; y++)
  828. {
  829. var tile = new Tile();
  830. //if (num >= 100) tile.Type = (ushort)b.ReadInt16();
  831. //else
  832. tile.Type = b.ReadByte();
  833. if (tile.Type == 0) tile.IsActive = false;
  834. else
  835. {
  836. tile.IsActive = true;
  837. tile.Type = (byte)(tile.Type - 1);
  838. var tileProperty = TileProperties[tile.Type];
  839. if (string.Equals(tileProperty.Name, "UNKNOWN", StringComparison.InvariantCultureIgnoreCase))
  840. {
  841. throw new ArgumentOutOfRangeException(string.Format("Unknown tile tile: {0}, please add tile id {0} too your settings.xml.\r\nBE SURE TO INCLUDE THE isFramed PROPERTY (sprites=true, blocks=false).\r\nYou are seeing this message due to an update or mod.", tile.Type));
  842. }
  843. //tConfig code for handling custom tiles
  844. /*
  845. //newcode
  846. if (Main.tile[j, k].type >= Main.maxTileSets)
  847. {
  848. string name = Config.tileDefs.load[Main.tile[j, k].type];
  849. int ID = 0;
  850. if (!String.IsNullOrEmpty(name) && Config.tileDefs.ID.TryGetValue(name, out ID))
  851. {
  852. //Debug.WriteLine("Updating tile type:" + Main.tile[j, num5].type + " to " + Main.tileID[Main.tileLoad[Main.tile[j, num5].type]]);
  853. Main.tile[j, k].type = (ushort)ID;
  854. }
  855. else if (Main.tile[j, k].type >= Main.maxTileSets)// + Config.customTileAmt)// || String.IsNullOrWhiteSpace(Main.tileName[Main.tile[j, k].type]))
  856. {
  857. Debug.WriteLine("World Load Error: Tile " + Main.tile[j, k].type + " does not exist");
  858. //loadSuccess = false;
  859. //loadFailed = true;
  860. binaryReader.Close();
  861. fileStream.Close();
  862. string tilename = Main.tile[j, k].type.ToString();
  863. Config.tileDefs.load.TryGetValue(Main.tile[j, k].type, out tilename);
  864. string mess = "Tile '" + tilename + "' does not exist";
  865. string modname = "";
  866. if (Config.tileDefs.loadModname.TryGetValue(Main.tile[j, k].type, out modname))
  867. mess += "\nMod '" + modname + "' needs to be loaded";
  868. throw new Exception(mess);
  869. return false;
  870. }
  871. }*/
  872. // if (tile.Type == (int)sbyte.MaxValue)
  873. // tile.IsActive = false;
  874. if (tileProperty.IsFramed)
  875. {
  876. // torches didn't have extra in older versions.
  877. if (w.Version < 28 && tile.Type == 4)
  878. {
  879. tile.U = 0;
  880. tile.V = 0;
  881. }
  882. else
  883. {
  884. tile.U = b.ReadInt16();
  885. tile.V = b.ReadInt16();
  886. //if (tile.Type == 128) //armor stand
  887. // tile.Frame = new PointShort((short)(tile.Frame.X % 100), tile.Frame.Y);
  888. if ((int)tile.Type == 144) //timer
  889. tile.V = 0;
  890. }
  891. }
  892. else
  893. {
  894. tile.U = -1;
  895. tile.V = -1;
  896. }
  897. }
  898. tile.Wall = b.ReadByte();
  899. //tConfig code for handling custom walls
  900. /*
  901. if (Main.tile[j, k].wall >= Main.maxWallTypes)
  902. {
  903. string name = Config.wallDefs.load[Main.tile[j, k].wall];
  904. int ID = 0;
  905. if (!String.IsNullOrEmpty(name) && Config.wallDefs.ID.TryGetValue(name, out ID))
  906. {
  907. Main.tile[j, k].wall = (byte)ID;
  908. }
  909. else if (Main.tile[j, k].wall >= Main.maxWallTypes + Config.customWallAmt || String.IsNullOrWhiteSpace(Config.wallDefs.name[Main.tile[j, k].wall]))
  910. {
  911. Debug.WriteLine("World Load Error: Wall " + Main.tile[j, k].wall + " does not exist");
  912. //loadSuccess = false;
  913. //loadFailed = true;
  914. binaryReader.Close();
  915. fileStream.Close();
  916. string tilename = Main.tile[j, k].wall.ToString();
  917. Config.wallDefs.load.TryGetValue(Main.tile[j, k].wall, out tilename);
  918. string mess = "Wall " + tilename + " does not exist";
  919. string modname = "";
  920. if (Config.wallDefs.loadModname.TryGetValue(Main.tile[j, k].wall, out modname))
  921. mess += "\nMod " + modname + " needs to be loaded";
  922. throw new Exception(mess);
  923. return false;
  924. }
  925. }*/
  926. tile.Liquid = b.ReadByte();
  927. if (tile.Liquid > 0) tile.IsLava = b.ReadBoolean();
  928. tile.HasWire = b.ReadBoolean();
  929. w.Tiles[x, y] = tile;
  930. var ptype = (Tile)prevtype.Clone();
  931. prevtype = (Tile)tile.Clone();
  932. int rle = b.ReadInt16();
  933. if (rle > 0)
  934. {
  935. for (int r = y + 1; r < y + rle + 1; r++)
  936. {
  937. var tcopy = (Tile)tile.Clone();
  938. w.Tiles[x, r] = tcopy;
  939. }
  940. y += rle;
  941. }
  942. }
  943. }
  944. }
  945. catch (Exception e)
  946. {
  947. b.Close();
  948. fileStream.Close();
  949. throw new Exception("Error loading tiles\n" + e.Message);
  950. }
  951. b.Close();
  952. fileStream.Close();
  953. }
  954. return true;
  955. }
  956. public static bool loadWorldChests(World w, int num, MemoryStream fileStream, MemoryStream modStream)
  957. {
  958. //string savePath = Path.Combine(Main.worldTempPath, "world.chests");
  959. //string modSavePath = Path.Combine(Main.worldTempPath, "world.chests.moddata");
  960. //using (FileStream fileStream = new FileStream(savePath, FileMode.Open))
  961. //{
  962. using (BinaryReader b = new BinaryReader(fileStream))
  963. {
  964. //BinaryReader modReader = new BinaryReader(modStream); //This stream contains mod data
  965. try
  966. {
  967. w.Chests.Clear();
  968. OnProgressChanged(null, new ProgressChangedEventArgs(100, "Loading Chests..."));
  969. for (int i = 0; i < 1000; i++)
  970. {
  971. if (b.ReadBoolean())
  972. {
  973. var chest = new Chest(b.ReadInt32(), b.ReadInt32());
  974. for (int slot = 0; slot < Chest.MaxItems; slot++)
  975. {
  976. var stackSize = b.ReadByte();
  977. chest.Items[slot].StackSize = stackSize;
  978. if (chest.Items[slot].StackSize > 0)
  979. {
  980. if (w.Version >= 38)
  981. chest.Items[slot].NetId = b.ReadInt32();
  982. else
  983. chest.Items[slot].SetFromName(b.ReadString());
  984. chest.Items[slot].StackSize = stackSize;
  985. // Read prefix
  986. if (w.Version >= 36)
  987. chest.Items[slot].Prefix = b.ReadByte();
  988. //Unique ID value associates this item with mod data
  989. chest.Items[slot].ModId = b.ReadUInt16();
  990. }
  991. }
  992. w.Chests.Add(chest);
  993. }
  994. }
  995. }
  996. catch (Exception e)
  997. {
  998. // modReader.Close();
  999. modStream.Close();
  1000. b.Close();
  1001. fileStream.Close();
  1002. throw new Exception("Error loading chests\n" + e);
  1003. }
  1004. //modReader.Close();
  1005. modStream.Close();
  1006. b.Close();
  1007. fileStream.Close();
  1008. }
  1009. return true;
  1010. }
  1011. public static bool loadWorldSigns(World w, int num, MemoryStream fileStream)
  1012. {
  1013. //string savePath = Path.Combine(Main.worldTempPath, "world.signs");
  1014. //using (FileStream fileStream = new FileStream(savePath, FileMode.Open))
  1015. //{
  1016. using (BinaryReader b = new BinaryReader(fileStream))
  1017. {
  1018. try
  1019. {
  1020. w.Signs.Clear();
  1021. OnProgressChanged(null, new ProgressChangedEventArgs(100, "Loading Signs..."));
  1022. for (int i = 0; i < 1000; i++)
  1023. {
  1024. if (b.ReadBoolean())
  1025. {
  1026. Sign sign = new Sign();
  1027. sign.Text = b.ReadString();
  1028. sign.X = b.ReadInt32();
  1029. sign.Y = b.ReadInt32();
  1030. w.Signs.Add(sign);
  1031. }
  1032. }
  1033. }
  1034. catch (Exception e)
  1035. {
  1036. b.Close();
  1037. fileStream.Close();
  1038. throw new Exception("Error loading signs\n" + e);
  1039. }
  1040. b.Close();
  1041. fileStream.Close();
  1042. }
  1043. return true;
  1044. }
  1045. public static bool loadWorldNPCs(World w, int num, MemoryStream fileStream)
  1046. {
  1047. //string savePath = Path.Combine(Main.worldTempPath, "world.NPCs");
  1048. //using (FileStream fileStream = n…

Large files files are truncated, but you can click here to view the full file