boskee / Minecraft

Simple Minecraft-inspired program using Python and Pyglet
MIT License
207 stars 33 forks source link

Splitting into Client/Server #70

Closed Nebual closed 11 years ago

Nebual commented 11 years ago

I am attempting to split what pyCraftr so far is into a networked game with a Client/Server relationship.

The vision is to have a dedicated Server process that handles terrain generation, loading, and saving the world. The Client process handles rendering, UI's/controls, and nearly everything to do with the Player object itself (its own movement, view, etc)

If the client wants to modify the world, it tells the server (and probably does the modification immediately locally so it feels less laggy). If the client's player moves, it tells the server its new position (which then relays that info to everyone else).

To do this, I have split world.py into a client portion and serverworld.py. The client world.py's functions will mostly be like

def add_block(self, args...):
    self.packetreceiver.send("please add the following block to the world: "+args)
def remove_block(self, args...):
    self.packetreceiver.send("please remove the following block to the world: "+args)
def show_sector(self, sector):
    self.packetreceiver.send("\1"+struct.pack("iii",*sector))

While the serverworld.py's versions of those functions will be basically whats in world.py now.

I know Bertrand and Ronmurphy are fairly busy this coming week so this might not even affect anyone, but I request an edit lock on world.py and server.py until what I have is stable enough to push.

ronmurphy commented 11 years ago

Sounds awesome! I will be gone for the week from friday to next friday, but I hope to have a few hours to pull new commits and see how items are progressing :)

Nebual commented 11 years ago

Reasonable progress!

I've got a working connection between (potentially multiple) clients and a server (serving a world). Theres a full multithreaded architecture up for sending variable length messages of various types both directions. Clients can request sectors and the server loads or generates them, along with a list of exposed blocks, and sends them to clients in the same format the savingsystem uses. Because clients no longer have to worry about saving, hide_sector now actually frees up the block information in memory. As a buffer, chunks aren't hidden until they're 12 chunks away, in contrast to the current view distance of 8 chunks. Because servers maintain a larger list of chunks in memory and are entirely independent of the client rendering thread, they can precompile lists of which blocks in a chunk are is_exposed, saving the client significant time and overall reducing drawn blocks by 25-80%, also reducing show_sector time a fair bit.

TODO: Make player spawn position depend on the server Make Client's world.add_block send the new block to the server Client's world.remove_block to the server Implement world_server.hide_sector (to save on memory, and to save mid execution) Synchronize player positions amongst multiple players

BertrandBordage commented 11 years ago

Nebual and I just had the first multiplayer game! We're thousands of kilometers away and… There is absolutely no lag issue! Everything is perfectly sync!

tfaris commented 11 years ago

Very cool. Had some issues getting the server to run at work but it's working fine here at home. Not seeing any block update lag, just the usual render/gen stuttering.

Now we just need player models!

BertrandBordage commented 11 years ago

@tfaris Using @Nebual's fork?

tfaris commented 11 years ago

Yeah. That's the only copy with client/server right? I pulled his master

BertrandBordage commented 11 years ago

Yes, that's the good one. There is still a few issues, but we're so close…

ronmurphy commented 11 years ago

going to do a merge soon?

BertrandBordage commented 11 years ago

Not in master I guess. The game now requires to manually start a server, even if you play locally. And there is no interface to type the IP adress you want to connect. When we'll have the same ease to create games and the same performance as in master (or more), we'll merge.

ronmurphy commented 11 years ago

ok, i just pulled the master from @Nebual . How to start the server manually? python world_server.py ? had to resolve one conflict, not to bad! If it is ok a may push the merge to my repo.

BertrandBordage commented 11 years ago

You have to specify a seed (any string): python world_server.py --seed something then you launch the regular game.

ronmurphy commented 11 years ago

i just figured that out. we need to make a button for "play offline game" that runs the needed seed gen then start the server silently i think.

BertrandBordage commented 11 years ago

Yep, that's the idea.

ronmurphy commented 11 years ago

i start the server with a seed, and it runs, then exists before i can start the client. this may be a windows issue

yeah, it starts then stops immediately.

BertrandBordage commented 11 years ago

You have to launch the client in a separate terminal. For the moment, the server isn't a daemon.

ronmurphy commented 11 years ago

i have two cmd.exe's launched... want me to do a short video to show what i am doing?

BertrandBordage commented 11 years ago

Yes, please :)

ronmurphy commented 11 years ago

ok, rendering the project, it make take 5-10 minutes for me to upload depending upon file size. will post a link then it is up.

ronmurphy commented 11 years ago

done, sorry for the wait, here it is.

http://solo-soft.com/vid/py_ws.mp4

BertrandBordage commented 11 years ago

Oh sorry, the file is server.py, not world_server.py.

ronmurphy commented 11 years ago

wow, that was improperly formatted, will post to pastebin and share by link

ronmurphy commented 11 years ago

http://pastebin.com/XtefPrTa

ronmurphy commented 11 years ago

only issue i had with the server world? i started at 0, -10000 ... had to fly up 10,000 blocks to find land. and are we doing small terrains? i had the walled garden type land (180 blocks?) but no wall.

BertrandBordage commented 11 years ago

You have to activate fly mode when the game starts. I never tested that walled garden terrain, so I can't help you.

ronmurphy commented 11 years ago

no it was just the the terrain stopped.. let me start it again and do a screencap. or maybe it wont happen again.

ronmurphy commented 11 years ago

nope, it was a one-time thing. works fine, except for a few missing chunks

BertrandBordage commented 11 years ago

Oh, in fact, I forgot to mention something: you have to change the IP address in client.py:15 to be 127.0.0.1. Otherwise you're playing on Nebual's server :)

And you can chat using T.

ronmurphy commented 11 years ago

yes, i have it as localhost (127.0.0.1)

tfaris commented 11 years ago

@BertrandBordage It seems like you might be on a different version? (at least from me) the IP was already localhost, and the chat isn't going across clients

BertrandBordage commented 11 years ago

Nebual made that update 1 hour ago.

ronmurphy commented 11 years ago

i just did a git pull from his repo. i am uploading what i have to my repo for you to see if you want to.

tfaris commented 11 years ago

Ah ok, derp. Got it now.

ronmurphy commented 11 years ago

i changed client.py

class PacketReceiver(Thread): def init (self, world, controller, ipport=("127.0.0.1", 1486)): # was "neb.nebtown.info" , nebual's server

i have my server running, cant seem to connect to it. this is the latest code pull from @Nebual . any ideas?

tfaris commented 11 years ago

Make sure it's actually listening on 127.0.0.1, eg. on my machine it uses my local network ip (192.168.1.8), so that's what I have to put into client.py. That's all I can think of.

ronmurphy commented 11 years ago

yup, that is it

this works for me, may work for others... i added this (the HOST)

from globals import BLOCKS_DIR, SECTOR_SIZE from savingsystem import null2, structuchar2, sector_to_blockpos

HOST = "192.168.56.1" #""127.0.0.1"

i put HOST = "192.168.56.9" <--(my ip) and then changed ipport=("127.0.0.1", 1486)): to ipport=(HOST, 1486)):

may be an option for some if you want local only games.

ronmurphy commented 11 years ago

see my comment here at bottom for auto-getting local-ip and setting it as host.

https://github.com/Nebual/Minecraft/commit/12f6ec2f8a2bba1738d18b630da8e60e3923682b#commitcomment-3092146

Nebual commented 11 years ago

You guys should hop in IRC!

You guessed it, 127.0.0.1 is entirely incompatible with normal IP addresses. The server defaults to binding to your 192.168 address, so use that if you want to connect locally.

I programatically aquire your 192.168 via a one liner I pulled off stackexchange, https://github.com/Nebual/Minecraft/commit/12f6ec2f8a2bba1738d18b630da8e60e3923682b#L2R102

If anyone's looking for something to do, a "connect" dialog for the main menu that lets you type in an IP would be awesome.

Nebual commented 11 years ago

Today's Progress Update: Players can now place/break blocks and have their changes are instantly shared amongst other players. a08864e2946e57916219329ae5af5ef98c7083a0 Enabled ingame chat, which also shows connects/disconnects. dc9136339f7f52f146a2a69c17d6db6127165b16 Created a new thread for serverside "occasional events", used it for grass spreading 60c66f60bd26150db1ee4e2f12602352ddfd5275 Packets are processed much faster. de60ddd409eacb9344eb2e9715f82606b83030c4 Added an IP Address box to the main menu 94a1dffd033987d4541766f5e28d99c70d534d5d Players now get their spawnpoint from the server and don't fall initially 6c9bbb00d9701ff1976275cc7ad69d007618a48f Both the client and the server now handle a lot of exceptions to do with quits, disconnects, and other things that may go wrong

Still big on the TODO is letting players see eachother. Going to need some help on that.