summaryrefslogblamecommitdiff
path: root/game/client.rpy
blob: 1d3d680c06812872ce1fdb381304864fd6e92334 (plain) (tree)
1
2
3
4
5
6
7
8
9





                                                                                 
              
                                                                   
                          
               



                                         
                                       
                                            
                                     
                                        
             

                                                                         

                
                         
                                                        

                                                                                
                                                                                         


                                               
                                                    

                                    
                                                                                
                                         
                                                                      
                                                           




                                                            
                                                                           
                                            
                                    

                                                                   
                                       

                                                                         
                                                    
                               

                                  











                                                                                

                                                                                 
                                                                          
               

                                           
                           

                          
 

                                                                                
                    



                                                       
 
                                                               


                                                                                                                         
 
                                                                       



                                                                        


                                       
                                                         


                                                                      



























                                                                                 
                     



                                                              
                                 

                                                                              





                                                                                                                                    


                                                                                
                                          
                                                                           


                                                               
                                          

              













                                                                         
                                               






                                                 


                                                














                                                                         
                                       




                                 

              
 
#################################################################################
#     This file is part of Mana Launcher.
#     Copyright (C) 2021  Jesusalva <jesusalva@tmw2.org>
#
#     Distributed under the MIT license, except for Steam parts.
#################################################################################
init 2 python:
    def handle_client(CLIENT_NAME="", launch=False, download=True):
        ## Local variables
        f=False
        if (CLIENT_NAME == ""):
            CLIENT_NAME=persistent.client

        ## Main loop
        if (CLIENT_NAME == "manaplus"):
            f=cli_manaplus(launch, download)
        elif (CLIENT_NAME == "mana"):
            f=cli_mana(launch, download)
        else:
            status_update("ERROR, unrecognized client: %s" % CLIENT_NAME)

        return f

    def launch_game(idx):
        global progress, responsive, statusmsg, MLP_DEST
        ########################################################################
        ## Setup
        RPCUpdate(persistent.serverlist[idx]["Name"], persistent.serverlist[idx]["Back"])
        HOST=persistent.serverlist[idx]["Host"]
        PORT=persistent.serverlist[idx]["Port"]
        CMD=handle_client(launch=True)
        OPT="-s %s -y evol2 -p %s -S" % (HOST, PORT)
        stdout("%s %s" % (CMD, OPT))

        ########################################################################
        ## Obtain access token from vault
        ## Failures are skipped (!!) unless they are a 403 (FORBIDDEN)
        statusmsg=_("Requesting credentials from Vault...")
        auth = {"vaultId": vaultId,
                "token": vaultToken,
                "world": persistent.serverlist[idx]["UUID"]}
        PWD=""
        try:
            r=vault.post(VAULT_HOST+"/world_pass", json=auth, timeout=15.0)
            ## We got the access credentials
            if r.status_code == 200:
                auth2=r.json()
                PWD=" -U %s -P %s" % (auth2["user"], auth2["pass"])
            ## We were refused by Vault
            elif r.status_code == 403:
                stdout("Warning: Connection was refused (Vault logout?)")
                statusmsg=_("You're not logged in.")
                time.sleep(1.0)
                responsive = False
                return
            ## We are rate-limited, try again
            elif r.status_code == 429:
                statusmsg=_("Rate limited, we'll try again...")
                time.sleep(15.0)
                r=vault.post(VAULT_HOST+"/world_pass", json=auth, timeout=15.0)
                ## Only accept OK this time
                if r.status_code != 200:
                    stdout("Get World Auth - Returned error %d" % r.status_code)
                    raise Exception("Vault returned error %d" % r.status_code)
                auth2=r.json()
                PWD=" -U %s -P %s" % (auth2["user"], auth2["pass"])
            ## Internal error, maybe?
            else:
                stdout("Get World Auth - Returned error code %d" % r.status_code)
                raise Exception("Vault returned error %d" % r.status_code)
        except:
            traceback.print_exc()
            statusmsg=_("TMW Vault Error.")
            time.sleep(2.5)
            progress = 100
            return

        ########################################################################
        ## Loop
        statusmsg=""
        try:
            ## Minimize to tray if set
            if not renpy.mobile and persistent.iconify:
                renpy.iconify()

            ## Sanitize input to avoid arbitrary code execution
            CMD=CMD.replace(";", "").replace("&", "").replace(">", "").replace("<", "").replace("|", "").replace("$", "")
            OPT=OPT.replace(";", "").replace("&", "").replace(">", "").replace("<", "").replace("|", "").replace("$", "")
            PWD=PWD.replace(";", "").replace("&", "").replace(">", "").replace("<", "").replace("|", "").replace("$", "")

            ## Launch your preferred game client, wait for it to finish
            if renpy.windows:
                app=execute("\"%s\" %s%s" % (CMD, OPT, PWD), shell=True)
            else:
                app=execute("%s %s%s" % (CMD, OPT, PWD), shell=True)

            ## Determine error messages
            if app == 7:
                stdout("[CLIENT] Mirror Lake triggered.")
                ## Give "plenty" time to ensure data will be available
                statusmsg=_("Synchronizing data...")
                time.sleep(0.5)
                try:
                    r=vault.post(VAULT_HOST+"/getlake", json=auth, timeout=15.0)
                    ## We got the access credentials
                    if r.status_code == 200:
                        goto=r.json()["world"]
                        stdout("MLP Target: %s" % str(goto))
                        if goto == "" or goto.lower() == "vault":
                            stdout("Mirror Lake False Positive")
                        else:
                            MLP_DEST=goto
                            progress=100
                            return
                    ## We were refused by Vault
                    elif r.status_code == 403:
                        stdout("Warning: Connection was refused (Vault logout?)")
                        statusmsg=_("You're not logged in.")
                        time.sleep(1.0)
                        responsive = False
                        return
                    else:
                        stdout("[CLIENT] Sync error code %d." % r.status_code)
                        statusmsg=_("Synchronization error.") # 500 = No Lake
                        time.sleep(1.0)
                except:
                    traceback.print_exc()
                    stdout("[CLIENT] Sync failed.")
                    statusmsg=_("Synchronization error.")
                    time.sleep(1.0)
            elif app:
                traceback.print_exc()
                stdout("[CLIENT] An error happened: %d" % app)
                #responsive = False
        except:
            traceback.print_exc()
            stdout("[FATAL] An error happened trying to launch the client D:")
            responsive = False

        # NOTE: Now we would like to un-minimize ourselves
        # But we cannot =/
        # There's a few tricks but not very nice...
        # https://stackoverflow.com/questions/45426203/minimize-window-with-python (Linux)
        # https://stackoverflow.com/questions/2791489/how-do-i-take-out-the-focus-or-minimize-a-window-with-python/2792059 (Windows)

        ########################################################################
        ## Cleanup
        statusmsg=_("Thanks for playing!")
        # time.sleep(0.1) ## TODO: Ensure the world finishes updating Vault
        progress=100

        # Clean discord RPC and go back to world selection menu
        RPCUpdate("Main Menu", "launcher")
        return

    def md5check_client():
      renpy.notify("Checking md5sum...")
      try:
        installdir=get_path(persistent.client)
        fname=handle_client(launch=True, download=False).split("/").pop()
        r=requests.get(persistent.host+"/%s.md5" % fname, timeout=10.0)
        md5up=r.text.replace("\n", "")

        md5us=md5sum(installdir+"/%s" % fname)
        if md5up != md5us:
            stdout("MD5 Mismatch: hashes differ", True)
            stdout("Ours: %s" % md5us, True)
            stdout("Them: %s" % md5up, True)
            shutil.rmtree(get_path(persistent.client))
            renpy.notify("Files are outdated!")
        else:
            renpy.notify("All files up to date!")
      except:
        traceback.print_exc()
        renpy.notify("An error happened.")
        return

    ############################################
    # TODO: Launch thread requesting /soul data
    def load_souldata():
        global progress, responsive, vaultId, vaultToken, mySoul
        try:
            auth = {"vaultId": vaultId,
                    "token": vaultToken}

            ## Make the POST request
            r=vault.post(VAULT_HOST+"/souldata", json=auth, timeout=15.0)
            if r.status_code != 200:
                raise Exception("Request error: %d" % r.status_code)
            dat=r.json()

            ## Update mySoul
            mySoul={}
            mySoul["level"]=dat["soulv"]
            mySoul["exp"]=dat["soulx"]
            mySoul["next"]=dat["varlv"]
            progress = 100
        except:
            traceback.print_exc()
            mySoul = None
            responsive = False
        return