/// <inheritdoc />
        public override void Write([NotNull] BitArray value, IWireStreamWriterStrategy dest)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            //The size must be equal to the length divided by 8 bits (1 byte) but we do not include the
            //remainder from a modular division. The reason for this is it's always sent as 4 byte chunks from
            //Trinitycore and the size is always in terms of an int array
            byte[] bitmask = new byte[value.Length / 8];

            ((ICollection)value).CopyTo(bitmask, 0);

            byte size = (byte)(bitmask.Length / sizeof(int));

            //Write the size as if it were an int array first
            dest.Write(size);

            dest.Write(bitmask);
        }
        protected void WriteMemberData(TType obj, [NotNull] IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            try
            {
                //replaced for perf

                /*foreach (IMemberSerializationMediator<TType> serializerInfo in orderedMemberInfos)
                 * {
                 *      serializerInfo.WriteMember(obj, dest);
                 * }*/
                for (int i = 0; i < orderedMemberInfos.Length; i++)
                {
                    orderedMemberInfos[i].WriteMember(obj, dest);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
        /// <inheritdoc />
        public override void WriteMember(TContainingType obj, IWireStreamWriterStrategy dest)
        {
            WriteCollectionSizeToField(obj);

            //TODO: Should we spend CPU cycles to reset the original value? This kind of changes the state of the DTO
            DecoratedMediator.WriteMember(obj, dest);
        }
        /// <inheritdoc />
        public override void Write(string value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            //Review the source for Trinitycore's string reading for their ByteBuffer (payload/packet) Type.
            //(ctr+f << for std::string): http://www.trinitycore.net/d1/d17/ByteBuffer_8h_source.html
            //They use 0 byte to terminate the string in the stream

            //We should check this so we don't try to decode
            //or write null. Null should be considered empty.
            if (!String.IsNullOrEmpty(value))
            {
                //TODO: Pointer hack for speed
                //Convert the string to bytes
                //Not sure about encoding yet
                byte[] stringBytes = EncodingStrategy.GetBytes(value);

                dest.Write(stringBytes);
            }

            //Write the null terminator; Client expects it.
            for (int i = 0; i < CharacterSize; i++)
            {
                dest.Write(0);
            }
        }
        /// <inheritdoc />
        public override void Write([NotNull] string value, IWireStreamWriterStrategy dest)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            int size = sizeProvider.Size(value, dest);

            //Now that we know the size, and the header will be written if it was needed, we can write it
            //Don't write the size. Leave it up to the strategy above
            decoratedSerializer.Write(value, dest);

            //the tricky part here is that the serializer just wrote the string plus the null terminator
            //So, if the length of the string was less than the expected size write some more 0s.
            //However, DO NOT write another null terminator either way because we already have one.
            if (value.Length < size)
            {
                dest.Write(new byte[(CharacterSize * (size - value.Length))]);
            }
        }
Exemple #6
0
        //From jackpoz's bot: https://github.com/jackpoz/BotFarm/blob/592dbc9dbb58c06175bffecfced56eba42107c9a/Client/World/Network/OutPacket.cs#L47
        /// <inheritdoc />
        public override void Write(PackedGuid value, IWireStreamWriterStrategy dest)
        {
            //TODO: Can we use span or stackalloc? Or maybe shared buffer?
            byte[] packGuid = GeneratePackedGuid(value, out int size);

            dest.Write(packGuid, 0, size);
        }
Exemple #7
0
 /// <inheritdoc />
 public override void Write(TObjectType[] value, IWireStreamWriterStrategy dest)
 {
     for (int i = 0; i < value.Length; i++)
     {
         ElementSerializer.Write(value[i], dest);
     }
 }
        /// <inheritdoc />
        public byte[] Serialize <TTypeToSerialize>(TTypeToSerialize data, IWireStreamWriterStrategy writer)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }
            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            //Conditional compile this because it's not really very efficient anymore to lookup if a type is serialized.
#if DEBUG || DEBUGBUILD
            if (!serializerStorageService.HasSerializerFor(data.GetType()))
            {
                throw new InvalidOperationException($"Serializer cannot serialize Type: {typeof(TTypeToSerialize).FullName} because it's not registered.");
            }
#endif

            if (!isCompiled)
            {
                throw new InvalidOperationException($"You cannot serialize before compiling the serializer.");
            }

            GetLeastDerivedSerializer(data.GetType()).Write(data, writer);

            return(writer.GetBytes());
        }
        //TODO: Error handling
        /// <inheritdoc />
        public override void Write(TComplexType value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            //invoke before serialization if it's available
            (value as ISerializationEventListener)?.OnBeforeSerialization();

            //Writes base members first and goes down the inheritance line
            //WARNING: This caused HUGE perf probleems. Several orders of magnitude slower than Protobuf
            //We MUST not check if the serializer exists and we must precache the gets.
            if (reversedInheritanceHierarchy.Count() != 0)
            {
                foreach (Type t in reversedInheritanceHierarchy)
                {
                    if (serializerProviderService.HasSerializerFor(t))                     //TODO: Should we remove this check for perf?
                    {
                        serializerProviderService.Get(t).ObjectIntoWriter(value, dest);
                    }
                }
            }

            WriteMemberData(value, dest);
        }
Exemple #10
0
        /// <inheritdoc />
        public override void Write(bool value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            dest.Write(ConvertFromBool(value));
        }
        public override void WriteMember(object obj, [NotNull] IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            WriteMember((TContainingType)obj, dest);
        }
Exemple #12
0
        /// <inheritdoc />
        public void ObjectIntoWriter(object obj, IWireStreamWriterStrategy dest)
        {
            if (obj == null)
            {
                throw new ArgumentNullException(nameof(obj));
            }

            ObjectIntoWriter((TType)obj, dest);
        }
Exemple #13
0
        /// <inheritdoc />
        public override void Write(string value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            decoratedSerializer.Write(new string(value.Reverse().ToArray()), dest);
        }
        /// <inheritdoc />
        public override void Write(TEnumType value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            serializerStrategy.Write(GenericMath.Convert <TEnumType, TBaseType>(value), dest);
        }
Exemple #15
0
        /// <inheritdoc />
        public override void Write(TEnumType value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            //Just write the string to the stream
            decoratedSerializer.Write(value.ToString(), dest);
        }
Exemple #16
0
        /// <inheritdoc />
        public void WriteMember(TContainingType obj, IWireStreamWriterStrategy dest)
        {
            //Check if we should read
            if (!(bool)isReadWriteEnabledGetter.Getter(obj))
            {
                return;
            }

            DecoratedMediator.WriteMember(obj, dest);
        }
        /// <inheritdoc />
        public override void Write(byte[] value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            //MUST copy or it will modify the external objects
            byte[] bytes = value.ToArray();
            Array.Reverse(bytes);
            dest.Write(bytes);
        }
        /// <inheritdoc />
        public override void Write(string value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            //TODO: Pointer hack for speed
            byte[] stringBytes = EncodingStrategy.GetBytes(value);

            dest.Write(stringBytes);             //Just don't write terminator. Very simple.
        }
        /// <summary>
        /// Creates a realtime crypto stream reader.
        /// </summary>
        /// <param name="dest">The <see cref="IWireStreamWriterStrategy"/> to decorate.</param>
        /// <param name="sessionCrypto"></param>
        protected CryptoStreamWriter([NotNull] IWireStreamWriterStrategy dest, [NotNull] ISessionPacketCryptoService sessionCrypto)
            : base(sessionCrypto)
        {
            //We don't implement the writing ourselves because it could be a default behavior
            //our we may need network stream reading, which may block, or anything under the sun
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            Dest = dest;
        }
        /// <inheritdoc />
        public override void Write(DateTime value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            //Based on ByteBuffer.h from the Trinitycore Project as well as Jackpoz's 3.3.5 packet bot.
            //Trinitycore: append<uint32>((lt.tm_year - 100) << 24 | lt.tm_mon << 20 | (lt.tm_mday - 1) << 14 | lt.tm_wday << 11 | lt.tm_hour << 6 | lt.tm_min);

            //pass to decorated serializer
            decoratedSerializer.Write(ConvertDateTimeToIntegerRepresentation(ref value), dest);
        }
Exemple #21
0
        /// <inheritdoc />
        public override void Write(TType[] value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            int size = SizeStrategyService.Size <TType[], TType>(value, dest);

            //We no longer verify size thanks to PHANTASY STAR ONLINE. Thanks Sega. Sometimes we have to fake the size

            dest.Write(value.Reinterpret());
        }
Exemple #22
0
        /// <inheritdoc />
        public virtual void ObjectIntoWriter(TType obj, IWireStreamWriterStrategy dest)
        {
            if (obj == null)
            {
                throw new ArgumentNullException(nameof(obj));
            }
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            //This is a simple type so the only way to write it is to just write the value
            this.Write(obj, dest);
        }
        /// <inheritdoc />
        public SkipSomeBytesWireStreamWriterStrategyDecorator([NotNull] IWireStreamWriterStrategy decoratedWriter, int byteNumberToSkip)
        {
            if (decoratedWriter == null)
            {
                throw new ArgumentNullException(nameof(decoratedWriter));
            }
            if (byteNumberToSkip < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(byteNumberToSkip));
            }

            DecoratedWriter  = decoratedWriter;
            ByteNumberToSkip = byteNumberToSkip;
        }
Exemple #24
0
        public OneTimeCryptoStreamWriter([NotNull] IWireStreamWriterStrategy dest, [NotNull] ISessionPacketCryptoService sessionCrypto)
            : base(dest, sessionCrypto)
        {
            //The starting state is default
            //The writer can only write when it's in default state.
            WriterState = State.Default;

            //Lazily encrypt the stream's bytes.
            //This means it can ONLY be done once.
            CryptoByteRepresentation = new Lazy <byte[]>(() =>
            {
                WriterState = State.Crypted;
                return(sessionCrypto.ProcessBytes(dest.GetBytes(), 0));
            }, true);
        }
        /// <inheritdoc />
        public void Write(int value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            //If the key shouldn't be written then we avoid writing it
            //It may be that the data is needed to be left in the stream to indicate
            //something about the type later down the line.
            if (!typeHandlingFlags.HasFlag(InformationHandlingFlags.DontWrite))
            {
                KeyTypeSerializerStrategy.Write(GenericMath.Convert <int, TKeyType>(value), dest);
            }
        }
        public override void ObjectIntoWriter(TType obj, IWireStreamWriterStrategy dest)
        {
            if (obj == null)
            {
                throw new ArgumentNullException(nameof(obj));
            }
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            //This method is only responsible for writing the members
            //Even if we're suppose to write type data for this type we don't
            //Just members
            WriteMemberData(obj, dest);
        }
Exemple #27
0
        /// <inheritdoc />
        public int Size <TCollectionType, TElementType>(TCollectionType collection, IWireStreamWriterStrategy writer)
            where TCollectionType : IEnumerable, IEnumerable <TElementType>
        {
            if (collection == null)
            {
                throw new ArgumentNullException(nameof(collection));
            }
            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            //This is a fixed size stragey. Don't look at the collection
            //Don't write anything to the stream either. Consumers know the size too

            return(FixedSize);
        }
        /// <inheritdoc />
        public override void Write(TType value, [NotNull] IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            bool isPopulated = PopulateSharedBufferWith(value);

            if (!isPopulated)
            {
                throw new InvalidOperationException($"Failed to populate {nameof(SharedByteBuffer)} in {nameof(SharedBufferTypeSerializer<TType>)} for Type: {typeof(TType)} with Value: {value}.");
            }

            //At this point the SharedBuffer contains the serialized representation of the value
            //DO NOT RELEASE LOCK UNTIL WRITTEN
            dest.Write(SharedByteBuffer.Value);
        }
Exemple #29
0
        /// <inheritdoc />
        public override void Write(TObjectType[] value, IWireStreamWriterStrategy dest)
        {
            if (dest == null)
            {
                throw new ArgumentNullException(nameof(dest));
            }

            int size = sizeStrategyService.Size <TObjectType[], TObjectType>(value, dest);

            //We no longer verify size thanks to PHANTASY STAR ONLINE. Thanks Sega. Sometimes we have to fake the size

            //We can't use Size because sometimes the offset might may force this to go out of bounds.
            //only write what we have, the size is not relevant here and may be written differently in the stream.
            for (int i = 0; i < value.Length; i++)
            {
                decoratedSerializer.Write(value[i], dest);
            }
        }
        /// <inheritdoc />
        public override void Write(LinearPathMoveInfo value, IWireStreamWriterStrategy dest)
        {
            if (value == null)
            {
                return;
            }

            dest.Write(value.LastIndex.Reinterpret());

            dest.Write(value.FinalPosition.X.Reinterpret());
            dest.Write(value.FinalPosition.Y.Reinterpret());
            dest.Write(value.FinalPosition.Z.Reinterpret());

            if (value.LastIndex > 1 && value.SplineMiddlePoints != null)
            {
                dest.Write(value.SplineMiddlePoints);
            }
        }