#1 15. März 2006 Online-RPG: Server-Seite Hi, ich freue mich, dass es nun endlich eine Showcase-Unterteilung in dieser Section gibt. Danke an Raid-Rush! Ich mach jetzt mal den ersten und biete einen noch-nicht vollständigen Code eines Online-RPG-Servers. Der Server ist in Python geschrieben. Einiges zur Geschichte und Idee: Ich wusst mal wieder ned, was ich programmieren sollte. Dann hab ich bisschen rumgefragt und am Ende kam dann ein Projekt mit 2 anderen Leuten zusammen. Der eine schreibt den Windows-Clienten mit Visual Basic, der andere macht HP und entwickelt Ideen und Ich schreib die Serverseite. Das Spiel soll in Richtung D&D gehen, weiteres ist aber noch ned klar, also braucht keine Fragen zu stellen . Jeder, der will und ein etwas fortgeschrittenes Projekt angehen will, kann selbst seinen eigenen Clienten jetzt coden. Dazu müsst ihr nur meinen Code etwas interpretieren ( die Schlüsselwörter stehen alle als Commentare drin ) und schon braucht ihr nur noch Socket aufmachen, über port 1337 connecten ( Die IP gibts per PN bei mir ) und eure Funktionen nach Schlüsselwörter aufbauen. Zu diesem Code: An sich gefällt mir mein Source-Code, aber teilweise ist er etwas "unschön" mit den globals geraten. Und ich denke kaum, irgendjemand wird ihn auf das erste mal durchlesen gleich interpretieren können. Also habt ihr auch Zeit, etwas zu knobeln Ausserdem hoff ich, dass er jetzt reinpasst, weil er doch bisher gute 450 Zeilen hat und noch sehr viele dazukommen werden ( PvP = Player vs Player z.b. ). Dieser Code ist also kein vollständiger, sondern nur ein Stück und ich werde nach und nach ihn erweitern. Viel Spass beim interpretieren Für Fragen und Verbesserungsvorschläge steh ich offen ^^. Mfg, Kolazomai Code: Code: #!/usr/bin/python # Name des RPGs # Coded by Kolazomai # ICQ: 329-573-284 # Published under GPL ##################################### ### Name des RPGs ### ##################################### print "###################################" print "### Name des RPGs ###" print "### Server Edition ###" print "###################################" print "Starting Server now ..." ### import ### import SocketServer,os from SocketServer import ThreadingTCPServer from time import gmtime, strftime,sleep ### ### Log ### logfile = "/home/cordel/Heldensagen.log" log = open(logfile,"w") ### ### Variables ### port = 1337 # port clients = {} # {ip:client,...} ips = [] # ips message_pot = {} # messages , i dont know whether i need it messages = [] # same group_all = [] # w00t message_all = "" # ... Login = False # ... gibts = False # ... locals_users = {"Heim":[], "Wald":[], "Gebirge":[], "Tropfsteinhoehle":[], "Vulkan":[], "Untoten-Gruft":[], "Verlassene Zwergenmine":[], "Troll-Lagerstaetten":[], "Hauptstadt Gut":[], "Hauptstadt Boese":[]} # {location:[name1,name2,name3],...} ### # This is a very powerful Variable # It will look like that: # {Name:{Name:<name>,Race:<race>,..},Name2:{...}} # I do have just to call # users_data[Name][<info>] and i get what i want users_data = {} # Values: # Name,Race,Level,Mana,current Mana,Hp,current Hp, # Staerke,Geschick,Avaibility,Location,Experience ### ###### ### class Main ### class main_: def __init__(self): pass # def login(self,data): global Login login_data = data.split('!') ### Get User's Data ### self.users_data_file = open('/home/cordel/rpg/users/' +str(login_data[0])+'.txt','r') self.users_data = self.users_data_file.read() self.users_data = self.users_data.split('\n') self.users_data_file.close() ### if self.users_data[1] == login_data[1]: print_("Server: Login Correct :>") Login = True else: print_("Server: Login Incorrect!") Login = False # def new(self,data): global gibts self.x = data.split("!") try: #File exist? os.stat("/home/cordel/rpg/users/" +str(self.x[0])+".txt") gibts = True except OSError: # no it doesn't self.a = open("/home/cordel/rpg/users/" +str(self.x[0])+".txt","w") self.a.write(str(self.x[0])+'\n')#0.Name self.a.write(str(self.x[1])+'\n')#1.Pass self.a.write(str(self.x[2])+'\n')#2.Race self.a.write("1"+"\n")#3.Level self.a.write("80"+"\n")#4.Mana self.a.write("10"+"\n")#5.Staerke self.a.write("6"+"\n")#6.Geschick self.a.write("100"+"\n")#7.Leben , HP self.a.write("100"+"\n")#8.current HP self.a.write("80"+"\n")#9.current Mana self.a.write("0"+"\n")#10.current Experience self.a.close() # Add this player to all_players# all_players_file = file("/home/cordel/rpg/all_users.txt","a") all_players_file.write(str(self.x[0])+"\n")#Player's name all_players_file.close() # # def get_char_info(self,name,ip): global users_data self.users_data_file = open('/home/cordel/rpg/users/' +str(name)+'.txt','r') self.users_data = self.users_data_file.read() self.users_data = self.users_data.split('\n') self.users_data_file.close() ############################################################## # What i do now: # # there is users_data # # I will pick up the logined user # # and make a new dic for him # # {"Name":"Name",<datas>} # # So all_names will look like that: # # [<ip>:{"name":"Kolazomai","race":"Human",...},<ip>:{...}] # # then I only have to call users_data[client][<info>] # # and i get what i want # ############################################################## # Now i will try to fetch all character-infos # # # # Now i add it to my powerful users_data - variable users_data[name] = {"NAME":str(self.users_data[0]), "RACE":str(self.users_data[2]), "LEVEL":str(self.users_data[3]), "MANA":str(self.users_data[4]), "STAERKE":str(self.users_data[5]), "GESCHICK":str(self.users_data[6]), "LEBEN":str(self.users_data[7]), "CURRENT_LEBEN":str(self.users_data[8]), "CURRENT_MANA":str(self.users_data[9]), "LOCATION":"Heim", "AVAI":0, # short form of Avaibility "EXPERIENCE":str(self.users_data[10])} # puhh, hard job xD # ### ### def print_ ### def print_(it): log.write(str(it)+"\n") print it ### ### def Player Versus Player ### class pvp_: def __init__(self): pass # ------------------------------ def start(self,datas,client): # datas = <cmd><opponent> # There are several pvp-commands if datas[0:3] == "atc": # Return Avaibility what_to_return = "pvpatc" # pvp + command what_to_return += users_data[datas[3:]]["AVAI"] what_to_return += "|" # final letter return what_to_return elif datas[0:3] == "dul": # Send Opp's-Charinfos what_to_return = pvp.get_char_info_opp(datas[3:]) return clients[client]+"!pvpdul"+what_to_return # ------------------------------ def get_char_info_opp(self,opp): print "Get the infos now ..." infos = users_data[opp] # Add the receiving Client's name what_datas = "" for x in infos.values(): what_datas += str(x) what_datas += "!" # Now i got all infos what_datas += "|" # final letter return what_datas ### ### Setting the Server-Routine ### class handling(SocketServer.StreamRequestHandler): def handle(self): client,address = self.client_address print_(str(client)+" is here!") main = main_() active = True while active == True: data = self.request.recv(1000) if client in clients: print_(str(clients[client])+"["+str(client)+"]"+ " said: "+str(data) +" [" +strftime("%a, %d %b %Y %H:%M:%S",gmtime()) +"]") else: print_(str(client)+" said: "+str(data) +" [" +strftime("%a, %d %b %Y %H:%M:%S",gmtime()) +"]") # I will proove, whether # data is a 0-byte-string # if yes, i close the connection if data == "" or data[0:4] == "quit": quit_() active = False break ################# # Now I split data # It's like that: # %<cmd1>%<cmd2>%<cmd3>%<cmdN> # and get some dic # *************************************** # *ALL messages, being received and sent* # *will have a | at the end * # *************************************** data_split = data.split("|") # data_split looks like that: # ['','cmd1','cmd2','cmd3','cmdN'] # I will remove Null-Strings # cause it only takes performance ################# try: data_split.remove('') except: pass ################# print data_split for data_ran in data_split: global message_pot,log,Login,ips,gibts,messages global group_all,message_all,users_data,locals_users if data_ran[0:3] == "log": #logUser!Pass!Race main.login(data_ran[3:]) ips += ["127.0.0.1"]# main.get_char_info("Some_Player","127.0.0.1")# main.login("Some_Player!Some_Player!Mensch")# clients["127.0.0.1"] = "Some_Player"# if Login == True: aa = data_ran[3:].split("!") clients[client] = aa[0] print client,"is now also known as",clients[client] ips += [client] self.request.send(clients[client]+ "!pra"+ "Server: Login erfolgreich!|") main.get_char_info(clients[client],client) # Add this user to the Home-Location locals_users["Heim"].append(clients[client]) Login = False # nur zur Sicherheit elif data_ran[0:3] == "msg": x = data_ran.split('!') #msg!empfaenger!absender!nachricht empfaenger = x[1] absender = x[2] nachricht = x[3] #<Empfaenger>!msg<Nachricht>!<Absender> if empfaenger in messages: self.request.send(str(absender)+"!"+"msg" +str(empfaenger) +"did not receive a previous msg yet" +"!Server|") elif empfaenger <> "all": #the message message_pot[empfaenger] = ( str(empfaenger)+"!" +"msg"+str(nachricht)+"!" +str(absender) ) # add empfaenger to the list messages += [empfaenger] elif empfaenger == "all": # message to all # What i do now: # Add all online Users to group_all # Then create a message_all # If a user req now # I will proove,whether he is in group_all # if yes, i will sent him the message_all # and remove him from group_all # if no, nothing happens # The Problem is, that all guys have to req # till its possible again to send a generall msg if group_all == []: la = [] for x in ips: la += [clients[x]] group_all += la message_all = ( str(empfaenger)+"!" +"msg"+str(nachricht)+"!" +str(absender) ) else: self.request.send(str(absender)+"!"+"msg" +"Can't send a msg" +" to all at the moment" +"!Server|") elif data_ran[0:3] == "req": #req #for chat print "req" if clients[client] in messages: print message_pot #remove the empfaenger messages.remove(clients[client]) #messagepop self.request.send(str (message_pot.pop (clients[client])) +"|") if clients[client] in group_all: self.request.send(message_all+"|") group_all.remove(clients[client]) elif data_ran[0:3] == "new": #newUser!Pass!Race main.new(data_ran[3:]) :mad:_you = data_ran[3:].split("!") # I should work with # if user in all_users.txt: ... if gibts == True: # Account existing allready # editieren ------> V V V V V V V V V V V V V V V self.request.send(str(:mad:_you[0])+"!praServer:"+ " Account does allready exist!|") gibts = False else: self.request.send(str(:mad:_you[0])+"!praServer:"+ " Neuer Benutzer angelegt!|") elif data_ran == "quit": quit_() # active = False will stop the while-statement # unfortunately he'll end it, before breaking active = False # Now i leave the for-statement break elif data_ran[0:3] == "onl": #onl #Send back who's online print "onl" send_it = "all!onlall!" for x in ips: if x <> client: send_it += str(clients[x])+"!" # returns the Names send_it += "$" self.request.send(send_it+"|")# send the data elif data_ran == "save_log": #Save the log and open it again! log.close() log = open(logfile,"a") quit_() break elif data_ran == "akt": #<Empfaenger>!akt<Level>!<Leben im moment> #!<Leben gesamt>!<Mana im Moment>!<Mana gesamt> #!<Geschicklichkeit>!<Staerke>!<Erfahrung>!$ a = clients[client] self.request.send(str(clients[client])+"!"+ "akt"+ str(users_data[a]["LEVEL"])+"!"+ str(users_data[a]["CURRENT_LEBEN"])+"!"+ str(users_data[a]["LEBEN"])+"!"+ str(users_data[a]["CURRENT_MANA"])+"!"+ str(users_data[a]["MANA"])+"!"+ str(users_data[a]["GESCHICK"])+"!"+ str(users_data[a]["STAERKE"])+"!"+ str(users_data[a]["EXPERIENCE"])+"!"+ "$"+ "|") elif data_ran[0:3] == "sav": #savName!Pass!Rasse #!Level!Mana!Staerke! #Geschick!Leben!Leben im moment!Mana im moment! #current Experience x = data_ran[3:].split("!") users_file_ = file("/home/cordel/rpg/users/"+ str(clients[client])+".txt","w") users_file_.write(str(x[0])+"\n")#Name users_file_.write(str(x[1])+"\n")#Password users_file_.write(str(x[2])+"\n")#Rasse users_file_.write(str(x[3])+"\n")#Level users_file_.write(str(x[4])+"\n")#Mana users_file_.write(str(x[5])+"\n")#Staerke users_file_.write(str(x[6])+"\n")#Geschick users_file_.write(str(x[7])+"\n")#Leben users_file_.write(str(x[8])+"\n")#current leben users_file_.write(str(x[9])+"\n")#current mana users_file_.write(str(x[10])+"\n")#current Experience # lots of writing :o users_file_.close() main.get_char_info(clients[client],client) elif data_ran[0:3] == "ara": # ara = actualise place of residence # syntax: araLocality # example: araWood # ------------------ # i send back: ( in 1 string ) # <Empfaenger>!ara<Spielerinmeinemgebiet1(name)>? #<Spielerinmeimemgebiet1(verfuegbarkeit)! #<spielerinmeinemgebiet2(name)>? #<Spielerinmeimemgebiet2(verfuegbarkeit)!$ # --------------- # Localities # Heim ::: 1 # Wald ::: 2 # Gebirge ::: 3 # Tropfsteinhoehle ::: 4 # Vulkan ::: 5 # Untoten-Gruft ::: 6 # Verlassene Zwergmine ::: 7 # Troll-Lagerstaetten ::: 8 # Hauptstadt Gut ::: 9 # Hauptstadt Boese ::: 10 ######################### x = data_ran[3:].split("!") # This is all users in the specified locality teh_clients = locals_users[x[0]] message_ara = (str(clients[client])+"!"+ "ara") for x in range(len(teh_clients)): # I add to message_ara # the name of the boyz in the locations ( teh_clients ) # and then the available key in the users_data if teh_clients[x] <> clients[client]: message_ara += (str(teh_clients[x])+"?"+ str(users_data[teh_clients[x]]["AVAI"])+ "!") message_ara += "Some_Player?0!$" # final letter :-) # Now send it ;-) # print message_ara self.request.send(message_ara+"|") elif data_ran[0:3] == "soa": # soa = *S*-tatus *O*-f *A*-vailability # 0 = available # 1 = not available users_data[clients[client]]["AVAI"] = int(data_ran[3]) elif data_ran[0:3] == "apr": x = data_ran[3:].split("!") # aprNewLocation!OldLocation # user changes location try: # remove user of the location locals_users[x[1]].remove(clients[client]) except: pass # add this user to the location locals_users[x[0]].append(clients[client]) # change the users_data -variable users_data[clients[client]]["LOCATION"] = x[0] elif data_ran[0:3] == "pvp": # pvp<cmd><person> # Send pvp the datas what_to_send = pvp.start(data_ran[3:],client) # It will return, what i need self.request.send(what_to_send) print what_to_send else: print data_ran print "What the F***??" print "Wrong command oO" ### # Where is select case ;-) ? # # Bah, i should've written all in classes :S # # Damnit xD # ### # End of For :P print "/* EoF */" ### ### def quit_ ### def quit_(): #.pop removes the name try: print_(str(clients.pop(client))+"["+str(client)+"]"+ " left!") except: pass #remove the ip try: ips.remove(client) except: pass # remove him from Location try: locals_users[users_data[clients[client]]["LOCATION"]].remove(clients [client]) except: pass try: del users_data[clients[client]] except: pass try: group_all.remove(clients[client]) except: pass ### # Init pvp # pvp = pvp_() # ### Starting the Server ### server = ThreadingTCPServer(("",port), handling) server.serve_forever() ### + Multi-Zitat Zitieren