Sign in to follow this  
Iderik

How do I communicate between server and client?

Recommended Posts

Hello, maybe my topic title wasn't that good, but I did my best. The question is how I should communicate between the server and the client, in what way? I mean if I should send the x and y position, I know I shouldn't send it with a string. Then what should I use? Vectors? Bytes?!+ Protocol thingy?1 (As you see I'm really new to this!) I'm coding in C# with Lidgren network library. So if you know some Lidgren, please give me some code example. Or atleast explain to me how this is working. Here is a protocol for open tibia:
void GameProtocol::reciveLoop()
{
    do {
        unsigned char oldopt;
        while(!(m_netMsg->end()))
        {
            unsigned char opt = m_netMsg->GetByte();
            switch(opt)
            {
                case 0x0A: //player id
                    m_pPlayer->setUID(m_netMsg->GetU32());
                    m_netMsg->SkipBytes(3);
                    break;
                    
                case 0x0B: //access opts
                    m_netMsg->SkipBytes(32);
                    break;
                    
                case 0x1E: //ping
                    break;
                    
                case 0x64: //map description
                { 
		          m_pPlayer->pos = m_netMsg->GetPosition(); 
				  setMapDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, m_pPlayer->pos.z, 18, 14);  
                }                          
                break;
                
                case 0xBE: //floor change up
                {
		          m_pPlayer->pos.z -= 1;
				  int skip = 0;
                  //going to surface
	              if(m_pPlayer->pos.z == 7) 
				  {
		             //floor 7 and 6 already set
		             setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, 5, 18, 14, 3, &skip);
		             setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, 4, 18, 14, 4, &skip);
		             setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, 3, 18, 14, 5, &skip);
		             setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, 2, 18, 14, 6, &skip);
		             setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, 1, 18, 14, 7, &skip);
		             setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, 0, 18, 14, 8, &skip);
	              }
	              //underground, going one floor up (still underground)
	              else if(m_pPlayer->pos.z > 7) 
				  {
		            setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, m_pPlayer->pos.z - 2, 18, 14, 3, &skip);
 	              }

	              m_pPlayer->pos.x += 1;
	              m_pPlayer->pos.y += 1;
               
                }     
                break;
                
                case 0xBF: //floor change down
                { 
	              m_pPlayer->pos.z += 1;
				  int skip = 0;
	              //going from surface to underground
	              if(m_pPlayer->pos.z == 8) 
				  {
                   setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, m_pPlayer->pos.z, 18, 14, -1, &skip);
                   setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, m_pPlayer->pos.z + 1, 18, 14, -2, &skip);
                   setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, m_pPlayer->pos.z + 2, 18, 14, -3, &skip);
	               }
	               //going further down
	               else if(m_pPlayer->pos.z > 8 && m_pPlayer->pos.z < 14) 
				   {
                   setFloorDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, m_pPlayer->pos.z + 2, 18, 14, -3, &skip);
	               }

	               m_pPlayer->pos.x -= 1;
	               m_pPlayer->pos.y -= 1;
	            }
	            break;

                case 0x65: //move north
                {			
 	               m_pPlayer->pos.y--;
	               setMapDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, m_pPlayer->pos.z, 18, 1); 
                }
                break;

                case 0x66: //move east
                {				
 	               m_pPlayer->pos.x++;
	               setMapDescription(m_pPlayer->pos.x + 9, m_pPlayer->pos.y - 6, m_pPlayer->pos.z, 1, 14);
                }
                break;

                case 0x67: //move south
                {				
 	               m_pPlayer->pos.y++;
	               setMapDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y + 7, m_pPlayer->pos.z, 18, 1);
	            }
 			    break;

                case 0x68: //move west
                {			
   		           m_pPlayer->pos.x--;
	               setMapDescription(m_pPlayer->pos.x - 8, m_pPlayer->pos.y - 6, m_pPlayer->pos.z, 1, 14);
	            }
 			    break;
 			    
                case 0x69: //tile update
	            {
                   Position pos = m_netMsg->GetPosition(); 
                   setTileDescription(pos);
	            }
 			    break;

                case 0x6A: //thing appear
	            {          
		           Position pos = m_netMsg->GetPosition();
                   Thing* thing = internalGetThing();
				   if(!thing) break;
				   Tile* tile = m_pMap->getTile(pos);

                   tile->addThing(thing); 
	            }
 			    break;

                case 0x6B: //thing transform
	            {
                   m_netMsg->SkipBytes(6);
				   unsigned short id = m_netMsg->GetU16();
				   if(id < 0x64)
                      m_netMsg->SkipBytes(5);    

	            }
 			    break;

	            case 0x6C: //thing disappear

                   m_netMsg->SkipBytes(6); 
				   break;

                case 0x6D: //thing move

                   m_netMsg->SkipBytes(11); 
				   break;

                case 0x6E: //open container
                {
                        m_netMsg->SkipBytes(3);
                        m_netMsg->SkipBytes(m_netMsg->GetU16());
                        m_netMsg->SkipBytes(2);
                        int count = m_netMsg->GetByte();
                        for(int x = 0; x != count; x++)
                        {
                            unsigned short id = m_netMsg->GetU16();
                            if(ItemsSprites::getInstance()->getItemType(id)->stackable ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_SPLASH ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_FLUID)
                                m_netMsg->SkipBytes(1);
                        }
	            }
 			    break;

                case 0x6F: //close container

                    m_netMsg->SkipBytes(1);
                    break;

                case 0x70: //add item into container
                {
                    
                        m_netMsg->SkipBytes(1);
                        unsigned short id = m_netMsg->GetU16();
                        if(ItemsSprites::getInstance()->getItemType(id)->stackable ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_SPLASH ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_FLUID)
                            m_netMsg->SkipBytes(1);
	            }
 			    break;

                case 0x71: //transform item in container
                {
                        m_netMsg->SkipBytes(2);
                        unsigned short id = m_netMsg->GetU16();
                        if(ItemsSprites::getInstance()->getItemType(id)->stackable ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_SPLASH ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_FLUID)
                            m_netMsg->SkipBytes(1);
	            }
 			    break;

                case 0x72: //remove item from container

                    m_netMsg->SkipBytes(2);
                    break;

                case 0x78: //add inventory item
                {
                    
                        m_netMsg->SkipBytes(1);
                        unsigned short id = m_netMsg->GetU16();
                        if(ItemsSprites::getInstance()->getItemType(id)->stackable ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_SPLASH ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_FLUID)
                            m_netMsg->SkipBytes(1);
	            }
 			    break;

                case 0x79: //remove inventory item

                    m_netMsg->SkipBytes(1);
                    break;

                case 0x7D: //trade init
                {

                        m_netMsg->SkipBytes(m_netMsg->GetU16());
                        int count = m_netMsg->GetByte();
                        for(int x = 0; x != count; x++)
                        {
                            unsigned short id = m_netMsg->GetU16();
                            if(ItemsSprites::getInstance()->getItemType(id)->stackable ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_SPLASH ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_FLUID)
                                m_netMsg->SkipBytes(1);
                        }
	            }
 			    break;

                case 0x7E: //trade response
                {
                        m_netMsg->SkipBytes(m_netMsg->GetU16());
                        int count = m_netMsg->GetByte();
                        for(int x = 0; x != count; x++)
                        {
                            unsigned short id = m_netMsg->GetU16();
                            if(ItemsSprites::getInstance()->getItemType(id)->stackable ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_SPLASH ||
                                ItemsSprites::getInstance()->getItemType(id)->group == ITEM_GROUP_FLUID)
                                m_netMsg->SkipBytes(1);
                        }
	            }
 			    break;

                case 0x82: //light

                    m_netMsg->SkipBytes(2);
                    break;

                case 0x83: //magic effect

                    m_netMsg->SkipBytes(6);
                    break;

                case 0x84: //animated message

                    m_netMsg->SkipBytes(6);
                    m_netMsg->SkipBytes(m_netMsg->GetU16());
                    break;

                case 0x85: //distance shot

                    m_netMsg->SkipBytes(11);
                    break;

                case 0x86: //creature square

                    m_netMsg->SkipBytes(5);
                    break;

                case 0x8C: //creature health

                    m_netMsg->SkipBytes(5);
                    break;

                case 0x8D: //creature light

                    m_netMsg->SkipBytes(6);
                    break;

                case 0x8E: //creature changed outfit

                   m_netMsg->SkipBytes(9);
				   break;

                case 0x8F: //creature changed speed

                    m_netMsg->SkipBytes(6);
                    break;

                case 0x90: //creature skull update

                    m_netMsg->SkipBytes(5);
                    break;

                case 0x91: //creature shield update

                    m_netMsg->SkipBytes(5);
                    break;

                case 0x96: //text window

                    m_netMsg->SkipBytes(6);
                    m_netMsg->SkipBytes(m_netMsg->GetU16());
                    break;

                case 0xA0: //player statistics
 
                    m_netMsg->SkipBytes(20);
                    break;

                case 0xA1: //player skills

                    m_netMsg->SkipBytes(14);
                    break;

                case 0xA2: //player icons

                    m_netMsg->SkipBytes(1);
                    break;

                case 0xA3: //attack cancel

                    break;

                case 0xAA: //creature said something
                {
                        m_netMsg->SkipBytes(m_netMsg->GetU16());
                        unsigned char tp = m_netMsg->GetByte();
                        switch(tp)
                        {
                            case 0:
                            case 1:
                            case 2:
                            case 3:
                            case 17:
                                m_netMsg->SkipBytes(5);
                                break;
                            case 5:
                                m_netMsg->SkipBytes(2);
                                break;
                        }
                        m_netMsg->SkipBytes(m_netMsg->GetU16());
	            }
 			    break;

                case 0xAB: //channel list
                {
                        unsigned char count = m_netMsg->GetByte();
                        for(int x = 0; x != count; x++)
                        {
                            m_netMsg->SkipBytes(2);
                            m_netMsg->SkipBytes(m_netMsg->GetU16());
                        }
	            }
 			    break;

                case 0xAC: //open channel

                    m_netMsg->SkipBytes(2);
                    m_netMsg->SkipBytes(m_netMsg->GetU16());
                    break;

                case 0xAD: //open private channel
                
                    m_netMsg->SkipBytes(m_netMsg->GetU16());
                    break;

                case 0xB4: //text message

                    m_netMsg->SkipBytes(1);
                    m_netMsg->SkipBytes(m_netMsg->GetU16());
                    break;

                case 0xB5: //cancel walk


                    break;

                case 0xC8: //open outfit window

                    m_netMsg->SkipBytes(7);
                    break;

                case 0xD2: //add vip

                    m_netMsg->SkipBytes(4);
                    m_netMsg->SkipBytes(m_netMsg->GetU16());
                    m_netMsg->SkipBytes(1);
                    break;

                case 0xD3: //vip login

                    m_netMsg->SkipBytes(4);
                    break;

                case 0xD4: //vip logout

                    m_netMsg->SkipBytes(4);
                    break;

                default:
                    printf("Unknown packet header in game protocol 0x%X,previus packet header: 0x%X\n",opt,oldopt);
                    break;
            }
            oldopt = opt;
        }
	} while(m_netMsg->ReadFromSocket(m_sock));
}
void GameProtocol::setMapDescription(int x, int y, int z, int width, int height)
{
	int startz, endz, zstep, skip = 0;

	if(z > 7)
	{
		startz = z - 2;
		endz = std::min(15, z + 2);
		zstep = 1;
	}
	else {
		startz = 7;
		endz = 0;
		zstep = -1;
	}

	int zDescriptionOffset = 0;
	for(int nz = startz; nz != endz + zstep; nz += zstep)
		setFloorDescription(x, y, nz, width, height, z - nz, &skip);
}

void GameProtocol::setFloorDescription(int x, int y, int z, int width, int height, int offset, int* skipTiles)
{
	int cc = 0;
	int optbyte;
	int skip = *skipTiles;
	for (int nx = 0; nx < width; nx++){
		for (int ny = 0; ny < height; ny++) {				
			if(skip == 0){
				optbyte = m_netMsg->InspectU16();
				if(optbyte >= 0xFF00){
					skip = (m_netMsg->GetU16() & 0xFF);
					cc++;
				}
				else{
					//read tile 
					Position pos = Position(x + nx + offset, y + ny + offset, z);
					setTileDescription(pos);
					cc++;

					skip = (m_netMsg->GetU16() & 0xFF);
				}
			}
			else{
				cc++;
				skip--;
			}
		}
	}
	*skipTiles = skip;
}

void GameProtocol::setTileDescription(Position pos)
{
    Tile *tile = new Tile(pos);
    m_pMap->setTile(pos, tile);

	while(true)
	{
		unsigned short id = m_netMsg->InspectU16();
		if(id >= 0xFF00)
			return;
		else {
			Thing* thing = internalGetThing();
			if(thing)
			   tile->addThing(thing);
		} 
	}
}

Thing* GameProtocol::internalGetThing()
{
	unsigned short id = m_netMsg->GetU16();
	if(id == 0x0061 || id == 0x0062)
	{
        Creature* creature = NULL;
		if(id == 0x0062)
		 //creature is known
			creature = KnownCreatures[m_netMsg->GetU32()];
		
		else if(id == 0x0061)
		{//creature is not known
			long remove = m_netMsg->GetU32(); //remove
			creature = new Creature;
			creature->setUID(m_netMsg->GetU32());
			creature->setName(m_netMsg->GetString()); //name
			KnownCreatures[creature->getUID()] = creature; 
		}
		creature->setHealth(m_netMsg->GetU8());
		creature->setDirection(m_netMsg->GetU8());

		creature->setLookType(m_netMsg->GetU8()); //creature->looktype
        unsigned short lookType = m_netMsg->GetU8();
        if(lookType != 0)
		{                               
			creature->setLookHead(m_netMsg->GetU8());
			creature->setLookBody(m_netMsg->GetU8());
			creature->setLookLegs(m_netMsg->GetU8());
			creature->setLookFeet(m_netMsg->GetU8());
		}
		else
		{
			creature->setLookType(m_netMsg->GetU16()); //extended lookbody
		}

		creature->setLightColor(m_netMsg->GetU8()); 
		creature->setLightLevel(m_netMsg->GetU8());
		creature->setSpeed(m_netMsg->GetU16());

		creature->setIconSkull(m_netMsg->GetU8()); //skull
		creature->setIconShield(m_netMsg->GetU8()); //shield 
		return creature;
	}
	else if(id == 0x0063)
 	{ 
		Creature* creature = KnownCreatures[m_netMsg->GetU32()];
		m_netMsg->GetU16(); //0x0063
		creature->setDirection(m_netMsg->GetU8());

		return creature;
	}
	else
	{
		Item* item = new Item(id);
		if(item->hasCountOrSubType())
			item->setItemCountOrSubType(m_netMsg->GetByte());
		return item;
	}
}
Thanks alot of replies.

Share this post


Link to post
Share on other sites
Like previous poster said; check out the tutorial on ziggyware or examine the samples provided with the library to see how the client and server is set up.
For positions... maybe something like this:


NetMessage msg = new NetMessage();
msg.Write((byte)MessageTypes.Position);
msg.Write(player.X);
msg.Write(player.Y);



I made up the MessageTypes thing... you'll probably need something like it to distinguish between a position message and a "new player" message. It's also probably a good idea to put some more info in there, such as orientation and maybe some status bits.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this