internal void _Write(NetBuffer buffer) { if (subID == 0) // special case if unassigned { buffer.Write((byte)0); } else if (allocator == NetworkPlayer.server) // optimized case for allocator == server { buffer.WriteVariableInt32(-subID); } else // general case { buffer.WriteVariableInt32(subID); allocator._Write(buffer); } }
// Outgoing message public NetworkMessage(NetworkBaseLocal network, NetworkFlags flags, Channel channel, string name, InternalCode internCode, NetworkPlayer target, NetworkPlayer exclusion, NetworkViewID viewID) { if (target != NetworkPlayer.unassigned) { flags |= NetworkFlags.Unbuffered; } this.flags = flags; this.channel = ((flags & NetworkFlags.Unreliable) == 0) ? (NetChannel)channel : NetChannel.Unreliable; if (isBuffered) { if (!(isReliable)) { Utility.Exception("Message can not be buffered and unreliable"); } } // TODO: optimize by calculating initial buffer size by bit-flags & args // TODO: optimize by stripping unnecessary data if we have a direct connection i.e. is server // TODO: remove the default 4 bytes allocated by the default NetBuffer constructor. #if !NO_POOLING if (isReliable) { stream = new BitStream(true, isTypeSafe); //The Bitstream for reliable RPCs (including buffered RPCs) should not be written to pooled Bitreams, that would be dangerous during resend. } else { stream = (isTypeSafe) ? _bitStreamPoolOutgoingTypeSafe.GetNext() : _bitStreamPoolOutgoing.GetNext(); } #else stream = new BitStream(true, isTypeSafe); #endif var buffer = stream._buffer; connection = null; this.name = name; this.internCode = internCode; sender = network._localPlayer; this.target = target; exclude = exclusion; this.viewID = viewID; // write header to stream: HeaderFlags headerFlags = 0; // TODO: optimize away exclude and target PlayerID when sent from a regular uLink Server by faking it into a simple broadcast message if (isBroadcast) { headerFlags |= (hasExcludeID)? HeaderFlags.HasBroadcastExcludePlayerID : HeaderFlags.Broadcast; } else if (hasTargetID) { headerFlags |= HeaderFlags.HasTargetPlayerID; } if (hasViewID && isInternal) { headerFlags |= HeaderFlags.HasInternalCodeAndViewID; } else if (hasViewID) { headerFlags |= (isBuffered) ? HeaderFlags.HasNameAndViewIDAndIsBuffered : HeaderFlags.HasNameAndViewID; } else { headerFlags |= HeaderFlags.HasInternalCode; } if (hasTimestamp) { headerFlags |= (isBuffered) ? HeaderFlags.Has40BitTimestamp : HeaderFlags.Has16BitTimestamp; } if (isTypeSafe) { headerFlags |= HeaderFlags.HasTypeCodes; } buffer.Write((byte)headerFlags); if (hasTargetID) { this.target._Write(buffer); } if (hasExcludeID) { exclude._Write(buffer); } if (hasViewID) { this.viewID._Write(buffer); } if (isInternal) { buffer.Write((byte)internCode); } else { buffer.Write(name); } if (hasTimestamp) { localTimeSent = NetworkTime.localTime; rawServerTimeSent = localTimeSent + network.rawServerTimeOffset; #if PIKKO_BUILD ulong timestampInMillis = (ulong)NetTime.ToMillis(localTimestamp); #else rawServerTimeSent = localTimeSent + network.rawServerTimeOffset; ulong timestampInMillis = (ulong)NetTime.ToMillis(rawServerTimeSent); #endif buffer.Write(timestampInMillis, (isBuffered) ? 40 : 16); } buffer.PositionBits = buffer.LengthBits; }
// Outgoing forwarded message (non-auth server uses this) public NetworkMessage(NetworkBaseLocal network, NetworkMessage msg, NetworkPlayer originalSender) { flags = msg.flags; connection = msg.connection; channel = msg.channel; localTimeSent = msg.localTimeSent; monotonicServerTimeSent = msg.monotonicServerTimeSent; rawServerTimeSent = msg.rawServerTimeSent; name = msg.name; internCode = msg.internCode; sender = originalSender; target = msg.target; exclude = msg.exclude; viewID = msg.viewID; stream = new BitStream(isTypeSafe); var buffer = stream._buffer; HeaderFlags headerFlags = 0; if (sender != network._localPlayer) { headerFlags |= HeaderFlags.HasOriginalSenderPlayerID; } if (isBroadcast) { headerFlags |= (hasExcludeID) ? HeaderFlags.HasBroadcastExcludePlayerID : HeaderFlags.Broadcast; } else if (hasTargetID) { headerFlags |= HeaderFlags.HasTargetPlayerID; } if (hasViewID && isInternal) { headerFlags |= HeaderFlags.HasInternalCodeAndViewID; } else if (hasViewID) { headerFlags |= (isBuffered) ? HeaderFlags.HasNameAndViewIDAndIsBuffered : HeaderFlags.HasNameAndViewID; } else { headerFlags |= HeaderFlags.HasInternalCode; } // TODO: use 24bit timestamp if needed if (hasTimestamp) { headerFlags |= HeaderFlags.Has16BitTimestamp; } if (isTypeSafe) { headerFlags |= HeaderFlags.HasTypeCodes; } buffer.Write((byte)headerFlags); if (sender != network._localPlayer) { sender._Write(buffer); } if (hasTargetID) { target._Write(buffer); } if (hasExcludeID) { exclude._Write(buffer); } if (hasViewID) { viewID._Write(buffer); } if (internCode == InternalCode.None) { buffer.Write(name); } else { buffer.Write((byte)internCode); } if (hasTimestamp) { #if PIKKO_BUILD ulong timestampInMillis = (ulong)NetTime.ToMillis(localTimestamp); #else ulong timestampInMillis = (ulong)NetTime.ToMillis(rawServerTimeSent); #endif // TODO: use 24bit timestamp if needed buffer.Write(timestampInMillis, 16); } buffer.PositionBits = buffer.LengthBits; int argpos = msg.stream._buffer.PositionBytes; stream._buffer.Write(msg.stream._buffer.Data, argpos, msg.stream._buffer.LengthBytes - argpos); }
public void WriteNetworkPlayer(NetworkPlayer value) { value._Write(_buffer); }