2using System.Collections.Generic;
6using Terraria.Utilities;
10 internal static class MapIO
13 internal static void WriteModFile(
string path,
bool isCloudSave) {
14 path = Path.ChangeExtension(path,
".tmap");
17 using (MemoryStream stream =
new MemoryStream()) {
19 hasModData = WriteModMap(writer);
21 data = stream.ToArray();
25 FileUtilities.WriteAllBytes(path, data, isCloudSave);
28 if (isCloudSave && SocialAPI.Cloud !=
null) {
29 SocialAPI.Cloud.Delete(path);
38 internal static void ReadModFile(
string path,
bool isCloudSave) {
39 path = Path.ChangeExtension(path,
".tmap");
40 if (!FileUtilities.Exists(path, isCloudSave)) {
43 byte[] buffer = FileUtilities.ReadAllBytes(path, isCloudSave);
44 using (MemoryStream stream =
new MemoryStream(buffer)) {
52 ISet<ushort> types =
new HashSet<ushort>();
53 for (
int i = 0; i < Main.maxTilesX; i++) {
54 for (
int j = 0; j < Main.maxTilesY; j++) {
55 ushort type = Main.Map[i, j].Type;
56 if (type >= MapHelper.modPosition) {
61 if (types.Count == 0) {
64 writer.Write((ushort)types.Count);
65 foreach (ushort type
in types) {
67 if (MapLoader.entryToTile.ContainsKey(type)) {
68 ModTile tile = TileLoader.GetTile(MapLoader.entryToTile[type]);
70 writer.Write(tile.mod.Name);
71 writer.Write(tile.Name);
72 writer.Write((ushort)(type - MapHelper.tileLookup[tile.Type]));
74 else if (MapLoader.entryToWall.ContainsKey(type)) {
75 ModWall wall = WallLoader.GetWall(MapLoader.entryToWall[type]);
77 writer.Write(wall.mod.Name);
78 writer.Write(wall.Name);
79 writer.Write((ushort)(type - MapHelper.wallLookup[wall.Type]));
85 writer.Write((ushort)0);
93 IDictionary<ushort, ushort> table =
new Dictionary<ushort, ushort>();
94 ushort count = reader.ReadUInt16();
95 for (ushort k = 0; k < count; k++) {
96 ushort type = reader.ReadUInt16();
97 bool isTile = reader.ReadBoolean();
98 string modName = reader.ReadString();
99 string name = reader.ReadString();
100 ushort option = reader.ReadUInt16();
101 Mod mod = ModLoader.GetMod(modName);
105 ushort tileType = (ushort)mod.TileType(name);
107 if (option >= MapLoader.modTileOptions(tileType)) {
110 newType = (ushort)MapHelper.TileToLookup(tileType, option);
114 ushort wallType = (ushort)mod.WallType(name);
116 if (option >= MapLoader.modWallOptions(wallType)) {
119 newType = (ushort)(MapHelper.wallLookup[wallType] + option);
123 table[type] = newType;
125 ReadMapData(reader, table);
128 internal static void WriteMapData(
BinaryWriter writer) {
130 bool nextModTile =
false;
134 MapTile tile = Main.Map[i, j];
135 if (tile.Type >= MapHelper.modPosition && tile.Light > 18) {
143 WriteMapTile(ref i, ref j, writer, ref nextModTile);
153 while (NextTile(ref i, ref j));
159 internal static void ReadMapData(
BinaryReader reader, IDictionary<ushort, ushort> table) {
162 bool nextModTile =
false;
165 byte skip = reader.ReadByte();
166 while (skip == 255) {
167 for (
byte k = 0; k < 255; k++) {
168 if (!NextTile(ref i, ref j)) {
172 skip = reader.ReadByte();
174 for (
byte k = 0; k < skip; k++) {
175 if (!NextTile(ref i, ref j)) {
183 ReadMapTile(ref i, ref j, table, reader, ref nextModTile);
185 while (NextTile(ref i, ref j));
188 internal static void WriteMapTile(ref
int i, ref
int j,
BinaryWriter writer, ref
bool nextModTile) {
189 MapTile tile = Main.Map[i, j];
191 byte[] data =
new byte[9];
193 data[index] = (byte)tile.Type;
195 data[index] = (
byte)(tile.Type >> 8);
197 if (tile.Light < 255) {
199 data[index] = tile.Light;
202 if (tile.Color > 0) {
204 data[index] = tile.Color;
210 while (NextTile(ref nextI, ref nextJ)) {
211 MapTile nextTile = Main.Map[nextI, nextJ];
212 if (tile.Equals(ref nextTile) && sameCount < UInt32.MaxValue) {
217 else if (nextTile.Type >= MapHelper.modPosition && nextTile.Light > 18) {
228 data[index] = (byte)sameCount;
230 if (sameCount > 255) {
232 data[index] = (byte)(sameCount >> 8);
234 if (sameCount > UInt16.MaxValue) {
236 data[index] = (byte)(sameCount >> 16);
238 data[index] = (byte)(sameCount >> 24);
244 writer.Write(data, 0, index);
247 internal static void ReadMapTile(ref
int i, ref
int j, IDictionary<ushort, ushort> table,
249 byte flags = reader.ReadByte();
250 ushort type = table[reader.ReadUInt16()];
251 byte light = (flags & 1) == 1 ? reader.ReadByte() : (byte)255;
252 byte color = (flags & 2) == 2 ? reader.ReadByte() : (byte)0;
253 MapTile tile = MapTile.Create(type, light, color);
254 Main.Map.SetTile(i, j, ref tile);
255 if ((flags & 4) == 4) {
257 if ((flags & 16) == 16) {
258 sameCount = reader.ReadUInt32();
260 else if ((flags & 8) == 8) {
261 sameCount = reader.ReadUInt16();
264 sameCount = reader.ReadByte();
266 for (uint k = 0; k < sameCount; k++) {
267 NextTile(ref i, ref j);
268 tile = MapTile.Create(type, light, color);
269 Main.Map.SetTile(i, j, ref tile);
272 if ((flags & 32) == 32) {
277 private static bool NextTile(ref
int i, ref
int j) {
279 if (j >= Main.maxTilesY) {
282 if (i >= Main.maxTilesX) {