tModLoader v0.11.8.9
A mod to make and play Terraria mods
MapIO.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.IO;
4using Terraria.Map;
5using Terraria.Social;
6using Terraria.Utilities;
7
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}