Created
October 28, 2017 18:32
-
-
Save HurricanKai/6013140b91d66485444db291699aff88 to your computer and use it in GitHub Desktop.
An Implementation of IMinecraftStream
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
namespace Lib | |
{ | |
public class MinecraftStream : Stream, IMinecraftStream | |
{ | |
public Stream BaseStream { get; set; } | |
public MemoryStream ms; | |
public Encoding StringEncoding { get; set; } | |
public MinecraftStream(Stream baseStream) | |
{ | |
BaseStream = baseStream; | |
StringEncoding = Encoding.BigEndianUnicode; | |
ms = new MemoryStream(4096); | |
} | |
public override bool CanRead { get { return BaseStream.CanRead; } } | |
public override bool CanSeek { get { return BaseStream.CanSeek; } } | |
public override bool CanWrite { get { return BaseStream.CanWrite; } } | |
public override void Flush() | |
{ | |
ms.WriteTo(BaseStream); | |
BaseStream.Flush(); | |
} | |
public override long Length | |
{ | |
get { return BaseStream.Length; } | |
} | |
public override long Position | |
{ | |
get { return BaseStream.Position; } | |
set { BaseStream.Position = value; } | |
} | |
public override int Read(byte[] buffer, int offset, int count) | |
{ | |
return BaseStream.Read(buffer, offset, count); | |
} | |
public override long Seek(long offset, SeekOrigin origin) | |
{ | |
return BaseStream.Seek(offset, origin); | |
} | |
public override void SetLength(long value) | |
{ | |
BaseStream.SetLength(value); | |
} | |
public override void Write(byte[] buffer, int offset, int count) | |
{ | |
ms.Write(buffer, offset, count); | |
} | |
public byte ReadUInt8() | |
{ | |
int value = BaseStream.ReadByte(); | |
if (value == -1) | |
throw new EndOfStreamException(); | |
return (byte)value; | |
} | |
public void WriteUInt8(byte value) | |
{ | |
WriteByte(value); | |
} | |
public sbyte ReadInt8() | |
{ | |
return (sbyte)ReadUInt8(); | |
} | |
public void WriteInt8(sbyte value) | |
{ | |
WriteUInt8((byte)value); | |
} | |
public ushort ReadUInt16() | |
{ | |
return (ushort)( | |
(ReadUInt8() << 8) | | |
ReadUInt8()); | |
} | |
public void WriteUInt16(ushort value) | |
{ | |
Write(new[] | |
{ | |
(byte)((value & 0xFF00) >> 8), | |
(byte)(value & 0xFF) | |
}, 0, 2); | |
} | |
public short ReadInt16() | |
{ | |
return (short)ReadUInt16(); | |
} | |
public void WriteInt16(short value) | |
{ | |
WriteUInt16((ushort)value); | |
} | |
public uint ReadUInt32() | |
{ | |
return (uint)( | |
(ReadUInt8() << 24) | | |
(ReadUInt8() << 16) | | |
(ReadUInt8() << 8) | | |
ReadUInt8()); | |
} | |
public void WriteUInt32(uint value) | |
{ | |
Write(new[] | |
{ | |
(byte)((value & 0xFF000000) >> 24), | |
(byte)((value & 0xFF0000) >> 16), | |
(byte)((value & 0xFF00) >> 8), | |
(byte)(value & 0xFF) | |
}, 0, 4); | |
} | |
public int ReadInt32() | |
{ | |
return (int)ReadUInt32(); | |
} | |
public void WriteInt32(int value) | |
{ | |
WriteUInt32((uint)value); | |
} | |
public ulong ReadUInt64() | |
{ | |
return unchecked( | |
((ulong)ReadUInt8() << 56) | | |
((ulong)ReadUInt8() << 48) | | |
((ulong)ReadUInt8() << 40) | | |
((ulong)ReadUInt8() << 32) | | |
((ulong)ReadUInt8() << 24) | | |
((ulong)ReadUInt8() << 16) | | |
((ulong)ReadUInt8() << 8) | | |
(ulong)ReadUInt8()); | |
} | |
public void WriteUInt64(ulong value) | |
{ | |
Write(new[] | |
{ | |
(byte)((value & 0xFF00000000000000) >> 56), | |
(byte)((value & 0xFF000000000000) >> 48), | |
(byte)((value & 0xFF0000000000) >> 40), | |
(byte)((value & 0xFF00000000) >> 32), | |
(byte)((value & 0xFF000000) >> 24), | |
(byte)((value & 0xFF0000) >> 16), | |
(byte)((value & 0xFF00) >> 8), | |
(byte)(value & 0xFF) | |
}, 0, 8); | |
} | |
public long ReadInt64() | |
{ | |
return (long)ReadUInt64(); | |
} | |
public void WriteInt64(long value) | |
{ | |
WriteUInt64((ulong)value); | |
} | |
public byte[] ReadUInt8Array(int length) | |
{ | |
var result = new byte[length]; | |
if (length == 0) return result; | |
int n = length; | |
while (true) | |
{ | |
n -= Read(result, length - n, n); | |
if (n == 0) | |
break; | |
System.Threading.Thread.Sleep(1); | |
} | |
return result; | |
} | |
public void WriteUInt8Array(byte[] value) | |
{ | |
Write(value, 0, value.Length); | |
} | |
public void WriteUInt8Array(byte[] value, int offset, int count) | |
{ | |
Write(value, offset, count); | |
} | |
public sbyte[] ReadInt8Array(int length) | |
{ | |
return (sbyte[])(Array)ReadUInt8Array(length); | |
} | |
public void WriteInt8Array(sbyte[] value) | |
{ | |
Write((byte[])(Array)value, 0, value.Length); | |
} | |
public ushort[] ReadUInt16Array(int length) | |
{ | |
var result = new ushort[length]; | |
if (length == 0) return result; | |
for (int i = 0; i < length; i++) | |
result[i] = ReadUInt16(); | |
return result; | |
} | |
public void WriteUInt16Array(ushort[] value) | |
{ | |
for (int i = 0; i < value.Length; i++) | |
WriteUInt16(value[i]); | |
} | |
public short[] ReadInt16Array(int length) | |
{ | |
return (short[])(Array)ReadUInt16Array(length); | |
} | |
public void WriteInt16Array(short[] value) | |
{ | |
WriteUInt16Array((ushort[])(Array)value); | |
} | |
public uint[] ReadUInt32Array(int length) | |
{ | |
var result = new uint[length]; | |
if (length == 0) return result; | |
for (int i = 0; i < length; i++) | |
result[i] = ReadUInt32(); | |
return result; | |
} | |
public void WriteUInt32Array(uint[] value) | |
{ | |
for (int i = 0; i < value.Length; i++) | |
WriteUInt32(value[i]); | |
} | |
public int[] ReadInt32Array(int length) | |
{ | |
return (int[])(Array)ReadUInt32Array(length); | |
} | |
public void WriteInt32Array(int[] value) | |
{ | |
WriteUInt32Array((uint[])(Array)value); | |
} | |
public ulong[] ReadUInt64Array(int length) | |
{ | |
var result = new ulong[length]; | |
if (length == 0) return result; | |
for (int i = 0; i < length; i++) | |
result[i] = ReadUInt64(); | |
return result; | |
} | |
public void WriteUInt64Array(ulong[] value) | |
{ | |
for (int i = 0; i < value.Length; i++) | |
WriteUInt64(value[i]); | |
} | |
public long[] ReadInt64Array(int length) | |
{ | |
return (long[])(Array)ReadUInt64Array(length); | |
} | |
public void WriteInt64Array(long[] value) | |
{ | |
WriteUInt64Array((ulong[])(Array)value); | |
} | |
public unsafe float ReadSingle() | |
{ | |
uint value = ReadUInt32(); | |
return *(float*)&value; | |
} | |
public unsafe void WriteSingle(float value) | |
{ | |
WriteUInt32(*(uint*)&value); | |
} | |
public unsafe double ReadDouble() | |
{ | |
ulong value = ReadUInt64(); | |
return *(double*)&value; | |
} | |
public unsafe void WriteDouble(double value) | |
{ | |
WriteUInt64(*(ulong*)&value); | |
} | |
public bool ReadBoolean() | |
{ | |
return ReadUInt8() != 0; | |
} | |
public void WriteBoolean(bool value) | |
{ | |
WriteUInt8(value ? (byte)1 : (byte)0); | |
} | |
public string ReadString() | |
{ | |
short length = ReadInt16(); | |
if (length == 0) return string.Empty; | |
var data = ReadUInt8Array(length * 2); | |
return StringEncoding.GetString(data); | |
} | |
public void WriteString(string value) | |
{ | |
WriteInt16((short)value.Length); | |
if (value.Length > 0) | |
WriteUInt8Array(StringEncoding.GetBytes(value)); | |
} | |
// TODO: string8 is modified UTF-8, which has a special representation of the NULL character | |
public string ReadString8() | |
{ | |
short length = ReadInt16(); | |
if (length == 0) return string.Empty; | |
var data = ReadUInt8Array((int)length); | |
return Encoding.UTF8.GetString(data); | |
} | |
public void WriteString8(string value) | |
{ | |
WriteInt16((short)value.Length); | |
if (value.Length > 0) | |
WriteUInt8Array(Encoding.UTF8.GetBytes(value)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment