mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-23 12:42:22 -04:00
Optimise level sending - instead of compressing to temp memorystream, compress directly to network.
This commit is contained in:
parent
16a1b372e4
commit
eed355e7af
@ -513,6 +513,7 @@
|
||||
<Compile Include="Levels\Physics\TntPhysics.cs" />
|
||||
<Compile Include="Levels\Physics\ZombiePhysics.cs" />
|
||||
<Compile Include="Levels\Zones.cs" />
|
||||
<Compile Include="Network\LevelChunkStream.cs" />
|
||||
<Compile Include="Player\Chat.cs" />
|
||||
<Compile Include="Player\Entities.cs" />
|
||||
<Compile Include="Player\Group\Group.cs" />
|
||||
|
85
Network/LevelChunkStream.cs
Normal file
85
Network/LevelChunkStream.cs
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright 2015 MCGalaxy
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace MCGalaxy {
|
||||
public sealed class LevelChunkStream : Stream {
|
||||
public override bool CanRead { get { return false; } }
|
||||
public override bool CanSeek { get { return false; } }
|
||||
public override bool CanWrite { get { return true; } }
|
||||
|
||||
static Exception ex = new NotSupportedException("Stream does not support length/seeking.");
|
||||
public override void Flush() { }
|
||||
public override long Length { get { throw ex; } }
|
||||
public override long Position { get { throw ex; } set { throw ex; } }
|
||||
public override int Read(byte[] buffer, int offset, int count) { throw ex; }
|
||||
public override long Seek(long offset, SeekOrigin origin) { throw ex; }
|
||||
public override void SetLength(long length) { throw ex; }
|
||||
|
||||
internal int index, position, length;
|
||||
Player p;
|
||||
byte[] data = new byte[chunkSize + 4];
|
||||
const int chunkSize = 1024;
|
||||
|
||||
public LevelChunkStream(Player p) {
|
||||
this.p = p;
|
||||
}
|
||||
|
||||
public override void Close() {
|
||||
if (index > 0) WritePacket();
|
||||
p = null;
|
||||
base.Close();
|
||||
}
|
||||
|
||||
public override void Write(byte[] buffer, int offset, int count) {
|
||||
while (count > 0) {
|
||||
int copy = Math.Min(chunkSize - index, count);
|
||||
if (copy <= 8) {
|
||||
for (int i = 0; i < copy; i++)
|
||||
data[index + i + 3] = buffer[offset + i];
|
||||
} else {
|
||||
Buffer.BlockCopy(buffer, offset, data, index + 3, copy);
|
||||
}
|
||||
offset += copy; index += copy; count -= copy;
|
||||
|
||||
if (index != chunkSize) continue;
|
||||
WritePacket();
|
||||
data = new byte[chunkSize + 4];
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteByte(byte value) {
|
||||
data[index + 3] = value;
|
||||
index++;
|
||||
|
||||
if (index != chunkSize) return;
|
||||
WritePacket();
|
||||
index = 0;
|
||||
}
|
||||
|
||||
void WritePacket() {
|
||||
data[0] = Opcode.LevelDataChunk;
|
||||
NetUtils.WriteU16((ushort)index, data, 1);
|
||||
data[1027] = (byte)(100 * (float)position / length);
|
||||
p.SendRaw(data);
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -343,9 +343,6 @@ namespace MCGalaxy {
|
||||
lastCheckpointIndex = -1;
|
||||
|
||||
try {
|
||||
int usedLength = 0;
|
||||
byte[] buffer = CompressRawMap(out usedLength);
|
||||
|
||||
if (hasBlockDefs) {
|
||||
if (oldLevel != null && oldLevel != level)
|
||||
RemoveOldLevelCustomBlocks(oldLevel);
|
||||
@ -353,22 +350,10 @@ namespace MCGalaxy {
|
||||
}
|
||||
|
||||
SendRaw(Opcode.LevelInitialise);
|
||||
int totalRead = 0;
|
||||
while (totalRead < usedLength) {
|
||||
byte[] packet = new byte[1028]; // need each packet separate for Mono
|
||||
packet[0] = Opcode.LevelDataChunk;
|
||||
short length = (short)Math.Min(buffer.Length - totalRead, 1024);
|
||||
NetUtils.WriteI16(length, packet, 1);
|
||||
Buffer.BlockCopy(buffer, totalRead, packet, 3, length);
|
||||
packet[1027] = (byte)(100 * (float)totalRead / buffer.Length);
|
||||
using (LevelChunkStream s = new LevelChunkStream(this))
|
||||
CompressRawMap(s);
|
||||
|
||||
SendRaw(packet);
|
||||
if (ip != "127.0.0.1")
|
||||
Thread.Sleep(Server.updateTimer.Interval > 1000 ? 100 : 10);
|
||||
totalRead += length;
|
||||
}
|
||||
|
||||
buffer = new byte[7];
|
||||
byte[] buffer = new byte[7];
|
||||
buffer[0] = Opcode.LevelFinalise;
|
||||
NetUtils.WriteI16((short)level.Width, buffer, 1);
|
||||
NetUtils.WriteI16((short)level.Height, buffer, 3);
|
||||
@ -403,10 +388,9 @@ namespace MCGalaxy {
|
||||
return success;
|
||||
}
|
||||
|
||||
unsafe byte[] CompressRawMap(out int usedLength) {
|
||||
unsafe void CompressRawMap(LevelChunkStream dst) {
|
||||
const int bufferSize = 64 * 1024;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
MemoryStream temp = new MemoryStream();
|
||||
int bIndex = 0;
|
||||
|
||||
// Store locally instead of performing func call for every block in map
|
||||
@ -419,9 +403,10 @@ namespace MCGalaxy {
|
||||
convCPE[i] = Block.ConvertCPE((byte)i);
|
||||
}
|
||||
|
||||
using (GZipStream compressor = new GZipStream(temp, CompressionMode.Compress, true)) {
|
||||
using (GZipStream compressor = new GZipStream(dst, CompressionMode.Compress, true)) {
|
||||
NetUtils.WriteI32(level.blocks.Length, buffer, 0);
|
||||
compressor.Write(buffer, 0, sizeof(int));
|
||||
dst.length = level.blocks.Length;
|
||||
|
||||
// compress the map data in 64 kb chunks
|
||||
if (hasCustomBlocks) {
|
||||
@ -435,6 +420,7 @@ namespace MCGalaxy {
|
||||
|
||||
bIndex++;
|
||||
if (bIndex == bufferSize) {
|
||||
dst.position = i;
|
||||
compressor.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
}
|
||||
}
|
||||
@ -450,14 +436,13 @@ namespace MCGalaxy {
|
||||
|
||||
bIndex++;
|
||||
if (bIndex == bufferSize) {
|
||||
dst.position = i;
|
||||
compressor.Write(buffer, 0, bufferSize); bIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bIndex > 0) compressor.Write(buffer, 0, bIndex);
|
||||
}
|
||||
usedLength = (int)temp.Length;
|
||||
return temp.GetBuffer();
|
||||
}
|
||||
|
||||
void RemoveOldLevelCustomBlocks(Level oldLevel) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user