Terraria ModLoader  0.11.7.8
A mod to make and play Terraria mods
MapIO.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using Terraria.Map;
5 using Terraria.Social;
6 using Terraria.Utilities;
7 
8 namespace Terraria.ModLoader.IO
9 {
10  internal static class MapIO
11  {
12  //in Terraria.Map.MapHelper.SaveMap at end of try block call MapIO.WriteModFile(text, isCloudSave);
13  internal static void WriteModFile(string path, bool isCloudSave) {
14  path = Path.ChangeExtension(path, ".tmap");
15  bool hasModData;
16  byte[] data;
17  using (MemoryStream stream = new MemoryStream()) {
18  using (BinaryWriter writer = new BinaryWriter(stream)) {
19  hasModData = WriteModMap(writer);
20  writer.Flush();
21  data = stream.ToArray();
22  }
23  }
24  if (hasModData) {
25  FileUtilities.WriteAllBytes(path, data, isCloudSave);
26  }
27  else {
28  if (isCloudSave && SocialAPI.Cloud != null) {
29  SocialAPI.Cloud.Delete(path);
30  }
31  else {
32  File.Delete(path);
33  }
34  }
35  }
36  //in Terraria.Map.WorldMap.Load after calling MapHelper.load methods
37  // call MapIO.ReadModFile(text2, isCloudSave);
38  internal static void ReadModFile(string path, bool isCloudSave) {
39  path = Path.ChangeExtension(path, ".tmap");
40  if (!FileUtilities.Exists(path, isCloudSave)) {
41  return;
42  }
43  byte[] buffer = FileUtilities.ReadAllBytes(path, isCloudSave);
44  using (MemoryStream stream = new MemoryStream(buffer)) {
45  using (BinaryReader reader = new BinaryReader(stream)) {
46  ReadModMap(reader);
47  }
48  }
49  }
50 
51  internal static bool WriteModMap(BinaryWriter writer) {
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) {
57  types.Add(type);
58  }
59  }
60  }
61  if (types.Count == 0) {
62  return false;
63  }
64  writer.Write((ushort)types.Count);
65  foreach (ushort type in types) {
66  writer.Write(type);
67  if (MapLoader.entryToTile.ContainsKey(type)) {
68  ModTile tile = TileLoader.GetTile(MapLoader.entryToTile[type]);
69  writer.Write(true);
70  writer.Write(tile.mod.Name);
71  writer.Write(tile.Name);
72  writer.Write((ushort)(type - MapHelper.tileLookup[tile.Type]));
73  }
74  else if (MapLoader.entryToWall.ContainsKey(type)) {
75  ModWall wall = WallLoader.GetWall(MapLoader.entryToWall[type]);
76  writer.Write(false);
77  writer.Write(wall.mod.Name);
78  writer.Write(wall.Name);
79  writer.Write((ushort)(type - MapHelper.wallLookup[wall.Type]));
80  }
81  else {
82  writer.Write(true);
83  writer.Write("");
84  writer.Write("");
85  writer.Write((ushort)0);
86  }
87  }
88  WriteMapData(writer);
89  return true;
90  }
91 
92  internal static void ReadModMap(BinaryReader reader) {
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);
102  ushort newType = 0;
103  if (mod != null) {
104  if (isTile) {
105  ushort tileType = (ushort)mod.TileType(name);
106  if (tileType != 0) {
107  if (option >= MapLoader.modTileOptions(tileType)) {
108  option = 0;
109  }
110  newType = (ushort)MapHelper.TileToLookup(tileType, option);
111  }
112  }
113  else {
114  ushort wallType = (ushort)mod.WallType(name);
115  if (wallType != 0) {
116  if (option >= MapLoader.modWallOptions(wallType)) {
117  option = 0;
118  }
119  newType = (ushort)(MapHelper.wallLookup[wallType] + option);
120  }
121  }
122  }
123  table[type] = newType;
124  }
125  ReadMapData(reader, table);
126  }
127 
128  internal static void WriteMapData(BinaryWriter writer) {
129  byte skip = 0;
130  bool nextModTile = false;
131  int i = 0;
132  int j = 0;
133  do {
134  MapTile tile = Main.Map[i, j];
135  if (tile.Type >= MapHelper.modPosition && tile.Light > 18) {
136  if (!nextModTile) {
137  writer.Write(skip);
138  skip = 0;
139  }
140  else {
141  nextModTile = false;
142  }
143  WriteMapTile(ref i, ref j, writer, ref nextModTile);
144  }
145  else {
146  skip++;
147  if (skip == 255) {
148  writer.Write(skip);
149  skip = 0;
150  }
151  }
152  }
153  while (NextTile(ref i, ref j));
154  if (skip > 0) {
155  writer.Write(skip);
156  }
157  }
158 
159  internal static void ReadMapData(BinaryReader reader, IDictionary<ushort, ushort> table) {
160  int i = 0;
161  int j = 0;
162  bool nextModTile = false;
163  do {
164  if (!nextModTile) {
165  byte skip = reader.ReadByte();
166  while (skip == 255) {
167  for (byte k = 0; k < 255; k++) {
168  if (!NextTile(ref i, ref j)) {
169  return;
170  }
171  }
172  skip = reader.ReadByte();
173  }
174  for (byte k = 0; k < skip; k++) {
175  if (!NextTile(ref i, ref j)) {
176  return;
177  }
178  }
179  }
180  else {
181  nextModTile = false;
182  }
183  ReadMapTile(ref i, ref j, table, reader, ref nextModTile);
184  }
185  while (NextTile(ref i, ref j));
186  }
187 
188  internal static void WriteMapTile(ref int i, ref int j, BinaryWriter writer, ref bool nextModTile) {
189  MapTile tile = Main.Map[i, j];
190  byte flags = 0;
191  byte[] data = new byte[9];
192  int index = 1;
193  data[index] = (byte)tile.Type;
194  index++;
195  data[index] = (byte)(tile.Type >> 8);
196  index++;
197  if (tile.Light < 255) {
198  flags |= 1;
199  data[index] = tile.Light;
200  index++;
201  }
202  if (tile.Color > 0) {
203  flags |= 2;
204  data[index] = tile.Color;
205  index++;
206  }
207  int nextI = i;
208  int nextJ = j;
209  uint sameCount = 0;
210  while (NextTile(ref nextI, ref nextJ)) {
211  MapTile nextTile = Main.Map[nextI, nextJ];
212  if (tile.Equals(ref nextTile) && sameCount < UInt32.MaxValue) {
213  sameCount++;
214  i = nextI;
215  j = nextJ;
216  }
217  else if (nextTile.Type >= MapHelper.modPosition && nextTile.Light > 18) {
218  flags |= 32;
219  nextModTile = true;
220  break;
221  }
222  else {
223  break;
224  }
225  }
226  if (sameCount > 0) {
227  flags |= 4;
228  data[index] = (byte)sameCount;
229  index++;
230  if (sameCount > 255) {
231  flags |= 8;
232  data[index] = (byte)(sameCount >> 8);
233  index++;
234  if (sameCount > UInt16.MaxValue) {
235  flags |= 16;
236  data[index] = (byte)(sameCount >> 16);
237  index++;
238  data[index] = (byte)(sameCount >> 24);
239  index++;
240  }
241  }
242  }
243  data[0] = flags;
244  writer.Write(data, 0, index);
245  }
246 
247  internal static void ReadMapTile(ref int i, ref int j, IDictionary<ushort, ushort> table,
248  BinaryReader reader, ref bool nextModTile) {
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) {
256  uint sameCount;
257  if ((flags & 16) == 16) {
258  sameCount = reader.ReadUInt32();
259  }
260  else if ((flags & 8) == 8) {
261  sameCount = reader.ReadUInt16();
262  }
263  else {
264  sameCount = reader.ReadByte();
265  }
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);
270  }
271  }
272  if ((flags & 32) == 32) {
273  nextModTile = true;
274  }
275  }
276 
277  private static bool NextTile(ref int i, ref int j) {
278  j++;
279  if (j >= Main.maxTilesY) {
280  j = 0;
281  i++;
282  if (i >= Main.maxTilesX) {
283  return false;
284  }
285  }
286  return true;
287  }
288  }
289 }