mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-10-08 13:34:54 -04:00
138 lines
3.4 KiB
C#
138 lines
3.4 KiB
C#
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
|
using System;
|
|
using System.Net.Sockets;
|
|
|
|
namespace ClassicalSharp.Network {
|
|
|
|
public class NetReader {
|
|
|
|
public byte[] buffer = new byte[4096 * 5];
|
|
public int index = 0, size = 0;
|
|
Socket socket;
|
|
|
|
public NetReader(Socket socket) {
|
|
this.socket = socket;
|
|
}
|
|
|
|
public void ReadPendingData() {
|
|
if (socket.Available == 0) return;
|
|
// NOTE: Always using a read call that is a multiple of 4096
|
|
// (appears to?) improve read performance.
|
|
int recv = socket.Receive(buffer, size, 4096 * 4, SocketFlags.None);
|
|
size += recv;
|
|
}
|
|
|
|
public void Skip(int byteCount) {
|
|
index += byteCount;
|
|
}
|
|
|
|
public void RemoveProcessed() {
|
|
size -= index;
|
|
if (size > 0) // only copy left over bytes
|
|
Buffer.BlockCopy(buffer, index, buffer, 0, size);
|
|
index = 0;
|
|
// We don't need to zero the old bytes, since they will be overwritten when ReadData() is called.
|
|
}
|
|
|
|
public int ReadInt32() {
|
|
int value = buffer[index] << 24 | buffer[index + 1] << 16 |
|
|
buffer[index + 2] << 8 | buffer[index + 3];
|
|
index += 4;
|
|
return value;
|
|
}
|
|
|
|
public short ReadInt16() {
|
|
short value = (short)(buffer[index] << 8 | buffer[index + 1]);
|
|
index += 2;
|
|
return value;
|
|
}
|
|
|
|
public sbyte ReadInt8() {
|
|
sbyte value = (sbyte)buffer[index];
|
|
index++;
|
|
return value;
|
|
}
|
|
|
|
public ushort ReadUInt16() {
|
|
ushort value = (ushort)(buffer[index] << 8 | buffer[index + 1]);
|
|
index += 2;
|
|
return value;
|
|
}
|
|
|
|
public byte ReadUInt8() {
|
|
byte value = buffer[index];
|
|
index++;
|
|
return value;
|
|
}
|
|
|
|
public byte[] ReadBytes(int length) {
|
|
byte[] data = new byte[length];
|
|
Buffer.BlockCopy(buffer, index, data, 0, length);
|
|
index += length;
|
|
return data;
|
|
}
|
|
|
|
public string ReadCp437String() {
|
|
int length = GetString(false, Utils.StringLength);
|
|
return new String(characters, 0, length);
|
|
}
|
|
|
|
public string ReadAsciiString() {
|
|
int length = GetString(true, Utils.StringLength);
|
|
return new String(characters, 0, length);
|
|
}
|
|
|
|
public string ReadAsciiString(int maxLength) {
|
|
int length = GetString(true, maxLength);
|
|
return new String(characters, 0, length);
|
|
}
|
|
|
|
internal string ReadChatString(ref byte messageType) {
|
|
int length = GetString(false, Utils.StringLength);
|
|
|
|
int offset = 0;
|
|
if (length >= womDetail.Length && IsWomDetailString()) {
|
|
length -= womDetail.Length;
|
|
offset = womDetail.Length;
|
|
messageType = (byte)MessageType.Status3;
|
|
}
|
|
return new String(characters, offset, length);
|
|
}
|
|
|
|
static char[] characters = new char[Utils.StringLength];
|
|
const string womDetail = "^detail.user=";
|
|
static bool IsWomDetailString() {
|
|
for (int i = 0; i < womDetail.Length; i++) {
|
|
if (characters[i] != womDetail[i])
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int GetString(bool ascii, int maxLength) {
|
|
int length = 0;
|
|
|
|
for (int i = maxLength - 1; i >= 0; i--) {
|
|
byte code = buffer[index + i];
|
|
if (length == 0 && !(code == 0 || code == 0x20))
|
|
length = i + 1;
|
|
|
|
if (ascii) {
|
|
characters[i] = code >= 0x7F ? '?' : (char)code;
|
|
continue;
|
|
}
|
|
|
|
// Treat code as an index in code page 437
|
|
if (code < 0x20) {
|
|
characters[i] = Utils.ControlCharReplacements[code];
|
|
} else if (code < 0x7F) {
|
|
characters[i] = (char)code;
|
|
} else {
|
|
characters[i] = Utils.ExtendedCharReplacements[code - 0x7F];
|
|
}
|
|
}
|
|
index += maxLength;
|
|
return length;
|
|
}
|
|
}
|
|
} |