def EndGame(): global State global sent_bytes, sent_times, sent_min, sent_max global playerid global wqueue global send_last_update State = "Idle" print "GAME IS OVER!!!!" print "sent %d bytes,%d times, %d bytes/time avg\n" % \ (sent_bytes, sent_times, sent_bytes / sent_times) print "sent_min: %d, sent_max: %d\n" % (sent_min, sent_max) msg = neitris_utils.MsgPack(neitris_utils.GAMEOVER, "", 0, playerid) wqueue.put_nowait(msg) send_last_update = 1
def ServeIt(): global clients TICKEVENT = pygame.USEREVENT SPEEDEVENT = pygame.USEREVENT + 1 SrvState = "Idle" # Starting Select Server: done = 0 while not done: if SrvState == "Starting": events = pygame.event.get() for event in events: if event.type == TICKEVENT: print " got tickevent" countdown = countdown - 1 msgdata = struct.pack("B", countdown) for cli in clients: msgout = neitris_utils.MsgPack(neitris_utils.GAMESTART, msgdata, clients[cli][0], 0) outbuf[cli].append(msgout) if countdown > 0: print "Counting: %d..." % (countdown) else: print "GO!!!" pygame.time.set_timer(TICKEVENT, 0) SrvState = "Playing" pygame.time.set_timer(SPEEDEVENT, neitris_cfg.SPEED_INCR_TIME) if SrvState == "Playing": events = pygame.event.get() for event in events: if event.type == SPEEDEVENT: print " got speedevent" #msgdata = struct.pack("B", INCRSPEED) for cli in clients: msgout = neitris_utils.MsgPack(neitris_utils.INCRSPEED, "", clients[cli][0], 0) outbuf[cli].append(msgout) # The one and only call to select - There is one missing optional argument # in the select call which can be used to set a timeout or timeout behavior. readables, writeables, exceptions = select(readsocks,readsocks,[]) #writesocks,[]) for sockobj in readables: if sockobj in mainsocks: # port socket: accept new client #newsock, address = sockobj.accept() newsock = Xaccept(sockobj) address = '???' print 'Connect:', address, id(newsock) readsocks.append(newsock) else: # This is already an open connection, handle it try: data = Xrecv(sockobj, 1024, 0) #data = sockobj.recv(1024) #print '\tgot', data, 'on', id(sockobj) # No data received: the client has closed the connection if not data: #sockobj.close() Xclose(sockobj) readsocks.remove(sockobj) if SrvState == "Playing": msgout = neitris_utils.MsgPack(neitris_utils.GAMEOVER, "",0, clients[id(sockobj)][0]) # Mark Client as Disconnected, # to erase after gameover for cli in clients: if cli != id(sockobj): outbuf[cli].append(msgout) del clients[id(sockobj)] del outbuf[id(sockobj)] del inbuf[id(sockobj)] print "closing ", id(sockobj) if len(clients) == 0: print "Game Has ended due to client disconnection" SrvState = "Idle" # some data was received - process it else: try: inbuf[id(sockobj)] = inbuf[id(sockobj)] + data except KeyError: inbuf[id(sockobj)] = data while 1: # Wait for a full header if len(inbuf[id(sockobj)]) < 5: break; (length, pload, cmd, dst, src) = \ neitris_utils.MsgUnpack(inbuf[id(sockobj)]) # After reading the full header wait for a full # packet, since we know now the packet length if len(inbuf[id(sockobj)]) < length + 5: break; # take the msg pload msg = inbuf[id(sockobj)][5:(length+5)] inbuf[id(sockobj)] = inbuf[id(sockobj)][(length+5):] # Now process the packet based on the cmd and the # server's state if cmd == neitris_utils.REGPLAYER: if SrvState == "Idle": # find a PID to assign to new player for reg in range(1, 256): found = 1 for cli in clients: if reg == clients[cli][0]: found = 0 break; if found: pid = reg break if not found: continue # pid msg St clients[id(sockobj)]=[pid, msg, 0] pidpacked = struct.pack("B",pid) msgout = neitris_utils.MsgPack\ (neitris_utils.REGPLAYERACK, pidpacked,pid,0) outbuf[id(sockobj)]=[] outbuf[id(sockobj)].append(msgout) print "New player joined the game..." print " Player Name: ", msg print " ID: ", pid print " object ID: ", id(sockobj) else: print "Cannot Join While game in progress" msgout = neitris_utils.MsgPack(neitris_utils.REGPLAYERNACK, "Game in progress",0,0) outbuf[id(sockobj)]=[] outbuf[id(sockobj)].append(msgout) readsocks.remove(sockobj) elif cmd == neitris_utils.STARTREQ and SrvState == "Idle": print "got STARTREQ MSG FROM ", id(sockobj) clients[id(sockobj)][2] = 1 start = 1 for i in clients: if clients[i][2] == 0: start = 0 break if start == 1: pygame.time.set_timer(TICKEVENT, 1000) SrvState = "Starting" countdown = 4 print "Server initiating Game Start" msgdata = struct.pack("B", len(clients)) for cli in clients: msgdata = msgdata + struct.pack("!BH", clients[cli][0], len(clients[cli][1])) msgdata = msgdata + clients[cli][1] msgout = neitris_utils.MsgPack(neitris_utils.GAMEINFO, msgdata, 0, 0) print "queeued GAMEINFO for ", cli for cli in clients: outbuf[cli].append(msgout) start = 0 elif cmd == neitris_utils.SENDSTATE: # and \ # SrvState == "Playing": msgout = neitris_utils.MsgPack(cmd, pload[:length], dst, src) for cli in clients: if cli!= id(sockobj): outbuf[cli].append(msgout) elif cmd == neitris_utils.GAMEOVER and \ SrvState == "Playing": print "Received Game over from ", id(sockobj) msgout = neitris_utils.MsgPack(cmd, "", 0, src) for cli in clients: if cli!= id(sockobj): outbuf[cli].append(msgout) clients[id(sockobj)][2] = 0 end = 1 for i in clients: if clients[i][2] == 1: end = 0 break if end == 1: print " Game has ended..." pygame.time.set_timer(SPEEDEVENT, 0) msgout = neitris_utils.MsgPack(cmd,"",0,0) for cli in clients: outbuf[cli].append(msgout) # Send IncrVicts to winner msgout = neitris_utils.MsgPack( neitris_utils.INCRVICTS,"", clients[id(sockobj)][0],0) outbuf[id(sockobj)].append(msgout) SrvState = "Idle" elif cmd == neitris_utils.POWERUP and \ SrvState == "Playing": msgout = neitris_utils.MsgPack(cmd, pload[:length], dst, src) #print "powerup rcvd: ", pload[:length] for cli in clients: if clients[cli][0] == dst: outbuf[cli].append(msgout) except: raise # Get ready to write for sockobj in writeables: try: if outbuf[id(sockobj)] != []: message = outbuf[id(sockobj)].pop(0) #sockobj.send( "%s" % (message)) Xsend(sockobj, "%s" % (message), 0) #print "sending to ", id(sockobj)," data: ", message except KeyError: pass pygame.time.wait(1)
def neitris_main_loop(rq, wq): global state_change, playerid global sent_times, sent_bytes, sent_max, sent_min global screen, background, window global State global wqueue, rqueue global players global delay global tick global donatorlines global send_last_update wqueue = wq rqueue = rq flash_powerup = 0 # Initially, get user's name and sent it to server to register player print 'We need a name for you' playername = raw_input("enter a player name: ") print 'Name: %s' % playername msg = neitris_utils.MsgPack(neitris_utils.REGPLAYER, playername, 0, 0) print "msg to send: ", msg[5:], " with len: ", len(msg) wqueue.put_nowait(msg) wait_id = 0 print 'waiting for id' # Then wait for registration acknowledgement while not wait_id: while not rqueue.empty(): msg = rqueue.get_nowait() (length, data, cmd, dst, src) = neitris_utils.MsgUnpack(msg) if cmd == neitris_utils.REGPLAYERACK: (playerid, ) = struct.unpack("B", data) wait_id = 1 break elif cmd == neitris_utils.REGPLAYERNACK: print "Cannot Join!" print "Reason given from server:", data #readsock.close() Xclose(readsock) sys.exit(0) print "Registered with the Server, got id: ", playerid players[playerid] = None window = pygame.display.set_mode((250, 600)) pygame.display.set_caption('Neitris') screen = pygame.display.get_surface() background = pygame.Surface(screen.get_size()) background = background.convert() background.fill((0, 0, 0)) font = pygame.font.Font(None, 25) text = font.render("Press START to start game", 1, (140, 140, 140)) textpos = text.get_rect() textsurf = pygame.Surface(screen.get_size()) textpos.centerx = textsurf.get_rect().centerx textpos.centery = 270 textsurf.blit(text, textpos) screen.blit(textsurf, (0, 0)) pygame.display.flip() while True: # Process Messages from the server and other clients ProcessMsg(rqueue) # Process events input(pygame.event.get(), players[playerid]) # periodically (10 times/sec) send updates to other clients if (delay == UPDATE_FREQ and State == "Playing") or \ send_last_update == 1: delay = 0 send_last_update = 0 data = players[playerid].GetMatrixStream() #data = zlib.compress(data,9) l = len(data) sent_bytes = sent_bytes + l sent_times = sent_times + 1 if l > sent_max: sent_max = l if l < sent_min: sent_min = l msg = neitris_utils.MsgPack(neitris_utils.SENDSTATE, data, 0, playerid) wqueue.put_nowait(msg) if not send_last_update: flash_powerup = players[playerid].MonitorPowerups() # Generate and destroy powerups in the matrix players[playerid].GeneratePowerup() # Process Cleared (i.e. from the matrix) Powerups if State == "Playing": players[playerid].ProcessClearedPowerups(wqueue) players[playerid].ProcessActivePowerups(donatorlines, wqueue) donatorlines = 0 if tick: tick = 0 players[playerid].ProcessActivePowerupsTimed() # Update Screen if state_change or flash_powerup: for p in players: #screen.blit(background, (players[p].srcx, 0)) players[p].DrawMatrix(screen, bricks, dots, players, background) font = pygame.font.Font(None, 25) caption_text = '%s and %s are on disjoint XIA networks' % ( players[1].name, players[2].name) caption = font.render(caption_text, 1, (159, 218, 238)) textpos = caption.get_rect() textsurf = pygame.Surface((500, 100)) textpos.centerx = textsurf.get_rect().centerx + 25 textpos.centery = 25 textsurf.blit(caption, textpos) caption_text1 = 'but can still communicate using fallback IPv4' caption1 = font.render(caption_text1, 1, (159, 218, 238)) textpos1 = caption.get_rect() textpos1.centerx = textsurf.get_rect().centerx + 25 textpos1.centery = 45 textsurf.blit(caption1, textpos1) caption_text2 = 'addresses (4IDs).' caption2 = font.render(caption_text2, 1, (159, 218, 238)) textpos2 = caption.get_rect() textpos2.centerx = textsurf.get_rect().centerx + 25 textpos2.centery = 65 textsurf.blit(caption2, textpos2) screen.blit(textsurf, (0, 0)) screen.blit(info, (30, 20)) pygame.display.flip() state_change = 0 flash_powerup = 0 pygame.time.wait(10)
def ProcessMsg(rqueue): global state_change global matrix_enemy global players global State global wqueue global screen, background while not rqueue.empty(): msg = rqueue.get_nowait() (length, data, cmd, dst, src) = neitris_utils.MsgUnpack(msg) #print "received msg ", msg, " with data: ",data, " and cmd: ",cmd if cmd == neitris_utils.SENDSTATE: #data = zlib.decompress(data) state_change = 1 players[src].PutMatrixStream(data) elif cmd == neitris_utils.GAMEINFO: print "Got GAMEINFO msg:", data (pnr, ) = struct.unpack("B", data[0]) print "There are ", pnr, " players in the game" window = None screen = None #background = None window = pygame.display.set_mode((250 * pnr, 700)) pygame.display.set_caption('Neitris') screen = pygame.display.get_surface() #background = pygame.Surface(screen.get_size()) #background = background.convert() #background.fill((0, 0, 0)) data = data[1:] if players[playerid] == None: victories = 0 else: victories = players[playerid].victories players = {} for i in range(pnr): (pid, length) = struct.unpack("!BH", data[:3]) playermatrix = neitris_class.Matrix(i * 250, 100) playermatrix.pid = pid playermatrix.name = data[3:(length + 3)] playermatrix.active = 1 players[pid] = playermatrix #players.append([id, data[3:(length+3)]]) data = data[(length + 3):] print "The following players are in the game: " players[playerid].player_list = [] players[playerid].player_dict_active = {} players[playerid].player_list.append(-1) players[playerid].player_dict_active[-1] = 1 for i in players: print i, players[i].name players[playerid].player_list.append(i) if i != playerid: players[playerid].player_dict_active[i] = 1 else: players[playerid].player_dict_active[i] = 0 #simply store the entire playrs dict into the player obj for i in players: players[i].players = players players[i].victories = 0 players[playerid].victories = victories elif cmd == neitris_utils.GAMESTART: data, = struct.unpack("B", data) if data > 0: print "Counting: ", data else: print "GO!!!" startgame = pygame.event.Event(STARTGAME_EVENT, start=0) pygame.event.post(startgame) elif cmd == neitris_utils.GAMEOVER: if src == 0: print "Game is over!!!" State = "Idle" else: print "Player %s has lost..." % (players[src].name) players[src].active = 0 players[playerid].player_dict_active[src] = 0 if players[playerid].victim == src: players[playerid].ChangeVictim("victimdied") elif cmd == neitris_utils.INCRVICTS: print "You are the winner of this game" players[playerid].victories = players[playerid].victories + 1 print "Victories: ", players[playerid].victories # Send last update to other players data = players[playerid].GetMatrixStream() msg = neitris_utils.MsgPack(neitris_utils.SENDSTATE, data, 0, playerid) wqueue.put_nowait(msg) players[playerid].DrawMatrix(screen, bricks, dots, players, background) pygame.display.flip() elif cmd == neitris_utils.INCRSPEED: if players[playerid].speedidx != 0: players[playerid].speedidx = players[playerid].speedidx - 1 print "Increasing speed. New speed: ", \ speed[players[playerid].speedidx] elif cmd == neitris_utils.POWERUP: pup_id, = struct.unpack("B", data[0]) pupobj = copy.deepcopy(powerups[pup_id]) if pupobj.pid == 255: # DONATORRCVD linesrcvd, = struct.unpack("B", data[1]) print "From player", src, "got donator and ", linesrcvd, "lines" pupobj.lines = linesrcvd elif pupobj.pid == 17: # SWAPSCR dir, = struct.unpack("B", data[1]) data = data[2:] if dir == 0: # just rcvd swapscreen # If not dead, send screen to peer if State == "Playing": dataout = players[playerid].GetSwapData() dataout = struct.pack("BB", 17, 1) + dataout msg = neitris_utils.MsgPack(neitris_utils.POWERUP, dataout, src, playerid) wqueue.put_nowait(msg) players[playerid].PutSwapData(data) else: # received back others data players[playerid].PutSwapData(data) else: print "From player ", src, " got ", pupobj.name, " with id ", pupobj.pid players[playerid].powerups_active[pup_id] = pupobj
def input(events, matrix): global State global speed, count, lines global donatorlines global state_change global sent_bytes global sent_times, sent_min, sent_max global playerid global wqueue, rqueue global delay global tick global speed global TICKEVENT curlines = 0 for event in events: if event.type == QUIT: sys.exit(0) elif event.type == KEYDOWN and event.key == KEY_START \ and State == "Idle": State = "WaitStart" msg = neitris_utils.MsgPack(neitris_utils.STARTREQ, "", 0, playerid) print "msg to send: ", msg[5:], " with len: ", len(msg) wqueue.put_nowait(msg) elif event.type == KEYDOWN and event.key == KEY_RSTWINS: if players[playerid] != None: players[playerid].victories = 0 elif State == "WaitStart" and event.type == STARTGAME_EVENT: pygame.time.set_timer(TICKEVENT, 100) matrix.Initialize() matrix.NewShape() State = "Playing" count = 0 lines = 0 state_change = 1 sent_bytes = 0 sent_times = 0 sent_min = 1000 sent_max = 0 #players[playerid].victim = -1 #for p in players: # if p != playerid: ### players[playerid].victim = p # break players[playerid].ChangeVictim("init") print "Initial Victim is player nr ", players[playerid].victim print "Game is starting" elif State == "Playing": if ( (event.type == USEREVENT and \ count >= speed[players[playerid].speedidx] ) or (event.type == KEYDOWN and event.key == KEY_DOWN)): count = 0 state_change = 1 if matrix.MoveDown() == 0: curlines = curlines + matrix.ClearCompleted() #print "cleared lines: ", lines if (matrix.NewShape() == 0): EndGame() pygame.time.set_timer(TICKEVENT, 0) if (event.type == USEREVENT and \ count < speed[players[playerid].speedidx]): count = count + 1 if event.type == USEREVENT: if delay == UPDATE_FREQ: delay = 0 else: delay = delay + 1 if event.type == TICKEVENT: tick = 1 if event.type == KEYDOWN: if event.key == KEY_LEFT: matrix.MoveLeft() elif event.key == KEY_RIGHT: matrix.MoveRight() elif event.key == KEY_RLEFT and pygame.key.get_mods( ) & KMOD_SHIFT: matrix.RotateRight() elif event.key == KEY_RLEFT: matrix.RotateLeft() elif event.key == KEY_DROP: matrix.Drop() curlines = curlines + matrix.ClearCompleted() #print "cleared lines: ", lines if (matrix.NewShape() == 0): EndGame() elif event.key == KEY_USEANTIDOTE: players[playerid].UseAntidote() elif event.key == KEY_VICTIM: players[playerid].ChangeVictim("normal") state_change = 1 lines = lines + curlines donatorlines = donatorlines + curlines return