private static void WriteSprites(BinaryWriter writer, ICollection <Thing> sprites, Dictionary <Sector, int> sectorids) { List <Thing> validsprites = new List <Thing>(sprites.Count); bool first = true; foreach (var s in sprites) { // Skip player start sprite... if (first) { first = false; continue; } // Sprites must be inside an existing sector if (s.Sector == null || s.Sector.IsDisposed) { s.DetermineSector(); } if (s.Sector == null) { continue; } validsprites.Add(s); } // UINT16LE Number of sprites in the map writer.Write((ushort)validsprites.Count); foreach (Thing s in validsprites) { // INT32LE x, y, z writer.Write((int)s.Position.x); writer.Write((int)-s.Position.y); // Transform to match Build coords... writer.Write(GetBuildHeight((int)s.Position.z)); // Transform to match Build coords... // INT16LE cstat writer.Write((ushort)FlagsToInt(s.Flags)); // INT16LE picnum writer.Write((short)s.TileIndex); // INT8 shade, UINT8 pal writer.Write((sbyte)s.Shade); writer.Write((byte)s.PaletteIndex); // UINT8 clipdist, filler writer.Write((byte)s.ClipDistance); writer.Write((byte)0); // UINT8 xrepeat, yrepeat, xpanning, ypanning writer.Write((byte)s.RepeatX); writer.Write((byte)s.RepeatY); writer.Write((byte)s.OffsetX); writer.Write((byte)s.OffsetY); // INT16LE sectnum, statnum, ang, owner writer.Write((short)sectorids[s.Sector]); writer.Write((short)s.Status); writer.Write((short)Angle2D.RadToBuild(s.Angle)); writer.Write((short)s.Owner); // INT16LE xvel, yvel, zvel writer.Write((short)s.Velocity.x); writer.Write((short)s.Velocity.y); writer.Write((short)s.Velocity.z); // INT16LE lotag, hitag, extra writer.Write((short)s.LoTag); writer.Write((short)s.HiTag); writer.Write((short)s.Extra); } }
public override void Write(MapSet map, Stream mapdata) { // Make collections var buildwallids = new Dictionary <int, BuildWall>(map.Sidedefs.Count); var wallids = new Dictionary <Sidedef, int>(map.Sidedefs.Count); var sectorids = new Dictionary <Sector, int>(map.Sectors.Count); // Walls must be stored on per-sector basis... foreach (Sector s in map.Sectors) { if (s.Sidedefs == null || s.Sidedefs.Count < 3) { continue; } var sectorsidelists = Tools.GetSortedSectorSides(s); if (sectorsidelists.Count == 0) { continue; } foreach (List <Sidedef> sideslist in sectorsidelists) { // Add to lookup table for (int i = 0; i < sideslist.Count; i++) { wallids.Add(sideslist[i], wallids.Count); } // Create BuildWalls for (int i = 0; i < sideslist.Count; i++) { var bw = new BuildWall(sideslist[i]); int next = (i < sideslist.Count - 1 ? i + 1 : 0); // Connect last wall to the first one bw.NextWallIndex = wallids[sideslist[next]]; bw.Side = sideslist[i]; buildwallids.Add(buildwallids.Count, bw); } } sectorids.Add(s, sectorids.Count); } // Fill in OtherWallIndex and OtherSectorIndex foreach (var group in wallids) { if (group.Key.Other != null) { buildwallids[group.Value].OtherWallIndex = wallids[group.Key.Other]; buildwallids[group.Value].OtherSectorIndex = sectorids[group.Key.Other.Sector]; } } // Write map structures using (BinaryWriter writer = new BinaryWriter(mapdata)) { // Write map header writer.Write(Version); // First sprite must be player start Thing playerstart = map.GetThingByIndex(0); //TODO: check this BEFORE saving the map! if (playerstart == null) { throw new InvalidDataException("Map has no Player start!"); } if (playerstart.Sector == null || playerstart.Sector.IsDisposed) { playerstart.DetermineSector(); } if (playerstart.Sector == null) { throw new InvalidDataException("Player start must be inside a sector!"); } // Write player start point writer.Write((int)playerstart.Position.x); writer.Write((int)-playerstart.Position.y); // Transform to match Build coords... writer.Write(GetBuildHeight((int)playerstart.Position.z)); // Transform to match Build coords... // Write player starting angle writer.Write((ushort)Angle2D.RadToBuild(playerstart.Angle)); // Write sector number containing the start point writer.Write((ushort)sectorids[playerstart.Sector]); // Write sectors WriteSectors(writer, sectorids.Keys); // Write walls WriteWalls(writer, buildwallids.Values); // Write sprites WriteSprites(writer, map.Things, sectorids); } }