class GameMenu(ScreenManager): player_count = NumericProperty() players = ListProperty() disconnected = BooleanProperty() w_game = ObjectProperty() w_start_button = ObjectProperty() w_join_button = ObjectProperty() w_join_game_box = ObjectProperty() w_join_game_adapter = ObjectProperty() def __init__(self): super(GameMenu, self).__init__() self.w_start_button.bind(on_release = self.start_game) self.w_join_button.bind(on_release = self.find_network_game) args_converter = lambda row_index, rec: {'text': '%s on %s:%s'%(rec['game_name'],str(rec['ip_address']),str(rec['port'])) , 'size_hint_y': 0.1} adapter = ListAdapter(data = [], args_converter=args_converter, cls=ListItemButton, selection_mode='single', allow_empty_selection=True) self.w_join_game_list_view = ListView(size_hint = (0.6, 0.6), pos_hint = {'center_x':0.5, 'center_y':0.6}, adapter = adapter) self.w_join_game_box.add_widget(self.w_join_game_list_view) self.w_join_game_list_view.adapter.bind(on_selection_change = self.network_game_join) self.player_spec = [] self.server = None self.disconnected = False def find_network_game(self, *args): print('looking for network games') import msocket self.w_join_game_list_view.adapter.data = [] self.server = msocket.BroadcastClient(game_id, BROADCAST_PORT, callback = self.network_broadcaster_callback) self.current = 'join_game' def stop_server(self): if self.server is not None: self.server.stop() self.server = None def network_broadcaster_callback(self, *args): Clock.schedule_once(functools.partial(self.network_game_found, *args)) def network_game_found(self, *args): (ip, bport), (game_id, game_name, gport), dt = args data = self.w_join_game_list_view.adapter.data[:] data.append({'ip_address': ip, 'game_name': game_name, 'port': gport}) self.w_join_game_list_view.adapter.data = data self.w_join_game_list_view.populate() def network_game_join(self, adapter): if len(adapter.selection) == 0: return sel = adapter.selection[0] data = adapter.data[sel.index] gname = data['game_name'] ip = data['ip_address'] gport = data['port'] import msocket self.stop_server() try: self.server = msocket.TurnBasedClient(game_id, gname, ip, gport, self.server_callback) except: #TODO: NOTIFY USER THAT CLIENT COULDN'T CONNECT return self.disconnected = False self.server.send('hello',None) def start_network_server(self): import msocket self.server = msocket.TurnBasedServer(game_id, game_name, BROADCAST_PORT, GAME_PORT, self.num_network_players, callback = self.server_callback) self.disconnected = False def server_callback(self, *args): Clock.schedule_once(functools.partial(self.server_msg, *args)) def server_msg(self, *args): msg, data, dt = args board = self.w_game.children[0] if msg == 'players_joined': #all players have joined net_players = [x for x in range(self.player_count) if self.players[x]==2] self.server.queue.put(('player_ids',net_players)) self.start_network_game(self.player_spec) elif msg == 'hello': #remote player says hello, send the initial game data player_id, data = data players_id = [x for x in range(len(board.players))] board.players[player_id].queue.put(('s_hello', (player_id, players_id))) elif msg == 's_hello': #data contains this players id and a list of player id's in turn order player_id, players_id = data spec = [] for x in range(len(players_id)): ps = PlayerSpec('Player '+str(x), color_lookup[x], 0 if players_id[x] == player_id else 2) spec.append(ps) self.start_network_game(spec) elif msg == 'select': #player wants to select a die player_id, (pid, die_num) = data p = board.players[pid] die = p.dice[die_num] board.select_die(die) #self.server.send(player_id, True, die_num, die.value) elif msg == 's_select': #notify player whether they have selected a die and the roll result player_id, die_num, roll_value = data p = board.players[player_id] die = p.dice[die_num] board.select_die(die, roll_value) elif msg == 'place': #player wants to place a die player_id, (pid, hex_pos) = data t = board.tiles[hex_pos] board.place_die(t) #self.server.send(True, hex_pos) elif msg == 's_place': #notify player whether the die has been placed success, hex_pos = data t = board.tiles[hex_pos] board.place_die(t, False) elif msg == 's_restart': #resposne to the game restart # data is success self.start_network_game() elif msg == 's_quitgame': #response to the game quit # data is success self.server.stop() self.server = None self.current = 'main' elif msg == 'connection_error': board.w_state_label.color = white # board.w_state_label.bg_color = grey board.w_state_label.text = 'Disconnected - game over' board.game_over = True self.server = None self.disconnected = True def start_network_game(self, spec = None): if spec is not None: self.player_spec = spec board = self.w_game.children[0] board.server = self.server board.setup_game(self.player_spec) board.start_game() self.current = 'game' try: net_players = [x for x in range(self.player_count) if self.players[x]==2] for x in range(len(net_players)): board.players[net_players[x]].queue = self.server.players[x].queue except AttributeError: pass def restart_game(self): if self.disconnected: return False if self.server is not None: try: self.server.notify_clients('s_restart',None) except AttributeError: return False board = self.w_game.children[0] board.setup_game(self.player_spec) board.start_game() try: net_players = [x for x in range(self.player_count) if self.players[x]==2] for x in range(len(net_players)): board.players[net_players[x]].queue = self.server.players[x].queue except AttributeError: pass self.current = 'game' def join_game(self, *args): pass def start_game(self, *args): self.player_spec = [] self.num_network_players = 0 for x in range(self.player_count): ps = PlayerSpec('Player '+str(x+1), color_lookup[x], self.players[x]) if ps.type == 2: self.num_network_players += 1 self.player_spec.append(ps) if self.num_network_players > 0: self.start_network_server() self.current = 'host_wait' else: board = self.w_game.children[0] board.server = None board.setup_game(self.player_spec) board.start_game() self.current = 'game'
class Table(BoxLayout): def __init__(self, data_ap, **kwargs): super(Table, self).__init__(**kwargs) self.app = App.get_running_app() ## first check if len data = 0 add label to alert user if len(data_ap) is 0: self.add_widget(Label(text="No Data", font_size='32dp')) return ######################## ## HEADER ######################## self.container_header = GridLayout(cols=3, size_hint_y=None, height=(self.app.row_height*0.55), spacing=10) listview_header_widgets = [Label(text="CHUNK"), Label(text="FOUND"), Label(text="SCORE", size_hint_x=0.2)] for x in range(3): self.container_header.add_widget(listview_header_widgets[x]) self.add_widget(self.container_header) ######################## ## GRID ######################## self.container_table = GridLayout(cols=2) # This is quite an involved args_converter, so we should go through the # details. A CompositeListItem instance is made with the args # returned by this converter. The first three, text, size_hint_y, # height are arguments for CompositeListItem. The cls_dicts list contains # argument sets for each of the member widgets for this composite: # ListItemButton and ListItemLabel. args_converter = \ lambda row_index, obj: \ {'text': obj.chunk, 'value': obj.chunk, 'size_hint_y': None, 'height': self.app.row_height * 0.5, 'cls_dicts': [{'cls': Cell, 'kwargs': {'text': obj.chunk, 'id': obj.chunk}}, {'cls': Cell, 'kwargs': {'text': obj.found, 'id': obj.chunk, 'is_representing_cls': True}}, {'cls': Cell, 'kwargs': {'text': str(obj.score), 'id': obj.chunk, 'size_hint_x': 0.2}}]} self.list_adapter = ListAdapter( data=self.first_fill(data_ap), args_converter=args_converter, selection_mode='single', propagate_selection_to_data=True, allow_empty_selection=False, cls=CompositeListItem) # Use the adapter in our ListView: self.list_view = ListView(adapter=self.list_adapter) print 'chunck selezionato: ', self.list_adapter.selection[0].children[2].text chunk = MarkupLabel(self.list_adapter.selection[0].children[2].text).markup print 'selected: ', self.list_adapter.selection[0].children[2].id self.detail_view = RowDetailView(chunk=self.list_adapter.selection[0].children[2].id) self.list_adapter.bind(on_selection_change=self.detail_view.row_changed) self.container_table.add_widget(self.list_view) self.add_widget(self.container_table) self.add_widget(self.detail_view) def update(self, rows): d = [] for row in rows: d.append(Row(chunk=row.chunk, found=row.found, score=row.score)) self.list_adapter.data = d self.list_view.populate() def first_fill(self, rows): d = [] for row in rows: d.append(Row(chunk=row.chunk, found=row.found, score=row.score)) return d