예제 #1
0
		public ReliableMulticastWriter(Uri uri)
		{
			_sendBufferSize = 256*1024;
			_uri = uri;

			_socket = new ReliableMulticastSocket();
			_socketWriter = new SocketWriter(_socket);
		}
예제 #2
0
		public BufferedChunkWriter(Fiber fiber, Scheduler scheduler, ChunkWriter output, int bufferLengthInBytes)
		{
			_waitAfterMinFlush = 10.Milliseconds();
			_fiber = fiber;
			_scheduler = scheduler;
			_output = output;

			_inputBuffer = new Chunk(bufferLengthInBytes);
			_outputBuffer = new Chunk(bufferLengthInBytes);

			_minFlushLength = bufferLengthInBytes/2;
		}
예제 #3
0
        public void ShouldLogDataOnSend()
        {
            var buffer = Enumerable.Range(0, 10).Select(i => (byte)i).ToArray();
            var stream = new MemoryStream();
            var logger = LoggingHelper.GetTraceEnabledLogger();
            var writer = new ChunkWriter(stream, logger.Object);

            // Write data
            writer.OpenChunk();
            writer.Write(buffer, 0, buffer.Length);
            writer.CloseChunk();

            logger.Verify(x => x.Trace("C: {0}", It.IsAny <string>()), Times.Never);

            writer.Send();

            logger.Verify(x => x.Trace("C: {0}", It.IsAny <string>()), Times.Once);
        }
예제 #4
0
        private static byte[] GenerateMessageChunk(int messageSize)
        {
            var buffer = Enumerable.Range(0, messageSize).Select(i => i % byte.MaxValue).Select(i => (byte)i).ToArray();
            var stream = new MemoryStream();
            var writer = new ChunkWriter(stream);

            writer.OpenChunk();
            writer.Write(buffer, 0, buffer.Length);
            writer.CloseChunk();

            // Append end of message marker
            writer.OpenChunk();
            writer.CloseChunk();

            writer.Flush();
            writer.Send();

            return(stream.ToArray());
        }
예제 #5
0
        public Node GetNode(Uri uri)
        {
            string key = uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped);

            Node result;

            if (_nodes.TryGetValue(key, out result))
            {
                return(result);
            }

            ChunkWriter chunkWriter = GetWriter(uri);

            result = new RemoteNode(new ShuntChannel(), chunkWriter, _fiberFactory, _scheduler, _serializer);

            _nodes.Add(key, result);

            return(result);
        }
예제 #6
0
        public async void ShouldResetCapacityWhenAboveMaxBufferSizeAfterEachSendAsync()
        {
            var buffer = new byte[1536];
            var stream = new MemoryStream();
            var logger = new Mock <ILogger>();
            var writer = new ChunkWriter(stream, 512, 1024, logger.Object);

            writer.OpenChunk();
            writer.Write(buffer, 0, buffer.Length);
            writer.CloseChunk();
            await writer.SendAsync();

            writer.OpenChunk();
            writer.Write(buffer, 0, buffer.Length);
            writer.CloseChunk();
            await writer.SendAsync();

            logger.Verify(l => l.Info(It.IsRegex("^Shrinking write buffers to the"), It.IsAny <object[]>()), Times.Exactly(2));
        }
예제 #7
0
        public Queue(string topic, int queueId)
        {
            Topic   = topic;
            QueueId = queueId;
            Key     = new QueueKey(topic, queueId);

            _jsonSerializer = ObjectContainer.Resolve <IJsonSerializer>();
            _chunkManager   = new ChunkManager(
                "QueueChunk-" + Key.ToString(),
                BrokerController.Instance.Setting.QueueChunkConfig,
                BrokerController.Instance.Setting.IsMessageStoreMemoryMode,
                new List <string> {
                Topic, QueueId.ToString()
            });                                                 //Topic + QueueId.ToString()
            _chunkWriter      = new ChunkWriter(_chunkManager);
            _chunkReader      = new ChunkReader(_chunkManager, _chunkWriter);
            _queueSettingFile = Path.Combine(_chunkManager.ChunkPath, QueueSettingFileName);
            _logger           = ObjectContainer.Resolve <ILoggerFactory>().Create(this.GetType().FullName);
        }
예제 #8
0
파일: Program.cs 프로젝트: zzms/estore
        static void CreateChunks(string root, string path, ChunkManager chunkManager, int singleFileIndexCount, int dataUnitSize, int totalAggNumber, int indexCountForSingleAgg)
        {
            if (Directory.Exists(root))
            {
                Directory.Delete(root, true);
            }
            Directory.CreateDirectory(root);

            if (Directory.Exists(path))
            {
                Directory.Delete(path, true);
            }
            Directory.CreateDirectory(path);

            var chunkWriter = new ChunkWriter(chunkManager);

            chunkWriter.Open();

            var watch     = Stopwatch.StartNew();
            var format    = "{0}{1:00000000000000}";
            var aggPrefix = "aggregate_";

            for (var i = 0; i < totalAggNumber; i++)
            {
                var sourceId = string.Format(format, aggPrefix, i);
                for (var j = 0; j < indexCountForSingleAgg; j++)
                {
                    var record = new StreamIndex()
                    {
                        SourceId     = sourceId,
                        CommandId    = ObjectId.GenerateNewStringId(),
                        Version      = j + 1,
                        BodyPosition = 10000L
                    };
                    chunkWriter.Write(record);
                }
            }

            chunkWriter.Close();

            Console.WriteLine("Create event index success, aggCount: {0}, totalEventIndexCount: {1}, timeSpent: {2}ms", totalAggNumber, totalAggNumber * indexCountForSingleAgg, watch.ElapsedMilliseconds);
        }
예제 #9
0
            public void ShouldWriteBytesCorrectlyWhenMessageIsGreaterThanChunkSize()
            {
                var stream  = new MemoryStream();
                var chunker = new ChunkWriter(stream, 6);

                byte[] bytes = new byte[10];
                for (int i = 0; i < bytes.Length; i++)
                {
                    bytes[i] = (byte)(i + 1);
                }

                chunker.OpenChunk();
                chunker.Write(bytes, 0, bytes.Length);
                chunker.CloseChunk();
                chunker.Send();

                byte[] expected = { 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x00, 0x04, 0x07, 0x08, 0x09, 0x0A };

                Assert.Equal(expected, stream.ToArray());
            }
예제 #10
0
        void CreateLocalNode(Uri uri, UntypedChannel input)
        {
            string key = uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped);

            ChunkWriter chunkWriter = GetWriter(uri);

            _localNode = new RemoteNode(input, chunkWriter, _fiberFactory, _scheduler, _serializer);

            try
            {
                GetReader(uri, _localNode);
            }
            catch
            {
                _localNode.Dispose();
                throw;
            }

            _nodes.Add(key, _localNode);
        }
예제 #11
0
        private Stream BuildBinStream()
        {
            MemoryStream ms = new MemoryStream(8192);
            BinaryWriter bw = new BinaryWriter(ms);

            ChunkWriter cw         = new ChunkWriter(bw, Vault);
            var         stringsSet = new HashSet <string>();

            var strings = Vault.SaveContext.Collections.SelectMany(CollectStrings).ToList();

            stringsSet.UnionWith(strings);
            var stringsChunk = new BinStringsChunk {
                Strings = new List <string>(stringsSet)
            };

            cw.WriteChunk(stringsChunk);
            cw.WriteChunk(new EndChunk());

            return(ms);
        }
예제 #12
0
        public void Write(ChunkWriter chunkWriter)
        {
            chunkWriter.BinaryWriter.Write(1);
            chunkWriter.BinaryWriter.Write(3);
            chunkWriter.BinaryWriter.Write(3);
            chunkWriter.BinaryWriter.Write(0x13371337);
            chunkWriter.BinaryWriter.Write(0);

            var nameBytes = new char[0x1C];

            nameBytes[0] = 'H';
            nameBytes[1] = 'E';
            nameBytes[2] = 'L';
            nameBytes[3] = 'L';
            nameBytes[4] = 'O';
            chunkWriter.BinaryWriter.Write(nameBytes);
            for (var i = 0; i < 0x78; i++)
            {
                chunkWriter.BinaryWriter.Write((byte)i);
            }
        }
예제 #13
0
        public void Write_NormalChunk_SuccessfulWrite()
        {
            var targetStream = new MemoryStream();
            var chunk        = new Chunk
            {
                AsciiHeader = "MTrk",
                Data        = new byte[] { 0xFF, 0x10, 0x00 }
            };

            using (var writer = new ChunkWriter(targetStream)) {
                writer.Write(chunk);
            }

            var expectedBytes = new byte[]
            {
                0x4D, 0x54, 0x72, 0x6B,
                0x00, 0x00, 0x00, 0x03,
                0xFF, 0x10, 0x00
            };

            targetStream.ToArray().ShouldBe(expectedBytes);
        }
예제 #14
0
        public void ShouldCloseTheChunkWithCorrectSize(int chunkSize)
        {
            var buffer = Enumerable.Range(0, chunkSize).Select(i => i % byte.MaxValue).Select(i => (byte)i).ToArray();
            var stream = new MemoryStream();
            var writer = new ChunkWriter(stream);

            // Write data
            writer.OpenChunk();
            writer.Write(buffer, 0, buffer.Length);
            writer.CloseChunk();

            // End Of Message Marker
            writer.OpenChunk();
            writer.CloseChunk();

            // Write To Underlying Stream
            writer.Send();

            var constructed = ConstructMessage(stream.ToArray());

            constructed.Should().HaveCount(chunkSize);
            constructed.Should().Equal(buffer);
        }
예제 #15
0
 private static void WriteSprites(ChunkWriter chunkIO, List <WadSprite> spriteTable)
 {
     chunkIO.WriteChunkWithChildren(Wad2Chunks.Sprites, () =>
     {
         for (int i = 0; i < spriteTable.Count; ++i)
         {
             var sprite = spriteTable[i];
             chunkIO.WriteChunkWithChildren(Wad2Chunks.Sprite, () =>
             {
                 LEB128.Write(chunkIO.Raw, sprite.Texture.Image.Width);
                 LEB128.Write(chunkIO.Raw, sprite.Texture.Image.Height);
                 chunkIO.WriteChunkInt(Wad2Chunks.SpriteIndex, i);
                 chunkIO.WriteChunkArrayOfBytes(Wad2Chunks.SpriteData, sprite.Texture.Image.ToByteArray());
                 chunkIO.WriteChunk(Wad2Chunks.SpriteSides, () => {
                     chunkIO.Raw.Write(sprite.Alignment.X0);
                     chunkIO.Raw.Write(sprite.Alignment.Y0);
                     chunkIO.Raw.Write(sprite.Alignment.X1);
                     chunkIO.Raw.Write(sprite.Alignment.Y1);
                 });
             });
         }
     });
 }
예제 #16
0
        public void Init(ChunkManagerConfig eventDataChunkConfig, ChunkManagerConfig aggregateIndexChunkConfig, ChunkManagerConfig commandIndexChunkConfig)
        {
            _eventDataChunkManager = new ChunkManager("EventDataChunk", eventDataChunkConfig, false);
            _eventDataChunkWriter  = new ChunkWriter(_eventDataChunkManager);
            _eventDataChunkReader  = new ChunkReader(_eventDataChunkManager, _eventDataChunkWriter);

            _aggregateIndexChunkManager = new ChunkManager("AggregateIndexChunk", aggregateIndexChunkConfig, false);
            _aggregateIndexChunkWriter  = new ChunkWriter(_aggregateIndexChunkManager);
            _aggregateIndexChunkReader  = new ChunkReader(_aggregateIndexChunkManager, _aggregateIndexChunkWriter);

            _commandIndexChunkManager = new ChunkManager("CommandIndexChunk", commandIndexChunkConfig, false);
            _commandIndexChunkWriter  = new ChunkWriter(_commandIndexChunkManager);
            _commandIndexChunkReader  = new ChunkReader(_commandIndexChunkManager, _commandIndexChunkWriter);

            _eventDataChunkManager.Load(ReadEventStreamRecord);
            _aggregateIndexChunkManager.Load(ReadIndexRecord);
            _commandIndexChunkManager.Load(ReadIndexRecord);

            _eventDataChunkWriter.Open();
            _aggregateIndexChunkWriter.Open();
            _commandIndexChunkWriter.Open();

            LoadIndexData();
        }
        public void Write(ArraySegment <byte> buffer, bool chunk)
        {
            lock (_writeLock)
            {
                if (buffer.Count == 0)
                {
                    return;
                }

                try
                {
                    if (!_canWrite)
                    {
                        return;
                    }

                    if (chunk && buffer.Array != null)
                    {
                        var beginChunkBytes = ChunkWriter.BeginChunkBytes(buffer.Count);
                        _outputStream.Write(beginChunkBytes.Array, beginChunkBytes.Offset, beginChunkBytes.Count);
                    }

                    _outputStream.Write(buffer.Array ?? _nullBuffer, buffer.Offset, buffer.Count);

                    if (chunk && buffer.Array != null)
                    {
                        _outputStream.Write(_endChunkBytes, 0, _endChunkBytes.Length);
                    }
                }
                catch (Exception ex)
                {
                    _canWrite = false;
                    _logger.ConnectionError(_connectionId, ex);
                }
            }
        }
예제 #18
0
	// Save a PNG image to the specified stream.
	public static void Save(Stream stream, Image image)
			{
				Frame frame = image.GetFrame(0);
				byte[] buffer = new byte [1024];
				ChunkWriter writer = new ChunkWriter(stream);
				int colorType, bitDepth;
				int sigRed, sigGreen, sigBlue, sigAlpha;
				int paletteSize, posn;
				int[] palette;
				ZlibCompressor compressor;
				ScanlineWriter scanlineWriter;
				OutputFunc func;
				int y;

				// Determine the color type and bit depth for the image.
				sigRed = -1;
				sigGreen = -1;
				sigBlue = -1;
				sigAlpha = -1;
				paletteSize = 0;
				switch(frame.PixelFormat)
				{
					case PixelFormat.Format16bppRgb555:
					{
						sigRed = 5;
						sigGreen = 5;
						sigBlue = 5;
						colorType = 2;
						bitDepth = 8;
					}
					break;

					case PixelFormat.Format16bppRgb565:
					{
						sigRed = 5;
						sigGreen = 6;
						sigBlue = 5;
						colorType = 2;
						bitDepth = 8;
					}
					break;

					case PixelFormat.Format24bppRgb:
					case PixelFormat.Format32bppRgb:
					{
						colorType = 2;
						bitDepth = 8;
					}
					break;

					case PixelFormat.Format1bppIndexed:
					{
						colorType = 3;
						bitDepth = 1;
						paletteSize = 2;
					}
					break;

					case PixelFormat.Format4bppIndexed:
					{
						colorType = 3;
						bitDepth = 4;
						paletteSize = 16;
					}
					break;

					case PixelFormat.Format8bppIndexed:
					{
						colorType = 3;
						bitDepth = 8;
						paletteSize = 256;
					}
					break;

					case PixelFormat.Format16bppArgb1555:
					{
						sigRed = 5;
						sigGreen = 5;
						sigBlue = 5;
						sigAlpha = 1;
						colorType = 6;
						bitDepth = 8;
					}
					break;

					case PixelFormat.Format32bppPArgb:
					case PixelFormat.Format32bppArgb:
					{
						colorType = 6;
						bitDepth = 8;
					}
					break;

					case PixelFormat.Format16bppGrayScale:
					{
						colorType = 0;
						bitDepth = 16;
					}
					break;

					case PixelFormat.Format48bppRgb:
					{
						colorType = 2;
						bitDepth = 16;
					}
					break;

					case PixelFormat.Format64bppPArgb:
					case PixelFormat.Format64bppArgb:
					{
						colorType = 6;
						bitDepth = 16;
					}
					break;

					default: throw new FormatException("unknown format");
				}

				// Write out the PNG magic number.
				stream.Write(magic, 0, magic.Length);

				// Write the header chunk.
				Utils.WriteInt32B(buffer, 0, frame.Width);
				Utils.WriteInt32B(buffer, 4, frame.Height);
				buffer[8] = (byte)bitDepth;
				buffer[9] = (byte)colorType;
				buffer[10] = (byte)0;			// Compression method.
				buffer[11] = (byte)0;			// Filter method.
				buffer[12] = (byte)0;			// Interlace method.
				writer.Write(PngReader.IHDR, buffer, 0, 13);

				// Write the significant bits chunk if necessary.
				if(sigAlpha != -1)
				{
					buffer[0] = (byte)sigRed;
					buffer[1] = (byte)sigGreen;
					buffer[2] = (byte)sigBlue;
					buffer[3] = (byte)sigAlpha;
					writer.Write(PngReader.sBIT, buffer, 0, 4);
				}
				else if(sigRed != -1)
				{
					buffer[0] = (byte)sigRed;
					buffer[1] = (byte)sigGreen;
					buffer[2] = (byte)sigBlue;
					writer.Write(PngReader.sBIT, buffer, 0, 3);
				}

				// Write the palette and transparency chunks.
				if(paletteSize > 0)
				{
					Array.Clear(buffer, 0, buffer.Length);
					palette = frame.Palette;
					if(palette != null)
					{
						for(posn = 0; posn < palette.Length &&
									  posn < paletteSize; ++posn)
						{
							buffer[posn * 3] = (byte)(palette[posn] >> 16);
							buffer[posn * 2 + 1] = (byte)(palette[posn] >> 8);
							buffer[posn * 2 + 2] = (byte)(palette[posn]);
						}
					}
					writer.Write(PngReader.PLTE, buffer, 0, paletteSize * 3);
					if(frame.TransparentPixel >= 0 &&
					   frame.TransparentPixel < paletteSize)
					{
						for(posn = 0; posn < paletteSize; ++posn)
						{
							buffer[posn] = (byte)0xFF;
						}
						buffer[frame.TransparentPixel] = (byte)0x00;
						writer.Write(PngReader.tRNS, buffer, 0,
									 frame.TransparentPixel + 1);
					}
				}

				// Compress and write the scanlines to the output stream.
				compressor = new ZlibCompressor(writer);
				scanlineWriter = new ScanlineWriter
					(compressor, frame.Width, frame.PixelFormat);
				func = GetOutputFunc(frame.PixelFormat);
				for(y = 0; y < frame.Height; ++y)
				{
					func(frame, y, scanlineWriter.Buffer);
					scanlineWriter.FlushScanline();
				}
				compressor.Finish();

				// Write the end chunk.
				writer.Write(PngReader.IEND, buffer, 0, 0);
			}
예제 #19
0
 /// <inheritdoc />
 public void Write(ChunkWriter chunkWriter)
 {
     chunkWriter.BinaryWriter.Write(_resource.Data);
 }
예제 #20
0
        static void WriteChunkPerfTest()
        {
            ECommonConfiguration
            .Create()
            .UseAutofac()
            .RegisterCommonComponents()
            .UseLog4Net()
            .RegisterUnhandledExceptionHandler()
            .BuildContainer();

            var         storeRootPath = ConfigurationManager.AppSettings["storeRootPath"];                                 //文件存储根目录
            var         threadCount   = int.Parse(ConfigurationManager.AppSettings["concurrentThreadCount"]);              //并行写数据的线程数
            var         recordSize    = int.Parse(ConfigurationManager.AppSettings["recordSize"]);                         //记录大小,字节为单位
            var         recordCount   = int.Parse(ConfigurationManager.AppSettings["recordCount"]);                        //总共要写入的记录数
            var         syncFlush     = bool.Parse(ConfigurationManager.AppSettings["syncFlush"]);                         //是否同步刷盘
            FlushOption flushOption;

            Enum.TryParse(ConfigurationManager.AppSettings["flushOption"], out flushOption);                                //同步刷盘方式
            var chunkSize          = 1024 * 1024 * 1024;
            var flushInterval      = 100;
            var maxRecordSize      = 5 * 1024 * 1024;
            var chunkWriteBuffer   = 128 * 1024;
            var chunkReadBuffer    = 128 * 1024;
            var chunkManagerConfig = new ChunkManagerConfig(
                Path.Combine(storeRootPath, @"sample-chunks"),
                new DefaultFileNamingStrategy("message-chunk-"),
                chunkSize,
                0,
                0,
                flushInterval,
                false,
                syncFlush,
                flushOption,
                Environment.ProcessorCount * 8,
                maxRecordSize,
                chunkWriteBuffer,
                chunkReadBuffer,
                5,
                1,
                1,
                5,
                10 * 10000,
                true);
            var chunkManager = new ChunkManager("sample-chunk", chunkManagerConfig, false);
            var chunkWriter  = new ChunkWriter(chunkManager);

            chunkManager.Load(ReadRecord);
            chunkWriter.Open();
            var record = new BufferLogRecord
            {
                RecordBuffer = new byte[recordSize]
            };
            var count = 0L;
            var performanceService = ObjectContainer.Resolve <IPerformanceService>();

            performanceService.Initialize("WriteChunk").Start();

            for (var i = 0; i < threadCount; i++)
            {
                Task.Factory.StartNew(() =>
                {
                    while (true)
                    {
                        var current = Interlocked.Increment(ref count);
                        if (current > recordCount)
                        {
                            break;
                        }
                        var start = DateTime.Now;
                        chunkWriter.Write(record);
                        performanceService.IncrementKeyCount("default", (DateTime.Now - start).TotalMilliseconds);
                    }
                });
            }

            Console.ReadLine();

            chunkWriter.Close();
            chunkManager.Close();
        }
예제 #21
0
        private static LevelSettingsIds WriteLevelSettings(ChunkWriter chunkIO, LevelSettings settings)
        {
            var levelSettingIds = new LevelSettingsIds(settings);

            using (var chunkSettings = chunkIO.WriteChunk(Prj2Chunks.Settings, long.MaxValue))
            {
                chunkIO.WriteChunkString(Prj2Chunks.FontTextureFilePath, settings.FontTextureFilePath ?? "");
                chunkIO.WriteChunkString(Prj2Chunks.SkyTextureFilePath, settings.SkyTextureFilePath ?? "");
                chunkIO.WriteChunkString(Prj2Chunks.Tr5ExtraSpritesFilePath, settings.Tr5ExtraSpritesFilePath ?? "");
                using (var chunkOldWadSoundPaths = chunkIO.WriteChunk(Prj2Chunks.OldWadSoundPaths))
                {
                    chunkIO.WriteChunkEmpty(Prj2Chunks.OldWadSoundUpdateTag1_0_8);
                    foreach (WadSoundPath soundPath in settings.WadSoundPaths)
                    {
                        using (var chunkOldWadSoundPath = chunkIO.WriteChunk(Prj2Chunks.OldWadSoundPath))
                        {
                            chunkIO.WriteChunkString(Prj2Chunks.OldWadSoundPathPath, soundPath.Path);
                            chunkIO.WriteChunkEnd();
                        }
                    }
                    chunkIO.WriteChunkEnd();
                }
                chunkIO.WriteChunkString(Prj2Chunks.GameDirectory, settings.GameDirectory ?? "");
                chunkIO.WriteChunkString(Prj2Chunks.GameLevelFilePath, settings.GameLevelFilePath ?? "");
                chunkIO.WriteChunkString(Prj2Chunks.GameExecutableFilePath, settings.GameExecutableFilePath ?? "");
                chunkIO.WriteChunkBool(Prj2Chunks.GameEnableQuickStartFeature, settings.GameEnableQuickStartFeature);
                chunkIO.WriteChunkInt(Prj2Chunks.GameVersion, (long)settings.GameVersion);
                chunkIO.WriteChunkInt(Prj2Chunks.Tr5LaraType, (long)settings.Tr5LaraType);
                chunkIO.WriteChunkInt(Prj2Chunks.Tr5Weather, (long)settings.Tr5WeatherType);
                chunkIO.WriteChunkInt(Prj2Chunks.TexturePadding, (long)settings.TexturePadding);
                chunkIO.WriteChunkBool(Prj2Chunks.RemapAnimatedTextures, settings.RemapAnimatedTextures);
                chunkIO.WriteChunkBool(Prj2Chunks.Dither16BitTextures, settings.Dither16BitTextures);
                chunkIO.WriteChunkBool(Prj2Chunks.AgressiveTexturePacking, settings.AgressiveTexturePacking);
                chunkIO.WriteChunkBool(Prj2Chunks.AgressiveFloordataPacking, settings.AgressiveFloordataPacking);
                chunkIO.WriteChunkVector3(Prj2Chunks.DefaultAmbientLight, settings.DefaultAmbientLight);
                chunkIO.WriteChunkInt(Prj2Chunks.DefaultLightQuality, (long)settings.DefaultLightQuality);
                chunkIO.WriteChunkBool(Prj2Chunks.OverrideLightQuality, settings.OverrideIndividualLightQualitySettings);
                chunkIO.WriteChunkString(Prj2Chunks.ScriptDirectory, settings.ScriptDirectory ?? "");
                chunkIO.WriteChunkInt(Prj2Chunks.SoundSystem, (int)settings.SoundSystem);
                using (var chunkWads = chunkIO.WriteChunk(Prj2Chunks.Wads, long.MaxValue))
                {
                    foreach (ReferencedWad wad in settings.Wads)
                    {
                        using (var chunkWad = chunkIO.WriteChunk(Prj2Chunks.Wad))
                        {
                            chunkIO.WriteChunkString(Prj2Chunks.WadPath, wad.Path ?? "");
                            chunkIO.WriteChunkEnd();
                        }
                    }
                    chunkIO.WriteChunkEnd();
                }
                using (var chunkSounds = chunkIO.WriteChunk(Prj2Chunks.SoundsCatalogs, long.MaxValue))
                {
                    foreach (ReferencedSoundsCatalog soundRef in settings.SoundsCatalogs)
                    {
                        using (var chunkSound = chunkIO.WriteChunk(Prj2Chunks.SoundsCatalog))
                        {
                            chunkIO.WriteChunkString(Prj2Chunks.SoundsCatalogPath, soundRef.Path ?? "");
                            chunkIO.WriteChunkEnd();
                        }
                    }
                    chunkIO.WriteChunkEnd();
                }
                using (var chunkSelectedSounds = chunkIO.WriteChunk(Prj2Chunks.SelectedSounds, long.MaxValue))
                {
                    foreach (int selectedSound in settings.SelectedSounds)
                    {
                        chunkIO.WriteChunkInt(Prj2Chunks.SelectedSound, selectedSound);
                    }
                    chunkIO.WriteChunkEnd();
                }
                using (var chunkTextures = chunkIO.WriteChunk(Prj2Chunks.Textures, long.MaxValue))
                {
                    int index = 0;
                    foreach (LevelTexture texture in settings.Textures)
                    {
                        using (var chunkLevelTexture = chunkIO.WriteChunk(Prj2Chunks.LevelTexture))
                        {
                            chunkIO.WriteChunkInt(Prj2Chunks.LevelTextureIndex, index);
                            chunkIO.WriteChunkString(Prj2Chunks.LevelTexturePath, texture.Path ?? "");
                            chunkIO.WriteChunkString(Prj2Chunks.LevelTextureCustomBumpmapPath, texture.BumpPath ?? "");
                            chunkIO.WriteChunkBool(Prj2Chunks.LevelTextureConvert512PixelsToDoubleRows, texture.Convert512PixelsToDoubleRows);
                            chunkIO.WriteChunkBool(Prj2Chunks.LevelTextureReplaceMagentaWithTransparency, texture.ReplaceMagentaWithTransparency);
                            using (var chunkLevelTextureFootStepSounds = chunkIO.WriteChunk(Prj2Chunks.LevelTextureFootStepSounds))
                            {
                                chunkIO.Raw.Write(texture.FootStepSoundWidth);
                                chunkIO.Raw.Write(texture.FootStepSoundHeight);
                                for (int y = 0; y < texture.FootStepSoundHeight; ++y)
                                {
                                    for (int x = 0; x < texture.FootStepSoundWidth; ++x)
                                    {
                                        chunkIO.Raw.Write((byte)texture.GetFootStepSound(x, y));
                                    }
                                }
                            }
                            using (var chunkLevelTextureBumpmaps = chunkIO.WriteChunk(Prj2Chunks.LevelTextureBumpmaps))
                            {
                                chunkIO.Raw.Write(texture.BumpMappingWidth);
                                chunkIO.Raw.Write(texture.BumpMappingHeight);
                                for (int y = 0; y < texture.BumpMappingHeight; ++y)
                                {
                                    for (int x = 0; x < texture.BumpMappingWidth; ++x)
                                    {
                                        chunkIO.Raw.Write((byte)texture.GetBumpMapLevel(x, y));
                                    }
                                }
                            }
                            chunkIO.WriteChunkEnd();
                        }
                        levelSettingIds.LevelTextures.Add(texture, index++);
                    }
                    chunkIO.WriteChunkEnd();
                }
                using (var chunkImportedGeometries = chunkIO.WriteChunk(Prj2Chunks.ImportedGeometries, long.MaxValue))
                {
                    int index = 0;
                    foreach (ImportedGeometry importedGeometry in settings.ImportedGeometries)
                    {
                        using (var chunkImportedGeometry = chunkIO.WriteChunk(Prj2Chunks.ImportedGeometry))
                        {
                            chunkIO.WriteChunkInt(Prj2Chunks.ImportedGeometryIndex, index);
                            chunkIO.WriteChunkString(Prj2Chunks.ImportedGeometryName, importedGeometry.Info.Name);
                            chunkIO.WriteChunkString(Prj2Chunks.ImportedGeometryPath, importedGeometry.Info.Path);
                            chunkIO.WriteChunkFloat(Prj2Chunks.ImportedGeometryScale, importedGeometry.Info.Scale);
                            chunkIO.WriteChunkInt(Prj2Chunks.ImportedGeometryPosAxisFlags,
                                                  (importedGeometry.Info.SwapXY ? 1 : 0) |
                                                  (importedGeometry.Info.SwapXZ ? 2 : 0) |
                                                  (importedGeometry.Info.SwapYZ ? 4 : 0) |
                                                  (importedGeometry.Info.FlipX ? 8 : 0) |
                                                  (importedGeometry.Info.FlipY ? 16 : 0) |
                                                  (importedGeometry.Info.FlipZ ? 32 : 0));
                            chunkIO.WriteChunkInt(Prj2Chunks.ImportedGeometryTexAxisFlags, importedGeometry.Info.FlipUV_V ? 4 : 0);
                            chunkIO.WriteChunkBool(Prj2Chunks.ImportedGeometryInvertFaces, importedGeometry.Info.InvertFaces);
                            chunkIO.WriteChunkEnd();
                        }
                        levelSettingIds.ImportedGeometries.Add(importedGeometry, index++);
                    }
                    chunkIO.WriteChunkEnd();
                }
                using (var chunkAnimatedTextureSets = chunkIO.WriteChunk(Prj2Chunks.AnimatedTextureSets, long.MaxValue))
                {
                    foreach (AnimatedTextureSet set in settings.AnimatedTextureSets)
                    {
                        using (var chunkAnimatedTextureSet = chunkIO.WriteChunk(Prj2Chunks.AnimatedTextureSet))
                        {
                            chunkIO.WriteChunkString(Prj2Chunks.AnimatedTextureSetName, set.Name ?? "");
                            chunkIO.WriteChunkInt(Prj2Chunks.AnimatedTextureSetType, (int)set.AnimationType);
                            chunkIO.WriteChunkFloat(Prj2Chunks.AnimatedTextureSetFps, set.Fps);
                            chunkIO.WriteChunkInt(Prj2Chunks.AnimatedTextureSetUvRotate, set.UvRotate);
                            using (var chunkAnimatedTextureFrames = chunkIO.WriteChunk(Prj2Chunks.AnimatedTextureFrames))
                            {
                                foreach (AnimatedTextureFrame frame in set.Frames)
                                {
                                    using (var chunkAnimatedTextureFrame = chunkIO.WriteChunk(Prj2Chunks.AnimatedTextureFrame, 120))
                                    {
                                        LEB128.Write(chunkIO.Raw, levelSettingIds.LevelTextures[frame.Texture]);
                                        chunkIO.Raw.Write(frame.TexCoord0);
                                        chunkIO.Raw.Write(frame.TexCoord1);
                                        chunkIO.Raw.Write(frame.TexCoord2);
                                        chunkIO.Raw.Write(frame.TexCoord3);
                                        LEB128.Write(chunkIO.Raw, frame.Repeat);
                                    }
                                }

                                chunkIO.WriteChunkEnd();
                            }
                            chunkIO.WriteChunkEnd();
                        }
                    }
                    chunkIO.WriteChunkEnd();
                }
                using (var chunkAutoMergeStatics = chunkIO.WriteChunk(Prj2Chunks.AutoMergeStaticMeshes, UInt16.MaxValue))
                {
                    foreach (var entry in settings.AutoStaticMeshMerges)
                    {
                        using  (var chunkAutoMergeEntry = chunkIO.WriteChunk(Prj2Chunks.AutoMergeStaticMeshEntry3))
                        {
                            chunkIO.Raw.Write(entry.meshId);
                            chunkIO.Raw.Write(entry.InterpretShadesAsEffect);
                            chunkIO.Raw.Write(entry.TintAsAmbient);
                            chunkIO.Raw.Write(entry.ClearShades);
                        }
                    }
                    chunkIO.WriteChunkEnd();
                }
                using (var chunkPalette = chunkIO.WriteChunk(Prj2Chunks.Palette, UInt16.MaxValue))
                {
                    chunkIO.Raw.Write((ushort)settings.Palette.Count);
                    foreach (var color in settings.Palette)
                    {
                        chunkIO.Raw.Write(color.R);
                        chunkIO.Raw.Write(color.G);
                        chunkIO.Raw.Write(color.B);
                    }
                    chunkIO.WriteChunkEnd();
                }
                chunkIO.WriteChunkEnd();
            };

            return(levelSettingIds);
        }
예제 #22
0
 static Task Write(ChunkWriter writer, byte[] chunk) => writer.WriteAsync(new UserData(), chunk, 0, chunk.Length);
예제 #23
0
 public static void WriteChunks(ChunkWriter writer)
 {
     writer.Write(nameof(AppReady), AppReady);
 }
예제 #24
0
 public void Append <TBody>(Chunk <TBody> chunk, ChunkWriter chunkWriter, Serializer <TBody> serializer) where TBody : class
 {
     Append(chunk.Configuration, chunkWriter.ChunkToStreamAsync(chunk, serializer));
 }
예제 #25
0
 public static void WriteChunks(ChunkWriter writer)
 {
     writer.Write(nameof(JoinedProfile), JoinedProfile);
     writer.Write(nameof(SendTransferNotifications), SendTransferNotifications);
 }
예제 #26
0
        public void ChunkedPrefixMustBeHexCrLfWithoutLeadingZeros(int dataCount, string expected)
        {
            var beginChunkBytes = ChunkWriter.BeginChunkBytes(dataCount);

            Assert.Equal(Encoding.ASCII.GetBytes(expected), beginChunkBytes.ToArray());
        }
예제 #27
0
        private static void WriteRooms(ChunkWriter chunkIO, Dictionary <Room, int> rooms, LevelSettingsIds levelSettingIds)
        {
            // Allocate object indices
            var objectInstanceLookup = new Dictionary <ObjectInstance, int>();

            foreach (Room room in rooms.Keys)
            {
                foreach (ObjectInstance objectInstance in room.AnyObjects)
                {
                    objectInstanceLookup.Add(objectInstance, objectInstanceLookup.Count);
                }
            }

            // Save
            using (var chunkRooms = chunkIO.WriteChunk(Prj2Chunks.Rooms, long.MaxValue))
            {
                foreach (Room room in rooms.Keys)
                {
                    using (var chunkRoom = chunkIO.WriteChunk(Prj2Chunks.Room, long.MaxValue))
                    {
                        LEB128.Write(chunkIO.Raw, room.NumXSectors);
                        LEB128.Write(chunkIO.Raw, room.NumZSectors);

                        // Write basic properties
                        chunkIO.WriteChunkInt(Prj2Chunks.RoomIndex, rooms.TryGetOrDefault(room, -1));
                        chunkIO.WriteChunkString(Prj2Chunks.RoomName, room.Name);
                        chunkIO.WriteChunkVector3(Prj2Chunks.RoomPosition, room.Position);
                        chunkIO.WriteChunkArrayOfBytes(Prj2Chunks.RoomTags, System.Text.Encoding.UTF8.GetBytes(string.Join(" ", room.Tags)));

                        // Write sectors
                        using (var chunkRoomSectors = chunkIO.WriteChunk(Prj2Chunks.RoomSectors))
                        {
                            for (int z = 0; z < room.NumZSectors; z++)
                            {
                                for (int x = 0; x < room.NumXSectors; x++)
                                {
                                    using (var chunkSector = chunkIO.WriteChunk(Prj2Chunks.Sector, LEB128.MaximumSize2Byte))
                                    {
                                        chunkIO.Raw.Write(x + z * room.NumXSectors);
                                        var b = room.Blocks[x, z];

                                        long combinedFlag = (b.IsAnyWall ? 1L : 0) | (b.ForceFloorSolid ? 2L : 0) | ((long)b.Flags << 2);
                                        chunkIO.WriteChunkInt(Prj2Chunks.SectorProperties, combinedFlag);
                                        using (var chunkSectorFloor = chunkIO.WriteChunk(Prj2Chunks.SectorFloor, LEB128.MaximumSize1Byte))
                                        {
                                            long flag = (b.Floor.SplitDirectionIsXEqualsZ ? 1L : 0) | ((long)b.Floor.DiagonalSplit << 1);
                                            LEB128.Write(chunkIO.Raw, flag);
                                            for (BlockEdge edge = 0; edge < BlockEdge.Count; ++edge)
                                            {
                                                LEB128.Write(chunkIO.Raw, b.Floor.GetHeight(edge));
                                            }
                                            for (BlockEdge edge = 0; edge < BlockEdge.Count; ++edge)
                                            {
                                                LEB128.Write(chunkIO.Raw, b.GetHeight(BlockVertical.Ed, edge));
                                            }
                                        }
                                        using (var chunkSectorCeiling = chunkIO.WriteChunk(Prj2Chunks.SectorCeiling, LEB128.MaximumSize1Byte))
                                        {
                                            long flag = (b.Ceiling.SplitDirectionIsXEqualsZ ? 1L : 0) | ((long)b.Ceiling.DiagonalSplit << 1);
                                            LEB128.Write(chunkIO.Raw, flag);
                                            for (BlockEdge edge = 0; edge < BlockEdge.Count; ++edge)
                                            {
                                                LEB128.Write(chunkIO.Raw, b.Ceiling.GetHeight(edge));
                                            }
                                            for (BlockEdge edge = 0; edge < BlockEdge.Count; ++edge)
                                            {
                                                LEB128.Write(chunkIO.Raw, b.GetHeight(BlockVertical.Rf, edge));
                                            }
                                        }
                                        for (BlockFace face = 0; face < BlockFace.Count; face++)
                                        {
                                            var texture = b.GetFaceTexture(face);
                                            if (texture.Texture == null)
                                            {
                                                continue;
                                            }

                                            if (texture.Texture is LevelTexture)
                                            {
                                                using (var chunkTextureLevelTexture = chunkIO.WriteChunk(Prj2Chunks.TextureLevelTexture2, LEB128.MaximumSize1Byte))
                                                {
                                                    int textureIndex = levelSettingIds.LevelTextures[(LevelTexture)texture.Texture];

                                                    LEB128.Write(chunkIO.Raw, (long)face);
                                                    chunkIO.Raw.Write(texture.TexCoord0);
                                                    chunkIO.Raw.Write(texture.TexCoord1);
                                                    chunkIO.Raw.Write(texture.TexCoord2);
                                                    chunkIO.Raw.Write(texture.TexCoord3);
                                                    chunkIO.Raw.Write(texture.ParentArea.Start);
                                                    chunkIO.Raw.Write(texture.ParentArea.End);
                                                    LEB128.Write(chunkIO.Raw, (texture.DoubleSided ? 1L : 0) | ((long)texture.BlendMode << 1));
                                                    LEB128.Write(chunkIO.Raw, textureIndex);
                                                }
                                            }
                                            else if (texture.Texture == TextureInvisible.Instance)
                                            {
                                                chunkIO.WriteChunkInt(Prj2Chunks.TextureInvisible, (long)face);
                                            }
                                            else
                                            {
                                                throw new NotSupportedException("Unsupported texture type " + texture.Texture.GetType().Name);
                                            }
                                        }
                                        chunkIO.WriteChunkEnd();
                                    }
                                }
                            }
                            chunkIO.WriteChunkEnd();
                        }

                        // Write room properties
                        chunkIO.WriteChunkVector3(Prj2Chunks.RoomAmbientLight, room.AmbientLight);
                        chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagCold, room.FlagCold);
                        chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagDamage, room.FlagDamage);
                        chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagHorizon, room.FlagHorizon);
                        chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagOutside, room.FlagOutside);
                        chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagNoLensflare, room.FlagNoLensflare);
                        chunkIO.WriteChunkBool(Prj2Chunks.RoomFlagExcludeFromPathFinding, room.FlagExcludeFromPathFinding);
                        chunkIO.WriteChunkInt(Prj2Chunks.RoomType, (int)room.Type);
                        chunkIO.WriteChunkInt(Prj2Chunks.RoomTypeStrength, room.TypeStrength);
                        chunkIO.WriteChunkInt(Prj2Chunks.RoomLightEffect, (int)room.LightEffect);
                        chunkIO.WriteChunkInt(Prj2Chunks.RoomLightEffectStrength2, room.LightEffectStrength);
                        chunkIO.WriteChunkInt(Prj2Chunks.RoomReverberation, (int)room.Reverberation);
                        chunkIO.WriteChunkInt(Prj2Chunks.RoomLightInterpolationMode, (int)room.LightInterpolationMode);
                        chunkIO.WriteChunkBool(Prj2Chunks.RoomLocked, room.Locked);
                        chunkIO.WriteChunkBool(Prj2Chunks.RoomHidden, room.Hidden);
                        if (room.AlternateRoom != null && rooms.ContainsKey(room.AlternateRoom))
                        {
                            using (var chunkRoomAlternate = chunkIO.WriteChunk(Prj2Chunks.RoomAlternate, LEB128.MaximumSize1Byte))
                            {
                                chunkIO.WriteChunkInt(Prj2Chunks.AlternateGroup, room.AlternateGroup);
                                chunkIO.WriteChunkInt(Prj2Chunks.AlternateRoom, rooms[room.AlternateRoom]);
                                chunkIO.WriteChunkEnd();
                            }
                        }

                        // Write room objects
                        WriteObjects(chunkIO, room.AnyObjects, rooms, levelSettingIds, objectInstanceLookup);
                        chunkIO.WriteChunkEnd();
                    }
                }
                chunkIO.WriteChunkEnd();
            }
        }
예제 #28
0
        private static void WriteObjects(ChunkWriter chunkIO, IEnumerable <ObjectInstance> objects,
                                         Dictionary <Room, int> rooms, LevelSettingsIds levelSettingIds,
                                         Dictionary <ObjectInstance, int> objectInstanceLookup)
        {
            using (var chunkObjects = chunkIO.WriteChunk(Prj2Chunks.Objects, long.MaxValue))
            {
                foreach (var o in objects)
                {
                    if (o is MoveableInstance)
                    {
                        chunkIO.WriteChunkWithChildren(Prj2Chunks.ObjectMovable3, () =>
                        {
                            var instance = (MoveableInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            chunkIO.Raw.Write(instance.Position);
                            chunkIO.Raw.Write(instance.RotationY);
                            LEB128.Write(chunkIO.Raw, (long?)instance.ScriptId ?? -1);
                            chunkIO.Raw.Write(instance.WadObjectId.TypeId);
                            chunkIO.Raw.Write(instance.Ocb);
                            chunkIO.Raw.Write(instance.Invisible);
                            chunkIO.Raw.Write(instance.ClearBody);
                            chunkIO.Raw.Write(instance.CodeBits);
                            chunkIO.Raw.Write(instance.Color);
                            chunkIO.WriteChunkInt(Prj2Chunks.ObjectItemLuaId, instance.LuaId);
                        });
                    }
                    else if (o is StaticInstance)
                    {
                        chunkIO.WriteChunkWithChildren(Prj2Chunks.ObjectStatic2, () =>
                        {
                            var instance = (StaticInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            chunkIO.Raw.Write(instance.Position);
                            chunkIO.Raw.Write(instance.RotationY);
                            LEB128.Write(chunkIO.Raw, (long?)instance.ScriptId ?? -1);
                            chunkIO.Raw.Write(instance.WadObjectId.TypeId);
                            chunkIO.Raw.Write(instance.Color);
                            chunkIO.Raw.Write((int)0); // Unused 32 bit value
                            chunkIO.Raw.Write(instance.Ocb);
                            chunkIO.WriteChunkInt(Prj2Chunks.ObjectItemLuaId, instance.LuaId);
                        });
                    }
                    else if (o is CameraInstance)
                    {
                        using (var chunk = chunkIO.WriteChunk(Prj2Chunks.ObjectCamera, LEB128.MaximumSize1Byte))
                        {
                            var instance = (CameraInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            chunkIO.Raw.Write(instance.Position);
                            LEB128.Write(chunkIO.Raw, (long?)instance.ScriptId ?? -1);
                            chunkIO.Raw.Write(instance.Fixed);
                        }
                    }
                    else if (o is FlybyCameraInstance)
                    {
                        chunkIO.WriteChunkWithChildren(Prj2Chunks.ObjectFlyBy, () =>
                        {
                            var instance = (FlybyCameraInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            chunkIO.Raw.Write(instance.Position);
                            chunkIO.Raw.Write(instance.RotationY);
                            chunkIO.Raw.Write(instance.RotationX);
                            chunkIO.Raw.Write(instance.Roll);
                            LEB128.Write(chunkIO.Raw, (long?)instance.ScriptId ?? -1);
                            chunkIO.Raw.Write(instance.Speed);
                            chunkIO.Raw.Write(instance.Fov);
                            LEB128.Write(chunkIO.Raw, instance.Flags);
                            LEB128.Write(chunkIO.Raw, instance.Number);
                            LEB128.Write(chunkIO.Raw, instance.Sequence);
                            LEB128.Write(chunkIO.Raw, instance.Timer);
                        });
                    }
                    else if (o is SinkInstance)
                    {
                        using (var chunk = chunkIO.WriteChunk(Prj2Chunks.ObjectSink, LEB128.MaximumSize1Byte))
                        {
                            var instance = (SinkInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            chunkIO.Raw.Write(instance.Position);
                            LEB128.Write(chunkIO.Raw, (long?)instance.ScriptId ?? -1);
                            chunkIO.Raw.Write(instance.Strength);
                        }
                    }
                    else if (o is SoundSourceInstance)
                    {
                        using (var chunk = chunkIO.WriteChunk(Prj2Chunks.ObjectSoundSourceFinal, LEB128.MaximumSize1Byte))
                        {
                            var instance = (SoundSourceInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            chunkIO.Raw.Write(instance.Position);
                            chunkIO.Raw.Write(instance.SoundId);
                            chunkIO.Raw.Write((int)instance.PlayMode);
                            LEB128.Write(chunkIO.Raw, -1);
                        }
                    }
                    else if (o is LightInstance)
                    {
                        using (var chunk = chunkIO.WriteChunk(Prj2Chunks.ObjectLight4, LEB128.MaximumSize2Byte))
                        {
                            var instance = (LightInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            LEB128.Write(chunkIO.Raw, (long)instance.Type);
                            chunkIO.Raw.Write(instance.Position);
                            chunkIO.Raw.Write(instance.RotationY);
                            chunkIO.Raw.Write(instance.RotationX);
                            chunkIO.Raw.Write(instance.Intensity);
                            chunkIO.Raw.Write(instance.Color);
                            chunkIO.Raw.Write(instance.InnerRange);
                            chunkIO.Raw.Write(instance.OuterRange);
                            chunkIO.Raw.Write(instance.InnerAngle);
                            chunkIO.Raw.Write(instance.OuterAngle);
                            chunkIO.Raw.Write(instance.Enabled);
                            chunkIO.Raw.Write(instance.IsObstructedByRoomGeometry);
                            chunkIO.Raw.Write(instance.IsDynamicallyUsed);
                            chunkIO.Raw.Write(instance.IsStaticallyUsed);
                            chunkIO.Raw.Write(instance.IsUsedForImportedGeometry);
                            chunkIO.Raw.Write((byte)instance.Quality);
                        }
                    }
                    else if (o is PortalInstance && rooms.ContainsKey(((PortalInstance)o).AdjoiningRoom))
                    {
                        using (var chunk = chunkIO.WriteChunk(Prj2Chunks.ObjectPortal, LEB128.MaximumSize2Byte))
                        {
                            var instance = (PortalInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            LEB128.Write(chunkIO.Raw, instance.Area.X0);
                            LEB128.Write(chunkIO.Raw, instance.Area.Y0);
                            LEB128.Write(chunkIO.Raw, instance.Area.X1);
                            LEB128.Write(chunkIO.Raw, instance.Area.Y1);
                            LEB128.Write(chunkIO.Raw, rooms[instance.AdjoiningRoom]);
                            chunkIO.Raw.Write((byte)instance.Direction);
                            chunkIO.Raw.Write((byte)instance.Opacity);
                        }
                    }
                    else if (o is GhostBlockInstance)
                    {
                        using (var chunk = chunkIO.WriteChunk(Prj2Chunks.ObjectGhostBlock, LEB128.MaximumSize2Byte))
                        {
                            var instance = (GhostBlockInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            LEB128.Write(chunkIO.Raw, instance.Area.X0);
                            LEB128.Write(chunkIO.Raw, instance.Area.Y0);
                            LEB128.Write(chunkIO.Raw, instance.Floor.XnZn);
                            LEB128.Write(chunkIO.Raw, instance.Floor.XnZp);
                            LEB128.Write(chunkIO.Raw, instance.Floor.XpZn);
                            LEB128.Write(chunkIO.Raw, instance.Floor.XpZp);
                            LEB128.Write(chunkIO.Raw, instance.Ceiling.XnZn);
                            LEB128.Write(chunkIO.Raw, instance.Ceiling.XnZp);
                            LEB128.Write(chunkIO.Raw, instance.Ceiling.XpZn);
                            LEB128.Write(chunkIO.Raw, instance.Ceiling.XpZp);
                        }
                    }
                    else if (o is VolumeInstance)
                    {
                        using (var chunk = chunkIO.WriteChunk(Prj2Chunks.ObjectTriggerVolumeTest, LEB128.MaximumSize2Byte))
                        {
                            var instance = (VolumeInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));

                            var shape = instance.Shape();
                            chunkIO.Raw.Write((byte)shape);

                            switch (shape)
                            {
                            case VolumeShape.Box:
                            {
                                var bv = instance as BoxVolumeInstance;
                                chunkIO.Raw.Write(bv.Size);
                                chunkIO.Raw.Write(bv.RotationY);
                                chunkIO.Raw.Write(bv.RotationX);
                            }
                            break;

                            case VolumeShape.Prism:
                            {
                                var pv = instance as PrismVolumeInstance;
                                chunkIO.Raw.Write(pv.Scale);
                                chunkIO.Raw.Write(pv.RotationY);
                            }
                            break;

                            case VolumeShape.Sphere:
                                chunkIO.Raw.Write((instance as SphereVolumeInstance).Scale);
                                break;
                            }

                            chunkIO.Raw.Write(instance.Position);
                            chunkIO.Raw.Write((ushort)instance.Activators);
                            chunkIO.Raw.WriteStringUTF8(instance.Scripts.Name);
                            chunkIO.Raw.WriteStringUTF8(instance.Scripts.Environment);
                            chunkIO.Raw.WriteStringUTF8(instance.Scripts.OnEnter);
                            chunkIO.Raw.WriteStringUTF8(instance.Scripts.OnInside);
                            chunkIO.Raw.WriteStringUTF8(instance.Scripts.OnLeave);
                        }
                    }
                    else if (o is TriggerInstance)
                    {
                        using (var chunk = chunkIO.WriteChunk(Prj2Chunks.ObjectTrigger2, LEB128.MaximumSize2Byte))
                        {
                            Action <ITriggerParameter> writeTriggerParameter = (ITriggerParameter parameter) =>
                            {
                                if (parameter is TriggerParameterUshort)
                                {
                                    LEB128.Write(chunkIO.Raw, 0);
                                    LEB128.Write(chunkIO.Raw, ((TriggerParameterUshort)parameter).Key);
                                }
                                else if (parameter is ObjectInstance)
                                {
                                    LEB128.Write(chunkIO.Raw, 1);
                                    LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault((ObjectInstance)parameter));
                                }
                                else if (parameter is Room)
                                {
                                    LEB128.Write(chunkIO.Raw, 2);
                                    LEB128.Write(chunkIO.Raw, rooms.TryGetOrDefault((Room)parameter));
                                }
                                else
                                {
                                    LEB128.Write(chunkIO.Raw, -1);
                                };
                            };

                            var instance = (TriggerInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            LEB128.Write(chunkIO.Raw, instance.Area.X0);
                            LEB128.Write(chunkIO.Raw, instance.Area.Y0);
                            LEB128.Write(chunkIO.Raw, instance.Area.X1);
                            LEB128.Write(chunkIO.Raw, instance.Area.Y1);
                            chunkIO.WriteChunkInt(Prj2Chunks.ObjectTrigger2Type, (long)instance.TriggerType);
                            chunkIO.WriteChunkInt(Prj2Chunks.ObjectTrigger2TargetType, (long)instance.TargetType);
                            chunkIO.WriteChunk(Prj2Chunks.ObjectTrigger2Target, () => writeTriggerParameter(instance.Target), 32);
                            chunkIO.WriteChunk(Prj2Chunks.ObjectTrigger2Timer, () => writeTriggerParameter(instance.Timer), 32);
                            chunkIO.WriteChunk(Prj2Chunks.ObjectTrigger2Extra, () => writeTriggerParameter(instance.Extra), 32);
                            chunkIO.WriteChunkInt(Prj2Chunks.ObjectTrigger2CodeBits, instance.CodeBits);
                            chunkIO.WriteChunkBool(Prj2Chunks.ObjectTrigger2OneShot, instance.OneShot);
                            chunkIO.WriteChunkEnd();
                        }
                    }
                    else if (o is ImportedGeometryInstance)
                    {
                        chunkIO.WriteChunkWithChildren(Prj2Chunks.ObjectImportedGeometry3, () =>
                        {
                            var instance = (ImportedGeometryInstance)o;
                            LEB128.Write(chunkIO.Raw, objectInstanceLookup.TryGetOrDefault(instance, -1));
                            chunkIO.Raw.Write(instance.Position);
                            chunkIO.Raw.Write(instance.RotationY);
                            chunkIO.Raw.Write(instance.RotationX);
                            chunkIO.Raw.Write(instance.Roll);
                            chunkIO.Raw.Write(instance.Scale);
                            LEB128.Write(chunkIO.Raw, instance.Model == null ?
                                         -1 :
                                         levelSettingIds.ImportedGeometries[instance.Model]);

                            chunkIO.WriteChunkInt(Prj2Chunks.ObjectImportedGeometryLightingModel, (int)instance.LightingModel);
                            chunkIO.WriteChunkBool(Prj2Chunks.ObjectImportedGeometrySharpEdges, instance.SharpEdges);
                            chunkIO.WriteChunkBool(Prj2Chunks.ObjectImportedGeometryHidden, instance.Hidden);
                        });
                    }
                    else
                    {
                        logger.Warn("Object " + o + " not supported.");
                    }
                }
                chunkIO.WriteChunkEnd();
            };
        }
예제 #29
0
 static void Write(ChunkWriter writer)
 {
 }
예제 #30
0
		// Constructor.
		public ZlibCompressor(ChunkWriter writer)
				{
					this.writer = writer;
					this.deflater = new Deflater();
					this.outBuffer = new byte [4096];
					this.outLen = 0;
					this.wroteBlock = false;
				}
예제 #31
0
파일: PngWriter.cs 프로젝트: i-e-b/Form8sn
        // Save a PNG image to the specified stream.
        public static void Save(Stream stream, PortableImage image)
        {
            Frame frame = image.GetFrame(0);

            byte[]      buffer = new byte [1024];
            ChunkWriter writer = new ChunkWriter(stream);
            int         colorType, bitDepth;
            int         sigRed, sigGreen, sigBlue, sigAlpha;
            int         paletteSize, posn;

            int[]          palette;
            ZlibCompressor compressor;
            ScanlineWriter scanlineWriter;
            OutputFunc     func;
            int            y;

            // Determine the color type and bit depth for the image.
            sigRed      = -1;
            sigGreen    = -1;
            sigBlue     = -1;
            sigAlpha    = -1;
            paletteSize = 0;
            switch (frame.PixelFormat)
            {
            case PixelFormat.Format16bppRgb555:
            {
                sigRed    = 5;
                sigGreen  = 5;
                sigBlue   = 5;
                colorType = 2;
                bitDepth  = 8;
            }
            break;

            case PixelFormat.Format16bppRgb565:
            {
                sigRed    = 5;
                sigGreen  = 6;
                sigBlue   = 5;
                colorType = 2;
                bitDepth  = 8;
            }
            break;

            case PixelFormat.Format24bppRgb:
            case PixelFormat.Format32bppRgb:
            {
                colorType = 2;
                bitDepth  = 8;
            }
            break;

            case PixelFormat.Format1bppIndexed:
            {
                colorType   = 3;
                bitDepth    = 1;
                paletteSize = 2;
            }
            break;

            case PixelFormat.Format4bppIndexed:
            {
                colorType   = 3;
                bitDepth    = 4;
                paletteSize = 16;
            }
            break;

            case PixelFormat.Format8bppIndexed:
            {
                colorType   = 3;
                bitDepth    = 8;
                paletteSize = 256;
            }
            break;

            case PixelFormat.Format16bppArgb1555:
            {
                sigRed    = 5;
                sigGreen  = 5;
                sigBlue   = 5;
                sigAlpha  = 1;
                colorType = 6;
                bitDepth  = 8;
            }
            break;

            case PixelFormat.Format32bppPArgb:
            case PixelFormat.Format32bppArgb:
            {
                colorType = 6;
                bitDepth  = 8;
            }
            break;

            case PixelFormat.Format16bppGrayScale:
            {
                colorType = 0;
                bitDepth  = 16;
            }
            break;

            case PixelFormat.Format48bppRgb:
            {
                colorType = 2;
                bitDepth  = 16;
            }
            break;

            case PixelFormat.Format64bppPArgb:
            case PixelFormat.Format64bppArgb:
            {
                colorType = 6;
                bitDepth  = 16;
            }
            break;

            default: throw new FormatException("unknown format");
            }

            // Write out the PNG magic number.
            stream.Write(magic, 0, magic.Length);

            // Write the header chunk.
            Utils.WriteInt32B(buffer, 0, frame.Width);
            Utils.WriteInt32B(buffer, 4, frame.Height);
            buffer[8]  = (byte)bitDepth;
            buffer[9]  = (byte)colorType;
            buffer[10] = (byte)0;                                       // Compression method.
            buffer[11] = (byte)0;                                       // Filter method.
            buffer[12] = (byte)0;                                       // Interlace method.
            writer.Write(PngReader.IHDR, buffer, 0, 13);

            // Write the significant bits chunk if necessary.
            if (sigAlpha != -1)
            {
                buffer[0] = (byte)sigRed;
                buffer[1] = (byte)sigGreen;
                buffer[2] = (byte)sigBlue;
                buffer[3] = (byte)sigAlpha;
                writer.Write(PngReader.sBIT, buffer, 0, 4);
            }
            else if (sigRed != -1)
            {
                buffer[0] = (byte)sigRed;
                buffer[1] = (byte)sigGreen;
                buffer[2] = (byte)sigBlue;
                writer.Write(PngReader.sBIT, buffer, 0, 3);
            }

            // Write the palette and transparency chunks.
            if (paletteSize > 0)
            {
                Array.Clear(buffer, 0, buffer.Length);
                palette = frame.Palette;
                if (palette != null)
                {
                    for (posn = 0; posn < palette.Length &&
                         posn < paletteSize; ++posn)
                    {
                        buffer[posn * 3]     = (byte)(palette[posn] >> 16);
                        buffer[posn * 2 + 1] = (byte)(palette[posn] >> 8);
                        buffer[posn * 2 + 2] = (byte)(palette[posn]);
                    }
                }
                writer.Write(PngReader.PLTE, buffer, 0, paletteSize * 3);
                if (frame.TransparentPixel >= 0 &&
                    frame.TransparentPixel < paletteSize)
                {
                    for (posn = 0; posn < paletteSize; ++posn)
                    {
                        buffer[posn] = (byte)0xFF;
                    }
                    buffer[frame.TransparentPixel] = (byte)0x00;
                    writer.Write(PngReader.tRNS, buffer, 0,
                                 frame.TransparentPixel + 1);
                }
            }

            // Compress and write the scanlines to the output stream.
            compressor     = new ZlibCompressor(writer);
            scanlineWriter = new ScanlineWriter
                                 (compressor, frame.Width, frame.PixelFormat);
            func = GetOutputFunc(frame.PixelFormat);
            for (y = 0; y < frame.Height; ++y)
            {
                func(frame, y, scanlineWriter.Buffer);
                scanlineWriter.FlushScanline();
            }
            compressor.Finish();

            // Write the end chunk.
            writer.Write(PngReader.IEND, buffer, 0, 0);
        }
예제 #32
0
        private bool BuildScripts()
        {
            string scriptPath = _dstPath + "\\Script.dat";

            if (File.Exists(scriptPath))
            {
                File.Delete(scriptPath);
            }

            using (var stream = File.OpenWrite(scriptPath))
            {
                var chunkIO = new ChunkWriter(new byte[] { 0x54, 0x52, 0x35, 0x4D }, new BinaryWriterFast(stream));

                // Main flags
                chunkIO.WriteChunk(Tr5MainFlags, () =>
                {
                    LEB128.Write(chunkIO.Raw, (_loadSave ? 1 : 0));
                    LEB128.Write(chunkIO.Raw, (_playAnyLevel ? 1 : 0));
                    LEB128.Write(chunkIO.Raw, (_flyCheat ? 1 : 0));
                    LEB128.Write(chunkIO.Raw, (_diagnostics ? 1 : 0));
                    LEB128.Write(chunkIO.Raw, _levelFarView);
                    chunkIO.Raw.WriteStringUTF8(_intro);
                });

                // Game strings
                foreach (var stringsObj in _languageStrings)
                {
                    chunkIO.WriteChunk(Tr5MainStrings, () =>
                    {
                        chunkIO.Raw.WriteStringUTF8(stringsObj.Name);
                        LEB128.Write(chunkIO.Raw, stringsObj.Strings.Count);
                        foreach (var str in stringsObj.Strings)
                        {
                            chunkIO.Raw.WriteStringUTF8(str);
                        }
                    });
                }

                // Audio tracks
                chunkIO.WriteChunk(Tr5MainAudioTracks, () =>
                {
                    LEB128.Write(chunkIO.Raw, _tracks.Count);
                    foreach (var track in _tracks)
                    {
                        chunkIO.Raw.WriteStringUTF8(track);
                    }
                });

                // Levels
                foreach (var level in _levels)
                {
                    chunkIO.WriteChunkWithChildren(Tr5MainLevel, () =>
                    {
                        // Level informations
                        chunkIO.WriteChunk(Tr5MainLevelInfo, () =>
                        {
                            chunkIO.Raw.WriteStringUTF8(level.FileName);
                            chunkIO.Raw.WriteStringUTF8(level.LoadScreen);
                            chunkIO.Raw.WriteStringUTF8(level.Background);
                            LEB128.Write(chunkIO.Raw, GetStringIndex(level.Name));
                            LEB128.Write(chunkIO.Raw, level.AudioTrack);
                        });

                        // Level flags
                        chunkIO.WriteChunk(Tr5MainLevelFlags, () =>
                        {
                            LEB128.Write(chunkIO.Raw, (level.Horizon ? 1 : 0));
                            LEB128.Write(chunkIO.Raw, (level.Sky ? 1 : 0));
                            LEB128.Write(chunkIO.Raw, (level.ColAddHorizon ? 1 : 0));
                            LEB128.Write(chunkIO.Raw, (level.Lightning ? 1 : 0));
                            LEB128.Write(chunkIO.Raw, (level.ResetInventory ? 1 : 0));
                            LEB128.Write(chunkIO.Raw, level.LaraType);
                            LEB128.Write(chunkIO.Raw, level.UVRotate);
                            LEB128.Write(chunkIO.Raw, (level.LevelFarView != 0 ? level.LevelFarView : _levelFarView));
                            LEB128.Write(chunkIO.Raw, (level.Rumble ? 1 : 0));
                            LEB128.Write(chunkIO.Raw, (byte)(level.Weather));
                            LEB128.Write(chunkIO.Raw, (level.UnlimitedAir ? 1 : 0));
                        });

                        // Puzzles and various things
                        foreach (var entry in level.Entries)
                        {
                            if (entry.Command.Name == "Puzzle")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelPuzzle, () =>
                                {
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[0].ToString()));
                                    LEB128.Write(chunkIO.Raw, (int)GetStringIndex(entry.Parameters[1].ToString()));
                                    for (int j = 2; j < 8; j++)
                                    {
                                        LEB128.Write(chunkIO.Raw, short.Parse(entry.Parameters[j].ToString()));
                                    }
                                });
                            }
                            else if (entry.Command.Name == "Key")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelKey, () =>
                                {
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[0].ToString()));
                                    LEB128.Write(chunkIO.Raw, (int)GetStringIndex(entry.Parameters[1].ToString()));
                                    for (int j = 2; j < 8; j++)
                                    {
                                        LEB128.Write(chunkIO.Raw, short.Parse(entry.Parameters[j].ToString()));
                                    }
                                });
                            }
                            else if (entry.Command.Name == "Pickup")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelPickup, () =>
                                {
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[0].ToString()));
                                    LEB128.Write(chunkIO.Raw, (int)GetStringIndex(entry.Parameters[1].ToString()));
                                    for (int j = 2; j < 8; j++)
                                    {
                                        LEB128.Write(chunkIO.Raw, short.Parse(entry.Parameters[j].ToString()));
                                    }
                                });
                            }
                            if (entry.Command.Name == "Examine")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelExamine, () =>
                                {
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[0].ToString()));
                                    LEB128.Write(chunkIO.Raw, (int)GetStringIndex(entry.Parameters[1].ToString()));
                                    for (int j = 2; j < 8; j++)
                                    {
                                        LEB128.Write(chunkIO.Raw, short.Parse(entry.Parameters[j].ToString()));
                                    }
                                });
                            }
                            if (entry.Command.Name == "PuzzleCombo")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelPuzzleCombo, () =>
                                {
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[0].ToString()));
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[1].ToString()));
                                    LEB128.Write(chunkIO.Raw, (int)GetStringIndex(entry.Parameters[2].ToString()));
                                    for (int j = 3; j < 9; j++)
                                    {
                                        LEB128.Write(chunkIO.Raw, short.Parse(entry.Parameters[j].ToString()));
                                    }
                                });
                            }
                            else if (entry.Command.Name == "KeyCombo")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelKeyCombo, () =>
                                {
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[0].ToString()));
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[1].ToString()));
                                    LEB128.Write(chunkIO.Raw, (int)GetStringIndex(entry.Parameters[2].ToString()));
                                    for (int j = 3; j < 9; j++)
                                    {
                                        LEB128.Write(chunkIO.Raw, short.Parse(entry.Parameters[j].ToString()));
                                    }
                                });
                            }
                            else if (entry.Command.Name == "PickupCombo")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelPickupCombo, () =>
                                {
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[0].ToString()));
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[1].ToString()));
                                    LEB128.Write(chunkIO.Raw, (int)GetStringIndex(entry.Parameters[2].ToString()));
                                    for (int j = 3; j < 9; j++)
                                    {
                                        LEB128.Write(chunkIO.Raw, short.Parse(entry.Parameters[j].ToString()));
                                    }
                                });
                            }
                            else if (entry.Command.Name == "Layer1")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelLayer, () =>
                                {
                                    LEB128.Write(chunkIO.Raw, 1);
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[0].ToString()));
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[1].ToString()));
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[2].ToString()));
                                    LEB128.Write(chunkIO.Raw, sbyte.Parse(entry.Parameters[3].ToString()));
                                });
                            }
                            else if (entry.Command.Name == "Layer2")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelLayer, () =>
                                {
                                    LEB128.Write(chunkIO.Raw, 2);
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[0].ToString()));
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[1].ToString()));
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[2].ToString()));
                                    LEB128.Write(chunkIO.Raw, sbyte.Parse(entry.Parameters[3].ToString()));
                                });
                            }
                            else if (entry.Command.Name == "DistantFog")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelLayer, () =>
                                {
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[0].ToString()));
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[1].ToString()));
                                    LEB128.Write(chunkIO.Raw, byte.Parse(entry.Parameters[2].ToString()));
                                    LEB128.Write(chunkIO.Raw, int.Parse(entry.Parameters[3].ToString()));
                                });
                            }
                            else if (entry.Command.Name == "OnLevelStart" ||
                                     entry.Command.Name == "OnLevelFinish" ||
                                     entry.Command.Name == "OnLoadGame" ||
                                     entry.Command.Name == "OnSaveGame" ||
                                     entry.Command.Name == "OnLaraDeath" ||
                                     entry.Command.Name == "OnLevelControl" ||
                                     entry.Command.Name == "OnBeginFrame")
                            {
                                chunkIO.WriteChunk(Tr5MainLevelLuaEvent, () =>
                                {
                                    chunkIO.Raw.WriteStringUTF8(entry.Command.Name);
                                    chunkIO.Raw.WriteStringUTF8(entry.Parameters[0].ToString());
                                });
                            }
                        }
                    });
                }

                // EOF
                chunkIO.Raw.Write((int)0);

                chunkIO.Raw.Flush();
            }

            return(true);
        }
예제 #33
0
        private void WriteLevelTr5Main()
        {
            // Now begin to compile the geometry block in a MemoryStream
            byte[] geometryDataBuffer;
            using (var geometryDataStream = new MemoryStream())
            {
                var writer = new BinaryWriterEx(geometryDataStream); // Don't dispose
                ReportProgress(80, "Writing geometry data to memory buffer");

                const int filler = 0;
                writer.Write(filler);

                var numRooms = (uint)_level.Rooms.Count(r => r != null);
                writer.Write(numRooms);

                foreach (var r in _level.Rooms.Where(r => r != null))
                {
                    _tempRooms[r].WriteTr5(writer);
                }

                // Write floordata
                var numFloorData = (uint)_floorData.Count;
                writer.Write(numFloorData);
                writer.WriteBlockArray(_floorData);

                // Write meshes
                var offset = writer.BaseStream.Position;

                const int numMeshData = 0;
                writer.Write(numMeshData);
                var totalMeshSize = 0;

                for (var i = 0; i < _meshes.Count; i++)
                {
                    var meshSize = _meshes[i].WriteTr4AndTr5(writer);
                    totalMeshSize += (int)meshSize;
                }

                var offset2 = writer.BaseStream.Position;
                // ReSharper disable once SuggestVarOrType_BuiltInTypes
                uint meshDataSize = (uint)((offset2 - offset - 4) / 2);

                // Save the size of the meshes
                writer.BaseStream.Seek(offset, SeekOrigin.Begin);
                writer.Write(meshDataSize);
                writer.BaseStream.Seek(offset2, SeekOrigin.Begin);

                // Write mesh pointers
                writer.Write((uint)_meshPointers.Count);
                writer.WriteBlockArray(_meshPointers);

                // Write animations' data
                writer.Write((uint)_animations.Count);
                foreach (var anim in _animations)
                {
                    anim.Write(writer, _level);
                }

                writer.Write((uint)_stateChanges.Count);
                writer.WriteBlockArray(_stateChanges);

                writer.Write((uint)_animDispatches.Count);
                writer.WriteBlockArray(_animDispatches);

                writer.Write((uint)_animCommands.Count);
                writer.WriteBlockArray(_animCommands);

                writer.Write((uint)_meshTrees.Count);
                writer.WriteBlockArray(_meshTrees);

                writer.Write((uint)_frames.Count);
                writer.WriteBlockArray(_frames);

                writer.Write((uint)_moveables.Count);
                for (var k = 0; k < _moveables.Count; k++)
                {
                    writer.WriteBlock(_moveables[k]);
                    writer.Write((ushort)0xfeff);
                }

                writer.Write((uint)_staticMeshes.Count);
                writer.WriteBlockArray(_staticMeshes);

                // SPR block
                writer.WriteBlockArray(new byte[] { 0x53, 0x50, 0x52, 0x00 });

                writer.Write((uint)_spriteTextures.Count);
                writer.WriteBlockArray(_spriteTextures);

                writer.Write((uint)_spriteSequences.Count);
                writer.WriteBlockArray(_spriteSequences);

                // Write camera, flyby and sound sources
                writer.Write((uint)_cameras.Count);
                writer.WriteBlockArray(_cameras);

                writer.Write((uint)_flyByCameras.Count);
                writer.WriteBlockArray(_flyByCameras);

                writer.Write((uint)_soundSources.Count);
                writer.WriteBlockArray(_soundSources);

                // Write pathfinding data
                writer.Write((uint)_boxes.Length);
                writer.WriteBlockArray(_boxes);

                writer.Write((uint)_overlaps.Length);
                writer.WriteBlockArray(_overlaps);

                for (var i = 0; i < _boxes.Length; i++)
                {
                    writer.Write(_zones[i].GroundZone1_Normal);
                }
                for (var i = 0; i < _boxes.Length; i++)
                {
                    writer.Write(_zones[i].GroundZone2_Normal);
                }
                for (var i = 0; i < _boxes.Length; i++)
                {
                    writer.Write(_zones[i].GroundZone3_Normal);
                }
                for (var i = 0; i < _boxes.Length; i++)
                {
                    writer.Write(_zones[i].GroundZone4_Normal);
                }
                for (var i = 0; i < _boxes.Length; i++)
                {
                    writer.Write(_zones[i].FlyZone_Normal);
                }
                for (var i = 0; i < _boxes.Length; i++)
                {
                    writer.Write(_zones[i].GroundZone1_Alternate);
                }
                for (var i = 0; i < _boxes.Length; i++)
                {
                    writer.Write(_zones[i].GroundZone2_Alternate);
                }
                for (var i = 0; i < _boxes.Length; i++)
                {
                    writer.Write(_zones[i].GroundZone3_Alternate);
                }
                for (var i = 0; i < _boxes.Length; i++)
                {
                    writer.Write(_zones[i].GroundZone4_Alternate);
                }
                for (var i = 0; i < _boxes.Length; i++)
                {
                    writer.Write(_zones[i].FlyZone_Alternate);
                }

                // Write animated textures
                _textureInfoManager.WriteAnimatedTextures(writer);

                // Write object textures
                writer.Write(checked ((byte)_textureInfoManager.UvRotateCount));
                writer.Write(new byte[] { 0x54, 0x45, 0x58, 0x00 });

                _textureInfoManager.WriteTextureInfos(writer, _level);

                // Write items and AI objects
                writer.Write((uint)_items.Count);
                writer.WriteBlockArray(_items);

                writer.Write((uint)_aiItems.Count);
                writer.WriteBlockArray(_aiItems);

                // Write sound meta data
                PrepareSoundsData();
                WriteSoundMetadata(writer);

                // Finish it
                writer.Write((ushort)0xcdcd);
                writer.Write((ushort)0xcdcd);
                writer.Write((ushort)0xcdcd);

                geometryDataBuffer = geometryDataStream.ToArray();
            }

            using (var fs = new FileStream(_dest, FileMode.Create, FileAccess.Write, FileShare.None))
            {
                using (var writer = new BinaryWriterEx(fs))
                {
                    ReportProgress(90, "Writing final level");
                    writer.WriteBlockArray(new byte[] { 0x54, 0x52, 0x34, 0x00 });

                    ReportProgress(91, "Writing textures");

                    // The room texture tile count currently also currently contains the wad textures
                    // But lets not bother with those fields too much since they only matter when bump maps are used and we don't use them.
                    writer.Write((ushort)_textureInfoManager.NumRoomPages);
                    writer.Write((ushort)_textureInfoManager.NumObjectsPages);
                    // Bump map pages must be multiplied by 2 or tile index will be wrong
                    writer.Write((ushort)(_textureInfoManager.NumBumpPages * 2));

                    // Compress data
                    ReportProgress(95, "Compressing data");

                    byte[] texture32 = null;
                    int    texture32UncompressedSize = -1;
                    byte[] texture16 = null;
                    int    texture16UncompressedSize = -1;
                    byte[] textureMisc = null;
                    int    textureMiscUncompressedSize = -1;
                    byte[] geometryData = geometryDataBuffer;
                    int    geometryDataUncompressedSize = geometryData.Length;

                    using (Task Texture32task = Task.Factory.StartNew(() =>
                    {
                        texture32 = ZLib.CompressData(_texture32Data);
                        texture32UncompressedSize = _texture32Data.Length;
                    }))
                        using (Task Texture16task = Task.Factory.StartNew(() =>
                        {
                            byte[] texture16Data = PackTextureMap32To16Bit(_texture32Data, _level.Settings);
                            texture16 = ZLib.CompressData(texture16Data);
                            texture16UncompressedSize = texture16Data.Length;
                        }))
                            using (Task textureMiscTask = Task.Factory.StartNew(() =>
                            {
                                Stream textureMiscData = PrepareFontAndSkyTexture();
                                textureMisc = ZLib.CompressData(textureMiscData);
                                textureMiscUncompressedSize = (int)textureMiscData.Length;
                            }))

                                Task.WaitAll(Texture32task, Texture16task, textureMiscTask);

                    // Write data
                    ReportProgress(97, "Writing compressed data to file.");

                    writer.Write(texture32UncompressedSize);
                    writer.Write(texture32.Length);
                    writer.Write(texture32);

                    writer.Write(texture16UncompressedSize);
                    writer.Write(texture16.Length);
                    writer.Write(texture16);

                    writer.Write(textureMiscUncompressedSize);
                    writer.Write(textureMisc.Length);
                    writer.Write(textureMisc);

                    writer.Write((ushort)_level.Settings.Tr5LaraType);
                    writer.Write((ushort)_level.Settings.Tr5WeatherType);

                    for (var i = 0; i < 28; i++)
                    {
                        writer.Write((byte)0);
                    }

                    // In TR5 geometry data is not compressed
                    writer.Write(geometryDataUncompressedSize);
                    writer.Write(geometryDataUncompressedSize);
                    writer.Write(geometryData);

                    ReportProgress(98, "Writing WAVE sounds");
                    WriteSoundData(writer);

                    // Write extra data
                    _volumeScripts = new List <VolumeScriptInstance>();

                    using (var ms = new MemoryStream())
                    {
                        var chunkIO = new ChunkWriter(new byte[] { 0x54, 0x52, 0x35, 0x4D }, new BinaryWriterFast(ms));

                        int currRoom = 0;
                        foreach (var r in _level.Rooms.Where(r => r != null))
                        {
                            // Add further extra data conditions here, otherwise compiler will skip this room altogether
                            if (r.Volumes.Count() > 0)
                            {
                                currRoom++;
                            }
                            else
                            {
                                currRoom++;
                                continue;
                            }

                            using (var extraRoomDataChunk = chunkIO.WriteChunk(Tr5MainExtraRoomData))
                            {
                                // First and only param after signature is internal room number
                                chunkIO.Raw.Write(currRoom);

                                using (var volumeListChunk = chunkIO.WriteChunk(Tr5MainChunkVolumeList))
                                {
                                    var trRoom = _tempRooms[r];

                                    foreach (var vol in r.Volumes)
                                    {
                                        using (var volumeChunk = chunkIO.WriteChunk(Tr5MainChunkVolume))
                                        {
                                            int scriptIndex = 0;
                                            if (_volumeScripts.Contains(vol.Scripts))
                                            {
                                                scriptIndex = _volumeScripts.IndexOf(vol.Scripts);
                                            }
                                            else
                                            {
                                                _volumeScripts.Add(vol.Scripts);
                                                scriptIndex = _volumeScripts.Count - 1;
                                            }

                                            // FIXME is it needed?
                                            int add = 0;
                                            if (vol is BoxVolumeInstance)
                                            {
                                                add = (int)((vol as BoxVolumeInstance).Size.Y / 2.0f);
                                            }

                                            var X = (int)Math.Round(trRoom.Info.X + vol.Position.X);
                                            var Y = (int)-Math.Round(r.WorldPos.Y + vol.Position.Y + add);
                                            var Z = (int)Math.Round(trRoom.Info.Z + vol.Position.Z);

                                            if (vol is BoxVolumeInstance)
                                            {
                                                chunkIO.Raw.Write(0);
                                            }
                                            else if (vol is SphereVolumeInstance)
                                            {
                                                chunkIO.Raw.Write(1);
                                            }
                                            else if (vol is PrismVolumeInstance)
                                            {
                                                chunkIO.Raw.Write(2);
                                            }

                                            chunkIO.Raw.Write(X);
                                            chunkIO.Raw.Write(Y);
                                            chunkIO.Raw.Write(Z);
                                            chunkIO.Raw.Write((short)vol.Activators);
                                            chunkIO.Raw.Write(scriptIndex);

                                            if (vol is BoxVolumeInstance)
                                            {
                                                var bv   = (BoxVolumeInstance)vol;
                                                var min  = vol.Position - (bv.Size / 2.0f);
                                                var max  = vol.Position + (bv.Size / 2.0f);
                                                var rotY = (ushort)Math.Max(0, Math.Min(ushort.MaxValue,
                                                                                        Math.Round(bv.RotationY * (65536.0 / 360.0))));
                                                var rotX = (ushort)Math.Max(0, Math.Min(ushort.MaxValue,
                                                                                        Math.Round(bv.RotationX * (65536.0 / 360.0))));

                                                chunkIO.Raw.Write(rotY);
                                                chunkIO.Raw.Write(rotX);
                                                chunkIO.Raw.Write((short)min.X);
                                                chunkIO.Raw.Write((short)min.Y);
                                                chunkIO.Raw.Write((short)min.Z);
                                                chunkIO.Raw.Write((short)max.X);
                                                chunkIO.Raw.Write((short)max.Y);
                                                chunkIO.Raw.Write((short)max.Z);
                                            }
                                            else if (vol is SphereVolumeInstance)
                                            {
                                                chunkIO.Raw.Write((vol as SphereVolumeInstance).Size);
                                            }
                                            else if (vol is PrismVolumeInstance)
                                            {
                                                var pv = (PrismVolumeInstance)vol;
                                                chunkIO.Raw.Write(pv.RotationY);
                                                chunkIO.Raw.Write(pv.Size);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        /*
                         * using (var extraDataChunk = chunkIO.WriteChunk(Tr5MainExtraData))
                         * {
                         *  using (var volScriptListChunk = chunkIO.WriteChunk(Tr5MainChunkVolumeScriptList))
                         *  {
                         *      for (int i = 0; i < _volumeScripts.Count; i++)
                         *      {
                         *          var script = _volumeScripts[i];
                         *          using (var volScriptChunk = chunkIO.WriteChunk(Tr5MainChunkVolumeScript))
                         *          {
                         *              chunkIO.Raw.WriteStringUTF8(script.Name);
                         *
                         *              string onEnter = string.Empty;
                         *              string onInside = string.Empty;
                         *              string onLeave = string.Empty;
                         *
                         *              if (script.OnEnter.Trim().Length > 0)
                         *                  onEnter = "volscripts[" + i + "].OnEnter  = function(activator) \n" +
                         *                              _indent + script.OnEnter.Replace("\n", "\n" + _indent) + "\n" + "end;";
                         *
                         *              if (script.OnInside.Trim().Length > 0)
                         *                  onInside = "volscripts[" + i + "].OnInside = function(activator) \n" +
                         *                              _indent + script.OnInside.Replace("\n", "\n" + _indent) + "\n" + "end;";
                         *
                         *              if (script.OnLeave.Trim().Length > 0)
                         *                  onLeave  = "volscripts[" + i + "].OnLeave = function(activator) \n" +
                         *                              _indent + script.OnLeave.Replace("\n", "\n" + _indent) + "\n" + "end;";
                         *
                         *              string functionCode =
                         *                  onEnter  + (string.IsNullOrEmpty(onEnter)  ? string.Empty : "\n\n") +
                         *                  onInside + (string.IsNullOrEmpty(onInside) ? string.Empty : "\n\n") +
                         *                  onLeave  + (string.IsNullOrEmpty(onLeave)  ? string.Empty : "\n\n") ;
                         *
                         *              chunkIO.Raw.WriteStringUTF8(functionCode);
                         *          }
                         *      }
                         *  }
                         *
                         *  using (var chunkLuaIds = chunkIO.WriteChunk(Tr5MainChunkLuaIds))
                         *  {
                         *      for (int i = 0; i < _luaIdToItems.Count; i++)
                         *      {
                         *          chunkIO.WriteChunk(Tr5MainChunkLuaId, () =>
                         *          {
                         *              chunkIO.Raw.Write(_luaIdToItems.ElementAt(i).Key);
                         *              chunkIO.Raw.Write(_luaIdToItems.ElementAt(i).Value);
                         *          });
                         *      }
                         *  }
                         * }
                         */

                        chunkIO.Raw.Flush();

                        writer.Write((int)(ms.Length + 4));
                        writer.Write((int)(ms.Length + 4));
                        writer.Write(ms.ToArray(), 0, (int)ms.Length);
                        writer.Write((int)0);
                    }

                    ReportProgress(99, "Done");
                }
            }
        }
예제 #34
0
 void StoreSettings(ChunkWriter writer)
 {
 }