Understanding PyMMO

Started by
17 comments, last by Sky Warden 10 years, 11 months ago

Hi everybody. I saw a good source code that is made for MMO development with Python here. I've tried it and it worked. I really am interested in this source code and I want to learn it, but when I opened the script, it was pretty confusing for me. I'm new to network programming, so it's hard for me to understand it.

What I want to know is what does the source code do and how does it work. Can someone please add some comments in the Python scripts explaining parts of it. You can just explain one script or one part if this is bothering you too much, like maybe just the client part, etc. Every help will be appreciated.

Sorry if this sounds so newbie, but I really have no idea. unsure.png

Thank you.

Advertisement

I think you're going to get much more from people on this forum if you ask for help to understand a very specific piece of code. I doubt anyone is going to want to dig into someone else's code and comment it for you.

I've got a better idea: Why not try to comment it yourself? Take a copy of the code and read through it, but don't just read it like a book from start to finish. Get your self whiteboard or a big blank piece of paper and make notes and sketches about the various components of the code. For example, you can start by making a list of the source files:

- client.py

- encoding.py

- mkuser.py

- player.py

- server.py

- world.py

Next, open each file and take note of what it contains. Does it import anything? Make a note of that. What classes does it contain? What functions does it contain? Don't look at the code in too much detail, just look for names. If the code is written well, the names should give you good conceptual ideas.

Also look for `main` functions or a `if __name__ == "__main__"` block in the code, or something like that. Find the "entry point" of the client and server (see the README.txt). From the entry point, read through the first few steps of what it is doing. What kind of functions is it calling? What kind of objects is it creating? What are the relationships of those objects?

Once you think understand the conceptual idea about a piece of code (a class, a function, etc.), add some comments. Even if you're wrong, just add comments about what you THINK the code is doing. Correct them later if you need to. Comments can even be questions, like "# why is this necessary?".

Have you run the code? If not, do it. Try the different examples in the README. Become a "power user" first. Then, start thinking about what feature you might add. Make it something small. Try to build it, and ask questions if you need help.

I hope that helps. =)

I think you're going to get much more from people on this forum if you ask for help to understand a very specific piece of code. I doubt anyone is going to want to dig into someone else's code and comment it for you.

I've got a better idea: Why not try to comment it yourself? Take a copy of the code and read through it, but don't just read it like a book from start to finish. Get your self whiteboard or a big blank piece of paper and make notes and sketches about the various components of the code. For example, you can start by making a list of the source files:

- client.py

- encoding.py

- mkuser.py

- player.py

- server.py

- world.py

Next, open each file and take note of what it contains. Does it import anything? Make a note of that. What classes does it contain? What functions does it contain? Don't look at the code in too much detail, just look for names. If the code is written well, the names should give you good conceptual ideas.

Also look for `main` functions or a `if __name__ == "__main__"` block in the code, or something like that. Find the "entry point" of the client and server (see the README.txt). From the entry point, read through the first few steps of what it is doing. What kind of functions is it calling? What kind of objects is it creating? What are the relationships of those objects?

Once you think understand the conceptual idea about a piece of code (a class, a function, etc.), add some comments. Even if you're wrong, just add comments about what you THINK the code is doing. Correct them later if you need to. Comments can even be questions, like "# why is this necessary?".

Have you run the code? If not, do it. Try the different examples in the README. Become a "power user" first. Then, start thinking about what feature you might add. Make it something small. Try to build it, and ask questions if you need help.

I hope that helps. =)

Yes. That does help me. I found out that my trouble was the way I tried to understand the code. Your guide helps me indeed.

Do you have any other tips to understand people's code? I'm going to use Twisted for the network. Just trying.

By the way, if I find something I can't understand, can I ask you here? :)

Do you have any other tips to understand people's code? I'm going to use Twisted for the network. Just trying.

Yep. One thing you can do is write tests for it, if it's not already tested. This way, you have a concrete method of exercising the code and to test if your assumptions about the code are correct.

Another thing you can do is to re-write parts of the code, meaning, copy it exactly by typing out each character. This is not the same as copy/paste. Copying the code by writing will give you a "muscle memory" for the code and you will notice subtle things as you are copying it that you wouldn't normally notice when you are just reading.

Last but not least, actually write some code of your own. Figure out what you want to build and see if you can use or modify the code to suit your needs.


By the way, if I find something I can't understand, can I ask you here?

Of course you can post questions to the forum. If you have a specific question, it's probably best to create a new post (and link back to this one for reference).

Thok has a very good point and I will add on to it quick! You need to learn how to read and understand code yourself. Half of being a programmer is being able to read and understand other peoples code and follow logic. As Thok said, you are more likely to get help if you ask about a specific block of code or system.

"The code you write when you learn a new language is shit.
You either already know that and you are wise, or you don’t realize it for many years and you are an idiot. Either way, your learning code is objectively shit." - L. Spiro

"This is called programming. The art of typing shit into an editor/IDE is not programming, it's basically data entry. The part that makes a programmer a programmer is their problem solving skills." - Serapth

"The 'friend' relationship in c++ is the tightest coupling you can give two objects. Friends can reach out and touch your privates." - frob

I think you're going to get much more from people on this forum if you ask for help to understand a very specific piece of code.

Normally that's 100% true. However, in this case, the person who wrote that code is the moderator of the Multiplayer + Networking forum here on Gamedev.net. So some specific questions may get answered over in that forum. However, I doubt anybody will have the time to go through and explain all of it.

Well, I have a small question about this. Since this question is too... simple, I don't think making a new thread is a good idea, so here we go.

Like I said, I'm new to network programming (I learn programming from the internet. I even haven't been in college). My question is simple. What kind of information does the client send to the server, and vice versa?

My current opinion is it's something like "the character moves. The character id is x, and it moves to [insert the movement vector here]." Is my assumption correct? My idea is to send a string which is the name of an available function in the server, along with the arguments needed. For example, here the command is move, so it will call move(char_id, vector) with Python exec(). Is it correct? Or is there a better way (I'm sure there is)?

Also, what things I should pay attention at while doing this? Is using exec() bad? Do you have any advice for doing this?

Thank you again. Sorry if this sounds too newbie, but well... I am. laugh.png

Well, I have a small question about this. Since this question is too... simple, I don't think making a new thread is a good idea, so here we go.

Like I said, I'm new to network programming (I learn programming from the internet. I even haven't been in college). My question is simple. What kind of information does the client send to the server, and vice versa?

My current opinion is it's something like "the character moves. The character id is x, and it moves to [insert the movement vector here]." Is my assumption correct? My idea is to send a string which is the name of an available function in the server, along with the arguments needed. For example, here the command is move, so it will call move(char_id, vector) with Python exec(). Is it correct? Or is there a better way (I'm sure there is)?

Also, what things I should pay attention at while doing this? Is using exec() bad? Do you have any advice for doing this?

Thank you again. Sorry if this sounds too newbie, but well... I am. laugh.png

I think you're mistaking `exec` for `eval`. And yes, you should be very careful using `eval`. Probably a better idea is creating a map of valid commands. Something like this:


def move_character(char_id, vector):
    # TODO:
    pass

def kill_character(char_id):
    # TODO:
    pass

command_map = {
  'move_character': move_character,
  'kill_character': kill_character,
}

So if the command sent the server is not one of the registered commands in `command_map`, you ignore it. This is a simple way you can start defining (and enforcing) the contract between client and server.

Try something simple like this and build on it as necessary.

I think you're mistaking `exec` for `eval`. And yes, you should be very careful using `eval`. Probably a better idea is creating a map of valid commands. Something like this:


def move_character(char_id, vector):
    # TODO:
    pass

def kill_character(char_id):
    # TODO:
    pass

command_map = {
  'move_character': move_character,
  'kill_character': kill_character,
}

So if the command sent the server is not one of the registered commands in `command_map`, you ignore it. This is a simple way you can start defining (and enforcing) the contract between client and server.

Try something simple like this and build on it as necessary.

Oh, yes. It's eval. I forgot about their difference. laugh.png

About the command_map, I actually have been thinking about that before. Using dictionary and check if the thing is in the dictionary. So, my assumption is right? The type of data sent between client and server is the instruction and the arguments needed? I have never coded any server stuff before, and I couldn't find such information in the Internet. I just used my own logic, which is questionable. unsure.png

Can you please explain a little more about the reason why I must be careful while using eval? I feel like it's rather risky, but I'm not sure why. I guess I'm just paranoid.

P.S. I just read an article about being careful with eval, but I don't really understand the namespace thingy.

Oh, yes. It's eval. I forgot about their difference.

About the command_map, I actually have been thinking about that before. Using dictionary and check if the thing is in the dictionary. So, my assumption is right? The type of data sent between client and server is the instruction and the arguments needed? I have never coded any server stuff before, and I couldn't find such information in the Internet. I just used my own logic, which is questionable.

Yes, pretty much. You need to figure out a clean way to pack 1) the instruction name and 2) the arguments on the client side, and a way to unpack them properly on the server side. A simple way to do this would be to encode this in JSON; that may not be terribly efficient, but it's a simple place to start. Python has standard libs for encoding and decoding JSON: http://docs.python.org/2/library/json.html.


Can you please explain a little more about the reason why I must be careful while using eval? I feel like it's rather risky, but I'm not sure why. I guess I'm just paranoid.

P.S. I just read an article about being careful with eval, but I don't really understand the namespace thingy.

Two words: "code injection". http://en.wikipedia.org/wiki/Code_injection

If you use `eval` to execute an arbitrary instruction, it is possible that a client could, for example, send the instruction name '__import__("sys").exit()' as a string, which would crash the server process once `eval` executes it. If the server process is being run as superuser (which it shouldn't be), technically this security hole could result in the server box getting completely 0wnz3d. If you're using an `eval` in a program which runs in isolation on a single machine and never hits the network, probably you don't need to care. But once you open the program up to a network and, more importantly, provide a server interface _directly_ to an `eval`, you do need to be careful.

Regardless of the security risks, there are almost always better alternatives to `eval`. In your case, using an explicitly defined map of instructions is one of those alternatives.

`eval` for Python is kind of like `goto` for C: Just because you CAN use it doesn't necessarily mean you SHOULD. =P

This topic is closed to new replies.

Advertisement