def __init__(self, *args, **kwargs): socketserver.ThreadingTCPServer.__init__(self, *args, **kwargs) self._stop = threading.Event() self.world = WorldServer(self) self.players = {} # Dict of all players connected. {ipaddress: requesthandler,} self.player_ids = [] # List of all players this session, indexes are their ID's [0: first requesthandler,] self.command_parser = CommandParser()
async def on_ready(): '''Triggers once the bot is connected''' bot.channel = bot.get_channel(args.channel) bot.parser = CommandParser(bot) await bot.change_presence(status=discord.Status.offline, afk=True) if bot.channel is None: if args.channel is not None: cprint('Invalid channel ID provided.', 'red') cprint('\n'.join(('Logged in as {0.user} in no specified channel.'.format(bot), 'Send a channel ID to start the program')), 'green') else: cprint('Logged in as {0.user} in #{0.channel.name}'.format(bot), 'green')
class CommandsTest(unittest.TestCase): def setUp(self): self.parser = CommandParser() def test_add_command(self): self.parser.add_command('plus', plus) self.assertEqual({'plus': plus}, self.parser._CommandParser__commands) def test_parse_arguments(self): result = self.parser.parse_arguments('(1, 2)') # ToDo def test_execute_key_error(self): self.parser.add_command('plus', plus) result = self.parser.execute('minus; 3') self.assertEqual('No such command', result) def test_execute(self): self.parser.add_command('plus', plus) result = self.parser.execute('plus; (1, 2)') self.assertEqual(3, result)
class IRCBotFactory(protocol.ClientFactory): protocol = IRCBot def __init__(self, hostname, port, channel, path): self.hostname = hostname self.port = port self.channel = channel self.path = path self.commands = CommandParser() def clientConnectionLost(self, connector, reason): print "Connection lost: {}".format(reason) print "Reconnecting..." connector.connect() def clientConnectionFailed(self, connector, reason): print "Connection failed: {}".format(reason) reactor.stop() def command(self, pattern): return self.commands.command(pattern)
def command_BLINK(argv): global blink_delay nargs = len(argv) if nargs == 0: blink_delay = 1.0 elif nargs == 1: blink_delay = float(argv[0]) else: raise TypeError("%s takes up to 1 argument (%d given)" % (__name__, nargs)) print("# set blink_delay=%f" % blink_delay) CP = CommandParser() CP.attach("BLINK", command_BLINK) ################################################################################ # MAIN LOOP time0 = time.monotonic() while True: #handle incoming commands num_rx = physcomp.get_usb_rx_count() if num_rx > 0: data = sys.stdin.read(num_rx) CP.feed(data) #handle the blinking time1 = time.monotonic() if time1 - time0 > blink_delay:
class GameController(Controller): def __init__(self, window): super(GameController, self).__init__(window) self.sector = None self.time_of_day = 0.0 self.count = 0 self.clock = 6 self.light_y = 1.0 self.light_z = 1.0 self.bg_red = 0.0 self.bg_green = 0.0 self.bg_blue = 0.0 self.hour_deg = 15.0 self.highlighted_block = None self.block_damage = 0 self.crack = None self.mouse_pressed = False self.last_key = None self.sorted = False def update(self, dt): sector = sectorize(self.player.position) if sector != self.sector: self.model.change_sectors(self.sector, sector) # When the world is loaded, show every visible sector. if self.sector is None: self.model.process_entire_queue() self.sector = sector self.model.content_update(dt) m = 8 df = min(dt, 0.2) for _ in xrange(m): self.player.update(df / m, self) if self.mouse_pressed: vector = self.player.get_sight_vector() block, previous = self.model.hit_test(self.player.position, vector, self.player.attack_range) if block: if self.highlighted_block != block: self.set_highlighted_block(block) else: self.set_highlighted_block(None) if self.highlighted_block: hit_block = self.model[self.highlighted_block] if hit_block.hardness >= 0: multiplier = 1 current_item = self.item_list.get_current_block() if current_item is not None: if isinstance(current_item, Tool): # tool if current_item.tool_type == hit_block.digging_tool: multiplier = current_item.multiplier self.block_damage += self.player.attack_power * dt * multiplier if self.block_damage >= hit_block.hardness: self.model.remove_block(self.player, self.highlighted_block) self.set_highlighted_block(None) if hit_block.drop_id is not None and self.player.add_item(hit_block.drop_id): self.item_list.update_items() self.inventory_list.update_items() self.update_time() self.camera.update(dt) def setup(self): glClearColor(self.bg_red, self.bg_green, self.bg_blue, 1) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glEnable(GL_LIGHT1) glEnable(GL_LIGHT2) glEnable(GL_ALPHA_TEST) glAlphaFunc(GL_GREATER, 0.1) glEnable(GL_BLEND) glEnable(GL_LINE_SMOOTH) if G.FOG_ENABLED: glEnable(GL_FOG) glFogfv(GL_FOG_COLOR, vec(self.bg_red, self.bg_green, self.bg_blue, 1)) glHint(GL_FOG_HINT, GL_DONT_CARE) glFogi(GL_FOG_MODE, GL_LINEAR) glFogf(GL_FOG_DENSITY, 0.35) glFogf(GL_FOG_START, 20.0) glFogf(GL_FOG_END, G.DRAW_DISTANCE) # 80) self.focus_block = Block(width=1.05, height=1.05) self.earth = vec(0.8, 0.8, 0.8, 1.0) self.white = vec(1.0, 1.0, 1.0, 1.0) self.ambient = vec(1.0, 1.0, 1.0, 1.0) self.polished = GLfloat(100.0) self.crack_batch = pyglet.graphics.Batch() if G.DISABLE_SAVE and world_exists(G.game_dir, G.SAVE_FILENAME): open_world(self, G.game_dir, G.SAVE_FILENAME) else: self.model = Model() self.player = Player((0, 0, 0), (-20, 0), game_mode=G.GAME_MODE) print("Game mode: " + self.player.game_mode) self.item_list = ItemSelector(self, self.player, self.model) self.inventory_list = InventorySelector(self, self.player, self.model) self.item_list.on_resize(self.window.width, self.window.height) self.inventory_list.on_resize(self.window.width, self.window.height) self.text_input = TextWidget(self.window, "", 0, 0, self.window.width, visible=False, font_name="Arial") self.text_input.push_handlers(on_toggled=self.on_text_input_toggled, key_released=self.text_input_callback) self.chat_box = TextWidget( self.window, "", 0, self.text_input.y + self.text_input.height + 50, self.window.width / 2, height=min(300, self.window.height / 3), visible=False, multi_line=True, readonly=True, font_size=14, font_name="Arial", background_color=(64, 64, 64, 200), ) self.command_parser = CommandParser() self.camera = Camera3D(target=self.player) if G.HUD_ENABLED: self.label = pyglet.text.Label( "", font_name="Arial", font_size=8, x=10, y=self.window.height - 10, anchor_x="left", anchor_y="top", color=(255, 255, 255, 255), ) pyglet.clock.schedule_interval_soft(self.model.process_queue, 1.0 / G.MAX_FPS) def update_time(self): """ The idle function advances the time of day. The day has 24 hours, from sunrise to sunset and from sunrise to second sunset. The time of day is converted to degrees and then to radians. """ if not self.window.exclusive: return time_of_day = self.time_of_day if self.time_of_day < 12.0 else 24.0 - self.time_of_day if time_of_day <= 2.5: self.time_of_day += 1.0 / G.TIME_RATE time_of_day += 1.0 / G.TIME_RATE self.count += 1 else: self.time_of_day += 20.0 / G.TIME_RATE time_of_day += 20.0 / G.TIME_RATE self.count += 1.0 / 20.0 if self.time_of_day > 24.0: self.time_of_day = 0.0 time_of_day = 0.0 side = len(self.model.sectors) * 2.0 self.light_y = 2.0 * side * sin(time_of_day * self.hour_deg * G.DEG_RAD) self.light_z = 2.0 * side * cos(time_of_day * self.hour_deg * G.DEG_RAD) if time_of_day <= 2.5: ambient_value = 1.0 else: ambient_value = 1 - (time_of_day - 2.25) / 9.5 self.ambient = vec(ambient_value, ambient_value, ambient_value, 1.0) # Calculate sky colour according to time of day. sin_t = sin(pi * time_of_day / 12.0) self.bg_red = 0.1 * (1.0 - sin_t) self.bg_green = 0.9 * sin_t self.bg_blue = min(sin_t + 0.4, 0.8) if fmod(self.count / 2, G.TIME_RATE) == 0: if self.clock == 18: self.clock = 6 else: self.clock += 1 def set_highlighted_block(self, block): self.highlighted_block = block self.block_damage = 0 if self.crack: self.crack.delete() self.crack = None def save_to_file(self): if G.DISABLE_SAVE: save_world(self, G.game_dir, G.SAVE_FILENAME) def on_mouse_press(self, x, y, button, modifiers): if self.window.exclusive: vector = self.player.get_sight_vector() block, previous = self.model.hit_test(self.player.position, vector, self.player.attack_range) if button == pyglet.window.mouse.LEFT: if block: self.mouse_pressed = True self.set_highlighted_block(None) else: if previous: hit_block = self.model[block] # show craft table gui if hit_block.id == craft_block.id: self.inventory_list.mode = 1 self.inventory_list.toggle(False) return if hit_block.id == furnace_block.id: self.inventory_list.mode = 2 self.inventory_list.toggle(False) return if hit_block.density >= 1: current_block = self.item_list.get_current_block() if current_block is not None: # if current block is an item, # call its on_right_click() method to handle this event if current_block.id >= G.ITEM_ID_MIN: current_block.on_right_click() else: localx, localy, localz = map(operator.sub, previous, normalize(self.player.position)) if localx != 0 or localz != 0 or (localy != 0 and localy != -1): self.model.add_block(previous, current_block) self.item_list.remove_current_block() elif ( self.item_list.get_current_block() and self.item_list.get_current_block().regenerated_health != 0 and self.player.health < self.player.max_health ): self.player.change_health(self.item_list.get_current_block().regenerated_health) self.item_list.get_current_block_item().change_amount(-1) self.item_list.update_health() self.item_list.update_items() else: self.window.set_exclusive_mouse(True) def on_mouse_release(self, x, y, button, modifiers): if self.window.exclusive: self.set_highlighted_block(None) self.mouse_pressed = False def on_mouse_motion(self, x, y, dx, dy): if self.window.exclusive: m = 0.15 x, y = self.player.rotation x, y = x + dx * m, y + dy * m y = max(-90, min(90, y)) self.player.rotation = (x, y) self.camera.rotate(x, y) def on_mouse_drag(self, x, y, dx, dy, button, modifiers): if button == pyglet.window.mouse.LEFT: self.on_mouse_motion(x, y, dx, dy) def on_key_press(self, symbol, modifiers): if symbol == G.TOGGLE_HUD_KEY: G.HUD_ENABLED = not G.HUD_ENABLED elif symbol == G.SAVE_KEY: self.save_to_file() elif symbol == G.INVENTORY_SORT_KEY: if self.last_key == symbol and not self.sorted: self.player.quick_slots.sort() self.player.inventory.sort() self.sorted = True else: self.player.quick_slots.change_sort_mode() self.player.inventory.change_sort_mode() self.item_list.update_items() self.inventory_list.update_items() elif symbol == G.INVENTORY_KEY: self.set_highlighted_block(None) self.mouse_pressed = False self.inventory_list.toggle() elif symbol == G.SOUND_UP_KEY: G.EFFECT_VOLUME = min(G.EFFECT_VOLUME + 0.1, 1) elif symbol == G.SOUND_DOWN_KEY: G.EFFECT_VOLUME = max(G.EFFECT_VOLUME - 0.1, 0) self.last_key = symbol def on_key_release(self, symbol, modifiers): if symbol == G.TALK_KEY: self.toggle_text_input() return pyglet.event.EVENT_HANDLED def on_resize(self, width, height): if G.HUD_ENABLED: self.label.y = height - 10 self.text_input.resize(x=0, y=0, width=self.window.width) self.chat_box.resize( x=0, y=self.text_input.y + self.text_input.height + 50, width=self.window.width / 2, height=min(300, self.window.height / 3), ) def set_3d(self): width, height = self.window.get_size() if G.FOG_ENABLED: glFogfv(GL_FOG_COLOR, vec(self.bg_red, self.bg_green, self.bg_blue, 1.0)) glEnable(GL_DEPTH_TEST) glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) glLoadIdentity() gluPerspective(G.FOV, width / float(height), G.NEAR_CLIP_DISTANCE, G.FAR_CLIP_DISTANCE) glMatrixMode(GL_MODELVIEW) glLoadIdentity() self.camera.transform() glEnable(GL_LIGHTING) glLightfv(GL_LIGHT0, GL_DIFFUSE, vec(0.9, 0.9, 0.9, 1.0)) glLightfv(GL_LIGHT0, GL_SPECULAR, vec(0.9, 0.9, 0.9, 1.0)) glLightfv(GL_LIGHT0, GL_POSITION, vec(1.0, self.light_y, self.light_z, 1.0)) glLightfv(GL_LIGHT1, GL_AMBIENT, self.ambient) glLightfv(GL_LIGHT2, GL_AMBIENT, self.ambient) glMaterialfv(GL_FRONT, GL_AMBIENT, self.earth) glMaterialfv(GL_FRONT, GL_DIFFUSE, self.white) glMaterialfv(GL_FRONT, GL_SHININESS, self.polished) def clear(self): glClearColor(self.bg_red, self.bg_green, self.bg_blue, 1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) def on_draw(self): self.clear() self.set_3d() glColor3d(1, 1, 1) self.model.batch.draw() self.model.transparency_batch.draw() self.crack_batch.draw() self.draw_focused_block() self.set_2d() if G.HUD_ENABLED: self.draw_label() self.item_list.draw() self.inventory_list.draw() self.text_input.draw() self.chat_box.draw() def show_cracks(self, hit_block, vertex_data): if self.block_damage: # also show the cracks crack_level = int(CRACK_LEVELS * self.block_damage / hit_block.hardness) # range: [0, CRACK_LEVELS[ if crack_level >= CRACK_LEVELS: return texture_data = crack_textures.texture_data[crack_level] count = len(texture_data) / 2 if self.crack: self.crack.delete() self.crack = self.crack_batch.add( count, GL_QUADS, self.model.group, ("v3f/static", vertex_data), ("t2f/static", texture_data) ) def draw_focused_block(self): glDisable(GL_LIGHTING) vector = self.player.get_sight_vector() position = self.model.hit_test(self.player.position, vector, self.player.attack_range)[0] if position: hit_block = self.model[position] if hit_block.density >= 1: self.focus_block.width = hit_block.width * 1.05 self.focus_block.height = hit_block.height * 1.05 vertex_data = self.focus_block.get_vertices(*position) if hit_block.hardness > 0.0: self.show_cracks(hit_block, vertex_data) glColor3d(0, 0, 0) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE) pyglet.graphics.draw(24, GL_QUADS, ("v3f/static", vertex_data)) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) def draw_label(self): x, y, z = self.player.position self.label.text = "%.1f %02d (%.2f, %.2f, %.2f) %d / %d" % ( self.time_of_day if (self.time_of_day < 12.0) else (24.0 - self.time_of_day), pyglet.clock.get_fps(), x, y, z, len(self.model._shown), len(self.model), ) self.label.draw() def write_line(self, text, **kwargs): self.chat_box.write_line(text, **kwargs) def text_input_callback(self, symbol, modifier): if symbol == G.VALIDATE_KEY: txt = self.text_input.text.replace("\n", "") try: ex = self.command_parser.execute(txt, controller=self, user=self.player, world=self.model) if ex != COMMAND_HANDLED: # Not a command self.write_line("> %s" % txt, color=(255, 255, 255, 255)) self.text_input.clear() except CommandException, e: error = str(e) self.write_line(error, color=COMMAND_ERROR_COLOR) return pyglet.event.EVENT_HANDLED
def setup(self): glClearColor(self.bg_red, self.bg_green, self.bg_blue, 1) glEnable(GL_LIGHTING) glEnable(GL_LIGHT0) glEnable(GL_LIGHT1) glEnable(GL_LIGHT2) glEnable(GL_ALPHA_TEST) glAlphaFunc(GL_GREATER, 0.1) glEnable(GL_BLEND) glEnable(GL_LINE_SMOOTH) if G.FOG_ENABLED: glEnable(GL_FOG) glFogfv(GL_FOG_COLOR, vec(self.bg_red, self.bg_green, self.bg_blue, 1)) glHint(GL_FOG_HINT, GL_DONT_CARE) glFogi(GL_FOG_MODE, GL_LINEAR) glFogf(GL_FOG_DENSITY, 0.35) glFogf(GL_FOG_START, 20.0) glFogf(GL_FOG_END, G.DRAW_DISTANCE) # 80) self.focus_block = Block(width=1.05, height=1.05) self.earth = vec(0.8, 0.8, 0.8, 1.0) self.white = vec(1.0, 1.0, 1.0, 1.0) self.ambient = vec(1.0, 1.0, 1.0, 1.0) self.polished = GLfloat(100.0) self.crack_batch = pyglet.graphics.Batch() if G.DISABLE_SAVE and world_exists(G.game_dir, G.SAVE_FILENAME): open_world(self, G.game_dir, G.SAVE_FILENAME) else: self.model = Model() self.player = Player((0, 0, 0), (-20, 0), game_mode=G.GAME_MODE) print("Game mode: " + self.player.game_mode) self.item_list = ItemSelector(self, self.player, self.model) self.inventory_list = InventorySelector(self, self.player, self.model) self.item_list.on_resize(self.window.width, self.window.height) self.inventory_list.on_resize(self.window.width, self.window.height) self.text_input = TextWidget(self.window, "", 0, 0, self.window.width, visible=False, font_name="Arial") self.text_input.push_handlers(on_toggled=self.on_text_input_toggled, key_released=self.text_input_callback) self.chat_box = TextWidget( self.window, "", 0, self.text_input.y + self.text_input.height + 50, self.window.width / 2, height=min(300, self.window.height / 3), visible=False, multi_line=True, readonly=True, font_size=14, font_name="Arial", background_color=(64, 64, 64, 200), ) self.command_parser = CommandParser() self.camera = Camera3D(target=self.player) if G.HUD_ENABLED: self.label = pyglet.text.Label( "", font_name="Arial", font_size=8, x=10, y=self.window.height - 10, anchor_x="left", anchor_y="top", color=(255, 255, 255, 255), ) pyglet.clock.schedule_interval_soft(self.model.process_queue, 1.0 / G.MAX_FPS)
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): inventory = "\0" * ( 4 * 40 ) # Currently, is serialized to be 4 bytes * (27 inv + 9 quickbar + 4 armor) = 160 bytes command_parser = CommandParser() operator = False def sendpacket(self, size, packet): self.request.sendall(struct.pack("i", 5 + size) + packet) def sendchat(self, txt, color=(255, 255, 255, 255)): txt = txt.encode('utf-8') self.sendpacket(len(txt) + 4, "\5" + txt + struct.pack("BBBB", *color)) def sendinfo(self, info, color=(255, 255, 255, 255)): info = info.encode('utf-8') self.sendpacket( len(info) + 4, "\5" + info + struct.pack("BBBB", *color)) def broadcast(self, txt): for player in self.server.players.itervalues(): player.sendchat(txt) def sendpos(self, pos_bytes, mom_bytes): self.sendpacket( 38, "\x08" + struct.pack("H", self.id) + mom_bytes + pos_bytes) def lookup_player(self, playername): # find player by name for player in self.server.players.values(): if player.username == playername: return player return None def handle(self): self.username = str(self.client_address) print "Client connecting...", self.client_address self.server.players[self.client_address] = self self.server.player_ids.append(self) self.id = len(self.server.player_ids) - 1 try: self.loop() except socket.error as e: if self.server._stop.isSet(): return # Socket error while shutting down doesn't matter if e[0] in (10053, 10054): print "Client %s %s crashed." % (self.username, self.client_address) else: raise e def loop(self): world, players = self.server.world, self.server.players while 1: byte = self.request.recv(1) if not byte: return # The client has disconnected intentionally packettype = struct.unpack("B", byte)[0] # Client Packet Type if packettype == 1: # Sector request sector = struct.unpack("iii", self.request.recv(4 * 3)) if sector not in world.sectors: with world.server_lock: world.open_sector(sector) if not world.sectors[sector]: #Empty sector, send packet 2 self.sendpacket(12, "\2" + struct.pack("iii", *sector)) else: msg = struct.pack("iii", *sector) + save_sector_to_string( world, sector) + world.get_exposed_sector(sector) self.sendpacket(len(msg), "\1" + msg) elif packettype == 3: # Add block positionbytes = self.request.recv(4 * 3) blockbytes = self.request.recv(2) position = struct.unpack("iii", positionbytes) blockid = G.BLOCKS_DIR[struct.unpack("BB", blockbytes)] with world.server_lock: world.add_block(position, blockid, sync=False) for address in players: if address is self.client_address: continue # He told us, we don't need to tell him players[address].sendpacket( 14, "\3" + positionbytes + blockbytes) elif packettype == 4: # Remove block positionbytes = self.request.recv(4 * 3) with world.server_lock: world.remove_block(struct.unpack("iii", positionbytes), sync=False) for address in players: if address is self.client_address: continue # He told us, we don't need to tell him players[address].sendpacket(12, "\4" + positionbytes) elif packettype == 5: # Receive chat text txtlen = struct.unpack("i", self.request.recv(4))[0] raw_txt = self.request.recv(txtlen).decode('utf-8') txt = "%s: %s" % (self.username, raw_txt) try: if raw_txt[0] == '/': ex = self.command_parser.execute(raw_txt, user=self, world=world) if ex != COMMAND_HANDLED: self.sendchat('$$rUnknown command.') else: # Not a command, send the chat to all players for address in players: players[address].sendchat(txt) print txt # May as well let console see it too except CommandException, e: self.sendchat(str(e), COMMAND_ERROR_COLOR) elif packettype == 6: # Player Inventory Update self.inventory = self.request.recv(4 * 40) #TODO: All player's inventories should be autosaved at a regular interval. elif packettype == 8: # Player Movement mom_bytes, pos_bytes = self.request.recv( 4 * 3), self.request.recv(8 * 3) self.momentum = struct.unpack("fff", mom_bytes) self.position = struct.unpack("ddd", pos_bytes) for address in players: if address is self.client_address: continue # He told us, we don't need to tell him #TODO: Only send to nearby players players[address].sendpacket( 38, "\x08" + struct.pack("H", self.id) + mom_bytes + pos_bytes)
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): inv = None def get_inv(self): global inv return inv def set_inv(self, value): global inv inv = value # if type(value[1]) == bytes: # raise Exception("") print("INVENTORY_EX:", value) inventory = property( get_inv, set_inv ) # "\0" * (4 * 40) # Currently, is serialized to be 4 bytes * (27 inv + 9 quickbar + 4 armor) = 160 bytes command_parser = CommandParser() operator = False def __init__(self, *args, **kwargs): super(ThreadedTCPRequestHandler, self).__init__(*args, **kwargs) self.packageSystem = PackageSystem(self.request) def sendpacket(self, size, packet): # py_000002 = struct.pack("i", 5 + size) # print(py_000002, packet) # if type(packet) == str: # packet = packet.encode("utf-8") # self.request.sendall(py_000002 + packet) if not hasattr(self, "packageSystem"): self.packageSystem = PackageSystem(self.request) # print("SENDPACKET_SERVER:", packet) if packet["packetType"] != 1 and packet["packetType"] != 2 else None # if packet["packetType"] == 6: # exit(0) self.packageSystem: PackageSystem self.packageSystem.sendall(packet) def sendchat(self, txt, color=(255, 255, 255, 255)): txt = txt.encode('utf-8') self.sendpacket(None, { "packetType": 5, "packet": { "message": txt, "color": color } }) # self.sendpacket(len(txt) + 4, b"\5" + txt + struct.pack("BBBB", *color)) def sendinfo(self, info, color=(255, 255, 255, 255)): info = info.encode('utf-8') self.sendpacket(None, { "packetType": 5, "packet": { "message": info, "color": color } }) # self.sendpacket(len(info) + 4, "\5" + info + struct.pack("BBBB", *color)) def broadcast(self, txt): for player in self.server.players.values(): player.sendchat(txt) def sendpos(self, pos_bytes, mom_bytes, *, momentum, position): self.sendpacket( None, { "packetType": 8, "packet": { "playerID": self.id, "momentum": momentum, "position": position } }) # self.sendpacket(38, "\x08" + struct.pack("H", self.id) + mom_bytes + pos_bytes) def lookup_player(self, playername): # find player by name for player in list(self.server.players.values()): if player.username == playername: return player return None def handle(self): self.username = str(self.client_address) print("Client connecting...", self.client_address) self.server.players[self.client_address] = self self.server.player_ids.append(self) self.id = len(self.server.player_ids) - 1 try: self.loop() except socket.error as e: if self.server._stop.isSet(): return # Socket error while shutting down doesn't matter if e[0] in (10053, 10054): print("Client %s %s crashed." % (self.username, self.client_address)) else: raise e def loop(self): world, players = self.server.world, self.server.players package_system = PackageSystem(self.request) while 1: # byte = self.request.recv(1) try: data = package_system.recv() except ValueError: return # print("Server recieved packet: %s" % data) packettype = data["packetType"] packet = data["packet"] # print(f"SERVERPACKET:", data) if packettype != 1 else None # if not byte: return # The client has disconnected intentionally # packettype = struct.unpack("B", byte)[0] # Client Packet Type if packettype == 1: # Sector request # sector = struct.unpack("iii", self.request.recv(4 * 3)) sector = packet["sector"] # print("SECTORCHANGE_CURRENT:", sector) # print("SECTORCHANGE_ALL:", world.sectors) # print("SECTORIZE_NEW:", sector in world.sectors) if sector not in world.sectors: with world.server_lock: world.open_sector(sector) if not world.sectors[sector]: # Empty sector, send packet 2 self.sendpacket(None, { "packetType": 2, "packet": { "sector": sector } }) # self.sendpacket(12, b"\2" + struct.pack("iii", *sector)) else: # py_000005 = save_sector_to_string(world, sector) # py_000003 = (py_000005.encode("utf-8") if type(py_000005) == str else py_000005) # py_000004 = world.get_exposed_sector(sector).encode("utf-8") # msg = struct.pack("iii", *sector) + py_000003 + py_000004 self.sendpacket( None, { "packetType": 1, "packet": { "sector": sector, "exposedSector": world.get_exposed_sector(sector), "sectorData": save_sector_to_string( world, sector) } }) # self.sendpacket(len(msg), b"\1" + msg) elif packettype == 3: # Add block # positionbytes = self.request.recv(4 * 3) # blockbytes = self.request.recv(2) position = packet["position"] blockid = G.BLOCKS_DIR[packet["block"]] # position = struct.unpack("iii", positionbytes) # blockid = G.BLOCKS_DIR[struct.unpack("BB", blockbytes)] with world.server_lock: world.add_block(position, blockid, sync=False) for address in players: if address is self.client_address: continue # He told us, we don't need to tell him players[address].packageSystem.send({ "packetType": 3, "packet": { "position": position, "block": blockid } }) # players[address].sendpacket(14, "\3" + positionbytes + blockbytes) elif packettype == 4: # Remove block # positionbytes = self.request.recv(4 * 3) with world.server_lock: world.remove_block(packet["position"], sync=False) for address in players: if address is self.client_address: continue # He told us, we don't need to tell him players[address].sendpacket(12, "\4" + positionbytes) elif packettype == 5: # Receive chat text # txtlen = struct.unpack("i", self.request.recv(4))[0] # raw_txt = self.request.recv(txtlen).decode('utf-8') raw_txt = packet["message"].decode() txt = "%s: %s" % (self.username.decode(), raw_txt) try: if raw_txt[0] == '/': ex = self.command_parser.execute(raw_txt, user=self, world=world) if ex != COMMAND_HANDLED: self.sendchat('$$rUnknown command.') else: # Not a command, send the chat to all players for address in players: players[address].sendchat(txt) print(txt) # May as well let console see it too except CommandException as e: self.sendchat(str(e), COMMAND_ERROR_COLOR) elif packettype == 6: # Player Inventory Update print("SERVER_PACKET06:", packet) self.inventory = packet["items"] # TODO: All player's inventories should be autosaved at a regular interval. pass elif packettype == 8: # Player Movement # mom_bytes, pos_bytes = self.request.recv(4 * 3), self.request.recv(8 * 3) # self.momentum = struct.unpack("fff", mom_bytes) # self.position = struct.unpack("ddd", pos_bytes) self.momentum = packet["momentum"] self.position = packet["position"] for address in players: if address is self.client_address: continue # He told us, we don't need to tell him # TODO: Only send to nearby players self.sendpacket( None, { "packetType": 8, "packet": { "playerID": self.id, "momentum": self.momentum, "position": self.position } }) # players[address].sendpacket(38, "\x08" + struct.pack("H", self.id) + mom_bytes + pos_bytes) elif packettype == 9: # Player Jump # raise NotImplementedError("Player Jump not implemented") for address in players: if address is self.client_address: continue # He told us, we don't need to tell him # TODO: Only send to nearby players players[address].sendpacket(None, { "packetType": 9, "package": { "playerID": self.id } }) # players[address].sendpacket(2, "\x09" + struct.pack("H", self.id)) elif packettype == 10: # Update Tile Entity # block_pos = struct.unpack("iii", self.request.recv(4 * 3)) # ent_size = struct.unpack("i", self.request.recv(4))[0] # world[block_pos].update_tile_entity(self.request.recv(ent_size)) pass elif packettype == 255: # Initial Login # txtlen = struct.unpack("i", self.request.recv(4))[0] # data2 = package_system.recv() self.username = packet["username"] # position = packet["position"] # self.username = self.request.recv(txtlen).decode('utf-8') self.position = None load_player(self, "world") for player in self.server.players.values(): player.sendchat("$$y%s has connected." % self.username) print("%s's username is %s" % (self.client_address, self.username)) position = (0, self.server.world.terraingen.get_height(0, 0) + 2, 0) if self.position is None: self.position = position # New player, set initial position # Send list of current players to the newcomer for player in self.server.players.values(): if player is self: continue name = player.username.encode('utf-8') self.sendpacket( None, { "packetType": 7, "packet": { "playerID": player.id, "username": name } }) # self.sendpacket(2 + len(name), '\7' + struct.pack("H", player.id) + name) # Send the newcomer's name to all current players name = self.username for player in self.server.players.values(): if player is self: continue player.sendpacket( None, { "packetType": 7, "packet": { "playerID": self.id, "username": name } }) # player.sendpacket(2 + len(name), '\7' + struct.pack("H", self.id) + name) # Send them the sector under their feet first so they don't fall sector = sectorize(position) if sector not in world.sectors: with world.server_lock: world.open_sector(sector) py_000001 = struct.pack("iii", *sector) sector_string = save_sector_to_string(world, sector) exposed_sector = world.get_exposed_sector(sector) # print(py_000001, sector_string, exposed_sector) msg = py_000001 + sector_string + exposed_sector.encode( 'utf-8') self.sendpacket( None, { "packetType": 1, "packet": { "sector": sector, "exposedSector": exposed_sector, "sectorData": sector_string } }) # self.sendpacket(len(msg), b"\1" + msg) # Send them their spawn position and world seed(for client side biome generator) seed_packet = make_string_packet(G.SEED) self.sendpacket( None, { "packetType": 255, "packet": { "position": position, "seed": G.SEED } }) # self.sendpacket(12 + len(seed_packet), # struct.pack("B", 255) + struct.pack("iii", *position) + seed_packet) print("IMPORTANT0004:", self.inventory) print("IMPORTANT0005:", len(self.inventory) + 1) self.sendpacket(None, { "packetType": 6, "packet": { "items": self.inventory } }) # self.sendpacket(len(self.inventory)+1, "\6" + self.inventory) else: print("Received unknown packettype", packettype) def finish(self): print("Client disconnected,", self.client_address, self.username) try: del self.server.players[self.client_address] except KeyError: pass for player in self.server.players.values(): player.sendchat("%s has disconnected." % self.username) # Send user list for player in self.server.players.values(): player.sendpacket(2 + 1, '\7' + struct.pack("H", self.id) + '\0') save_player(self, "world")
def start(self): cp = CommandParser() cp.add_command('show_movies', self.show_all_movies) cp.add_command('add_movie', self.add_movie) cp.add_command('add_projection', self.add_movie_projection) cp.add_command('show_projections', self.show_projections) cp.add_command('add_reservation', self.add_reservation) while True: user_input = input() if user_input == 'exit': break else: print(cp.execute(user_input))
def __init__(self, hostname, port, channel, path): self.hostname = hostname self.port = port self.channel = channel self.path = path self.commands = CommandParser()
def setUp(self): self.parser = CommandParser()