|
||
|
|||||||
| Network Modifications This forum is for modifications to the networking code of RunUO |
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 (permalink) |
|
Forum Expert
Join Date: Sep 2004
Age: 37
Posts: 1,006
|
I'm fairly certain that I just discovered a bug in PacketWriter.cs. I'm no expert on this stuff, by any means, so some peer review would be greatly appreciated.
Regardless, the AccountLoginAck() method of the Server.Network.AccountLoginAck class is: Code:
public AccountLoginAck( ServerInfo[] info ) : base( 0xA8 )
{
this.EnsureCapacity( 6 + (info.Length * 40) );
thisStream.Write( (byte) 0x5D ); // Unknown
thisStream.Write( (ushort) info.Length );
for ( int i = 0; i < info.Length; ++i )
{
ServerInfo si = info[i];
thisStream.Write( (ushort) i );
thisStream.WriteAsciiFixed( si.Name, 32 );
thisStream.Write( (byte) si.FullPercent );
thisStream.Write( (sbyte) si.TimeZone );
thisStream.Write( (int) Utility.GetAddressValue( si.Address.Address ) );
}
}
Of course, I turned on arithmetic overflow exceptions in my build, so this shouldn't really be an issue for most people... but, that's why this is in the Core Modifications forum rather than the Server forum. The best (immediate) solution that I can think of is to use Math.Abs like: Code:
thisStream.Write( (byte) Math.Abs(si.TimeZone) ); |
|
|
|
|
|
#2 (permalink) | |
|
ConnectUO Creator
Join Date: Jan 2004
Location: In your mom
Age: 27
Posts: 4,760
|
Quote:
Code:
/// <summary>
/// Writes a 1-byte signed integer value to the underlying stream.
/// </summary>
public void Write( sbyte value )
{
m_Stream.WriteByte( (byte) value );
}
__________________
Jeff Boulanger ConnectUO - Core Developer Want to help make ConnectUO better? Click here to submit your ideas/requests Use your talent to compete against other community members in RunUO hosted coding competitions If you know XNA (even if its just a little) or are a good artist(2d or 3d) and are interested in making games for a hobby send me a pm or drop by #xna in irc.runuo.com. I'm looking to put together a small game development team. Please do not pm me for support. If you are having issues please post in the appropriate forum. Thanks for your continued support of both ConnectUO and RunUO |
|
|
|
|
|
|
#3 (permalink) |
|
Administrator
Join Date: Aug 2002
Location: Baltimore, MD
Age: 25
Posts: 4,831
|
Since the client interprets this as a signed value, simply using Math.Abs yields a different and unintended result.
This discussion is really pointless though since: 1) The client doesn't do anything really useful with this value. 2) IIRC RunUO doesn't auto-supply a value for this, and most servers leave it 0. 3) It only causes a problem when you use non-standard compiler settings. IMO the stupidest "feature" of C# is arithmetic overflow exceptions. Especially in this case. 4) The correct solution would be to use the "unchecked()" syntax to instruct C# to ignore arithmetic exceptions for this piece of code, since it is, indeed, working correctly. But, if the language was sane, you wouldn't need to do that since the value was already explicitly cast to an sbyte.
__________________
Zippy, Razor Creator and RunUO Core Developer The RunUO Software Team "Intuition, like a flash of lightning, lasts only for a second. It generally comes when one is tormented by a difficult decipherment and when one reviews in his mind the fruitless experiments already tried. Suddenly the light breaks through and one finds after a few minutes what previous days of labor were unable to reveal." ~The Cryptonomicon |
|
|
|
|
|
#4 (permalink) |
|
Forum Expert
Join Date: Sep 2004
Age: 37
Posts: 1,006
|
All of that is certainly true Zippy, and I have no illusions that I've created this "problem" all by myself... However, I think that I may have a bit of an optimization for you based on this.
In PacketWriter.cs, there are several Write() methods that handle different variables being passed to it. The current method being used is (I'll just post the integer conversion one for an example): Code:
/// <summary>
/// Writes a 4-byte signed integer value to the underlying stream.
/// </summary>
public void Write( int value )
{
m_Buffer[0] = (byte)(value >> 24);
m_Buffer[1] = (byte)(value >> 16);
m_Buffer[2] = (byte)(value >> 8);
m_Buffer[3] = (byte) value;
m_Stream.Write( m_Buffer, 0, 4 );
}
Code:
/// <summary>
/// Writes a 4-byte unsigned integer value to the underlying stream.
/// </summary>
public void Write( uint value )
{
m_Buffer = BitConverter.GetBytes(value);
m_Stream.Write( m_Buffer, 0, 4 );
}
|
|
|
|
|
|
#5 (permalink) |
|
Administrator
Join Date: Aug 2002
Location: Baltimore, MD
Age: 25
Posts: 4,831
|
The bit shifts are done to ensure that the bytes are written in big endian order. BitConverter, AFAIK, is little endian. Thus it is the opposite of what you want.
__________________
Zippy, Razor Creator and RunUO Core Developer The RunUO Software Team "Intuition, like a flash of lightning, lasts only for a second. It generally comes when one is tormented by a difficult decipherment and when one reviews in his mind the fruitless experiments already tried. Suddenly the light breaks through and one finds after a few minutes what previous days of labor were unable to reveal." ~The Cryptonomicon |
|
|
|
|
|
#6 (permalink) |
|
Forum Expert
Join Date: Sep 2004
Age: 37
Posts: 1,006
|
Yea, I kind of figured that out last night...
![]() It's been a long time since I've messed around with endian'ness. What a PITA. It took me forever to figure out that that's what the problem was, and I honestly didn't know for sure until I just read your reply. damnit... now I really understand what you were saying about about the overflow check problems. I'm going to mess around with it some still, just for the heck of it. Thanks for the replies at least, I appreciate it. ![]() edit: in case anyone else is interested (I'm certain that Zippy know this...) here's a little example of the problem that BitConverter causes. Example program: Code:
using System;
using System.Collections.Generic;
using System.Text;
namespace BitConverter_test
{
class Program
{
static void Main(string[] args)
{
int integerTest = 123456;
byte[] bytearrTest1 = new byte[4];
byte[] bytearrTest2 = new byte[4];
bytearrTest1[0] = (byte)(integerTest >> 24);
bytearrTest1[1] = (byte)(integerTest >> 16);
bytearrTest1[2] = (byte)(integerTest >> 8);
bytearrTest1[3] = (byte)integerTest;
bytearrTest2 = BitConverter.GetBytes(integerTest);
Console.WriteLine("Byte array 1");
Console.WriteLine(bytearrTest1[0].ToString());
Console.WriteLine(bytearrTest1[1].ToString());
Console.WriteLine(bytearrTest1[2].ToString());
Console.WriteLine(bytearrTest1[3].ToString());
Console.WriteLine("Byte Array 2");
Console.WriteLine(bytearrTest2[0].ToString());
Console.WriteLine(bytearrTest2[1].ToString());
Console.WriteLine(bytearrTest2[2].ToString());
Console.WriteLine(bytearrTest2[3].ToString());
Console.WriteLine("Integer");
Console.WriteLine(integerTest.ToString());
Console.ReadLine();
}
}
}
notice how the two Byte arrays are mirrors of each other. Last edited by Ohms_Law; 07-07-2007 at 08:57 PM. |
|
|
|
|
|
#7 (permalink) |
|
Newbie
Join Date: Oct 2006
Posts: 13
|
All right. I've had the same problem, but I'm not quite as computer-savvy yet. I just want to get my server up and running so that I can focus on things more suited to my level of comprehension.
I'm not horrible with programming, so I can do line-by-line stuff and probably understand it, but big endian, little endian... I'm afraid that means nothing to me. All I know is that it's not writing correctly. I have those places in the core scripts pinpointed with an error log file, if you need to reference them, I can. Again, any help would be appreciated. - Sephur |
|
|
|
|
|
#8 (permalink) |
|
Newbie
Join Date: Jan 2005
Age: 25
Posts: 90
|
Disable arithmetic overflow exceptions in your project, or change the code to read something like
Code:
for ( int i = 0; i < info.Length; ++i )
{
ServerInfo si = info[i];
unchecked
{
thisStream.Write( (ushort) i );
thisStream.WriteAsciiFixed( si.Name, 32 );
thisStream.Write( (byte) si.FullPercent );
thisStream.Write( (sbyte) si.TimeZone );
thisStream.Write( (int) Utility.GetAddressValue( si.Address.Address ) );
}
}
|
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|