-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathClassicCoder.cs
110 lines (98 loc) · 3.83 KB
/
ClassicCoder.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipelines;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Example.Minecraft.Net.Packets;
using ProtoSocket;
namespace Example.Minecraft.Net
{
class ClassicCoder : IProtocolCoder<ClassicPacket>
{
/// <summary>
/// Defines the packet sizes.
/// </summary>
private static readonly Dictionary<PacketId, int> PacketSizes = new Dictionary<PacketId, int>() {
{ PacketId.Identification, 130 },
{ PacketId.Ping, 0 },
{ PacketId.LevelInitialize, 0 },
{ PacketId.LevelDataChunk, 1027 },
{ PacketId.LevelFinalize, 0 },
{ PacketId.AskBlock, 8 },
{ PacketId.SetBlock, 7 },
{ PacketId.SpawnPlayer, 73 },
{ PacketId.PositionAngle, 9 },
{ PacketId.Message, 65 }
};
private ReadState _state;
private PacketId _packetId;
private int _packetLength;
/// <summary>
/// Resets the coder state.
/// </summary>
public void Reset() {
_state = ReadState.PacketId;
_packetLength = 0;
}
/// <summary>
/// Defines the internal read states.
/// </summary>
enum ReadState
{
PacketId,
Payload
}
/// <summary>
/// Writes the frame to the buffer asyncronously.
/// </summary>
/// <param name="stream">The stream.</param>
/// <param name="frame">The frame.</param>
/// <param name="ctx">The coder context.</param>
/// <returns></returns>
public void Write(Stream stream, ClassicPacket frame, CoderContext<ClassicPacket> ctx) {
stream.WriteByte((byte)frame.Id);
stream.Write(frame.Payload, 0, frame.Payload.Length);
}
public bool Read(PipeReader reader, CoderContext<ClassicPacket> ctx, out ClassicPacket frame) {
if (reader.TryRead(out ReadResult result) && !result.IsCompleted) {
// get the sequence buffer
ReadOnlySequence<byte> buffer = result.Buffer;
try {
while (buffer.Length > 0) {
if (_state == ReadState.PacketId) {
// read in the packet id and setup the payload state
_packetId = (PacketId)buffer.First.Span[0];
_packetLength = PacketSizes[_packetId];
_state = ReadState.Payload;
// increment buffer
buffer = buffer.Slice(1);
} else if (_state == ReadState.Payload) {
if (buffer.Length >= _packetLength) {
// to array
byte[] packetPayload = buffer.Slice(0, _packetLength).ToArray();
// increment the amount we were able to copy in
buffer = buffer.Slice(_packetLength);
// output the frames
frame = new ClassicPacket() { Id = _packetId, Payload = packetPayload };
// reset the state
Reset();
return true;
} else {
break;
}
}
}
} finally {
reader.AdvanceTo(buffer.GetPosition(0), buffer.End);
}
}
// we didn't find a frame
frame = default;
return false;
}
}
}