public async Task <BspFileLoadResult> Load(Stream stream, IEnvironment environment) { return(await Task.Factory.StartNew(() => { var result = new BspFileLoadResult(); var map = new Map(); var so = _formatter.Deserialize(stream); foreach (var o in so) { if (o.Name == nameof(Root)) { map.Root.Unclone((Root)_factory.Deserialise(o)); } else { map.Data.Add((IMapData)_factory.Deserialise(o)); } } map.Root.DescendantsChanged(); result.Map = map; return result; })); }
private Solid ReadSolid(StreamReader rdr, UniqueNumberGenerator generator, BspFileLoadResult result) { var faces = new List <Face>(); string line; while ((line = CleanLine(rdr.ReadLine())) != null) { if (String.IsNullOrWhiteSpace(line)) { continue; } if (line == "}") { if (!faces.Any()) { return(null); } var poly = new Polyhedron(faces.Select(x => x.Plane)); var ret = new Solid(generator.Next("MapObject")); ret.Data.Add(new ObjectColor(Colour.GetRandomBrushColour())); foreach (var face in faces) { var pg = poly.Polygons.FirstOrDefault(x => x.Plane.Normal.EquivalentTo(face.Plane.Normal, 0.0075f)); // Magic number that seems to match VHE if (pg == null) { result.InvalidObjects.Add(poly); return(null); } face.Vertices.AddRange(pg.Vertices); } ret.Data.AddRange(faces); ret.DescendantsChanged(); return(ret); } else if (line == "patchDef2") { // Quake 3 has bezier faces // TODO: support bezier faces... while (CleanLine(rdr.ReadLine()) != "}") { // Skip... } } else if (line == "brushDef") { throw new Exception("Maps containing the 'brushDef' structure are not currently supported"); } else { faces.Add(ReadFace(line, generator)); } } return(null); }
public async Task <BspFileLoadResult> Load(Stream stream, IEnvironment environment) { var task = await Task.Factory.StartNew(async() => { var result = new BspFileLoadResult(); var map = new Map(); var so = _formatter.Deserialize(stream).ToList(); foreach (var s in so) { s.Name = s.Name?.ToLower(); } // If the sledge_native node is found, we should use it to maximise compatibility var native = so.FirstOrDefault(x => x.Name == "sledge_native"); if (native != null) { foreach (var o in native.Children) { if (o.Name == nameof(Root)) { map.Root.Unclone((Root)_factory.Deserialise(o)); } else { map.Data.Add((IMapData)_factory.Deserialise(o)); } } } else { // Load a VHE4 VMF format LoadVisgroups(map, so.FirstOrDefault(x => x.Name == "visgroups")); LoadWorld(map, so); LoadCameras(map, so.FirstOrDefault(x => x.Name == "cameras")); LoadCordon(map, so.FirstOrDefault(x => x.Name == "cordon")); await LoadViewSettings(map, so.FirstOrDefault(x => x.Name == "viewsettings"), environment); await Task.FromResult(0); } map.Root.DescendantsChanged(); result.Map = map; return(result); }); return(await task); }
public Task <BspFileLoadResult> Load(Stream stream, IEnvironment environment) { return(Task.Run(() => { using (var reader = new StreamReader(stream, Encoding.ASCII, true, 1024, false)) { var result = new BspFileLoadResult(); var map = new Map(); Read(map, reader); result.Map = map; return result; } })); }
public async Task <BspFileLoadResult> Load(Stream stream, IEnvironment environment) { return(await Task.Factory.StartNew(() => { using (var br = new BinaryReader(stream, Encoding.ASCII, true)) { var result = new BspFileLoadResult(); // Only RMF version 2.2 is supported for the moment. var version = Math.Round(br.ReadSingle(), 1); if (Math.Abs(version - 2.2) > 0.01) { throw new NotSupportedException("Incorrect RMF version number. Expected 2.2, got " + version + "."); } // RMF header test var header = br.ReadFixedLengthString(Encoding.ASCII, 3); if (header != "RMF") { throw new NotSupportedException("Incorrect RMF header. Expected 'RMF', got '" + header + "'."); } var map = new Map(); ReadVisgroups(map, br); ReadWorldspawn(map, br); // Some RMF files might not have the DOCINFO block so we check if we're at the end of the stream if (stream.Position < stream.Length) { // DOCINFO string check var docinfo = br.ReadFixedLengthString(Encoding.ASCII, 8); if (docinfo != "DOCINFO") { throw new NotSupportedException("Incorrect RMF format. Expected 'DOCINFO', got '" + docinfo + "'."); } ReadCameras(map, br); } result.Map = map; return result; } })); }
public async Task <BspFileLoadResult> Load(Stream stream, IEnvironment environment) { return(await Task.Factory.StartNew(() => { using (var reader = new StreamReader(stream, Encoding.ASCII, true, 1024, false)) { var result = new BspFileLoadResult(); var map = new Map(); var entities = ReadAllEntities(reader, map.NumberGenerator, result); var worldspawn = entities.FirstOrDefault(x => x.EntityData?.Name == "worldspawn") ?? new Entity(0) { Data = { new EntityData { Name = "worldspawn" } } }; entities.Remove(worldspawn); map.Root.Data.Replace(worldspawn.EntityData); foreach (var ch in worldspawn.Hierarchy.ToList()) { ch.Hierarchy.Parent = map.Root; } foreach (var entity in entities) { entity.Hierarchy.Parent = map.Root; } foreach (var obj in worldspawn.Hierarchy.ToList()) { obj.Hierarchy.Parent = map.Root; } map.Root.DescendantsChanged(); result.Map = map; return result; } })); }
private Entity ReadEntity(StreamReader rdr, UniqueNumberGenerator generator, BspFileLoadResult result) { var ent = new Entity(generator.Next("Face")) { Data = { new EntityData(), new ObjectColor(Colour.GetRandomBrushColour()) } }; string line; while ((line = CleanLine(rdr.ReadLine())) != null) { if (String.IsNullOrWhiteSpace(line)) { continue; } if (line[0] == '"') { ReadProperty(ent, line); } else if (line[0] == '{') { var s = ReadSolid(rdr, generator, result); if (s != null) { s.Hierarchy.Parent = ent; } } else if (line[0] == '}') { break; } } ent.DescendantsChanged(); return(ent); }
private List <Entity> ReadAllEntities(StreamReader rdr, UniqueNumberGenerator generator, BspFileLoadResult result) { var list = new List <Entity>(); string line; while ((line = CleanLine(rdr.ReadLine())) != null) { if (String.IsNullOrWhiteSpace(line)) { continue; } if (line == "{") { list.Add(ReadEntity(rdr, generator, result)); } } return(list); }