# The script of the game goes in this file. # Declare images #image bg room = Frame("gfx/bg/port.png", 0, 0) image dialog rebel = "gfx/dialog/rebel.png" # Declare characters used by this game. The color argument colorizes the # name of the character. define e = Character("Player") label splashscreen: centered "{b}{color=#f00}Disclaimer{/color}\n\nBy running this software, you affirm that you have the right to do so.\nNo license is provided for using this demo software.\n\n\ \ \ {color=#f00}This client may contain assets which {u}does not{/u} belongs to it.\n\ If you are the legal owner of an asset, or their legal representant,\n\ And find an asset of yours illegally used, please, fill a DMCA complaint\n\ by sending an email to {a=mailto:dmca@tmw2.org}dmca@tmw2.org{/a}.{/color}\n\ \n\ \n\ No warranties.{/b}{fast}" return init python: # FIXME: Drop dead if session_id mismatches (new "token") # Same as ondata? def onmsg(self, message): global tr_load, tr_val, tr_busy stdout("Server : " + message) # Inform whatever is waiting for us that a reply was obtained tr_load=True tr_val=str(received) # We do not clean tr_busy here return def ondata(self, msg, dtype, cont): #print("data received") """ on_data: callback object which is called when a message received. This is called before on_message or on_cont_message, and then on_message or on_cont_message is called. on_data has 4 argument. The 1st argument is this class object. The 2nd argument is utf-8 string which we get from the server. The 3rd argument is data type. ABNF.OPCODE_TEXT or ABNF.OPCODE_BINARY will be came. The 4th argument is continue flag. if 0, the data continue """ #renpy.notify(msg) return def onopen(self): global tr_busy, tr_load, tr_val, HOST print("Opening connection to %s" % HOST) tr_load=True tr_val="" tr_busy=False self.send("Ping") def onerror(self, err): stdout("ERROR RECEIVED") stdout("More details: %s" % repr(err)) stdout("An error happened: %s" % str(err)) renpy.full_restart() raise err # Inform you are now ingame label start: # Begin the initial displays # TODO: a fairy :( scene black show spinner at truecenter # Initial configuration python: tr_busy=True tr_val="" tr_load=False session_id=uuid.uuid4().hex "We shall now begin testing a websocket" python: ws=persistent.ws if (ws is not None): stdout("Socket exists, trying to reuse connection...") try: boom = send_packet_now("ping") if not boom: del boom raise del boom except: ws = None if ws is None: # server, sock, address # on_open=None, on_message=None, on_error=None, # on_close=None, on_ping=None, on_pong=None, # on_data=None): if (persistent.ssl_enabled): stdout(_("Opening new secure socket...")) ws = wsock.WebSocketApp("wss://"+HOST+":61000", on_data=ondata, on_error=onerror, on_open=onopen, on_message=onmsg) ws.on_open = onopen renpy.invoke_in_thread(ws.run_forever, sslopt={"cert_reqs": CERT_NONE}) else: stdout(_("Opening new socket...")) ws = wsock.WebSocketApp("ws://"+HOST+":61000", on_data=ondata, on_error=onerror, on_open=onopen, on_message=onmsg) ws.on_open = onopen renpy.invoke_in_thread(ws.run_forever) #ws.connect("wss://localhost:61000") while not tr_load: renpy.pause(0.02) hide spinner "Connection established!" $ send_packet("Hello world") "Message sent!" return # Run updater python: tr_load=False renpy.invoke_in_thread(GAME_UPDATER) while not tr_load: renpy.pause(0.1) tr_load=False renpy.invoke_in_thread(GAME_LOADER) while not tr_load: renpy.pause(0.1) # Open game scene bg town with Dissolve(0.3) pause 0.1 #show dialog rebel $ password=persistent.password $ email="" # Check if we need to register if persistent.password is None: call screen welcome return # Otherwise just login jump login # Registration procedures # You don't have an account yet label register_email: python: import re regex = '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$' email = "" # Ask player for their email while email == "": email=renpy.call_screen("input_box", "Welcome to %s!\nPlease insert your email to register an account: \n{size=12}Your account password will be emailed to you. This is the only way to recover a lost account. You can use an {a=https://www.tempmailaddress.com/}Temporary email{/a} if you wish.{/size}" % (config.name)) if not re.search(regex, email): email="" renpy.call_screen("msgbox", "The email you've entered is not valid.") # You've inserted a valid email raw=send_packet("register", """{"email": "%s"}""" % email) bt=json_decode(raw) try: password=bt["password"] valid=True except: # Either a SQL error, or a server error, or a connection error... # But either way, we can't proceed! renpy.call_screen("msgbox", "An error happened, maybe this email is already registered.\nPlease try again later.") valid=False # An error happened, return to login screen if not valid: jump start # Save data $ persistent.password=password jump login # Registration procedures # You already have an account and want to recover it label register_password: python: password="" while password == "": password=renpy.call_screen("input_box", "Welcome to %s!\nPlease insert your password: " % (config.name)) if not password.isalnum(): renpy.call_screen("msgbox", "The password you've entered is not valid.") password="" jump login # Login procedures label login: $message=login() # TODO=load message $ stdout(message) python: try: message=int(message) import copy dlcode=copy.copy(message) except: print "AN ERROR HAPPENED AT LOGIN TIME" stdout("Invalid: "+str(message)) message=-1 if (message < 5000): if (message == ERR_LOGIN_DEFAULT): e "Error Code: [message]{fast}\n\nCould not estabilish connection to server." jump login else: e "Error Code: [message]{fast}\n\nCannot login to server. Terminating." return # Successful login? Update client data and begin routines $ persistent.password=password $ dlcode-=5000 #$ ping_routine() $ renpy.invoke_in_thread(irc_loop) # We're now logged in, load misc data (TODO: What if ERR_ is returned?) $ who = -1 $ inv=get_inventory() python: for a in inv: Player["inv"].append(a) # Run AP Timer if needed if (Player["ap"] < Player["max_ap"]): ApTimer=Timer(360.0, ap_restore) ApTimer.start() # Remove some temporary variables $ del password if (email): $ del email jump prologue # Begin loop play music MUSIC_TOWN fadein 0.5 # Show news (if they exist and you haven't logged in past day) if dlcode: if (len(allnews) >= 1): call screen show_news else: $stdout("This server doesn't have a MOTD") # TODO: Daily login rewards screen label loop: # Delete predictions, if possible $ renpy.free_memory() # Maybe we're in combat? If we are, you cannot go to town if (Player["status"] >= ST_QUEST): window hide None $ renpy.call_screen("msgbox", "{b}Battle{/b}\n\nYou are in battle. You'll be brought back to combat.") #window show None $ Battle=reload_battle() # TODO: Handle errors if (Battle in [ERR_JSONDECODER]): e "Unknown Error: [ERR_JSONDECODER]" jump loop play music MUSIC_BATTLE.id() fadein 0.5 jump combat $ hud_show() menu: "Development Options" if config.developer: $message="Development login OK" menu: "Send ping packet": $message=send_packet("ping") pass "Redeclare Image": $m=renpy.call_screen("input_box", "Image Name: ") $renpy.image("redeclared", m) "We'll now display Redeclared" show redeclared at truecenter with dissolve pause "So?" hide redeclared with None pass "Quest Editor": jump quest_editors "List party members": $message=get_party(1) "Update client": jump updater_editors "Do nothing": pass "World Map": jump quest_select "Manage Party": jump party_lobby_enter "Show inventory": jump inventory "Visit tavern": jump tavern "PUB": # TODO this needs its own label if persistent.nickname is not None: python: while True: _return=renpy.call_screen("pub") if _return != "": res=irc_send(persistent.nickname, _return) else: break else: "ERROR" "You are not authorized to complete this operation.\n\nERR_NICK" "Logout": #$message=send_packet("logout") jump quit #"Server replies:" "[message]" #return if (message == OFFLINEMSG): "Server replies:" "[message]\n\nYou are offline?" return if (message not in [ERR_OK, OKMSG, True]): "Server replies:" "[message]" jump loop # This ends the game. return label restore: # Restore town view scene bg town #show dialog rebel play music MUSIC_TOWN fadein 0.5 $ hud_show() jump loop label prologue: $ hud_story() call SQ00001_prologue # Automatically begin quest $ Battle=loadquest(1) $ update_ap(-1) play music MUSIC_BATTLE.id() fadein 0.5 $ renpy.free_memory() window hide jump combat #"Go to Capital, where you'll be formally appointed and receive a mission" #"Graduating: You (tactician / whatever) - Auto-Presentation" #"You decide it is better to travel to the Capital not alone." #"Giulio, graduate as knight." #"If you complete the mission at Capital, you'll get a job." # --> Mission is derailed if favor of more epic adventure #"Reaching Capital is a test on itself, to see if you have what it takes." #"You can use Crystals to recruit mercenaries and colleagues." # We may want to automatically begin fight 01, and keep important info # on story.json (in case you close the app) jump restore label quit: $ stdout("Received quit signal!") python: # Delete pinger try: Pinger.stop() del Pinger except: pass # Delete ApTimer try: ApTimer.cancel() del ApTimer except: pass # If needed, logout try: token=Player["token"] send_packet("logout") del Player except: pass # If needed, close the socket try: ws.close() except: pass # Delete variables try: del allunitsbase del allunits del header del allnews del allstory del allworld del alltaverns except: pass # Terminate IRC connection try: irc_kill() except NameError: pass # Data cleaned up # Destroy the socket $ persistent.ws = None $ print("Sockets closed and data flushed!") return