MineCraft config editor part 2
February 28, 2012 2 Comments
In our last tutorial I left you with some homework to produce a docsting describing the steps we need to do in order to get our MineCraft config editor up and running.
This is what I came up with:
'''Minecraft config editor: This is an editor for the Minecraft server.properties file. It: * opens the file server.properties * reads, then closes the file * parses each line by -- stripping leading and trailing whitespace -- if the line starts with "#", marks it as a comment -- splits the line into a key, value pair, with the pair separated by a "=" sign -- if the value of the pair is either "true" or "false", the entry is marked as a boolean (ie its only values are either true or false) * displays each key, value entry on the screen allowing you to edit it * renames the server.properties file to server.properties.bup (overwriting any existing file of that name from earlier edits) * opens a new file called server.properties * writes each of the entries to that new file * closes the server.properties file. '''
Did you get something like that? This is our script for writing the program. Most of it we can already do. In fact, the only thing we can’t do at the moment is ” displays each key, value entry on the screen allowing you to edit it”. Hey, notice anything different about that listing? I’ve found WordPress’s special tags for source code. If you run your mouse over it, some widgets will pop up so you can copy and paste the code.
The other part of your homework was to save the contents of the listing in the previous tute to a file called “server.properties”. You need to do that in order to run this tute. Post a comment if you have problems.
Before we dive into reading data from the file we need to think about how we will store the data that we read. From our docstring we can tell that we might need to store a property key, a property value, a comment and whether or not it’s a property which is only true or false. We could use a dictionary to store these but, since we’ve just found out about classes, we’re going to use a class instead. Each instance of the class will hold one line from the configuration file. We can use the From these we can make a class which describes the properties:
class configItem(object): # name of the class, it is based on an object called 'object' def __init__(self, line):# this is called each time an instance of the class is created line = line.strip() # this removes any white space at the start or end of the line # if it starts with a # it's a comment so check for it if line[:1] == "#": self.configKey = "#" self.configVal = line[1:] else: # otherwise assume it's of the form x = y spam = line.split("=") self.configKey = spam[0] self.configVal = spam[1] # now check to see whether the config item takes only the values "true" and "false" if self.configVal.lower() in ["true","false"]: self.isTrueFalse = True else: self.isTrueFalse = False
So, we have our class. What we need to do is read the data from the file (this, of course, won’t work if you haven’t already saved the file). See this tute for reading data from files.
# get data from the file fileName = "server.properties" fileObject = open(fileName,'rb') fileData = fileObject.read() fileObject.close()
Now we will create a configItem instance for each line. However, we’ll need to keep them in something, so we make an array to do that first.
configLines = [] for line in fileData.split('\n'): # this splits it into individual lines configLines.append(configItem(line))
So, our code at the moment looks like this:
class configItem(object): # name of the class, it is based on an object called 'object' def __init__(self, line):# this is called each time an instance of the class is created line = line.strip() # this removes any white space at the start or end of the line # if it starts with a # it's a comment so check for it if line[:1] == "#": self.configKey = "#" self.configVal = line[1:] else: # otherwise assume it's of the form x = y spam = line.split("=") self.configKey = spam[0] self.configVal = spam[1] # now check to see whether the config item takes only the values "true" and "false" if self.configVal.lower() in ["true","false"]: self.isTrueFalse = True else: self.isTrueFalse = False # get data from the file fileName = "server.properties" fileObject = open(fileName,'rb') fileData = fileObject.read() fileObject.close() configLines = [] for line in fileData.split('\n'): # this splits it into individual lines configLines.append(configItem(line)) for c in configLines: print "%s: %s, isTruefalse= %s"%(c.configKey, c.configVal, c.isTrueFalse)
Note: see this tute for what the %s means.
Debugging
When I run this code on my own copy of the server.properties file I get an error:
Traceback (most recent call last): File "serverEditor.py", line 33, in <module> configLines.append(configItem(line)) File "serverEditor.py", line 15, in __init__ self.configVal = spam[1] IndexError: list index out of range
I added a print statement in the class to print the line it received. It turned out that it had trouble because my file had some extra, blank lines at the end of it. So I have added some code to skip the line if it is empty:
for line in fileData.split('\n'): # this splits it into individual lines if line.strip()=='': continue configLines.append(configItem(line))
So now I get this output:
>python serverEditor.py #: Minecraft server properties, isTruefalse= False #: Date and time of creation of file, isTruefalse= False allow-nether: true, isTruefalse= True level-name: world, isTruefalse= False enable-query: false, isTruefalse= True allow-flight: false, isTruefalse= True server-port: 25565, isTruefalse= False level-type: DEFAULT, isTruefalse= False enable-rcon: false, isTruefalse= True level-seed: , isTruefalse= False server-ip: , isTruefalse= False spawn-npcs: true, isTruefalse= True white-list: false, isTruefalse= True spawn-animals: true, isTruefalse= True online-mode: true, isTruefalse= True pvp: true, isTruefalse= True difficulty: 1, isTruefalse= False gamemode: 0, isTruefalse= False max-players: 20, isTruefalse= False spawn-monsters: true, isTruefalse= True generate-structures: true, isTruefalse= True view-distance: 10, isTruefalse= False motd: A Minecraft Server, isTruefalse= False
You should check that the data is all correct. Note that if a line has a value of “true” or “false”, the corresponding item has an attribute called isTrueFalse, which is set to True. So far we have:
* created a class called configItem to describe each line in the file
* opened the file, read each line, and created an instance of the class for each line.
* when a configItem is instantiated, it parses the data which it is initialised with.
Next we will have to work out how to edit them.
Homework: think about what might go wrong with this code.
Here’s the complete code again:
'''Minecraft config editor: This is an editor for the Minecraft server.properties file. It: * opens the file server.properties * reads, then closes the file * parses each line by -- stripping leading and trailing whitespace -- if the line starts with "#", marks it as a comment -- splits the line into a key, value pair, with the pair separated by a "=" sign -- if the value of the pair is either "true" or "false", the entry is marked as a boolean (ie its only values are either true or false) * displays each key, value entry on the screen allowing you to edit it * renames the server.properties file to server.properties.bup (overwriting any existing file of that name from earlier edits) * opens a new file called server.properties * writes each of the entries to that new file * closes the server.properties file. ''' class configItem(object): # name of the class, it is based on an object called 'object' def __init__(self, line):# this is called each time an instance of the class is created line = line.strip() # this removes any white space at the start or end of the line # if it starts with a # it's a comment so check for it if line[:1] == "#": self.configKey = "#" self.configVal = line[1:] else: # otherwise assume it's of the form x = y spam = line.split("=") self.configKey = spam[0] self.configVal = spam[1] # now check to see whether the config item takes only the values "true" and "false" if self.configVal.lower() in ["true","false"]: self.isTrueFalse = True else: self.isTrueFalse = False # get data from the file fileName = "server.properties" fileObject = open(fileName,'rb') fileData = fileObject.read() fileObject.close() configLines = [] for line in fileData.split('\n'): # this splits it into individual lines if line.strip()=='': continue configLines.append(configItem(line)) for c in configLines: print "%s: %s, isTruefalse= %s"%(c.configKey, c.configVal, c.isTrueFalse)
Pingback: Linux News » Python4Kids New Tutorial: MineCraft config editor part 2
Pingback: Links 29/2/2012: Fedora 17 Alpha, MINIX 3.2.0 | Techrights