Jump to content

Raknet Bitstream Problems


DigitalHax
 Share

Recommended Posts

This is proving really good timing as I'm about to do a complete engine re-write (for various reasons) and I wanted to look at putting the foundations in for multi-player.

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

Just some code I've used/read before. If you use game states and state manager this can help simplify things. This is what I use myself. I've done this from memory so it's just to get the idea behind it and not 100% how mine looks.

 

void StateManager::NetworkUpdate()
{
  for(p=client->Receive(); p; client->DeallocatePacket(p), p=client->Receive())
  {
  // this reads the first byte of the packet and is the enum values like ID_REQUEST_LOGIN
  packetIdentifier = GetPacketIdentifier(p);

  // get the bitstream to read the data and ignore the message type so we can just read the game data right away when inside
  // our function
  RakNet::BitStream reader(p->data, p->length, false);
  reader->IgnoreBytes(sizeof(MessageID));
  // validate our current state has registered/subscribed to this network message
  if(_currentState->IsNetworkMessageRegistered(packetIdentifier))
  {
	 // if it has, fire the message off
	 _currentState->FireNetworkEvent(packetIdentifier, p, reader)
  }
  }
}
// inside base State class
map<MessageID, Event2<Packet*, BitStream&>> _networkMessages;
bool State::IsNetworkMessageRegistered(MessageID msg)
{
  if(_networkMessages.find(msg) != _networkMessages.end())
  return true;
  return false;
}
void State::FireNetworkEvent(MessageID msg, Packet* p, BitStream& reader)
{
  // this will fire the function that was bound to the message
  _networkMessages[msg].Raise(p, reader);
}

void GameplayState::OnEnter()
{
  // this replaces the need for a big ugly switch state and is how you link network messages to member functions
  _networkMessages[iD_RESPONSE_LOGIN].Bind(this, &GameplayState::OnResponseLogin);
}

void GameplayState::OnResponseLogin(Packet* p, BitStream& reader)
{
  RakString status;
  RakString reason;

  reader.Read(status);

  if(status == "failure")
  {
  reason = reader.Read(reason);
  printf("Failed to login: %s", reason.C_Str());
  }
}

 

 

This is the way I do things. A slight modification to this could be to make classes for each message type and a factory create said type using the message id.

void Gameplay::OnResponseLogin(LoginMessage& msg)
{
  if(msg.Status == "failure")
  printf("Failed to login: %s", msg.Reason);
}

 

This is "cleaner", but it adds more overhead to make work. With this you need a class for every message id and you'll end up with hundreds of small classes. It also requires some casting being done to the message class type. The nice thing about this is that inside the network function you don't have to worry about reading the data as that's been done for you in the message class itself. However, you'd still have to do that reading in the class, but if working in a team project it can lead to nice separation of duties.

These are just things I've done/learned from others and is no way the only way to do things, but just thought I'd share my experiences.

  • Upvote 1
Link to comment
Share on other sites

These are just things I've done/learned from others and is no way the only way to do things, but just thought I'd share my experiences.

Thanks for sharing Rick, this is all great background information. I'll read and digest :)

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

Guest Red Ocktober
The player on the server is very necessary, but it just doesn't require the visuals.

 

unless your server is also connected as one of the players... ie, not a dedicated server...

 

--Mike

  • Upvote 1
Link to comment
Share on other sites

I still think that network messages should be transferred in a low priority thread, like only once every 60 seconds. The rest can be done with AI prediction.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

I still think that network messages should be transferred in a low priority thread, like only once every 60 seconds. The rest can be done with AI prediction.

 

So you want to only send some network traffice once a min? Think if it took a minute before others see your chat messages. Or a minute to tell you that the other player actually picked up this item that you thought you picked up because you both got there at at the same time. As a player I'd be pretty pissed to think I have an item for 60 seconds before the game takes it back away from me because it finally realized I didn't really get there first to get it. The truth is almost nothing you do in a networked game will ever be spaced out that long. Prediction only masks the reality for a very short time to help the illusion. Letting corrections only happen every 60 seconds would cause all sorts of visible problems in games. I could do all sorts of cheats on the client within that 1 minute time window. 1 min is a very long time in the world of networking considering things generally happen around 100ms or so.

 

The 2 main things you are thinking about with online games:

 

1) Create the illusion of instant

2) Stop the cheating

 

These 2 things are the most important. If your game fails on either of these 2 the game will die quickly. Nobody likes lag and a sluggish game, and when your game is filled with cheaters nobody likes that either.

Link to comment
Share on other sites

I still think that network messages should be transferred in a low priority thread, like only once every 60 seconds. The rest can be done with AI prediction.

 

60 seconds is way too long. AI prediction cannot even come close to predicting that length ahead of time.

STS - Scarlet Thread Studios

AKA: Engineer Ken

 

Fact: Game Development is hard... very bloody hard.. If you are not prepared to accept that.. Please give up now!

Link to comment
Share on other sites

I'd much prefer factual advice from real experience over supposition (I have Mika on constant ignore due to his past history of this). It's a lot more helpful to people starting off down this route who may be hoping to get some good pointers from this thread.

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

So you want to only send some network traffice once a min? Think if it took a minute before others see your chat messages. Or a minute to tell you that the other player actually picked up this item that you thought you picked up because you both got there at at the

You can do it the other way around: Let the player request an item to pick up, and after some time the server will tell the player if the pickup was succesful. It doesn't have to appear as long waiting time, but you can have a game story why it takes sometimes longer to get an item, for example the item must be carefully removed to avoid it getting damaged. Kinda when you remove some jewel from a statue, it takes also time.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

You can do it the other way around: Let the player request an item to pick up, and after some time the server will tell the player if the pickup was succesful. It doesn't have to appear as long waiting time, but you can have a game story why it takes sometimes longer to get an item, for example the item must be carefully removed to avoid it getting damaged. Kinda when you remove some jewel from a statue, it takes also time.

 

Come on man lol

Link to comment
Share on other sites

That's the only way you can host a MMO on your own server with 1MBit/s connection. Movement can be point and click style, and fights can be easily predicted based on the equipment and enemy.

Ryzen 9 RX 6800M ■ 16GB XF8 Windows 11 ■
Ultra ■ LE 2.53DWS 5.6  Reaper ■ C/C++ C# ■ Fortran 2008 ■ Story ■
■ Homepage: https://canardia.com ■

Link to comment
Share on other sites

You guys just crack me up! Not one published game made with LE2 yet * and you're discussing what's required for an MMO biggrin.png

 

* I don't really count Hoodwink; as the only part of the engine it used was the renderer ... although full kudos to NA.

 

I'm off to start reading through the RAKNET documentation. Thanks to all who provided practical advice and provided pointers to key areas I'll need to familiarize myself with. I hope you'll provide some feedback as you develop you're multi-player engine DigitalHax and I'll try and do likewise. I'll be taking a look at your code too Scarlet, thanks for releasing your tutorials I'm sure they will be really helpful.

Intel Core i5 2.66 GHz, Asus P7P55D, 8Gb DDR3 RAM, GTX460 1Gb DDR5, Windows 7 (x64), LE Editor, GMax, 3DWS, UU3D Pro, Texture Maker Pro, Shader Map Pro. Development language: C/C++

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...