public static void Save(World world, string filename, bool resetTime = false, uint versionOverride = 0) { ErrorLogging.TelemetryClient?.TrackEvent(nameof(Save)); try { OnProgressChanged(world, new ProgressChangedEventArgs(0, "Validating World...")); world.Validate(); } catch (ArgumentOutOfRangeException err) { string msg = "There is a problem in your world.\r\n" + $"{err.ParamName}\r\n" + $"This world may not open in Terraria\r\n" + "Would you like to save anyways??\r\n"; if (MessageBox.Show(msg, "World Error", MessageBoxButton.YesNo, MessageBoxImage.Error) != MessageBoxResult.Yes) { return; } } catch (Exception ex) { string msg = "There is a problem in your world.\r\n" + $"{ex.Message}\r\n" + "This world may not open in Terraria\r\n" + "Would you like to save anyways??\r\n"; if (MessageBox.Show(msg, "World Error", MessageBoxButton.YesNo, MessageBoxImage.Error) != MessageBoxResult.Yes) { return; } } lock (_fileLock) { uint currentWorldVersion = world.Version; try { // set the world version for this save if (versionOverride > 0) { world.Version = versionOverride; } if (resetTime) { OnProgressChanged(world, new ProgressChangedEventArgs(0, "Resetting Time...")); world.ResetTime(); } if (filename == null) { return; } string temp = filename + ".tmp"; using (var fs = new FileStream(temp, FileMode.Create)) { using (var bw = new BinaryWriter(fs)) { if (world.Version > 87) { SaveV2(world, bw); } else { SaveV1(world, bw); } bw.Close(); fs.Close(); // make a backup of current file if it exists if (File.Exists(filename)) { string backup = filename + "." + DateTime.Now.ToString("yyyyMMddHHmmss") + ".TEdit"; File.Copy(filename, backup, true); } // replace actual file with temp save file File.Copy(temp, filename, true); // delete temp save file File.Delete(temp); OnProgressChanged(null, new ProgressChangedEventArgs(0, "World Save Complete.")); } } world._lastSave = File.GetLastWriteTimeUtc(filename); } finally { // restore the version if (versionOverride > 0) { world.Version = currentWorldVersion; } } } }
private static void WriteAnalyzeWorld(StreamWriter sb, World world, bool fullAnalysis = false) { try { world.Validate(); } catch (Exception ex) { sb.WriteLine(ex.Message); } WriteHeader(sb, world); WriteFlags(sb, world); if (!fullAnalysis) { return; } sb.WriteLine("===SECTION: Tiles==="); var tileCounts = new Dictionary <int, int>(); int activeTiles = 0; for (int x = 0; x < world.TilesWide; x++) { for (int y = 0; y < world.TilesHigh; y++) { var tile = world.Tiles[x, y]; if (tile.IsActive) { if (tileCounts.ContainsKey(tile.Type)) { tileCounts[tile.Type] += 1; } else { tileCounts.Add(tile.Type, 1); } activeTiles++; } } } float totalTiles = world.TilesWide * world.TilesHigh; int airTiles = (int)(totalTiles - activeTiles); sb.WriteLine("Air: {0} ({1:P2})", airTiles, airTiles / totalTiles); var tiles = tileCounts.OrderByDescending(kvp => kvp.Value); foreach (var tilePair in tiles) { string name = tilePair.Key.ToString(); if (World.TileProperties.Count >= tilePair.Key) { var prop = World.TileProperties[tilePair.Key]; if (prop != null) { name = prop.Name; } } sb.WriteLine("{0}: {1} ({2:P2})", name, tilePair.Value, tilePair.Value / totalTiles); } sb.WriteLine("===SECTION: Chests==="); sb.WriteProperty("Chest Count", world.Chests.Count); sb.WriteProperty("Chest Max Items", Chest.MaxItems); foreach (var chest in world.Chests) { sb.Write("[{0}, {1}] {2} - Contents: ", chest.X, chest.Y, chest.Name); for (int i = 0; i < Chest.MaxItems; i++) { Item item = chest.Items[i]; if (item == null) { sb.Write("[{0}]: Empty,", i.ToString()); } else { sb.Write("[{0}]: {1} - {2}{3},", i.ToString(), item.StackSize, item.PrefixName, item.Name); } } sb.WriteLine(); } sb.WriteLine("===SECTION: Signs==="); sb.WriteProperty("Sign Count", world.Signs.Count); foreach (var sign in world.Signs) { sb.Write("[{0}, {1}] {2}\r\n", sign.X, sign.Y, sign.Text); } sb.WriteLine("===SECTION: NPCs==="); sb.WriteProperty("NPC Count", world.NPCs.Count); foreach (var npc in world.NPCs) { sb.Write("ID: {0}, Name: {1}, Position: [{2:0.00}, {3:0.00}], {4}: [{5}, {6}]\r\n", npc.Name, npc.DisplayName, npc.Position.X, npc.Position.Y, npc.IsHomeless ? "Homeless" : "Home", npc.Home.X, npc.Home.Y); } sb.WriteLine("===SECTION: Tile Entities==="); sb.WriteProperty("Tile Entities Count", world.TileEntities.Count); foreach (var entity in world.TileEntities) { switch (entity.Type) { case 0: sb.Write("Dummy - ID: {0}, Position: [{1}, {2}], NPC: {3}\r\n", entity.Id, entity.PosX, entity.PosY, entity.Npc); break; case 1: sb.Write("ItemFrame - ID: {0}, Position: [{1}, {2}], ItemID: {3}, Prefix: {4}, Stack: {5}\r\n", entity.Id, entity.PosX, entity.PosY, entity.NetId, entity.Prefix, entity.StackSize); break; case 2: sb.Write("Logic Sensor - ID: {0}, Position: [{1}, {2}], LogicCheck: {3}, On: {4}\r\n", entity.Id, entity.PosX, entity.PosY, entity.LogicCheck, entity.On); break; } } }