Basic server with multiple players and common map

This commit is contained in:
pjht 2020-05-14 14:55:37 -05:00
parent f96dbf8013
commit 1f3304ad2d
3 changed files with 182 additions and 6 deletions

View File

@ -57,7 +57,9 @@ def recvall(sock):
return data
UNAME=input("UNAME:")
pygame.init()
pygame.display.set_caption(UNAME)
screen=pygame.display.set_mode((constants.WINDWIDTH,constants.WINDHEIGHT))
running=True
@ -70,10 +72,18 @@ key_to_dir={
pygame.K_RIGHT:"right"
}
map=Map(screen,None,0)
sock=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost",30000))
send_str(sock,UNAME)
send_str(sock,"GET_POS")
x=int(recv_str(sock))
y=int(recv_str(sock))
fac=recv_str(sock)
map=Map(screen,sock)
map.tiles={}
player=Player(0,0,map,screen,"PJHT","player_local")
player.direction="up"
player=Player(x,y,map,screen,"PJHT","player_local")
player.direction=fac
while running:
for event in pygame.event.get():
@ -101,8 +111,27 @@ while running:
direction="right"
if move:
player.move(direction)
send_str(sock,"SET_POS")
send_str(sock,str(player.x))
send_str(sock,str(player.y))
send_str(sock,player.direction)
screen.fill([0,0,0])
map.draw(player.x,player.y)
player.draw()
send_str(sock,"GET_POS_MAP")
pos_map=recv_hash(sock)
print(pos_map)
for uname,pos in pos_map.items():
if uname==UNAME:
continue
pos=eval(pos) # FIXME: Eval is dangerous
char=PlayerImg(screen,"player")
char.direction=pos[2]
offsetx=pos[0]-player.x
offsety=pos[1]-player.y
char.draw(constants.CENTERX+offsetx,constants.CENTERY+offsety)
pygame.display.flip()
sleep(0.1)
send_str(sock,"CLOSE")
sock.close()

View File

@ -18,10 +18,8 @@ class PlayerImg(Sprite):
frames[direction]=frame_array
return frames
def __init__(self,x,y,screen,type,*groups):
def __init__(self,screen,type,*groups):
super().__init__(groups)
self.x=x
self.y=y
self.screen=screen
self.frames=self.loadFrames(type)
self.frame=1

149
serv.py Normal file
View File

@ -0,0 +1,149 @@
import pygame
import sys
def my_load(path):
return None
mod=sys.modules["pygame.image"]
mod.load=my_load
sys.modules["pygame.image"]=mod
import os
import random
import select
import socket
import _thread
import pickle
import signal
import glob
import os.path
import lib.constants as constants
from lib.gameregistry import GameRegistry
from lib.map import Map
from lib.character import Character
from lib.block import Block
from lib.player import Player
from time import sleep
import blocks
import pprint
player_map={}
pos_map={}
map_changes={}
next_x=0
def recv_str(sock):
str=""
ch=""
while True:
ch=sock.recv(1).decode("utf-8")
if ch=="\n":
break
str+=ch
# print("Got string: "+str)
return str
def send_str(sock,str,print_str=True):
if print_str:
pass
# print("Sending string: "+str)
sock.send((str+"\n").encode("utf-8"))
def send_hash(sock,hash):
# print("Sending hash: "+pp.pformat(hash))
send_str(sock,str(len(hash)),False)
for key,val in hash.items():
send_str(sock,str(key),False)
send_str(sock,str(val),False)
def recvall(sock):
BUFF_SIZE=4096
data=b''
while True:
part=sock.recv(BUFF_SIZE)
data+=part
if len(part)<BUFF_SIZE:
break
# print("Got data: "+pp.pformat(pickle.loads(data)))
return data
def on_new_client(sock):
global player_map
global pos_map
global map
global map_changes
global next_x
username=recv_str(sock)
player_map[username]=sock
pos_map[username]=(next_x,0,"down")
map_changes[username]=[]
next_x+=1
while True:
msg=recv_str(sock)
if msg=="CLOSE":
del player_map[username]
del pos_map[username]
del map_changes[username]
elif msg=="GET_POS_MAP":
send_hash(sock,pos_map)
elif msg=="GET_POS":
send_str(sock,str(pos_map[username][0]))
send_str(sock,str(pos_map[username][1]))
send_str(sock,pos_map[username][2])
elif msg=="SET_POS":
pos_map[username]=(int(recv_str(sock)),int(recv_str(sock)),recv_str(sock))
elif msg=="BLOCK_AT_POS":
x=int(recv_str(sock))
y=int(recv_str(sock))
sock.send(pickle.dumps(map.tileAt(x,y)))
def handle_cmds():
while True:
if select.select([sys.stdin],[],[],0.0)[0]:
cmd=input()
cmd=cmd.split()
if len(cmd)>0:
if cmd[0]=="stop":
s.close()
f=open("worlds/map_{}.pkl".format(map_name),"wb")
pickle.dump(map,f)
f.close()
exit(1)
def exit_cleanup(signal,frame):
s.close()
f=open("worlds/map_{}.pkl".format(map_name),"wb")
pickle.dump(map,f)
f.close()
Block.init()
files=glob.glob("worlds/map_*.pkl")
if len(files)==0:
new="y"
else:
new=input("New world?").lower()
if new=="n" or new=="no":
i=1
map_map=[]
for name in files:
name=name.split("_")
name.pop(0)
name="_".join(name)
name,_=os.path.splitext(name)
print("{}. {}".format(i,name))
map_map.append(name)
i+=1
map_name=map_map[int(input("Which world?"))-1]
f=open("worlds/map_{}.pkl".format(map_name),"rb")
map=pickle.load(f)
f.close()
else:
map_name=input("World name:")
map=Map(None)
s=socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
host="localhost"
port=30000
s.bind((host, port))
s.listen(5)
_thread.start_new_thread(handle_cmds,())
signal.signal(signal.SIGINT, exit_cleanup)
while True:
c,addr=s.accept()
_thread.start_new_thread(on_new_client,(c,))