def load(cls, directory: str, definitions: str) -> World: wrapper = cls(directory, definitions) fp = open(path.join(directory, "level.dat"), "rb") root_tag = nbt.NBTFile(fileobj=fp) fp.close() return World(directory, root_tag, wrapper)
def readconsole(self, buff): """Internally-used function that parses a particular console line. """ if not self.wrapper.events.callevent( "server.consoleMessage", {"message": buff}): return False if len(buff) < 1: return # Standardize the line to only include the text (removing # time and log pre-pends) line_words = buff.split(' ')[self.prepends_offset:] # find the actual offset is where server output line # starts (minus date/time and info stamps). # .. and load the proper ops file if "Starting minecraft server version" in buff and \ self.prepends_offset == 0: for place in range(len(line_words)-1): self.prepends_offset = place if line_words[place] == "Starting": break line_words = buff.split(' ')[self.prepends_offset:] self.version = getargs(line_words, 4) semantics = self.version.split(".") release = get_int(getargs(semantics, 0)) major = get_int(getargs(semantics, 1)) minor = get_int(getargs(semantics, 2)) self.version_compute = minor + (major * 100) + (release * 10000) # 1.7.6 (protocol 5) is the cutoff where ops.txt became ops.json if self.version_compute > 10705 and self.protocolVersion < 0: self.protocolVersion = 5 self.refresh_ops() if len(line_words) < 1: return # the server attempted to print a blank line if len(line_words[0]) < 1: print('') return # parse or modify the server output section # # # Over-ride OP help console display if "/op <player>" in buff: new_usage = "player> [-s SUPER-OP] [-o OFFLINE] [-l <level>]" message = buff.replace("player>", new_usage) buff = message if "While this makes the game possible to play" in buff: prefix = " ".join(buff.split(' ')[:self.prepends_offset]) if not self.wrapper.wrapper_onlinemode: message = ( "%s Since you are running Wrapper in OFFLINE mode, THIS " "COULD BE SERIOUS!\n%s Wrapper is not handling any" " authenication.\n%s This is only ok if this wrapper " "is not accessible from either port %s or port %s" " (I.e., this wrapper is a multiworld for a hub server, or" " you are doing your own authorization via a plugin)." % ( prefix, prefix, prefix, self.server_port, self.wrapper.proxy.proxy_port)) else: message = ( "%s Since you are running Wrapper in proxy mode, this" " should be ok because Wrapper is handling the" " authenication, PROVIDED no one can access port" " %s from outside your network." % ( prefix, self.server_port)) if self.wrapper.proxymode: buff = message # check for server console spam before printing to wrapper console server_spaming = False for things in self.spammy_stuff: if things in buff: server_spaming = True # server_spaming setting does not stop it from being parsed below. if not server_spaming: if not self.server_muted: self.wrapper.write_stdout(buff, "server") else: self.queued_lines.append(buff) # region server console parsing section # read port of server if "Starting Minecraft server" in buff: self.server_port = get_int(buff.split('on *:')[1]) # confirm server start elif "Done (" in buff: self._toggle_server_started() self.changestate(STARTED) self.log.info("Server started") self.bootTime = time.time() # Getting world name elif "Preparing level" in buff: self.worldname = getargs(line_words, 2).replace('"', "") self.world = World(self.worldname, self) if self.wrapper.proxymode: self.entity_control = EntityControl(self) # Player Message if getargs(line_words, 0)[0] == "<": name = self.stripspecial(getargs(line_words, 0)[1:-1]) message = self.stripspecial(getargsafter(line_words, 1)) original = getargsafter(line_words, 0) self.wrapper.events.callevent("player.message", { "player": self.getplayer(name), "message": message, "original": original }) # Player Login elif getargs(line_words, 1) == "logged": name = self.stripspecial( getargs(line_words, 0)[0:getargs(line_words, 0).find("[")]) eid = get_int(getargs(line_words, 6)) locationtext = getargs(buff.split(" ("), 1)[:-1].split(", ") locationtext[0] = locationtext[0].replace("[world]", "") location = get_int( float(locationtext[0])), get_int( float(locationtext[1])), get_int( float(locationtext[2])) self.login(name, eid, location) # Player Logout elif "lost connection" in buff: name = getargs(line_words, 0) self.logout(name) # player action elif getargs(line_words, 0) == "*": name = self.stripspecial(getargs(line_words, 1)) message = self.stripspecial(getargsafter(line_words, 2)) self.wrapper.events.callevent("player.action", { "player": self.getplayer(name), "action": message }) # Player Achievement elif "has just earned the achievement" in buff: name = self.stripspecial(getargs(line_words, 0)) achievement = getargsafter(line_words, 6) self.wrapper.events.callevent("player.achievement", { "player": name, "achievement": achievement }) # /say command elif getargs( line_words, 0)[0] == "[" and getargs(line_words, 0)[-1] == "]": if self.getservertype != "vanilla": # Unfortunately, Spigot and Bukkit output things # that conflict with this. return name = self.stripspecial(getargs(line_words, 0)[1:-1]) message = self.stripspecial(getargsafter(line_words, 1)) original = getargsafter(line_words, 0) self.wrapper.events.callevent("server.say", { "player": name, "message": message, "original": original }) # Player Death elif getargs(line_words, 1) in self.deathprefixes: name = self.stripspecial(getargs(line_words, 0)) self.wrapper.events.callevent("player.death", { "player": self.getplayer(name), "death": getargsafter(line_words, 1) }) # server lagged elif "Can't keep up!" in buff: skipping_ticks = getargs(line_words, 17) self.wrapper.events.callevent("server.lagged", { "ticks": get_int(skipping_ticks) })
def readConsole(self, line): """ Internally-use function that parses a particular console line """ def args(i): try: return line.split(" ")[i] except: return "" def argsAfter(i): try: return " ".join(line.split(" ")[i:]) except: return "" if not self.wrapper.callEvent("server.consoleMessage", {"message": line}): return False print line deathPrefixes = [ "fell", "was", "drowned", "blew", "walked", "went", "burned", "hit", "tried", "died", "got", "starved", "suffocated", "withered" ] if not self.config["General"]["pre-1.7-mode"]: if len(args(3)) < 1: return if args( 3 ) == "Done": # Confirmation that the server finished booting self.changeState(2) self.log.info("Server started") self.bootTime = time.time() elif args(3) == "Preparing" and args( 4) == "level": # Getting world name self.worldName = args(5).replace('"', "") self.world = World(self.worldName, self) elif args(3)[0] == "<": # Player Message name = self.stripSpecial(args(3)[1:-1]) message = self.stripSpecial(argsAfter(4)) original = argsAfter(3) self.wrapper.callEvent( "player.message", { "player": self.getPlayer(name), "message": message, "original": original }) elif args(4) == "logged": # Player Login name = self.stripSpecial(args(3)[0:args(3).find("[")]) self.login(name) elif args(4) == "lost": # Player Logout name = args(3) self.logout(name) elif args(3) == "*": name = self.stripSpecial(args(4)) message = self.stripSpecial(argsAfter(5)) self.wrapper.callEvent("player.action", { "player": self.getPlayer(name), "action": message }) elif args(3)[0] == "[" and args(3)[-1] == "]": # /say command name = self.stripSpecial(args(3)[1:-1]) message = self.stripSpecial(argsAfter(4)) original = argsAfter(3) self.wrapper.callEvent("server.say", { "player": name, "message": message, "original": original }) elif args(4) == "has" and args( 8) == "achievement": # Player Achievement name = self.stripSpecial(args(3)) achievement = argsAfter(9) self.wrapper.callEvent("player.achievement", { "player": name, "achievement": achievement }) elif args(4) in deathPrefixes: # Player Death name = self.stripSpecial(args(3)) self.wrapper.callEvent("player.death", { "player": self.getPlayer(name), "death": argsAfter(4) }) else: if len(args(3)) < 1: return if args( 3 ) == "Done": # Confirmation that the server finished booting self.changeState(2) self.log.info("Server started") self.bootTime = time.time() elif args(3) == "Preparing" and args( 4) == "level": # Getting world name self.worldName = args(5).replace('"', "") self.world = World(self.worldName) elif args(3)[0] == "<": # Player Message name = self.stripSpecial(args(3)[1:-1]) message = self.stripSpecial(argsAfter(4)) original = argsAfter(3) self.wrapper.callEvent( "player.message", { "player": self.getPlayer(name), "message": message, "original": original }) elif args(4) == "logged": # Player Login name = self.stripSpecial(args(3)[0:args(3).find("[")]) self.login(name) elif args(4) == "lost": # Player Logout name = args(3) self.logout(name) elif args(3) == "*": name = self.stripSpecial(args(4)) message = self.stripSpecial(argsAfter(5)) self.wrapper.callEvent("player.action", { "player": self.getPlayer(name), "action": message }) elif args(3)[0] == "[" and args(3)[-1] == "]": # /say command name = self.stripSpecial(args(3)[1:-1]) message = self.stripSpecial(argsAfter(4)) original = argsAfter(3) if name == "Server": return self.wrapper.callEvent("server.say", { "player": name, "message": message, "original": original }) elif args(4) == "has" and args( 8) == "achievement": # Player Achievement name = self.stripSpecial(args(3)) achievement = argsAfter(9) self.wrapper.callEvent("player.achievement", { "player": name, "achievement": achievement }) elif args(4) in deathPrefixes: # Player Death name = self.stripSpecial(args(3)) deathMessage = self.config["Death"]["death-kick-messages"][ random.randrange( 0, len(self.config["Death"]["death-kick-messages"]))] if self.config["Death"][ "kick-on-death"] and name in self.config["Death"][ "users-to-kick"]: self.console("kick %s %s" % (name, deathMessage)) self.wrapper.callEvent("player.death", { "player": self.getPlayer(name), "death": argsAfter(4) })
def readconsole(self, buff): """Internally-used function that parses a particular console line. """ if len(buff) < 1: return # Standardize the line to only include the text (removing # time and log pre-pends) line_words = buff.split(' ')[self.prepends_offset:] # find the actual offset is where server output line # starts (minus date/time and info stamps). # .. and load the proper ops file if "Starting minecraft server version" in buff and \ self.prepends_offset == 0: for place in range(len(line_words)-1): self.prepends_offset = place if line_words[place] == "Starting": break line_words = buff.split(' ')[self.prepends_offset:] self.vitals.version = getargs(line_words, 4) semantics = self.vitals.version.split(".") release = get_int(getargs(semantics, 0)) major = get_int(getargs(semantics, 1)) minor = get_int(getargs(semantics, 2)) self.vitals.version_compute = minor + (major * 100) + (release * 10000) # noqa # 1.7.6 (protocol 5) is the cutoff where ops.txt became ops.json if self.vitals.version_compute > 10705 and self.vitals.protocolVersion < 0: # noqa self.vitals.protocolVersion = 5 self.wrapper.api.registerPermission("mc1.7.6", value=True) if self.vitals.version_compute < 10702 and self.wrapper.proxymode: self.log.warning("\nProxy mode cannot run because the " "server is a pre-Netty version:\n\n" "http://wiki.vg/Protocol_version_numbers" "#Versions_before_the_Netty_rewrite\n\n" "Server will continue in non-proxy mode.") self.wrapper.disable_proxymode() return self.refresh_ops() if len(line_words) < 1: return # the server attempted to print a blank line if len(line_words[0]) < 1: print('') return # parse or modify the server output section # # # Over-ride OP help console display if "/op <player>" in buff: new_usage = "player> [-s SUPER-OP] [-o OFFLINE] [-l <level>]" message = buff.replace("player>", new_usage) buff = message if "/whitelist <on|off" in buff: new_usage = "/whitelist <on|off|list|add|remvove|reload|offline|online>" # noqa message = new_usage buff = message if "While this makes the game possible to play" in buff: prefix = " ".join(buff.split(' ')[:self.prepends_offset]) if not self.wrapper.wrapper_onlinemode: message = ( "%s Since you are running Wrapper in OFFLINE mode, THIS " "COULD BE SERIOUS!\n%s Wrapper is not handling any" " authentication.\n%s This is only ok if this wrapper " "is not accessible from either port %s or port %s" " (I.e., this wrapper is a multiworld for a hub server, or" " you are doing your own authorization via a plugin)." % ( prefix, prefix, prefix, self.vitals.server_port, self.wrapper.proxy.proxy_port)) else: message = ( "%s Since you are running Wrapper in proxy mode, this" " should be ok because Wrapper is handling the" " authentication, PROVIDED no one can access port" " %s from outside your network." % ( prefix, self.vitals.server_port)) if self.wrapper.proxymode: buff = message # read port of server and display proxy port, if applicable if "Starting Minecraft server on" in buff: self.vitals.server_port = get_int(buff.split(':')[-1:][0]) # check for server console spam before printing to wrapper console server_spaming = False for things in self.vitals.spammy_stuff: if things in buff: server_spaming = True # server_spaming setting does not stop it from being parsed below. if not server_spaming: if not self.server_muted: self.wrapper.write_stdout(buff, "server") else: self.queued_lines.append(buff) first_word = getargs(line_words, 0) second_word = getargs(line_words, 1) # be careful about how these elif's are handled! # confirm server start if "Done (" in buff: self._toggle_server_started() self.changestate(STARTED) self.log.info("Server started") if self.wrapper.proxymode: self.log.info("Proxy listening on *:%s", self.wrapper.proxy.proxy_port) # noqa # Getting world name elif "Preparing level" in buff: self.vitals.worldname = getargs(line_words, 2).replace('"', "") self.world = World(self.vitals.worldname, self) # Player Message elif first_word[0] == "<": # get a name out of <name> name = self.stripspecial(first_word[1:-1]) message = self.stripspecial(getargsafter(line_words, 1)) original = getargsafter(line_words, 0) playerobj = self.getplayer(name) if playerobj: self.wrapper.events.callevent("player.message", { "player": self.getplayer(name), "message": message, "original": original }, abortable=False) """ eventdoc <group> core/mcserver.py <group> <description> Player chat scrubbed from the console. <description> <abortable> No <abortable> <comments> This event is triggered by console chat which has already been sent. This event returns the player object. if used in a string context, ("%s") it's repr (self.__str__) is self.username (no need to do str(player) or player.username in plugin code). <comments> <payload> "player": playerobject (self.__str__ represents as player.username) "message": <str> type - what the player said in chat. ('hello everyone') "original": The original line of text from the console ('<mcplayer> hello everyone`) <payload> """ # noqa else: self.log.debug("Console has chat from '%s', but wrapper has no " "known logged-in player object by that name.", name) # noqa # Player Login elif second_word == "logged": user_desc = first_word.split("[/") name = user_desc[0] ip_addr = user_desc[1].split(":")[0] eid = get_int(getargs(line_words, 6)) locationtext = getargs(buff.split(" ("), 1)[:-1].split(", ") # spigot versus vanilla # SPIGOT - [12:13:19 INFO]: *******[/] logged in with entity id 123 at ([world]316.86789318152546, 67.12426603789697, -191.9069627257038) # noqa # VANILLA - [23:24:34] [Server thread/INFO]: *******[/127.0.0.1:47434] logged in with entity id 149 at (46.29907483845001, 63.0, -270.1293488726086) # noqa if len(locationtext[0].split("]")) > 1: x_c = get_int(float(locationtext[0].split("]")[1])) else: x_c = get_int(float(locationtext[0])) y_c = get_int(float(locationtext[1])) z_c = get_int(float(locationtext[2])) location = x_c, y_c, z_c self.login(name, eid, location, ip_addr) # Player Logout elif "lost connection" in buff: name = first_word self.logout(name) # player action elif first_word == "*": name = self.stripspecial(second_word) message = self.stripspecial(getargsafter(line_words, 2)) self.wrapper.events.callevent("player.action", { "player": self.getplayer(name), "action": message }, abortable=False) # Player Achievement elif "has just earned the achievement" in buff: name = self.stripspecial(first_word) achievement = getargsafter(line_words, 6) self.wrapper.events.callevent("player.achievement", { "player": name, "achievement": achievement }, abortable=False) # /say command elif getargs( line_words, 0)[0] == "[" and first_word[-1] == "]": if self.getservertype != "vanilla": # Unfortunately, Spigot and Bukkit output things # that conflict with this. return name = self.stripspecial(first_word[1:-1]) message = self.stripspecial(getargsafter(line_words, 1)) original = getargsafter(line_words, 0) self.wrapper.events.callevent("server.say", { "player": name, "message": message, "original": original }, abortable=False) # Player Death elif second_word in self.deathprefixes: name = self.stripspecial(first_word) self.wrapper.events.callevent("player.death", { "player": self.getplayer(name), "death": getargsafter(line_words, 1) }, abortable=False) # server lagged elif "Can't keep up!" in buff: skipping_ticks = getargs(line_words, 17) self.wrapper.events.callevent("server.lagged", { "ticks": get_int(skipping_ticks) }, abortable=False) # player teleport elif second_word == "Teleported" and getargs(line_words, 3) == "to": playername = getargs(line_words, 2) # [SurestTexas00: Teleported SapperLeader to 48.49417131908783, 77.67081086259394, -279.88880690937475] # noqa if playername in self.wrapper.servervitals.players: playerobj = self.getplayer(playername) playerobj._position = [ get_int(float(getargs(line_words, 4).split(",")[0])), get_int(float(getargs(line_words, 5).split(",")[0])), get_int(float(getargs(line_words, 6).split("]")[0])), 0, 0 ] self.wrapper.events.callevent( "player.teleport", {"player": playerobj}, abortable=False) """ eventdoc <group> core/mcserver.py <group> <description> When player teleports. <description> <abortable> No <abortable> <comments> driven from console message "Teleported ___ to ....". <comments> <payload> "player": player object <payload> """ # noqa elif first_word == "Teleported" and getargs(line_words, 2) == "to": playername = second_word # Teleported SurestTexas00 to 48.49417131908783, 77.67081086259394, -279.88880690937475 # noqa if playername in self.wrapper.servervitals.players: playerobj = self.getplayer(playername) playerobj._position = [ get_int(float(getargs(line_words, 3).split(",")[0])), get_int(float(getargs(line_words, 4).split(",")[0])), get_int(float(getargs(line_words, 5))), 0, 0 ] self.wrapper.events.callevent( "player.teleport", {"player": playerobj}, abortable=False) """ eventdoc