Broken Code
Broken Code
The latest osi patch broke some code so far ive seen that walking if you stop you get stuck and paperdoll and other gumps wont pop up i dont know if there is an easy fix or not i would look more into it but tommorow the movers are coming and i dont know when ill have internet at the new house so i might be online again for like a month or so
Re: Broken Code
LOL, it's so funny when one byte can creates "holy cries"Link_of_Hyrule hat geschrieben:The latest osi patch broke some code so far ive seen that walking if you stop you get stuck and paperdoll and other gumps wont pop up i dont know if there is an easy fix or not i would look more into it but tommorow the movers are coming and i dont know when ill have internet at the new house so i might be online again for like a month or so

P.S. 6.0.1.7 patch does not break paperdolls, movers and a lot of gumps




well then how do you fix it?
EDIT: ok well i dont know what was up with walking and stuff last night but it seems to work on my dads pc anyways from what i can tell inventory is broken on both client and paperdolls are broken on kr other then that i think everything is fine im sure its an easy fix that we can fix quickly
and the latest patch for 2d says
2D Client vers. 1.45.5.1
Backend compatibility changes
EDIT:
ok well i just logged off and closed the client then logged back in and now nothing works again im guessing there must be a packet the client is getting that it doesnt like that causes it to freeze up i dont have any clue why if someone can packet log it i bet we can figure it out
EDIT: ok well i dont know what was up with walking and stuff last night but it seems to work on my dads pc anyways from what i can tell inventory is broken on both client and paperdolls are broken on kr other then that i think everything is fine im sure its an easy fix that we can fix quickly
and the latest patch for 2d says
2D Client vers. 1.45.5.1
Backend compatibility changes
EDIT:
ok well i just logged off and closed the client then logged back in and now nothing works again im guessing there must be a packet the client is getting that it doesnt like that causes it to freeze up i dont have any clue why if someone can packet log it i bet we can figure it out
And VendorBuyList too. Really, only two server-side packets: 0x3C and 0x25 and one client-side packet 0x08 changed.Sabresite hat geschrieben:For 6.0.1.7 - Have a list of added/modified packets? I know of only a few
Drop Request, Container Content, Update Container Content, and possibly Secure Trade Equip
I do not have an OSI account, so I cannot find out.
It seems that a few packets are sent with 0xFF prepend to them, when I drop an item to world, for example, the object property request 0xD6 is now 0xFF 0xD6 etc. Immediately following the 0xFF packet i have the item's serial being sent in another packet.
I'm wondering if 0xFF actually means a two part packet?
UPDATE: nvm, I'm stupid
I'm wondering if 0xFF actually means a two part packet?
UPDATE: nvm, I'm stupid
Here's my list of modifications (with KR support)
in NetState, declare a boolean property indicating whether the client version is the new client
First change is to the 0x8 packet, as indicated by many sources, there is now an extra one byte added to the packet. That byte is used to tell the server which slot the item was COMING from (not dropping into). The KR slot management is now done on the server side (maybe possible client exploit?), so, here goes:
Now, the problem is with the packet size. This handler has a registered size of 14 bytes (runuo handlers must register it's size, or set to zero for dynamic size packets). Depending on the client version, you want this to have either 14 bytes or 15 bytes, and you can't simply set it to zero because this packet contains no size information...OSI doesn't need to handle this because they will only support the new protocol. If you want to support the old clients also, you must modify MessagePump to "dirty hack" the issue away:
My entire MessagePump::HandleReceive(NetState), with KR seeding support. (I don't use the 0xFF packet for KR seeding, rather, KR sends 0xFFFFFFFF = -1 for the seed, that's enough to tell it's a KR client, much cleaner this way.
You may also notice there may be a few lines different from the 2.0 SVN version, that's because I don't use 2.0, the core was modified from V1.0.
Now, the "0xFF" problem, which is the server thinking it received 0xFF packets sent from the clients after dropping to the ground. That problem is caused by the size mismatch in the 0x08 handler. After dropping to the ground, the client sends 0xFFFFFFFF as the target UID. But since we are missing one byte from the handler (14 vs. 15), it only sees 0xFFFFFF, the next part of the packet is trimmed and prepended to the next packet - which is often the 0xD6 property list require. This is why we always see 0xFF 0xD6 after client drops to the ground.
Now we have this issue straight, the rest is simple:
the 0x25 Packet also have one byte added
The problem with these two packets above, is that they are fixed size packets. You cannot call EnsureCapacity on them, otherwise they become dynamic size and RunUO is confused.
but you can do it with the 0x3c packet
Now, the biggest challenge of all: The login process
Many have reported that their "GM" char cannot login, but their "Player" char can. Well, the problem is not with your GM char, it's because you've probably used the GM char most often, and upon login the client requests to open the backpack automatically. This causes a significant problem, because by the time the server sends the content update packet (0x25), the client version information has not arrived yet. Therefore the server will have no clue if the new packet is to be used.
To get around this problem, you must use another dirty hack: wait until the client version arrives before sending the login packets. I haven't got the time to write this portion up. Right now I simply sends a client version request upon login, and use a timer delay of 1 second on the DoLogin method. This allows everyone with a fast connection to use the new client. But if the client version packet fails to arrive within 1 second, you cannot login to the server (very poorly handled...but the goal is to get everyone to use the new client so I can remove these dirty hacks later).
Hope these helps...
Regards,
PQ
in NetState, declare a boolean property indicating whether the client version is the new client
Code: Alles auswählen
private static ClientVersion PostUOKRClient = new ClientVersion("6.0.1.7");
public bool UseKRPacket
{
get
{
return (m_Version != null && m_Version >= PostUOKRClient) || m_KRClient;
}
}
Code: Alles auswählen
public static void DropReq( NetState state, PacketReader pvSrc )
{
pvSrc.ReadInt32(); // serial, ignored
int x = pvSrc.ReadInt16();
int y = pvSrc.ReadInt16();
int z = pvSrc.ReadSByte();
if (state.UseKRPacket)
{
pvSrc.ReadByte();
}
Serial dest = pvSrc.ReadInt32();
Point3D loc = new Point3D( x, y, z );
Mobile from = state.Mobile;
if ( dest.IsMobile )
from.Drop( World.FindMobile( dest ), loc );
else if ( dest.IsItem )
from.Drop( World.FindItem( dest ), loc );
else
from.Drop( loc );
}
My entire MessagePump::HandleReceive(NetState), with KR seeding support. (I don't use the 0xFF packet for KR seeding, rather, KR sends 0xFFFFFFFF = -1 for the seed, that's enough to tell it's a KR client, much cleaner this way.
You may also notice there may be a few lines different from the 2.0 SVN version, that's because I don't use 2.0, the core was modified from V1.0.
Code: Alles auswählen
public bool HandleReceive( NetState ns )
{
ByteQueue buffer = ns.Buffer;
if (buffer == null || buffer.Length <= 0)
return true;
lock (buffer)
{
int length = buffer.Length;
if (!ns.Seeded)
{
if (buffer.Length >= 4)
{
buffer.Dequeue(m_Peek, 0, 4);
int seed = (m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3];
if (seed == 0)
{
Console.WriteLine("Login: {0}: Invalid client detected, disconnecting", ns);
ns.Dispose();
return false;
}
else if (seed == -1)
{
Console.WriteLine("Login: {0} is KR Client", ns);
ns.Send(new KRVerifier());
ns.IsKRClient = true;
}
ns.m_Seed = seed;
ns.Seeded = true;
length = buffer.Length;
}
else
{
return true;
}
}
//Console.WriteLine( "{" );
while ( length > 0 && ns.Running )
{
int packetID = buffer.GetPacketID();
if (!ns.SentFirstPacket && packetID != 0xF1 && packetID != 0xCF && packetID != 0x80 && packetID != 0x91 && packetID != 0xA4 && packetID!=0xE4)
{
Console.WriteLine( "Client: {0}: Encrypted client detected, disconnecting", ns );
ns.Dispose();
break;
}
PacketHandler handler = PacketHandlers.GetHandler( packetID );
if ( handler == null )
{
byte[] data = new byte[length];
length = buffer.Dequeue( data, 0, length );
new PacketReader( data, length, false ).Trace( ns );
break;
}
int packetLength = handler.Length;
// TODO: remove this dirty hack later for full 6.0.1.7 support
if (packetID == 0x8)
{
if (ns.UseKRPacket)
packetLength = 15;
else
packetLength = 14;
}
if ( packetLength <= 0 )
{
if ( length >= 3 )
{
packetLength = buffer.GetPacketLength();
if ( packetLength < 3 )
{
ns.Dispose();
break;
}
}
else
{
break;
}
}
if ( length >= packetLength )
{
if ( handler.Ingame && ns.Mobile == null )
{
Console.WriteLine( "Client: {0}: Sent ingame packet (0x{1:X2}) before having been attached to a mobile", ns, packetID );
ns.Dispose();
break;
}
else if ( handler.Ingame && ns.Mobile.Deleted )
{
ns.Dispose();
break;
}
else
{
ThrottlePacketCallback throttler = handler.ThrottleCallback;
if ( throttler != null && !throttler( ns ) )
{
m_Throttled.Enqueue( ns );
//Console.WriteLine( "}" );
return false;
}
//Console.WriteLine( handler.OnReceive.Method.Name );
PacketProfile profile = PacketProfile.GetIncomingProfile( packetID );
DateTime start = ( profile == null ? DateTime.MinValue : DateTime.Now );
byte[] packetBuffer;
if ( BufferSize >= packetLength )
packetBuffer = m_Buffers.AquireBuffer();
else
packetBuffer = new byte[packetLength];
packetLength = buffer.Dequeue( packetBuffer, 0, packetLength );
PacketReader r = new PacketReader( packetBuffer, packetLength, handler.Length != 0 );
handler.OnReceive( ns, r );
length = buffer.Length;
if ( BufferSize >= packetLength )
m_Buffers.ReleaseBuffer( packetBuffer );
if ( profile != null )
profile.Record( packetLength, DateTime.Now - start );
//Console.WriteLine( "Client: {0}: Unhandled packet 0x{1:X2}", ns, packetID );
//Utility.FormatBuffer( Console.Out, new System.IO.MemoryStream( r.Buffer ), r.Buffer.Length );
}
}
else
{
break;
}
}
//Console.WriteLine( "}" );
}
return true;
}
Now we have this issue straight, the rest is simple:
the 0x25 Packet also have one byte added
Code: Alles auswählen
public sealed class ContainerContentUpdate : Packet
{
public ContainerContentUpdate(Item item, bool uokr)
: base(0x25, uokr ? 21 : 20)
{
Serial parentSerial;
if ( item.Parent is Item )
{
parentSerial = ((Item)item.Parent).Serial;
}
else
{
Console.WriteLine( "Warning: ContainerContentUpdate on item with !(parent is Item)" );
parentSerial = Serial.Zero;
}
ushort cid = (ushort) item.ItemID;
if ( cid > 0x3FFF )
cid = 0x9D7;
m_Stream.Write( (int) item.Serial ); // 4
m_Stream.Write( (short) cid ); // 6
m_Stream.Write( (byte) 0 ); // 7 signed, itemID offset
m_Stream.Write( (ushort) item.Amount ); // 9
m_Stream.Write( (short) item.X ); // 11
m_Stream.Write((short)item.Y); // 13
if (uokr)
m_Stream.Write((byte)item.GridLocation); // 14 / 13 container grid location for UOKR client
m_Stream.Write( (int) parentSerial ); // 18 / 17
m_Stream.Write( (ushort) item.Hue ); // 20 / 19
}
}
Code: Alles auswählen
public sealed class SecureTradeEquip : Packet
{
public SecureTradeEquip( Item item, Mobile m, bool uokr ) : base( 0x25, uokr? 21:20 )
{
m_Stream.Write( (int) item.Serial );
m_Stream.Write( (short) item.ItemID );
m_Stream.Write( (byte) 0 );
m_Stream.Write( (short) item.Amount );
m_Stream.Write( (short) item.X );
m_Stream.Write((short)item.Y);
if (uokr)
m_Stream.Write((byte)item.GridLocation);
m_Stream.Write( (int) m.Serial );
m_Stream.Write( (short) item.Hue );
}
}
but you can do it with the 0x3c packet
Code: Alles auswählen
public sealed class ContainerContent : Packet
{
public ContainerContent( Mobile beholder, Item beheld, bool uokr ) : base( 0x3C )
{
ArrayList items = beheld.Items;
int count = items.Count;
this.EnsureCapacity(5 + (count * (uokr ? 20 : 19)));
long pos = m_Stream.Position;
int written = 0;
m_Stream.Write( (ushort) 0 );
for ( int i = 0; i < count; ++i )
{
Item child = (Item)items[i];
if ( !child.Deleted && beholder.CanSee( child ) )
{
Point3D loc = child.Location;
ushort cid = (ushort) child.ItemID;
if ( cid > 0x3FFF )
cid = 0x9D7;
m_Stream.Write( (int) child.Serial );
m_Stream.Write( (ushort) cid );
m_Stream.Write( (byte) 0 ); // signed, itemID offset
m_Stream.Write( (ushort) child.Amount );
m_Stream.Write( (short) loc.m_X );
m_Stream.Write((short)loc.m_Y);
if (uokr)
m_Stream.Write((byte)child.GridLocation);
m_Stream.Write( (int) beheld.Serial );
m_Stream.Write( (ushort) child.Hue );
++written;
}
}
m_Stream.Seek( pos, SeekOrigin.Begin );
m_Stream.Write( (ushort) written );
}
}
Code: Alles auswählen
public sealed class VendorBuyContent : Packet
{
public VendorBuyContent( ArrayList list , bool uokr ) : base( 0x3c )
{
this.EnsureCapacity(list.Count * (uokr ? 20 : 19) + 5);
m_Stream.Write( (short)list.Count );
//The client sorts these by their X/Y value.
//OSI sends these in wierd order. X/Y highest to lowest and serial loest to highest
//These are already sorted by serial (done by the vendor class) but we have to send them by x/y
//(the x74 packet is sent in 'correct' order.)
for ( int i = list.Count - 1; i >= 0; --i )
{
BuyItemState bis = (BuyItemState)list[i];
m_Stream.Write( (int)bis.MySerial );
m_Stream.Write( (ushort)(bis.ItemID & 0x3FFF) );
m_Stream.Write( (byte)0 );//itemid offset
m_Stream.Write( (ushort)bis.Amount );
m_Stream.Write( (short)(i+1) );//x
m_Stream.Write((short)1);//y
if ( uokr )
m_Stream.Write((byte)0); //grid location
m_Stream.Write( (int)bis.ContainerSerial );
m_Stream.Write( (ushort)bis.Hue );
}
}
}
Many have reported that their "GM" char cannot login, but their "Player" char can. Well, the problem is not with your GM char, it's because you've probably used the GM char most often, and upon login the client requests to open the backpack automatically. This causes a significant problem, because by the time the server sends the content update packet (0x25), the client version information has not arrived yet. Therefore the server will have no clue if the new packet is to be used.
To get around this problem, you must use another dirty hack: wait until the client version arrives before sending the login packets. I haven't got the time to write this portion up. Right now I simply sends a client version request upon login, and use a timer delay of 1 second on the DoLogin method. This allows everyone with a fast connection to use the new client. But if the client version packet fails to arrive within 1 second, you cannot login to the server (very poorly handled...but the goal is to get everyone to use the new client so I can remove these dirty hacks later).
Hope these helps...
Regards,
PQ
The exact reason for "no paperdoll", etc., is this:
upon login, client sends 0x5D packet, at this time, RunUO trys to connect the NetState object with the Mobile.
The problem occurs when the Mobile object gets moved out of the internal map, since a map update automatically puts all items on the mobile (and everything in range) to the Delta queue. The next core tick will result in a contentupdate sent to the netstate - at this time the client version information hasn't arrived yet, even the DoLogin() might not gets called if you are using a multicore processor.
The solution to this problem is to hold off setting the netstate object of the mobile until a client version has been received. This requires the server actively sending out a client version request and put everything into a timer delay loop, checking back on regular interval to see if client has replied. This also requires setting the 0xBD packet's "in game" property to false, and modify it's handler to accept null Mobile cases.
(Note that the BuffIcon support resets the 0xBD handler, you might want to modify that as well).
In the end, you want to achieve something like this:
23:56:10.5468 is where the problem starts
AFTER:
upon login, client sends 0x5D packet, at this time, RunUO trys to connect the NetState object with the Mobile.
The problem occurs when the Mobile object gets moved out of the internal map, since a map update automatically puts all items on the mobile (and everything in range) to the Delta queue. The next core tick will result in a contentupdate sent to the netstate - at this time the client version information hasn't arrived yet, even the DoLogin() might not gets called if you are using a multicore processor.
The solution to this problem is to hold off setting the netstate object of the mobile until a client version has been received. This requires the server actively sending out a client version request and put everything into a timer delay loop, checking back on regular interval to see if client has replied. This also requires setting the 0xBD packet's "in game" property to false, and modify it's handler to accept null Mobile cases.
(Note that the BuffIcon support resets the 0xBD handler, you might want to modify that as well).
In the end, you want to achieve something like this:
Code: Alles auswählen
BEFORE:
23:56:09.9687: Client -> Server 0x5D (Length: 73)
0 1 2 3 4 5 6 7 8 9 A B C D E F
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0000 5D ED ED ED ED ...
23:56:10.5312: Server -> Client 0x1B (Length: 37)
0 1 2 3 4 5 6 7 8 9 A B C D E F
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0000 1B 00 00 00 3A ....
23:56:10.5468: Server -> Client 0x25 (Length: 21)
0 1 2 3 4 5 6 7 8 9 A B C D E F
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0000 25 40 01 12 21 0E F0 00
23:56:10.5468: Server -> Client 0x40 (Length: 201)
0 1 2 3 4 5 6 7 8 9 A B C D E F
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0000 40 01 12 21 41 5C 27 24 ...
AFTER:
Code: Alles auswählen
00:37:19.6562: Client -> Server 0x5D (Length: 73)
0 1 2 3 4 5 6 7 8 9 A B C D E F
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0000 5D ED ED ED ED ....
00:37:19.6562: Server -> Client 0xBD (Length: 3)
0 1 2 3 4 5 6 7 8 9 A B C D E F
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0000 BD 00 03 ...
00:37:19.6562: Client -> Server 0xBD (Length: 11)
0 1 2 3 4 5 6 7 8 9 A B C D E F
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
0000 BD 00 0B 36 2E 30 2E 31 2E 37 00 ...6.0.1.7.