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);
 }