def set_storm_enabling(self, storm_flag): if storm_flag == 0: self.game_model.ENABLE_STORM = False garage_util.log_garage('storm disabled for room ' + str(self.room_id), True) else: self.game_model.ENABLE_STORM = True garage_util.log_garage('storm enabled for room ' + str(self.room_id), True)
def on_client_pick_up_weapon(self, evt): # pick up weapon event garage_util.log_garage('pick up weapon event') weapon_id = evt.var['weapon_id'] weapon_type = evt.var['weapon_type'] equip_slot = evt.var['equip_slot'] # TODO: add real check pick_success = True # if weapon_id not in self.game_model.weapons: # print 'wid', weapon_id, 'wtype', weapon_type # print 'pick up weapon failed' # pick_success = False if pick_success: # destroy weapon event evt_destroy_weapon = EventServerDestroyWeapon() evt_destroy_weapon.from_cid = evt.from_cid evt_destroy_weapon.var['weapon_id'] = weapon_id self.game_event_manager.broadcast_server_event(evt_destroy_weapon) # pick up weapon event evt_pick_up_weapon = EventServerPickUpWeapon() evt_pick_up_weapon.from_cid = evt.from_cid evt_pick_up_weapon.var['weapon_id'] = weapon_id evt_pick_up_weapon.var['weapon_type'] = weapon_type self.game_event_manager.send_server_event(evt.from_cid, evt_pick_up_weapon)
def on_client_hit(self, evt): # hit event """ | header | damage | hit_pos | hit_cid | 10 4 4x3 4 """ print 'hit event' fire_cid = evt.from_cid hit_cid = evt.var['hit_cid'] init_damage = evt.var['damage'] damage = float(init_damage) / 10000 self.client_infos[hit_cid].state.HP -= damage garage_util.log_garage('client ' + str(fire_cid) + ' hit ' + str(hit_cid) + ', damage ' + str(damage), True) evt_damage = EventServerDamage() evt_damage.from_cid = hit_cid evt_damage.var['fire_cid'] = fire_cid evt_damage.var['damage'] = init_damage self.game_event_manager.broadcast_server_event(evt_damage) # determine death # TODO: centralize death event if not self.client_infos[hit_cid].state.is_dead and self.client_infos[hit_cid].state.HP <= 0: self.client_infos[hit_cid].state.is_dead = True garage_util.log_garage('client ' + str(hit_cid) + ' dead', True) evt_death = EventServerPlayerDeath() evt_death.from_cid = hit_cid evt_death.var['killed_cid'] = hit_cid evt_death.var['killer_id'] = fire_cid self.game_event_manager.broadcast_server_event(evt_death)
def remove_client(self, cid): if cid in self.client_infos: self.client_infos.pop(cid, None) garage_util.log_garage('client ' + str(cid) + ' leaves room ' + str(self.room_id), True) # TESTING self.post_remove_client(cid) else: garage_util.log_garage('client ' + str(cid) + ' not in room ' + str(self.room_id) + '. no client removed from room')
def add_client(self, cid): if cid not in self.client_infos: new_client_state = self.ClientState() new_client_info = self.ClientInfo(new_client_state) self.client_infos[cid] = new_client_info garage_util.log_garage('client ' + str(cid) + ' entered room ' + str(self.room_id), True) self.post_add_client(cid) # TESTING else: garage_util.log_garage('client ' + str(cid) + ' already in room ' + str(self.room_id))
def on_client_heal(self, evt): from_cid = evt.from_cid if from_cid in self.client_infos: hp = self.client_infos[from_cid].state.HP hp += evt.var['heal_val'] if hp > 100: hp = 100 self.client_infos[from_cid].state.HP = hp garage_util.log_garage('client ' + str(from_cid) + ' healed to ' + str(hp), True)
def logout_client(self, cid): self.pre_logout_client(cid) # before logout actions if cid in self.client_connections: at_room = self.client_connections[cid].at_room if at_room >= 0: self.quit_room(cid) self.client_connections.pop(cid, None) garage_util.log_garage('client ' + str(cid) + ' logged out', True) else: garage_util.log_garage('client ' + str(cid) + ' not logged in. logout failed')
def on_client_start_game(self, evt): # echo start game # update client initial info cid = evt.from_cid if cid not in self.client_infos: garage_util.log_garage('game start failed. client ' + str(cid) + ' not in room ' + str(self.room_id)) return self.client_infos[cid].state.grid_x = evt.var['grid_x'] self.client_infos[cid].state.grid_y = evt.var['grid_y'] self.client_infos[cid].state.pos[0] = evt.var['pos_x'] self.client_infos[cid].state.pos[1] = evt.var['pos_y'] self.client_infos[cid].state.pos[2] = evt.var['pos_z'] self.client_infos[cid].state.rot[0] = evt.var['rot'][0] self.client_infos[cid].state.rot[1] = evt.var['rot'][1] self.client_infos[cid].state.rot[2] = evt.var['rot'][2] # notify new client of existing clients evt_spawn_old = EventServerSpawnPlayer() for existing_cid in self.client_infos: if existing_cid != cid: evt_spawn_old.from_cid = existing_cid existing_client_state = self.client_infos[existing_cid].state evt_spawn_old.var['car_id'] = existing_client_state.vid evt_spawn_old.var['grid_x'] = existing_client_state.grid_x evt_spawn_old.var['grid_y'] = existing_client_state.grid_y evt_spawn_old.var['pos_x'] = existing_client_state.pos[0] evt_spawn_old.var['pos_y'] = existing_client_state.pos[1] evt_spawn_old.var['pos_z'] = existing_client_state.pos[2] evt_spawn_old.var['rot'] = existing_client_state.rot evt_spawn_old.var['has_ship'] = '\x00' # False self.game_event_manager.send_server_event(cid, evt_spawn_old) # notify all clients to add new client evt_spawn_new = EventServerSpawnPlayer() evt_spawn_new.from_cid = cid current_state = self.client_infos[cid].state evt_spawn_new.var['car_id'] = current_state.vid evt_spawn_new.var['grid_x'] = current_state.grid_x evt_spawn_new.var['grid_y'] = current_state.grid_y evt_spawn_new.var['pos_x'] = current_state.pos[0] evt_spawn_new.var['pos_y'] = current_state.pos[1] evt_spawn_new.var['pos_z'] = current_state.pos[2] evt_spawn_new.var['rot'] = current_state.rot evt_spawn_new.var['has_ship'] = '\x01' # True # broadcast event self.game_event_manager.broadcast_server_event(evt_spawn_new, []) # start game evt_start_game = EventServerStartGame() evt_start_game.from_cid = -1 self.game_event_manager.send_server_event(cid, evt_start_game) pass
def create_room(self, rid=None): res_rid = 0 if rid and rid >= 0: res_rid = rid while res_rid in self.room_servers: res_rid += 1 new_room_server = self.room_server_class(self, res_rid) self.room_servers[rid] = new_room_server garage_util.log_garage('room ' + str(res_rid) + ' created', True) # run room server room_thread = threading.Thread(target=new_room_server.start_server) room_thread.start() return new_room_server
def login_client(self, cid, token, remote_ip, remote_port): res_code = '\x00' if cid not in self.client_connections: # TESTING login_success = GarageWebApi.check_session(cid, token) if login_success: new_connection = ClientConnection(remote_ip, remote_port) self.client_connections[cid] = new_connection res_code = '\x00' # 00 == login success garage_util.log_garage('Player ' + str(cid) + ' login success', True) # self.post_login_client(cid) # after login action else: res_code = '\x01' # 01 == authorization failed garage_util.log_garage( 'Player ' + str(cid) + ' info not correct. login failed', True) else: res_code = '\x02' # 02 == login conflict garage_util.log_garage('Player ' + str(cid) + ' already logged in') pkg_data = pack( '<ciicc', '\x12', get_current_millisecond_clamped(), cid, '\x0a', # \x0a == server login result event res_code, ) dlen = self.net_communicator.send_data(pkg_data, remote_ip, remote_port) garage_util.log_garage(str(dlen) + ' sent')
def assign_room(self, cid, pkg, rid=-1): room_id = 0 # default room id if rid >= 0: # if room id specified, use it room_id = rid else: # TESTING while room_id in self.room_servers and len( self.room_servers[room_id].client_infos) >= 80: room_id += 1 target_room = None if room_id not in self.room_servers: # create room if not exists target_room = self.create_room(room_id) else: target_room = self.room_servers[room_id] if not target_room: garage_util.log_garage('room error. no room available') else: if cid not in self.client_connections: garage_util.log_garage('client ' + str(cid) + ' not logged in') elif self.client_connections[cid].at_room >= 0: garage_util.log_garage( 'client ' + str(cid) + ' already in room ' + str(self.client_connections[cid].at_room), True) else: garage_util.log_garage('pass client ' + str(cid) + ' to room ' + str(room_id)) target_room.run_command('add_client', cid) self.client_connections[cid].at_room = room_id
def quit_room(self, cid): if cid in self.client_connections: at_room = self.client_connections[cid].at_room if at_room >= 0: garage_util.log_garage('client ' + str(cid) + ' requests to quit room ' + str(at_room)) self.room_servers[at_room].run_command('remove_client', cid) self.client_connections[cid].at_room = -1 else: garage_util.log_garage('client ' + str(cid) + ' not in any room. quit room failed') else: garage_util.log_garage('client ' + str(cid) + ' not logged in. quit room failed')
def solve_package(self, pkg): data = pkg.data addr = (pkg.ip, pkg.port) op_code = unpack('<c', data[0])[0] target_cid = unpack('<i', data[5:5 + 4])[0] if op_code <= '\x0f': # admin package if op_code == '\x01': # login token = self.parse_token(data) self.login_client(target_cid, token, addr[0], addr[1]) elif op_code == '\x02': # logout self.logout_client(target_cid) elif op_code <= '\x1f': # game package # TODO: move login handling to admin package if op_code == '\x12': # event event_id = unpack('<c', data[9:10])[0] if event_id == '\x06': # ping # TESTING if target_cid in self.client_connections: ping_start = unpack('<i', data[1:5])[0] pkg_data = pack('<ciici', '\x12', get_current_millisecond_clamped(), target_cid, '\x08', ping_start) dlen = self.net_communicator.send_data( pkg_data, addr[0], addr[1]) else: garage_util.log_garage( 'no echo for not logged in client' + str(target_cid)) return if event_id == '\x07': # login garage_util.log_garage('login event') token = self.parse_token(data) self.login_client(target_cid, token, addr[0], addr[1]) return if event_id == '\x0b': # re-login garage_util.log_garage('re-login event') relogin_res = '\x00' # 00 == ok if target_cid in self.client_connections: pkg_data = pack('<ciicc', '\x12', get_current_millisecond_clamped(), target_cid, '\x0d', relogin_res) dlen = self.net_communicator.send_data( pkg_data, addr[0], addr[1]) return if event_id == '\x08': # logout # TODO: logout garage_util.log_garage('logout event') self.logout_client(target_cid) return if event_id == '\x00': # match game request # TODO: move join room to separate package garage_util.log_garage('join room event') desired_rid = unpack('<i', data[14:18])[0] garage_util.log_garage('desired room id' + str(desired_rid)) self.assign_room(target_cid, pkg, desired_rid) # pass to room if necessary (game event) if target_cid in self.client_connections: at_room = self.client_connections[target_cid].at_room if at_room >= 0: self.room_servers[at_room].run_command( 'handle_package', pkg) elif op_code <= '\x2f': # sys info package pass
def parse_token(self, pkg_data): token = unpack('<i', pkg_data[14:18])[0] garage_util.log_garage('get session ' + str(token)) return token
def post_remove_client(self, cid): if len(self.client_infos) == 0: garage_util.log_garage('all clients left room ' + str(self.room_id) + '.', True) self.clear_room() # TESTING
def tick_extra(self): """ coroutine = main game model logic """ GAME_LOGIC_INTERVAL = 1.0 / 60 while True: try: if self.game_model.game_state == self.GameModel.GameState.GAME_RUNNING: # update fake clients if time.time() - self.last_ai_update_stamp > 1.0 / self.AI_UPDATE_RATE: self.last_ai_update_stamp = time.time() for ai_ind in range(100): if ai_ind in self.client_infos: self.client_infos[ai_ind].state.grid_x = pack('<i', random.randint(0, 5))[0] self.client_infos[ai_ind].state.grid_y = pack('<i', random.randint(0, 5))[0] self.client_infos[ai_ind].need_update = True pass # storm logic if self.game_model.ENABLE_STORM: # calculate shrinking storm if self.game_model.storm_shrink_start_stamp > 0: shrink_time = time.time() - self.game_model.storm_shrink_start_stamp # time after shrink start if shrink_time > 0: if shrink_time > self.game_model.storm_shrink_duration: self.game_model.cur_storm_center[0] = self.game_model.next_storm_center[0] self.game_model.cur_storm_center[1] = self.game_model.next_storm_center[1] self.game_model.cur_storm_radius = self.game_model.next_storm_radius self.game_model.storm_shrink_start_stamp = -1 garage_util.log_garage('shrinking done. current radius ' + str(self.game_model.cur_storm_radius) + ' current center ' + str(self.game_model.cur_storm_center[0]) + ', ' + str(self.game_model.cur_storm_center[1])) else: alpha = shrink_time / self.game_model.storm_shrink_duration self.game_model.cur_storm_center[0] = (1 - alpha) * self.game_model.prev_storm_center[0] + alpha * self.game_model.next_storm_center[0] self.game_model.cur_storm_center[1] = (1 - alpha) * self.game_model.prev_storm_center[1] + alpha * self.game_model.next_storm_center[1] self.game_model.cur_storm_radius = (1 - alpha) * self.game_model.prev_storm_radius + alpha * self.game_model.next_storm_radius # calculate storm damage # TESTING if time.time() - self.game_model.last_storm_damage_stamp > 2: # tick every 2 secs self.game_model.last_storm_damage_stamp = time.time() # SHOULD BE cur_storm_center # cur_center_xy = self.game_model.grid_xy_to_true(21, 51, 160, 160) cur_center_xy = self.game_model.cur_storm_center # print 'damage calc center:', self.game_model.cur_storm_center, ', damage radius:', self.game_model.cur_storm_radius # print 'current storm center', cur_center_xy for cid in self.client_infos: if self.client_infos[cid].state.HP > 0: # print 'client', cid, 'HP', self.client_infos[cid].state.HP client_xy = self.game_model.grid_xy_to_true( unpack('<h', self.client_infos[cid].state.grid_x + '\x00')[0], unpack('<h', self.client_infos[cid].state.grid_y + '\x00')[0], unpack('<h', self.client_infos[cid].state.pos[0] + '\x00')[0], unpack('<h', self.client_infos[cid].state.pos[1] + '\x00')[0] ) # print 'client pos', client_xy dx = client_xy[0] - cur_center_xy[0] dy = client_xy[1] - cur_center_xy[1] if dx * dx + dy * dy > self.game_model.cur_storm_radius * self.game_model.cur_storm_radius: damage = 10000 # print 'storm damage', damage self.client_infos[cid].state.HP -= damage / 10000 evt_damage = EventServerDamage() evt_damage.from_cid = cid # damaged client evt_damage.var['fire_cid'] = -1 # server evt_damage.var['damage'] = damage self.game_event_manager.broadcast_server_event(evt_damage) # determine death # TODO: centralize death event if not self.client_infos[cid].state.is_dead and self.client_infos[cid].state.HP <= 0: self.client_infos[cid].state.is_dead = True garage_util.log_garage('client ' + str(cid) + ' dead', True) evt_death = EventServerPlayerDeath() evt_death.from_cid = cid evt_death.var['killed_cid'] = cid evt_death.var['killer_id'] = -1 # -1 == storm self.game_event_manager.broadcast_server_event(evt_death) # update sand storm storm_span = self.game_model.cur_storm_duration if self.game_model.storm_pkg_count > 1: # if not first update, accumulate shrink delay and shrink time storm_span = self.game_model.cur_storm_duration + self.game_model.storm_shrink_delay + self.game_model.storm_shrink_duration if time.time() - self.game_model.last_storm_update_stamp > storm_span: # if time.time() - self.start_stamp < 15: # TESTING # return # counter update self.game_model.storm_pkg_count += 1 print 'storm update at time', time.time() self.game_model.last_storm_update_stamp = time.time() # calculate next storm # self.game_model.cur_storm_radius = self.game_model.next_storm_radius if self.game_model.storm_pkg_count > 1: self.game_model.next_storm_radius -= 5000 while self.game_model.next_storm_radius <= 0: self.game_model.next_storm_radius += 5000 self.game_model.next_storm_center[0] = self.game_model.cur_storm_center[0] + random.randint(1, 20000) - 10000 self.game_model.next_storm_center[1] = self.game_model.cur_storm_center[1] + random.randint(1, 20000) - 10000 # self.game_model.cur_storm_duration = 15 # must update last storm info for i in range(len(self.game_model.cur_storm_center)): self.game_model.prev_storm_center[i] = self.game_model.cur_storm_center[i] self.game_model.prev_storm_radius = self.game_model.cur_storm_radius # send update event evt_storm_update = EventServerUpdateSandStorm() evt_storm_update.from_cid = -1 # TESTING next_grids = self.game_model.true_xy_to_grid(self.game_model.next_storm_center[0], self.game_model.next_storm_center[1]) evt_storm_update.var['cur_center'] = [ pack('<h', next_grids[0])[0], pack('<h', next_grids[1])[0], pack('<h', next_grids[2])[0], pack('<h', next_grids[3])[0], ] # ['\x15', '\x33', '\xa0', '\xa0'] # self.game_model.cur_storm_center evt_storm_update.var['cur_radius'] = self.game_model.next_storm_radius # ACTUALLY NEXT STORM INFO shrink_speed = float( self.game_model.cur_storm_radius - self.game_model.next_storm_radius) / self.game_model.storm_shrink_duration if self.game_model.storm_pkg_count == 1: shrink_speed = 10000 evt_storm_update.var['shrink_speed'] = int(shrink_speed) evt_storm_update.var['time_to_appear_next'] = self.game_model.cur_storm_duration evt_storm_update.var['time_to_shrink'] = self.game_model.storm_shrink_delay self.game_event_manager.broadcast_server_event(evt_storm_update) # print 'center sent:', self.game_model.next_storm_center # set shrink start stamp, otherwise the shrink won't start if self.game_model.storm_pkg_count > 1: # IF NOT FIRST PACKAGE self.game_model.storm_shrink_start_stamp = time.time() + self.game_model.storm_shrink_delay # print 'storm radius:', self.game_model.cur_storm_radius # print 'time until next storm:', self.game_model.cur_storm_duration # print 'shrink duration:', self.game_model.storm_shrink_duration pass except Exception, e: print e gevent.sleep(GAME_LOGIC_INTERVAL)
def clear_room(self): garage_util.log_garage('clear room ' + str(self.room_id), True) self.game_model.game_model_init()