public override void OnDeserialize(NetworkReader reader, bool initialState) { var dirty = reader.ReadPackedUInt32(); if (dirty == 0) { return; } m_Slot = reader.ReadByte(); m_ReadyToBegin = reader.ReadBoolean(); }
public void OnDeserializeDelta(NetworkReader reader) { // This list can now only be modified by synchronization IsReadOnly = true; int changesCount = (int)reader.ReadUInt32(); for (int i = 0; i < changesCount; i++) { Operation operation = (Operation)reader.ReadByte(); // apply the operation only if it is a new change // that we have not applied yet bool apply = changesAhead == 0; T item = default; switch (operation) { case Operation.OP_ADD: item = reader.Read <T>(); if (apply) { objects.Add(item); } break; case Operation.OP_CLEAR: if (apply) { objects.Clear(); } break; case Operation.OP_REMOVE: item = reader.Read <T>(); if (apply) { objects.Remove(item); } break; } if (apply) { Callback?.Invoke(operation, item); } // we just skipped this change else { changesAhead--; } } }
public static ulong ReadUInt64(this NetworkReader reader) { ulong value = 0; value |= reader.ReadByte(); value |= ((ulong)reader.ReadByte()) << 8; value |= ((ulong)reader.ReadByte()) << 16; value |= ((ulong)reader.ReadByte()) << 24; value |= ((ulong)reader.ReadByte()) << 32; value |= ((ulong)reader.ReadByte()) << 40; value |= ((ulong)reader.ReadByte()) << 48; value |= ((ulong)reader.ReadByte()) << 56; return(value); }
public static NetworkBehaviour ReadNetworkBehaviour(this NetworkReader reader) { NetworkIdentity identity = reader.ReadNetworkIdentity(); if (identity == null) { return(null); } byte componentIndex = reader.ReadByte(); return(identity.NetworkBehaviours[componentIndex]); }
public static NetworkBehaviour.NetworkBehaviourSyncVar ReadNetworkBehaviourSyncVar(this NetworkReader reader) { uint netId = reader.ReadUInt(); byte componentIndex = default; // if netId is not 0, then index is also sent to read before returning if (netId != 0) { componentIndex = reader.ReadByte(); } return(new NetworkBehaviour.NetworkBehaviourSyncVar(netId, componentIndex)); }
public void OnDeserializeDelta(NetworkReader reader) { // This list can now only be modified by synchronization IsReadOnly = true; bool raiseOnChange = false; int changesCount = (int)reader.ReadPackedUInt32(); for (int i = 0; i < changesCount; i++) { var operation = (Operation)reader.ReadByte(); // apply the operation only if it is a new change // that we have not applied yet bool apply = changesAhead == 0; switch (operation) { case Operation.OP_ADD: DeserializeAdd(reader, apply); break; case Operation.OP_SET: DeserializeSet(reader, apply); break; case Operation.OP_CLEAR: DeserializeClear(apply); break; case Operation.OP_REMOVE: DeserializeRemove(reader, apply); break; } if (apply) { raiseOnChange = true; } // we just skipped this change else { changesAhead--; } } if (raiseOnChange) { OnChange?.Invoke(); } }
public static NetworkBehaviour ReadNetworkBehaviour(this NetworkReader reader) { // reuse ReadNetworkIdentity, get the component at index NetworkIdentity identity = ReadNetworkIdentity(reader); // a netId not being in spawned is common. // for example, "[SyncVar] NetworkBehaviour target" netId would not // be known on client if the monster walks out of proximity for a // moment. no need to log any error or warning here. if (identity == null) { return(null); } // if identity isn't null, then index is also sent to read before returning byte componentIndex = reader.ReadByte(); return(identity.NetworkBehaviours[componentIndex]); }
public void HandleMsg(NetworkReader reader) { byte op = reader.ReadByte(); int itemIndex = (int)reader.ReadPackedUInt32(); T item = DeserializeItem(reader); switch ((Operation)op) { case Operation.OP_ADD: m_Objects.Add(item); break; case Operation.OP_CLEAR: m_Objects.Clear(); break; case Operation.OP_INSERT: m_Objects.Insert(itemIndex, item); break; case Operation.OP_REMOVE: m_Objects.Remove(item); break; case Operation.OP_REMOVEAT: m_Objects.RemoveAt(itemIndex); break; case Operation.OP_SET: case Operation.OP_DIRTY: m_Objects[itemIndex] = item; break; } if (m_Callback != null) { m_Callback.Invoke((Operation)op, itemIndex); } }
public static NetworkBehaviour ReadNetworkBehaviour(this NetworkReader reader) { uint netId = reader.ReadUInt32(); if (netId == 0) { return(null); } // if netId is not 0, then index is also sent to read before returning byte componentIndex = reader.ReadByte(); if (NetworkIdentity.spawned.TryGetValue(netId, out NetworkIdentity identity)) { return(identity.NetworkBehaviours[componentIndex]); } // a netId not being in spawned is common. // for example, "[SyncVar] NetworkBehaviour target" netId would not // be known on client if the monster walks out of proximity for a // moment. no need to log any error or warning here. return(null); }
public SceneOperation sceneOperation; // Normal = 0, LoadAdditive = 1, UnloadAdditive = 2 public void Deserialize(NetworkReader reader) { sceneName = reader.ReadString(); sceneOperation = (SceneOperation)reader.ReadByte(); }
public void Deserialize(NetworkReader reader) { error = reader.ReadByte(); }
public static Color32 ReadColor32(this NetworkReader reader) => new Color32(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte());
public static ulong ReadPackedUInt64(this NetworkReader reader) { byte a0 = reader.ReadByte(); if (a0 < 241) { return(a0); } byte a1 = reader.ReadByte(); if (a0 >= 241 && a0 <= 248) { return(240 + ((a0 - (ulong)241) << 8) + a1); } byte a2 = reader.ReadByte(); if (a0 == 249) { return(2288 + ((ulong)a1 << 8) + a2); } byte a3 = reader.ReadByte(); if (a0 == 250) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16)); } byte a4 = reader.ReadByte(); if (a0 == 251) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24)); } byte a5 = reader.ReadByte(); if (a0 == 252) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32)); } byte a6 = reader.ReadByte(); if (a0 == 253) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40)); } byte a7 = reader.ReadByte(); if (a0 == 254) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48)); } byte a8 = reader.ReadByte(); if (a0 == 255) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48) + (((ulong)a8) << 56)); } throw new IndexOutOfRangeException("ReadPackedUInt64() failure: " + a0); }
public void Deserialize(NetworkReader reader) { sceneName = reader.ReadString(); sceneOperation = (SceneOperation)reader.ReadByte(); customHandling = reader.ReadBoolean(); }
// serialization is needed by OnSerialize and by manual sending from authority void DeserializeFromReader(NetworkReader reader) { // put it into a data point immediately DataPoint temp = new DataPoint { // deserialize position localPosition = reader.ReadVector3() }; // deserialize rotation if (compressRotation == Compression.None) { // read 3 floats = 16 byte float x = reader.ReadSingle(); float y = reader.ReadSingle(); float z = reader.ReadSingle(); temp.localRotation = Quaternion.Euler(x, y, z); } else if (compressRotation == Compression.Much) { // read 3 byte. scaling [0,255] to [0,360] float x = FloatBytePacker.ScaleByteToFloat(reader.ReadByte(), byte.MinValue, byte.MaxValue, 0, 360); float y = FloatBytePacker.ScaleByteToFloat(reader.ReadByte(), byte.MinValue, byte.MaxValue, 0, 360); float z = FloatBytePacker.ScaleByteToFloat(reader.ReadByte(), byte.MinValue, byte.MaxValue, 0, 360); temp.localRotation = Quaternion.Euler(x, y, z); } else if (compressRotation == Compression.Lots) { // read 2 byte, 5 bits per float Vector3 xyz = FloatBytePacker.UnpackUShortIntoThreeFloats(reader.ReadUInt16(), 0, 360); temp.localRotation = Quaternion.Euler(xyz.x, xyz.y, xyz.z); } temp.localScale = reader.ReadVector3(); temp.timeStamp = Time.time; // movement speed: based on how far it moved since last time // has to be calculated before 'start' is overwritten temp.movementSpeed = EstimateMovementSpeed(goal, temp, targetComponent.transform, syncInterval); // reassign start wisely // -> first ever data point? then make something up for previous one // so that we can start interpolation without waiting for next. if (start == null) { start = new DataPoint { timeStamp = Time.time - syncInterval, // local position/rotation for VR support localPosition = targetComponent.transform.localPosition, localRotation = targetComponent.transform.localRotation, localScale = targetComponent.transform.localScale, movementSpeed = temp.movementSpeed }; } // -> second or nth data point? then update previous, but: // we start at where ever we are right now, so that it's // perfectly smooth and we don't jump anywhere // // example if we are at 'x': // // A--x->B // // and then receive a new point C: // // A--x--B // | // | // C // // then we don't want to just jump to B and start interpolation: // // x // | // | // C // // we stay at 'x' and interpolate from there to C: // // x..B // \ . // \. // C // else { float oldDistance = Vector3.Distance(start.localPosition, goal.localPosition); float newDistance = Vector3.Distance(goal.localPosition, temp.localPosition); start = goal; // teleport / lag / obstacle detection: only continue at current // position if we aren't too far away // // // local position/rotation for VR support if (Vector3.Distance(targetComponent.transform.localPosition, start.localPosition) < oldDistance + newDistance) { start.localPosition = targetComponent.transform.localPosition; start.localRotation = targetComponent.transform.localRotation; start.localScale = targetComponent.transform.localScale; } } // set new destination in any case. new data is best data. goal = temp; }
public LocalPhysicsMode physicsMode; // None = 0, Physics3D = 1, Physics2D = 2 public override void Deserialize(NetworkReader reader) { sceneName = reader.ReadString(); sceneMode = (LoadSceneMode)reader.ReadByte(); physicsMode = (LocalPhysicsMode)reader.ReadByte(); }
public void OnDeserializeDelta(NetworkReader reader) { int changesCount = reader.ReadInt32(); for (int i = 0; i < changesCount; i++) { Operation operation = (Operation)reader.ReadByte(); // apply the operation only if it is a new change // that we have not applied yet bool apply = changesAhead == 0; int index = 0; T item; switch (operation) { case Operation.OP_ADD: item = DeserializeItem(reader); if (apply) { m_Objects.Add(item); } break; case Operation.OP_CLEAR: if (apply) { m_Objects.Clear(); } break; case Operation.OP_INSERT: index = reader.ReadInt32(); item = DeserializeItem(reader); if (apply) { m_Objects.Insert(index, item); } break; case Operation.OP_REMOVE: item = DeserializeItem(reader); if (apply) { m_Objects.Remove(item); } break; case Operation.OP_REMOVEAT: index = reader.ReadInt32(); if (apply) { m_Objects.RemoveAt(index); } break; case Operation.OP_SET: case Operation.OP_DIRTY: index = reader.ReadInt32(); item = DeserializeItem(reader); if (apply) { m_Objects[index] = item; } break; } SyncListChanged listChanged = Callback; if (apply && listChanged != null) { listChanged(operation, index); } // we just skipped this change if (!apply) { changesAhead--; } } }
public void OnDeserializeDelta(NetworkReader reader) { // This list can now only be modified by synchronization IsReadOnly = true; bool raiseOnChange = false; int changesCount = (int)reader.ReadPackedUInt32(); for (int i = 0; i < changesCount; i++) { var operation = (Operation)reader.ReadByte(); // apply the operation only if it is a new change // that we have not applied yet bool apply = changesAhead == 0; TKey key = default; TValue item = default; TValue oldItem = default; switch (operation) { case Operation.OP_ADD: key = DeserializeKey(reader); item = DeserializeItem(reader); if (apply) { objects[key] = item; } break; case Operation.OP_SET: key = DeserializeKey(reader); item = DeserializeItem(reader); if (apply) { oldItem = objects[key]; objects[key] = item; } break; case Operation.OP_CLEAR: if (apply) { objects.Clear(); } break; case Operation.OP_REMOVE: key = DeserializeKey(reader); item = DeserializeItem(reader); if (apply) { objects.Remove(key); } break; } if (apply) { RaiseEvents(operation, key, item, oldItem); raiseOnChange = true; } // we just skipped this change else { changesAhead--; } } if (raiseOnChange) { OnChange?.Invoke(); } }
public override void OnDeserialize(NetworkReader reader, bool initialState) { if (initialState) { //This gets excecuted ONLY on CLIENT whenever a client connects for the first time to obtain the 'full' set of data //Debug.Log("RECEIVING INITIAL TILE-INFO: " + gameObject.name); this.n_TileType = reader.ReadByte(); this.n_lowerTurf = reader.ReadByte(); this.n_upperTurf = reader.ReadByte(); this.n_hasDisposal = reader.ReadBoolean(); this.n_disposalConfig = reader.ReadByte(); this.n_hasBlue = reader.ReadBoolean(); this.n_blueConfig = reader.ReadByte(); this.n_hasRed = reader.ReadBoolean(); this.n_redConfig = reader.ReadByte(); SetAllTileData(); //myTile.UpdateFromNetwork(); } else { //This gets excecuted ONLY on client whenever updataPacket is invoked. the dirty bitmask itself is inaccesable // and should be send into the write/read buffer if its needed here to 'know' what is gonna change. // set dirtyBit Trigger 001<Tile> 010<Turf> 100<Pipe> ulong receivedDirtyBits = reader.ReadUInt64(); Debug.Log("RECEIVING DELTA TILE-INFO: " + gameObject.name + " :: " + receivedDirtyBits.ToString("X")); if ((receivedDirtyBits & 0b001) != 0u) { this.n_TileType = reader.ReadByte(); UpdateTile(); } if ((receivedDirtyBits & 0b010) != 0u) { this.n_lowerTurf = reader.ReadByte(); this.n_upperTurf = reader.ReadByte(); UpdateTurf(); } if ((receivedDirtyBits & 0b100) != 0u) { this.n_hasDisposal = reader.ReadBoolean(); this.n_disposalConfig = reader.ReadByte(); this.n_hasBlue = reader.ReadBoolean(); this.n_blueConfig = reader.ReadByte(); this.n_hasRed = reader.ReadBoolean(); this.n_redConfig = reader.ReadByte(); UpdateUnderPipes(true); } } }
/** * Check for internal networked messages like disconnect request */ private void handleInternalMessages() { if (lastInternalMessageFrame == Time.frameCount) { return; //already processed this frame } lastInternalMessageFrame = Time.frameCount; int connectionId; Byte[] data; while (ReceiveInternal(out connectionId, out data)) { if (LogFilter.Debug || debug) { Debug.Log("handleInternalMessages Got a message"); } try { SteamClient steamClient = steamConnectionMap.fromConnectionID[connectionId]; if (steamClient.state == SteamClient.ConnectionState.CONNECTED || steamClient.state == SteamClient.ConnectionState.CONNECTING) { NetworkReader reader = new NetworkReader(data); byte message = reader.ReadByte(); switch (message) { case (byte)InternalMessages.CONNECT: if (LogFilter.Debug || debug) { Debug.LogWarning("Received a request to Connect from " + steamClient.steamID); } //if we are a server and have spaces then accept the request to connect, else reject if (mode == Mode.SERVER && getNumberOfActiveConnection() < maxConnections) { //we have to queue this connection up so we can let the ReceiveFromHost method return the new connection steamNewConnections.Enqueue(connectionId); //send a message back to the client to confirm they have connected successfully SteamNetworking.SendP2PPacket(steamClient.steamID, acceptConnectMsgBuffer, (uint)acceptConnectMsgBuffer.Length, sendMethods[Channels.DefaultReliable], (int)SteamChannels.SEND_INTERNAL); } else { if (LogFilter.Debug || debug) { Debug.LogWarning("Rejected connect from " + steamClient.steamID + ". Active Connections: " + getNumberOfActiveConnection() + ", maxConnections: " + maxConnections); } SteamNetworking.CloseP2PSessionWithUser(steamClient.steamID); } steamClient.timeIdle = 0; break; case (byte)InternalMessages.ACCEPT_CONNECT: if (LogFilter.Debug || debug) { Debug.LogWarning("Received an accept to connect to " + steamClient.steamID); } //if we are a client and received this message from the server we are trying to connect to then connect, else reject if (mode == Mode.CLIENT && steamClient.steamID == steamClientServer.steamID) { //we have to queue this connection up so we can let the ReceiveFromHost method return the new connection steamNewConnections.Enqueue(connectionId); } else { Debug.LogError("Received an ACCEPT_CONNECT from wrong person"); SteamNetworking.CloseP2PSessionWithUser(steamClient.steamID); } steamClient.timeIdle = 0; break; case (byte)InternalMessages.DISCONNECT: if (LogFilter.Debug || debug) { Debug.LogWarning("Received an instruction to Disconnect from " + steamClient.steamID); } //requested to disconnect if (mode == Mode.CLIENT || mode == Mode.SERVER) { //disconnect this client closeSteamConnection(steamClient); } break; } } else { Debug.LogWarning("Received message for non connected client ?"); } } catch (KeyNotFoundException) { //shouldnt happen - ignore Debug.LogError("Received internal message from unknown.. connect?"); } } //check all connections to check they are healthy foreach (var connection in steamConnectionMap) { SteamClient steamClient = connection.Value; if (steamClient.state == SteamClient.ConnectionState.CONNECTED) { if (steamClient.timeIdle > (NetworkTime.PingFrequency + connectedTimeoutBuffer)) { //idle too long - disconnect Debug.LogWarning("Connection " + steamClient.connectionID + " timed out - going to disconnect"); internalDisconnect(steamClient); continue; } //If client then this will Not be called if the scene is loading. We dont want to count idle time if loading the scene for this reason //If Server then this will be called so we need to not count idle time for clients who are not "ready" as they are loading the scene and unable to communicate. The connect timeout will catch people that disconnect during scene load if (mode == Mode.CLIENT || (mode == Mode.SERVER && (!NetworkServer.connections.ContainsKey(steamClient.connectionID) || NetworkServer.connections[steamClient.connectionID].isReady))) { steamClient.timeIdle += Time.deltaTime; } } } }
public static Color32 ReadColor32(this NetworkReader reader) { return(new Color32(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte())); }
public static bool ReadBoolean(this NetworkReader reader) { return(reader.ReadByte() != 0); }
public byte errorCode; // byte instead of int because NetworkServer uses byte anyway. saves bandwidth. public override void Deserialize(NetworkReader reader) { errorCode = reader.ReadByte(); }
public static bool ReadBoolean(this NetworkReader reader) => reader.ReadByte() != 0;
// NOT an extension. otherwise weaver might accidentally use it. public static ulong DecompressVarUInt(NetworkReader reader) { byte a0 = reader.ReadByte(); if (a0 < 241) { return(a0); } byte a1 = reader.ReadByte(); if (a0 <= 248) { return(240 + ((a0 - (ulong)241) << 8) + a1); } byte a2 = reader.ReadByte(); if (a0 == 249) { return(2288 + ((ulong)a1 << 8) + a2); } byte a3 = reader.ReadByte(); if (a0 == 250) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16)); } byte a4 = reader.ReadByte(); if (a0 == 251) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24)); } byte a5 = reader.ReadByte(); if (a0 == 252) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32)); } byte a6 = reader.ReadByte(); if (a0 == 253) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40)); } byte a7 = reader.ReadByte(); if (a0 == 254) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48)); } byte a8 = reader.ReadByte(); if (a0 == 255) { return(a1 + (((ulong)a2) << 8) + (((ulong)a3) << 16) + (((ulong)a4) << 24) + (((ulong)a5) << 32) + (((ulong)a6) << 40) + (((ulong)a7) << 48) + (((ulong)a8) << 56)); } throw new IndexOutOfRangeException($"DecompressVarInt failure: {a0}"); }
/** * Check for internal networked messages like ping or disconnect request */ private void handleInternalMessages() { if (lastInternalMessageFrame == Time.frameCount) { return; //already processed this frame } lastInternalMessageFrame = Time.frameCount; int connectionId; TransportEvent transportEvent; Byte[] data; while (ReceiveInternal(out connectionId, out data)) { try { SteamClient steamClient = steamConnectionMap.fromConnectionID[connectionId]; if (steamClient.state == SteamClient.ConnectionState.CONNECTED) { float senderTime; NetworkReader reader = new NetworkReader(data); switch (reader.ReadByte()) { case (byte)InternalMessages.PING: //ping .. send a pong senderTime = reader.ReadSingle(); sendInternalPong(steamClient, senderTime); break; case (byte)InternalMessages.PONG: //pong .. update when we last received a pong senderTime = reader.ReadSingle(); steamClient.lastPong = Time.time; double rtt = LocalTime() - senderTime; _rtt.Add(rtt); break; case (byte)InternalMessages.DISCONNECT: if (LogFilter.Debug) { Debug.LogWarning("Received an instruction to Disconnect"); } //requested to disconnect if (mode == Mode.CLIENT || mode == Mode.SERVER) { //disconnect this client closeSteamConnection(steamClient); } break; } } } catch (KeyNotFoundException) { //shouldnt happen - ignore } } //check all connections to check they are healthy foreach (var connection in steamConnectionMap) { SteamClient steamClient = connection.Value; if (steamClient.state == SteamClient.ConnectionState.CONNECTED) { if (Time.time - steamClient.lastPong > PONG_TIMEOUT) { //idle too long - disconnect Debug.LogError("Connection " + steamClient.connectionID + " timed out - going to disconnect"); internalDisconnect(steamClient); continue; } if (Time.time - steamClient.lastPing > PING_FREQUENCY) { //time to ping sendInternalPing(steamClient); } } } }
public override void Deserialize(NetworkReader reader) { value = reader.ReadByte(); }
public static byte ReadByte(this NetworkReader reader) => reader.ReadByte();
public void OnDeserializeDelta(NetworkReader reader) { // This list can now only be modified by synchronization IsReadOnly = true; int changesCount = (int)reader.ReadPackedUInt32(); for (int i = 0; i < changesCount; i++) { Operation operation = (Operation)reader.ReadByte(); // apply the operation only if it is a new change // that we have not applied yet bool apply = changesAhead == 0; int index = 0; T oldItem = default; T newItem = default; switch (operation) { case Operation.OP_ADD: newItem = DeserializeItem(reader); if (apply) { index = objects.Count; objects.Add(newItem); } break; case Operation.OP_CLEAR: if (apply) { objects.Clear(); } break; case Operation.OP_INSERT: index = (int)reader.ReadPackedUInt32(); newItem = DeserializeItem(reader); if (apply) { objects.Insert(index, newItem); } break; case Operation.OP_REMOVEAT: index = (int)reader.ReadPackedUInt32(); if (apply) { oldItem = objects[index]; objects.RemoveAt(index); } break; case Operation.OP_SET: index = (int)reader.ReadPackedUInt32(); newItem = DeserializeItem(reader); if (apply) { oldItem = objects[index]; objects[index] = newItem; } break; } if (apply) { Callback?.Invoke(operation, index, oldItem, newItem); } // we just skipped this change else { changesAhead--; } } }
public static sbyte ReadSByte(this NetworkReader reader) => (sbyte)reader.ReadByte();