Advertisement

How should my Networking class send and receive info from my other classes?

Started by October 23, 2016 12:13 PM
8 comments, last by hplus0603 8 years ago

What's up, guys.

Basically my problem is that I don't know how to establish communication between my NetworkManager class and the other classes like Player, Object and so on.

The only two things NetworkManager does is to send and receive packets over the internet. That's why I need a way to somehow tell the other objects what I've received and then get some info from them in order to know what to send over the internet.

For now, I just pass all the other objects as arguments, but the code is getting pretty ugly and I need another way of doing this.

I was reading Game Programming Patterns by Robert Nystrom and I'm wondering, will it be ok if I use the Observer Pattern to do this?

I decided to ask here before I do it, because it's kind of a big architectural change and I don't want to spend my time doing the wrong thing.

If my NetworkManager communicated only with one type of objects, for example 'Player', I could just pass the Player as an argument and everything works, but now it's getting more complicated and I can't pass 100 arguments to every function.

I need a way of notifying other classes and sending them some info.(and receiving some info), without worrying about circular dependency and stuff

How to do it in a way that makes the code easy to read?

Never tried network stuff in a game, but throwing some ideas on the table.

Why is a network class a problem, while you have the same(!?) problem with the user?
I mean, don't all objects in the game interact with the user, displaying themselves, or getting input from the user?

Why is that not a problem?


In short, can't you consider the network to be a second 'user'?
Advertisement
[DISCLAIMER: I have no actual experience with this, but I have thought about it over the years, and I am a fairly good thinker. :)]

Alberth is basically right.

A first iteration of your main loop may look like this:
{
  * collect actions from player and submit them to the network
  * collect actions from the AI and from the network
  * execute actions
  * display
}
Of course if you need to wait to get the actions from the network every frame, there will be lag. So some thought is needed to make things run smoothly.

One possible solution is to introduce a delay before the actions are executed. Divide time into "turns" and when the user tries to do something you just schedule that action for 3 turns later, say. As long as you manage to propagate that information using the network within the 3 turns, everything will run smoothly. I believe this is what StarCraft did.

Other games (e.g., FPS) require faster reaction to the player's inputs, so different solutions are needed. I believe a common approach for those games is having a server that keeps track of what the official state of the world is, and each player is running a client. The clients send the actions of each player to the server, and the server sends updates to the clients to keep their states as synchronized as possible. The clients will display the locations of objects using extrapolation, so things seem to move smoothly even if we haven't heard from the server for a few frames. Important events, like people getting hit by a bullet, only happen when the server says they happen.

The latter solution sounds like it's very hard to get right, but many games have managed to pull it off. If by the nature of your game you can get away with the former solution, I would go for that.

No no guys, I was talking about a different thing. I didn't explain it very well, maybe.

My problem is with my code design, not with the network architecture.

My Networking class has only one job, and that is to deal with packets( sending and receiving ).

Now when I receive a 3d position ( 3 floats ), I need to somehow send that position to my player object. To do that, I need access to that object.

I can pass the object as an argument like this: myNetworkManager.receivePackets( Player& player ). This is the solution that I'm using now.

The problem is, it doesn't work so well, because I need to pass more and more arguments to that function and the code looks ugly.

I need to somehow notify the proper object when the NetworkManager has received a packet for it.

I want my network manager to deal with packets only, not receive all kinds of arguments and update logic.

My NetworkManager class kind of communicates with 5 more classes, and I was wondering, what is the best way to send messages between them?

Use a hash table.
Give each "thing" in your program an ID. Maybe the "scoreboardmanager" is ID 13, and objects are created with ID from 100 and up.
Write the ID that a message is intended for at the front of the message, together with length of message.
Then your network code can say:

while (!packet_is_empty(packet)) {
    auto id = read_an_int(packet);
    auto size = read_an_int(packet);
    auto data = read_packet_message(packet, size);
    auto entity = all_entities.find(id);
    if (!entity) {
        error("Entity ID " / id / " doesn't exist! Received from " / packet->source);
    } else {
        entity->receive_message(data);
    }
}
enum Bool { True, False, FileNotFound };

hplus, when I hear the word 'hashtable' I want to throw up.

But this seems perfectly doable by using std::map. So I will have a map that contains pointers to other objects and some ID connected with the object. Sounds really cool.

I will try it.

I remember that you posted the same thing in a previous post but I didn't get. Thanks for repeating :lol:

Advertisement

Prefer std::unordered_map (over std::map) in all cases where strict ordering is not required (most cases).

void hurrrrrrrr() {__asm sub [ebp+4],5;}

There are ten kinds of people in this world: those who understand binary and those who don't.

when I hear the word 'hashtable' I want to throw up


Why? The hash table is one of the most core data structures in software engineering, and almost all modern languages provide them built-in.
(Lua tables, PHP arrays, Python dicts, JavaScript objects are all basically a wrapper on top of a hash table.)
In C++, it's std::unordered_map<>.
enum Bool { True, False, FileNotFound };
In C++, it's std::unordered_map<>.

Yeah, I just found out that. :lol:

It just seems like magic to me because I don't know how it works and it seems kind of complicated, but who cares, I'm just going to use it, not reinvent it. :wink:

It just seems like magic to me


There's a way to fix that!

The classic book on the topic

An alternative in C++

The whole shebang

If you want to become an effective programmer, you owe it to yourself to read up on these topics! It will help you become a much better programmers.
enum Bool { True, False, FileNotFound };

This topic is closed to new replies.

Advertisement