UltimateZoneBuilder/Source/IO/DoomMapSetIO.cs

504 lines
15 KiB
C#
Raw Normal View History

2007-06-24 18:56:43 +00:00
#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
2007-06-16 19:53:51 +00:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
2007-06-24 18:56:43 +00:00
using System.IO;
using CodeImp.DoomBuilder.Map;
using CodeImp.DoomBuilder.Geometry;
#endregion
2007-06-16 19:53:51 +00:00
namespace CodeImp.DoomBuilder.IO
{
2007-06-24 18:56:43 +00:00
internal class DoomMapSetIO : MapSetIO
2007-06-16 19:53:51 +00:00
{
#region ================== Constants
#endregion
2007-06-24 18:56:43 +00:00
#region ================== Constructor / Disposer
2007-06-16 19:53:51 +00:00
2007-06-24 18:56:43 +00:00
// Constructor
public DoomMapSetIO(WAD wad, MapManager manager) : base(wad, manager)
2007-06-24 18:56:43 +00:00
{
}
2007-06-16 19:53:51 +00:00
#endregion
#region ================== Properties
public override int MaxSidedefs { get { return 65534; } }
2007-06-24 18:56:43 +00:00
#endregion
2007-06-24 18:56:43 +00:00
#region ================== Reading
2007-06-16 19:53:51 +00:00
2007-06-24 18:56:43 +00:00
// This reads a map from the file and returns a MapSet
public override MapSet Read(MapSet map, string mapname)
{
int firstindex;
Dictionary<int, Vertex> vertexlink;
Dictionary<int, Sector> sectorlink;
// Find the index where first map lump begins
firstindex = wad.FindLumpIndex(mapname) + 1;
2007-06-16 19:53:51 +00:00
2007-06-24 18:56:43 +00:00
// Read vertices
vertexlink = ReadVertices(map, firstindex);
2007-06-16 19:53:51 +00:00
2007-06-24 18:56:43 +00:00
// Read sectors
sectorlink = ReadSectors(map, firstindex);
2007-06-16 19:53:51 +00:00
2007-06-24 18:56:43 +00:00
// Read linedefs and sidedefs
ReadLinedefs(map, firstindex, vertexlink, sectorlink);
2007-06-16 19:53:51 +00:00
2007-06-24 18:56:43 +00:00
// Read things
ReadThings(map, firstindex);
// Return result;
return map;
}
// This reads the THINGS from WAD file
private void ReadThings(MapSet map, int firstindex)
{
MemoryStream mem;
BinaryReader reader;
int num, i, x, y, type, flags;
float angle;
Thing t;
// Get the lump from wad file
Lump lump = wad.FindLump("THINGS", firstindex);
if(lump == null) throw new Exception("Could not find required lump THINGS!");
// Prepare to read the items
mem = new MemoryStream(lump.Stream.ReadAllBytes());
num = (int)lump.Stream.Length / 10;
reader = new BinaryReader(mem);
// Read items from the lump
for(i = 0; i < num; i++)
{
// Read properties from stream
x = reader.ReadInt16();
y = reader.ReadInt16();
angle = reader.ReadInt16(); // TODO: Fix this!
type = reader.ReadUInt16();
flags = reader.ReadUInt16();
// Create new item
t = map.CreateThing();
t.Update(type, new Vector3D(x, y, 0f), angle, flags, 0, 0, Thing.EMPTY_ARGS);
t.DetermineSector();
}
// Done
mem.Dispose();
}
// This reads the VERTICES from WAD file
// Returns a lookup table with indices
private Dictionary<int, Vertex> ReadVertices(MapSet map, int firstindex)
2007-06-16 19:53:51 +00:00
{
2007-06-24 18:56:43 +00:00
MemoryStream mem;
Dictionary<int, Vertex> link;
BinaryReader reader;
int num, i, x, y;
Vertex v;
// Get the lump from wad file
Lump lump = wad.FindLump("VERTEXES", firstindex);
if(lump == null) throw new Exception("Could not find required lump VERTEXES!");
// Prepare to read the items
mem = new MemoryStream(lump.Stream.ReadAllBytes());
num = (int)lump.Stream.Length / 4;
reader = new BinaryReader(mem);
// Create lookup table
link = new Dictionary<int, Vertex>(num);
2007-06-16 19:53:51 +00:00
2007-06-24 18:56:43 +00:00
// Read items from the lump
for(i = 0; i < num; i++)
{
// Read properties from stream
x = reader.ReadInt16();
y = reader.ReadInt16();
// Create new item
v = map.CreateVertex(x, y);
2007-06-24 18:56:43 +00:00
// Add it to the lookup table
link.Add(i, v);
}
// Done
mem.Dispose();
// Return lookup table
return link;
2007-06-16 19:53:51 +00:00
}
2007-06-24 18:56:43 +00:00
// This reads the SECTORS from WAD file
// Returns a lookup table with indices
private Dictionary<int, Sector> ReadSectors(MapSet map, int firstindex)
2007-06-16 19:53:51 +00:00
{
2007-06-24 18:56:43 +00:00
MemoryStream mem;
Dictionary<int, Sector> link;
BinaryReader reader;
int num, i, hfloor, hceil, bright, special, tag;
string tfloor, tceil;
Sector s;
// Get the lump from wad file
Lump lump = wad.FindLump("SECTORS", firstindex);
if(lump == null) throw new Exception("Could not find required lump SECTORS!");
// Prepare to read the items
mem = new MemoryStream(lump.Stream.ReadAllBytes());
num = (int)lump.Stream.Length / 26;
reader = new BinaryReader(mem);
// Create lookup table
link = new Dictionary<int, Sector>(num);
// Read items from the lump
for(i = 0; i < num; i++)
2007-06-16 19:53:51 +00:00
{
2007-06-24 18:56:43 +00:00
// Read properties from stream
hfloor = reader.ReadInt16();
hceil = reader.ReadInt16();
tfloor = Lump.MakeNormalName(reader.ReadBytes(8), WAD.ENCODING);
tceil = Lump.MakeNormalName(reader.ReadBytes(8), WAD.ENCODING);
bright = reader.ReadInt16();
special = reader.ReadUInt16();
tag = reader.ReadUInt16();
// Create new item
s = map.CreateSector();
s.Update(hfloor, hceil, tfloor, tceil, special, tag);
2007-06-16 19:53:51 +00:00
2007-06-24 18:56:43 +00:00
// Add it to the lookup table
link.Add(i, s);
2007-06-16 19:53:51 +00:00
}
2007-06-24 18:56:43 +00:00
// Done
mem.Dispose();
// Return lookup table
return link;
2007-06-16 19:53:51 +00:00
}
2007-06-24 18:56:43 +00:00
// This reads the LINEDEFS and SIDEDEFS from WAD file
private void ReadLinedefs(MapSet map, int firstindex,
Dictionary<int, Vertex> vertexlink, Dictionary<int, Sector> sectorlink)
{
MemoryStream linedefsmem, sidedefsmem;
BinaryReader readline, readside;
Lump linedefslump, sidedefslump;
int num, i, offsetx, offsety, v1, v2;
int s1, s2, flags, action, tag, sc;
string thigh, tmid, tlow;
Linedef l;
Sidedef s;
// Get the linedefs lump from wad file
linedefslump = wad.FindLump("LINEDEFS", firstindex);
if(linedefslump == null) throw new Exception("Could not find required lump LINEDEFS!");
2007-06-16 19:53:51 +00:00
2007-06-24 18:56:43 +00:00
// Get the sidedefs lump from wad file
sidedefslump = wad.FindLump("SIDEDEFS", firstindex);
if(sidedefslump == null) throw new Exception("Could not find required lump SIDEDEFS!");
// Prepare to read the items
linedefsmem = new MemoryStream(linedefslump.Stream.ReadAllBytes());
sidedefsmem = new MemoryStream(sidedefslump.Stream.ReadAllBytes());
num = (int)linedefslump.Stream.Length / 14;
readline = new BinaryReader(linedefsmem);
readside = new BinaryReader(sidedefsmem);
// Read items from the lump
for(i = 0; i < num; i++)
{
// Read properties from stream
v1 = readline.ReadUInt16();
v2 = readline.ReadUInt16();
flags = readline.ReadUInt16();
action = readline.ReadUInt16();
tag = readline.ReadUInt16();
s1 = readline.ReadUInt16();
s2 = readline.ReadUInt16();
// Create new item
l = map.CreateLinedef(vertexlink[v1], vertexlink[v2]);
l.Update(flags, tag, action, Linedef.EMPTY_ARGS);
// Line has a front side?
if(s1 != ushort.MaxValue)
{
// Read front sidedef
sidedefsmem.Seek(s1 * 30, SeekOrigin.Begin);
offsetx = readside.ReadInt16();
offsety = readside.ReadInt16();
thigh = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
tmid = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
tlow = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
sc = readside.ReadUInt16();
// Create front sidedef
s = map.CreateSidedef(l, true, sectorlink[sc]);
s.Update(offsetx, offsety, thigh, tmid, tlow);
}
// Line has a back side?
if(s2 != ushort.MaxValue)
{
// Read back sidedef
sidedefsmem.Seek(s2 * 30, SeekOrigin.Begin);
offsetx = readside.ReadInt16();
offsety = readside.ReadInt16();
thigh = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
tmid = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
tlow = Lump.MakeNormalName(readside.ReadBytes(8), WAD.ENCODING);
sc = readside.ReadUInt16();
// Create back sidedef
s = map.CreateSidedef(l, false, sectorlink[sc]);
s.Update(offsetx, offsety, thigh, tmid, tlow);
}
}
// Done
linedefsmem.Dispose();
sidedefsmem.Dispose();
}
2007-06-16 19:53:51 +00:00
#endregion
2007-06-24 18:56:43 +00:00
#region ================== Writing
2007-06-16 19:53:51 +00:00
2007-06-24 18:56:43 +00:00
// This writes a MapSet to the file
public override void Write(MapSet map, string mapname, int position)
{
Dictionary<Vertex, int> vertexids = new Dictionary<Vertex,int>();
Dictionary<Sidedef, int> sidedefids = new Dictionary<Sidedef,int>();
Dictionary<Sector, int> sectorids = new Dictionary<Sector,int>();
IDictionary maplumps;
// First index everything
foreach(Vertex v in map.Vertices) vertexids.Add(v, vertexids.Count);
foreach(Sidedef sd in map.Sidedefs) sidedefids.Add(sd, sidedefids.Count);
foreach(Sector s in map.Sectors) sectorids.Add(s, sectorids.Count);
// Read map lumps
maplumps = manager.Configuration.ReadSetting("maplumpnames", new Hashtable());
// Write lumps to wad (note the backwards order because they
// are all inserted at position+1 when not found)
WriteSectors(map, position, maplumps.Count);
WriteVertices(map, position, maplumps.Count);
WriteSidedefs(map, position, maplumps.Count, sectorids);
WriteLinedefs(map, position, maplumps.Count, sidedefids, vertexids);
WriteThings(map, position, maplumps.Count);
}
// This writes the THINGS to WAD file
private void WriteThings(MapSet map, int position, int maxlumps)
{
MemoryStream mem;
BinaryWriter writer;
Lump lump;
int insertpos;
// Create memory to write to
mem = new MemoryStream();
writer = new BinaryWriter(mem, WAD.ENCODING);
// Go for all things
foreach(Thing t in map.Things)
{
// Write properties to stream
writer.Write((Int16)t.Position.x);
writer.Write((Int16)t.Position.y);
writer.Write((Int16)0); // TODO: Fix this!
writer.Write((UInt16)t.Type);
writer.Write((UInt16)0); // TODO: Fix this!
}
// Find insert position and remove old lump
insertpos = wad.FindLumpIndex("THINGS", position, position + maxlumps + 1);
if(insertpos == -1) insertpos = position + 1; else wad.RemoveAt(insertpos);
// Create the lump from memory
lump = wad.Insert("THINGS", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
}
// This writes the VERTEXES to WAD file
private void WriteVertices(MapSet map, int position, int maxlumps)
{
MemoryStream mem;
BinaryWriter writer;
Lump lump;
int insertpos;
// Create memory to write to
mem = new MemoryStream();
writer = new BinaryWriter(mem, WAD.ENCODING);
// Go for all vertices
foreach(Vertex v in map.Vertices)
{
// Write properties to stream
writer.Write((Int16)v.X);
writer.Write((Int16)v.Y);
}
// Find insert position and remove old lump
insertpos = wad.FindLumpIndex("VERTEXES", position, position + maxlumps + 1);
if(insertpos == -1) insertpos = position + 1; else wad.RemoveAt(insertpos);
// Create the lump from memory
lump = wad.Insert("VERTEXES", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
}
// This writes the LINEDEFS to WAD file
private void WriteLinedefs(MapSet map, int position, int maxlumps, IDictionary<Sidedef, int> sidedefids, IDictionary<Vertex, int> vertexids)
{
MemoryStream mem;
BinaryWriter writer;
Lump lump;
ushort sid;
int insertpos;
// Create memory to write to
mem = new MemoryStream();
writer = new BinaryWriter(mem, WAD.ENCODING);
// Go for all lines
foreach(Linedef l in map.Linedefs)
{
// Write properties to stream
writer.Write((UInt16)vertexids[l.Start]);
writer.Write((UInt16)vertexids[l.End]);
writer.Write((UInt16)0); // TODO: Fix this!
writer.Write((UInt16)0); // TODO: Fix this!
writer.Write((UInt16)0); // TODO: Fix this!
// Front sidedef
if(l.Front == null) sid = ushort.MaxValue;
else sid = (UInt16)sidedefids[l.Front];
writer.Write(sid);
// Back sidedef
if(l.Back == null) sid = ushort.MaxValue;
else sid = (UInt16)sidedefids[l.Back];
writer.Write(sid);
}
// Find insert position and remove old lump
insertpos = wad.FindLumpIndex("LINEDEFS", position, position + maxlumps + 1);
if(insertpos == -1) insertpos = position + 1; else wad.RemoveAt(insertpos);
// Create the lump from memory
lump = wad.Insert("LINEDEFS", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
}
// This writes the SIDEDEFS to WAD file
private void WriteSidedefs(MapSet map, int position, int maxlumps, IDictionary<Sector, int> sectorids)
{
MemoryStream mem;
BinaryWriter writer;
Lump lump;
int insertpos;
// Create memory to write to
mem = new MemoryStream();
writer = new BinaryWriter(mem, WAD.ENCODING);
// Go for all sidedefs
foreach(Sidedef sd in map.Sidedefs)
{
// Write properties to stream
writer.Write((Int16)0); // TODO: Fix this!
writer.Write((Int16)0); // TODO: Fix this!
writer.Write(Lump.MakeFixedName("", WAD.ENCODING)); // TODO: Fix this!
writer.Write(Lump.MakeFixedName("", WAD.ENCODING)); // TODO: Fix this!
writer.Write(Lump.MakeFixedName("", WAD.ENCODING)); // TODO: Fix this!
writer.Write((UInt16)sectorids[sd.Sector]);
}
// Find insert position and remove old lump
insertpos = wad.FindLumpIndex("SIDEDEFS", position, position + maxlumps + 1);
if(insertpos == -1) insertpos = position + 1; else wad.RemoveAt(insertpos);
// Create the lump from memory
lump = wad.Insert("SIDEDEFS", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
}
// This writes the SECTORS to WAD file
private void WriteSectors(MapSet map, int position, int maxlumps)
{
MemoryStream mem;
BinaryWriter writer;
Lump lump;
int insertpos;
// Create memory to write to
mem = new MemoryStream();
writer = new BinaryWriter(mem, WAD.ENCODING);
// Go for all sectors
foreach(Sector s in map.Sectors)
{
// Write properties to stream
writer.Write((Int16)0); // TODO: Fix this!
writer.Write((Int16)0); // TODO: Fix this!
writer.Write(Lump.MakeFixedName("", WAD.ENCODING)); // TODO: Fix this!
writer.Write(Lump.MakeFixedName("", WAD.ENCODING)); // TODO: Fix this!
writer.Write((Int16)0); // TODO: Fix this!
writer.Write((UInt16)0); // TODO: Fix this!
writer.Write((UInt16)0); // TODO: Fix this!
}
// Find insert position and remove old lump
insertpos = wad.FindLumpIndex("SECTORS", position, position + maxlumps + 1);
if(insertpos == -1) insertpos = position + 1; else wad.RemoveAt(insertpos);
// Create the lump from memory
lump = wad.Insert("SECTORS", insertpos, (int)mem.Length);
lump.Stream.Seek(0, SeekOrigin.Begin);
mem.WriteTo(lump.Stream);
2007-06-24 18:56:43 +00:00
}
2007-06-16 19:53:51 +00:00
#endregion
}
}