[Help]With this ShopFlag packet

07/07/2009 07:03 hunterman01#1
This is Not the WHOLE code but a little of what i have so far

*Credits to Kinshi*
Code:
public byte[] Senditem_vend(uint Item_Vend, byte Type)
        {
            ushort PacketType = 0x454;
            byte[] Packet = new byte[12];

            fixed (byte* p = Packet)
            {
                item_vend =>
                [item_id => uint32(),
                shop_id => uint32(),
                price => uint32(),
                item_type_id => uint32(),
                max_dura => uint16(),
                remaining_dura => uint16(),

I am not sure if i am doing this wrong but a little help would be appreciated
07/07/2009 08:39 CptSky#2
Quote:
Originally Posted by hunterman01 View Post
This is Not the WHOLE code but a little of what i have so far

*Credits to Kinshi*
Code:
public byte[] Senditem_vend(uint Item_Vend, byte Type)
        {
            ushort PacketType = 0x454;
            byte[] Packet = new byte[12];

            fixed (byte* p = Packet)
            {
                item_vend =>
                [item_id => uint32(),
                shop_id => uint32(),
                price => uint32(),
                item_type_id => uint32(),
                max_dura => uint16(),
                remaining_dura => uint16(),

I am not sure if i am doing this wrong but a little help would be appreciated
First your Length is false...
The structure look like this:
Code:
Packet_Length -> UInt16
Packet_Type -> UInt16
Item_UID -> UInt32
Shop_Id -> UInt32 or UInt16, I don't know
Item_Price -> UInt32
Item_Id -> UInt32
Item_CurDura -> UInt16
Item_MaxDura -> UInt16
Packet_Subtype -> Byte, for CPs or Money
07/07/2009 08:59 kinshi88#3
Wow man.
Look at how other packets are done, its not hard lol.

What I gave you was just the structure of it, you can't just C+P it in...
07/07/2009 15:12 hunterman01#4
Its not that i copied and pasted it just what you gave me looks NOTHING like the other packets thats why im having a little bit of trouble
07/07/2009 17:04 unknownone#5
What Kinshi gave you are packet definitions. They say what goes where in a packet in terms of their size and type. They aren't meant to be used directly, that should be obvious from the non-C# syntax. These definitions actually use PERL's associative array syntax, and are meant to be scripted to create your packet in C#.

The length and type are purposely omitted. They're the same in every packet. It's idiotic design to write them new every time. (And also, because the PERL script automates that for you anyway.)
07/07/2009 18:21 hunterman01#6
Thanks now i just gotta try and figure out how to do this
07/07/2009 20:03 unknownone#7
I thrown together the script I used in about 30 minutes when I needed it. It was just meant to save me time creating headers and code files for identical code structures for every packet. (In C++).

You'll need to modify most of the script to make it work with C#

Code:
use strict;
my $base_message_name;
my $namespace_name;
sub message_environment
{
    my $namespace = shift;
    my $base_message = shift;
    $namespace_name = $namespace;
    $base_message_name = $base_message;
};
sub enum {
    my $udt = shift;
    my $tcast = shift;
    return { 'udt' => "$udt", 'tcast' => $tcast, 'size_type' => 0 };
}
sub int8 {
    return { 'cpptype' => "int8_t", 'cstype' => "sbyte", 'size_type' => 1 }; 
}
sub int16 {
    return { 'cpptype' => "int16_t", 'cstype' => "short", 'size_type' => 2 }; 
}
sub int32 {
    return { 'cpptype' => "int32_t", 'cstype' => "long", 'size_type' => 4 }; 
}
sub uint8  {
    return { 'cpptype' => "uint8_t", 'cstype' => "byte", 'size_type' => 1 }; 
}
sub uint16 {
    return { 'cpptype' => "uint16_t", 'cstype' => "ushort", 'size_type' => 2 }; 
}
sub uint32 {
    return { 'cpptype' => "uint32_t", 'cstype' => "ulong", 'size_type' => 4 }; 
}
sub string {
    return { 'cpptype' => "std::string", 'cstype' => "string", 'size_type' => 4 }; 
}
sub string_list {
    return { 'cpptype' => "std::vector<std::string> ", 'cstype' => "list<string>", 'size_type' => 3 }; 
}
sub fixed_string {
    my $string_length = shift;
    return { 'cpptype' => "std::string", 'cstype' => "string", 'str_len' => "$string_length", 'size_type' => 0 }; 
}
sub define_message
{
    my $message_name = shift;
    my $message_properties = shift;
    my $message_id = shift;
    my $message_default_length = shift;
    
    my $ptype;
    my $cpptype;
    my $str_len;
    my $fld;
    my $size_type;
    my $current_pos=0;
    my $tcast;
    my $casttype;
    my $name_upper = "msg_$message_name";
    $name_upper =~ tr/a-z/A-Z/;
    
    open HEADER, ">packets/msg_$message_name.hpp" or die "unable to open header file\n";
    open SOURCE, ">packets/msg_$message_name.cpp" or die "unable to open source file\n";
    
    print HEADER "#ifndef msg_$message_name\_hpp\n";
    print HEADER "#define msg_$message_name\_hpp\n";
    print HEADER "\n";
    print HEADER "#include \"$base_message_name.hpp\"\n";
    print HEADER "\n";
    print HEADER "namespace $namespace_name\n";
    print HEADER "{\n";
    print HEADER "    class msg_$message_name : public $base_message_name\n";
    print HEADER "    {\n";
    print HEADER "        public:\n";
    print HEADER "            msg_$message_name();\n";
    print HEADER "            virtual ~msg_$message_name();\n";

    print SOURCE "#include \"msg_$message_name.hpp\"\n";
    print SOURCE "\n";
    print SOURCE "namespace $namespace_name\n";
    print SOURCE "{\n";
    print SOURCE "    msg_$message_name\::msg_$message_name()\n";
    print SOURCE "        :    $base_message_name(id_msg_$message_name, msg_$message_name\_default_size)\n";
    print SOURCE "    {\n";
    print SOURCE "\n";
    print SOURCE "    }\n";
    print SOURCE "\n";
    print SOURCE "    msg_$message_name\::~msg_$message_name() {}\n";
    print SOURCE "\n";
    
    $current_pos = 4;
    my @copy = @$message_properties;
    
    while ($fld = shift @copy) {
        $ptype = shift @copy;
        $cpptype = $ptype->{'cpptype'};
        $size_type = $ptype->{'size_type'};
        $tcast="";
        $str_len = 0;
        if (exists $ptype->{'str_len'}) {
            $str_len = $ptype->{'str_len'};
        }
        
        if (exists $ptype->{'tcast'}) {
            $tcast = $ptype->{'tcast'};
            $casttype = $tcast->{'cpptype'};
            $size_type = $tcast->{'size_type'};
            $cpptype = $ptype->{'udt'};
        }

        print HEADER "\n";
        print HEADER "            $cpptype $fld(void);\n";
        print HEADER "            void $fld($cpptype);\n";
        
        print SOURCE "\n";
        print SOURCE "    $cpptype msg_$message_name\::$fld(void)\n";
        print SOURCE "    {\n";
        if ($str_len==0) {
            if ($tcast) {
                print SOURCE "        return ($cpptype)read<$casttype>($current_pos);\n";
            }else {
                print SOURCE "        return read<$cpptype>($current_pos);\n";
            }
        } else {
            print SOURCE "        return read<$cpptype>($current_pos, $str_len);\n";
        }
        print SOURCE "    }\n";
        print SOURCE "\n";
        print SOURCE "    void msg_$message_name\::$fld($cpptype value)\n";
        print SOURCE "    {\n";
        if ($str_len==0) {
                if ($tcast) {
                print SOURCE "        write<$casttype>($current_pos, ($casttype)value);\n";
            }else {
                print SOURCE "        write<$cpptype>($current_pos, value);\n";
            }
        } else {
            print SOURCE "        write<$cpptype>($current_pos, value, $str_len);\n";
        }
        print SOURCE "    }\n";
        
        $current_pos = $current_pos + $size_type + $str_len;
    }

    print HEADER "    };\n";
    print HEADER "\n";
    print HEADER "    const int id_msg_$message_name = $message_id;\n";
    print HEADER "\n";
    print HEADER "    const int msg_$message_name\_default_size = $current_pos;\n";
    print HEADER "}\n";
    print HEADER "\n";
    print HEADER "#endif // msg_$message_name\_hpp";
    print HEADER "\n";
    
    print SOURCE "}\n";
    close HEADER;
    close SOURCE;
}
Given the example you're using. You wrap the definition as an argument to the define_message function, and it generates a header and code file containing this.

Code:
#example 
#note: blacknull is my namespace
#        base_message is the base class which contains the read<> and write<> templates.
#message_environment only needs calling once each time the script is run, but you can define multiple messages in the same run.

message_environment ( "blacknull", "base_message" );

define_message (
    item_vend => [
        item_id => uint32(),
        shop_id => uint32(),
        price => uint32(),
        item_type_id => uint32(),
        max_dura => uint16(),
        remaining_dura => uint16(),
        item_info_mode => enum("ITEM_INFO_MODE", uint16()),
        equipment_slot => enum("EQUIPMENT_SLOT", uint16()),
        socket_1 => uint8(),
        socket_2 => uint8(),
        reborn_effect => uint16(),
        composition => uint8(),
        enchant => uint8(),
        bless => uint8(),
        padding1 => uint16(),
        padding2 => uint32(),
    ], 0x454
);

Code:
/* msg_item_vend.hpp */
#ifndef msg_item_vend_hpp
#define msg_item_vend_hpp

#include "base_message.hpp"

namespace blacknull
{
    class msg_item_vend : public base_message
    {
        public:
            msg_item_vend();
            virtual ~msg_item_vend();

            uint32_t item_id(void);
            void item_id(uint32_t);

            uint32_t shop_id(void);
            void shop_id(uint32_t);

            uint32_t price(void);
            void price(uint32_t);

            uint32_t item_type_id(void);
            void item_type_id(uint32_t);

            uint16_t max_dura(void);
            void max_dura(uint16_t);

            uint16_t remaining_dura(void);
            void remaining_dura(uint16_t);

            ITEM_INFO_MODE item_info_mode(void);
            void item_info_mode(ITEM_INFO_MODE);

            EQUIPMENT_SLOT equipment_slot(void);
            void equipment_slot(EQUIPMENT_SLOT);

            uint8_t socket_1(void);
            void socket_1(uint8_t);

            uint8_t socket_2(void);
            void socket_2(uint8_t);

            uint16_t reborn_effect(void);
            void reborn_effect(uint16_t);

            uint8_t composition(void);
            void composition(uint8_t);

            uint8_t enchant(void);
            void enchant(uint8_t);

            uint8_t bless(void);
            void bless(uint8_t);

            uint16_t padding1(void);
            void padding1(uint16_t);

            uint32_t padding2(void);
            void padding2(uint32_t);
    };

    const int id_msg_item_vend = 1108;

    const int msg_item_vend_default_size = 41;
}

#endif // msg_item_vend_hpp
Code:
/* msg_item_vend.cpp */
#include "msg_item_vend.hpp"

namespace blacknull
{
    msg_item_vend::msg_item_vend()
        :    base_message(id_msg_item_vend, msg_item_vend_default_size)
    {

    }

    msg_item_vend::~msg_item_vend() {}


    uint32_t msg_item_vend::item_id(void)
    {
        return read<uint32_t>(4);
    }

    void msg_item_vend::item_id(uint32_t value)
    {
        write<uint32_t>(4, value);
    }

    uint32_t msg_item_vend::shop_id(void)
    {
        return read<uint32_t>(8);
    }

    void msg_item_vend::shop_id(uint32_t value)
    {
        write<uint32_t>(8, value);
    }

    uint32_t msg_item_vend::price(void)
    {
        return read<uint32_t>(12);
    }

    void msg_item_vend::price(uint32_t value)
    {
        write<uint32_t>(12, value);
    }

    uint32_t msg_item_vend::item_type_id(void)
    {
        return read<uint32_t>(16);
    }

    void msg_item_vend::item_type_id(uint32_t value)
    {
        write<uint32_t>(16, value);
    }

    uint16_t msg_item_vend::max_dura(void)
    {
        return read<uint16_t>(20);
    }

    void msg_item_vend::max_dura(uint16_t value)
    {
        write<uint16_t>(20, value);
    }

    uint16_t msg_item_vend::remaining_dura(void)
    {
        return read<uint16_t>(22);
    }

    void msg_item_vend::remaining_dura(uint16_t value)
    {
        write<uint16_t>(22, value);
    }

    ITEM_INFO_MODE msg_item_vend::item_info_mode(void)
    {
        return (ITEM_INFO_MODE)read<uint16_t>(24);
    }

    void msg_item_vend::item_info_mode(ITEM_INFO_MODE value)
    {
        write<uint16_t>(24, (uint16_t)value);
    }

    EQUIPMENT_SLOT msg_item_vend::equipment_slot(void)
    {
        return (EQUIPMENT_SLOT)read<uint16_t>(26);
    }

    void msg_item_vend::equipment_slot(EQUIPMENT_SLOT value)
    {
        write<uint16_t>(26, (uint16_t)value);
    }

    uint8_t msg_item_vend::socket_1(void)
    {
        return read<uint8_t>(28);
    }

    void msg_item_vend::socket_1(uint8_t value)
    {
        write<uint8_t>(28, value);
    }

    uint8_t msg_item_vend::socket_2(void)
    {
        return read<uint8_t>(29);
    }

    void msg_item_vend::socket_2(uint8_t value)
    {
        write<uint8_t>(29, value);
    }

    uint16_t msg_item_vend::reborn_effect(void)
    {
        return read<uint16_t>(30);
    }

    void msg_item_vend::reborn_effect(uint16_t value)
    {
        write<uint16_t>(30, value);
    }

    uint8_t msg_item_vend::composition(void)
    {
        return read<uint8_t>(32);
    }

    void msg_item_vend::composition(uint8_t value)
    {
        write<uint8_t>(32, value);
    }

    uint8_t msg_item_vend::enchant(void)
    {
        return read<uint8_t>(33);
    }

    void msg_item_vend::enchant(uint8_t value)
    {
        write<uint8_t>(33, value);
    }

    uint8_t msg_item_vend::bless(void)
    {
        return read<uint8_t>(34);
    }

    void msg_item_vend::bless(uint8_t value)
    {
        write<uint8_t>(34, value);
    }

    uint16_t msg_item_vend::padding1(void)
    {
        return read<uint16_t>(35);
    }

    void msg_item_vend::padding1(uint16_t value)
    {
        write<uint16_t>(35, value);
    }

    uint32_t msg_item_vend::padding2(void)
    {
        return read<uint32_t>(37);
    }

    void msg_item_vend::padding2(uint32_t value)
    {
        write<uint32_t>(37, value);
    }
}
The code here just points each part of the code to a place in the packet. The base class handles all the reading and writing.
07/07/2009 20:10 hunterman01#8
Thanks I appreciate it
07/07/2009 20:27 unknownone#9
Hmm, since I posted that, may as well give you this. It's an alternative syntax I wrote for Emme to generate the packets on his server. Also, builds straight to C#.
This time it uses the F# language rather than PERL. (You can download it from microsoft research).

Code:
module PacketGenerator
open System.IO

type PacketFieldType =
    | Byte of string * int
    | SByte of string * int
    | UInt16 of string * int
    | Int16 of string * int
    | UInt32 of string * int
    | Int32 of string * int
    | Int64 of string * int
    | UInt64 of string * int
    | String of string * int
    | FixedString of string * int * int
    | StringList of string * int
    
let genfield fieldtype name pos = "\n\t\tpublic " + fieldtype + " " + name + "\n\t\t{\n\t\t\tget { return base.Read" + fieldtype + "(" + pos.ToString() + "); }\n\t\t\tset { base.Write" + fieldtype + "(" + pos.ToString() + ", value); }\n\t\t}"                                                                            

let field field = 
    match field with
    | Byte(name, pos) -> genfield "Byte" name pos
    | SByte(name, pos) -> genfield "SByte" name pos
    | Int32(name, pos) -> genfield "Int32" name pos
    | UInt32(name, pos) -> genfield "UInt32" name pos
    | Int16(name, pos) -> genfield "Int16" name pos
    | UInt16(name, pos) -> genfield "UInt16" name pos
    | Int64(name, pos) -> genfield "Int64" name pos
    | UInt64(name, pos) -> genfield "UInt64" name pos
    | String(name, pos) -> genfield "String" name pos
    | FixedString(name, pos, len) -> "\n\t\tpublic String " + name + "\n\t\t{\n\t\t\tget { return base.ReadFixedString(" + pos.ToString() + ", " + len.ToString() + "); }\n\t\t\tset { base.WriteFixedString(value, " + pos.ToString() + ", " + len.ToString() + "); }\n\t\t}"  
    | StringList(name, pos) -> "\n\t\tpublic List<String> " + name + "\n\t\t{\n\t\t\tget { return base.ReadStringList(" + pos.ToString() + "); }\n\t\t\tset { base.WriteStringList(value, " + pos.ToString() + "); }\n\t\t}"

let genpacket name version packet =
    let f = File.CreateText(name.ToString() + ".cs")
    f.Write("using System;\nusing System.Text;\n\nnamespace Blacknull.Network.Protocol.Packets.Conquer.v" + version.ToString() + "\n{\n\tpublic class " + name + " : BasePacket\n\t{\n\t\tpublic " + name + "()\n\t\t\t: base (PacketType." + name + ")\n\t\t{\n\t\t}")
    List.iter (fun x->f.Write("\n" + field x)) packet
    f.Write("\n\t}\n}")
    f.Close()
Example use:
Code:
#load "PacketGenerator.fs"
open PacketGenerator

genpacket "CreateCharacterPacket" 5105 [
    FixedString("Username", 4, 16)
    FixedString("Heroname", 20, 16)
    FixedString("Password", 36, 16)
    Int16("Mesh", 52)
    Int16("Profession", 54)
    Int32("AccountID", 56)
    ]
Generates the output:
Code:
using System;
using System.Text;

namespace Blacknull.Network.Protocol.Packets.Conquer.v5105
{
	public class CreateCharacterPacket : BasePacket
	{
		public CreateCharacterPacket()
	    	: base (PacketType.CreateCharacterPacket)
		{
		}

		public String Username
		{
			get { return base.ReadFixedString(4, 16); }
			set { base.WriteFixedString(value, 4, 16); }
		}

		public String Heroname
		{
			get { return base.ReadFixedString(20, 16); }
			set { base.WriteFixedString(value, 20, 16); }
		}

		public String Password
		{
			get { return base.ReadFixedString(36, 16); }
			set { base.WriteFixedString(value, 36, 16); }
		}

		public Int16 Mesh
		{
			get { return base.ReadInt16(52); }
			set { base.WriteInt16(52, value); }
		}

		public Int16 Profession
		{
			get { return base.ReadInt16(54); }
			set { base.WriteInt16(54, value); }
		}

		public Int32 AccountID
		{
			get { return base.ReadInt32(56); }
			set { base.WriteInt32(56, value); }
		}
	}
}
07/08/2009 03:08 hunterman01#10
God dude how do you know all these other languages ~.0

Btw thanks