summaryrefslogblamecommitdiff
path: root/game/01_init.rpy
blob: 10f7908445e62c642671756f9972df2fb5ddbee3 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

















                                                                                        
                                                                               


                                              
                                                                         
                  
                                                           






                                                                                                        






                                                                                                                                                                         
 


                                            
                                                   




                                                                   


                                                                           

                                                 




                                     


                                                 
                        


                       
                      
                   
                                     

                   







                         
                  
              
                    







                                                                                                                       




                    

















                      
                      

                      
                      
                      






                      











                         
                         

                         

                         
 


















                               








                                    

                                  


                           




















                                                   






                               



                                                








































































                                                                                    
                                                                 
                                              
                                                          





                                                                                        
                                             



                               
                                  













                                                                      





                                                             
                       
                             






                                                    
                             





                                                    


















                                                          



                                                       
                                                                                 

                       
                                       
                         






                                                               
                                                                   



                                                     
                                                                                                                                                  


                                           
              





                                                        
                                                                       





                                               
                                                                      





                                               
                                                                      





                                               
                                                                      





                                             
                                                                    





                                                 
                                                                        




                                     



                                                                  




                                

                      
########################################################################################
#     This file is part of Spheres.
#     Copyright (C) 2019  Jesusalva

#     This library is free software; you can redistribute it and/or
#     modify it under the terms of the GNU Lesser General Public
#     License as published by the Free Software Foundation; either
#     version 2.1 of the License, or (at your option) any later version.

#     This library is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#     Lesser General Public License for more details.

#     You should have received a copy of the GNU Lesser General Public
#     License along with this library; if not, write to the Free Software
#     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
########################################################################################
# Definitions (critical appliances, classes, imports, renpy internals, updater)

init -3 python:
    renpy.add_python_directory("python-extra")
    import requests, zlib, base64, sys, copy, uuid, time, json, traceback
    import os.path
    from ws4py.client.threadedclient import WebSocketClient

    # set PYTHON_VERSION variable (should be 2713, 3605 could fail)
    PYTHON_VERSION="%d%d%02d" % (sys.version_info.major, sys.version_info.minor, sys.version_info.micro)
    PYTHON_VERSION=int(PYTHON_VERSION)

    # Ren'Py should come with Python 2.7.10 (2710), but just in case
    # After all, I only tested with 2.7.10, 2.7.13 and 2.7.15
    if (PYTHON_VERSION < 2700):
        raise Exception("WARNING: Python version is too old\nStrange bugs may happen on your client.\n\nClick on \"Ignore\" to continue.\nClick on \"Quit\" to exit.")
    # From Python 3.6.x up to Python 3.9.x supported
    elif (PYTHON_VERSION > 3600 and PYTHON_VERSION < 4000):
        pass
    else:
        raise Exception("WARNING: Python version is too recent\nStrange bugs may happen on your client.\n\nClick on \"Ignore\" to continue.\nClick on \"Quit\" to exit.")

    # Configuration
    config.autoreload = False
    config.save_on_mobile_background = False
    persistent.release_name = "Diamond Python VIII"
    if persistent.host is None:
        persistent.host="spheres.tmw2.org"
        persistent.serverlist=[["TMW2", "spheres.tmw2.org", 61000]]
        # FIXME: Set good defaults (=bad) for Android
        if renpy.android:
            persistent.ssl_enabled=False
        else:
            persistent.serverlist.append(["Localhost", "localhost", 61000])
    if persistent.MyUID is None:
        persistent.MyUID=uuid.uuid4().hex.upper()
    if (persistent.allfiles is None):
        persistent.allfiles=[]
    allfiles=[]
    HOST=str(persistent.host)
    PORT=str(persistent.port)
    FAILUREMSG="Request failed, Please try again"
    OFFLINEMSG="401 Unauthorized"
    OKMSG="200 OK"
    TIMEOUT_INTERVAL=5.0
    MAX_IRC_BUFFER=50
    SSL_IS_BROKEN=False
    CERT_NONE=0
    INT_MAX=2147483647
    MAX_RETRIES = 3
    debug=copy.copy(config.developer)
    TERMINATE=False
    CLOSING=False

    # Error Codes
    ERR_JSONDECODER=101
    ERR_LOGIN_DEFAULT=102
    ERR_INVALID=103
    ERR_TIMEOUT=104
    ERR_NOGEMS=105
    ERR_INVFULL=106
    ERR_SUMMON=108
    ERR_OK=200
    ERR_OUTDATED=401

    # All error code library
    ERRNO=[FAILUREMSG, OFFLINEMSG, OKMSG, ERR_LOGIN_DEFAULT, ERR_INVALID, ERR_TIMEOUT, ERR_NOGEMS, ERR_INVFULL, ERR_OK]

    # Core musics/sfx
    MUSIC_OPENING="sfx/bgm01.mp3"
    MUSIC_TOWN="sfx/bgm02.mp3"

    # Battle actions
    ACT_NONE    =0
    ACT_TURN    =1
    ACT_SUMMON  =2

    # Spheres actions
    AP_NONE     =False
    AP_SPHERE   =1
    AP_SKILL    =2

    # Status
    ST_TOWN     =0
    ST_QUEST    =1

    # Unit flags
    UF_NOLVL    =1
    UF_NOPART   =2
    UF_EXPUP    =4
    UF_EVOMAT   =8
    UF_SUPEREVO =64

    # Jobs
    Job_Swordsman   =1
    Job_Undefined1  =2
    Job_Mage        =3
    Job_Archer      =4
    Job_Undefined2  =5
    Job_Special     =6

    # IRC flags
    IRC_AUTH_NONE   =0
    IRC_AUTH_USER   =1
    IRC_AUTH_NICK   =2
    IRC_AUTH_CHAN   =3

    # Spheres
    SPH_NONE        =0
    SPH_WIDEATTACK  =1
    SPH_PIERCE      =2
    SPH_ASSAULT     =3
    SPH_HEAL        =4
    SPH_HEALALL     =5
    SPH_ATKUP       =6
    SPH_DEFUP       =7

    # Combat code
    SRV_SKILL       =1000
    SRV_SERVER      =9900
    SRV_WAVE        =9901
    SRV_SPHERE      =9902
    SRV_SUMMON      =9903
    SRV_NOCAST      =9904

    # Special error structs
    ERR_MOBSTRUCT   ={
            "name": "ERROR",
            "unit_id": 0,
            "max_hp": 0,
            "hp": 0,
            "atk": 0,
            "ele": 0,
            "status_effects": 0
            }
    ERR_PLAYERSTRUCT={
            "unit_id": 0,
            "max_hp": 0,
            "hp": 0,
            "atk": 0,
            "ele": 0,
            "status_effects": 0
            }


    # Returns human readable job
    def parse_job(JOB):
        if (JOB == Job_Swordsman):
            return _("Swordsmaster")
        elif (JOB == Job_Mage):
            return _("Wizard")
        elif (JOB == Job_Archer):
            return _("Ranger")
        elif (JOB == Job_Special):
            return _("Special")
        else:
            return _("???")

    # Smart Print command
    def stdout(message):
        if debug:
            if renpy.android:
                if not renpy.is_init_phase():
                    renpy.notify(message)
            else:
                print(message)
            renpy.write_log("[DEBUG] %s" % message)
        else:
            renpy.write_log("[GAME] %s" % message)
        return

    # Smart wait
    def sdelay(delta=0.02):
        try:
            renpy.pause(delta, hard=True)
        except:
            time.sleep(delta)
        return

    # IF Then Else (IFTE)
    def ifte(ifs, then, elses):
        if (ifs):
            return then
        else:
            return elses

    # Returns number of seconds since UNIX EPOCH
    def now():
        return int(time.time())

    # Global classes
    # We need to override standard list method. Original by Triptych (stackoverflow)
    class dlist(list):

        def __setitem__(self, index, value):
            size = len(self)
            if index >= size:
                self.extend(None for _ in range(size, index + 1))

            list.__setitem__(self, index, value)

    class ExecuteOnCall():
        def __init__(self, callable, *args, **kwargs):
            self.callable = callable
            self.args = args
            self.kwargs = kwargs

        def __call__(self):
            rv = self.callable(*self.args, **self.kwargs)
            return rv

        def id(self):
            return self.__call__()

    class RetString():
        def __init__(self, string):
            self.string = string

        def __call__(self):
            return self.string

        def id(self):
            return self.__call__()

    # Screen Functions/class
    # Override
    class SpheresMainMenu(MainMenu):
        def __call__(self):

            if not self.get_sensitive():
                return

            if self.confirm:
                if config.autosave_on_quit:
                    renpy.force_autosave()

                layout.yesno_screen(layout.MAIN_MENU, SpheresMainMenu(False))
            else:
                # Flush labels/sockets/timers as needed
                renpy.call_in_new_context("quit")
                # Restart
                renpy.full_restart(config.game_main_transition)

    class ExtraImage(renpy.display.im.Image):
        """
        Custom image manipulator, based on bink's code, topic 11732
        """

        def __init__(self, loc, **properties):
            """
            @param loc: Where the image really is (get_path already applied)
            """

            super(ExtraImage, self).__init__(loc, **properties)
            self.loc = loc

        def load(self, unscaled=False): # W0221
            try:
                #page = open(self.loc, "rb")
                #pd = page.read()
                #picdata = os.tmpfile()
                #picdata.write(pd)
                #picdata.seek(0) # reset seek position
                #stdout("Requested to open: %s" % repr(self.loc))
                picdata = open(self.loc, "rb")
                #stdout("Picdata is open (%s)" % self.loc)

                if unscaled:
                    surf = renpy.display.pgrender.load_image_unscaled(picdata, self.loc)
                else:
                    surf = renpy.display.pgrender.load_image(picdata, self.loc)

                #stdout("Picdata was closed")
                picdata.close()
                #page.close()

                return surf
            except Exception as e:
                if renpy.config.missing_image_callback:
                    im = renpy.config.missing_image_callback(self.loc)
                    if im is None:
                        raise e
                    return im.load()
                raise

    def virtpos(posix):
        if isinstance(posix, float):
            return posix*1024
        else:
            return posix/1024.0

    # File Managment Functions
    # We could use Android/data/org.renpy.mygame/files/game
    # to patch directly and achieve a better experience, BUT
    # 1. this code is old, and 2. save folder can easily be
    # retrieved from config and makes testing on Linux closer
    # to the actual android experience (saves on debugging)
    # Meanwhile, Windows has all sort of issues.
    def get_path(path):
        if not renpy.windows:
            path=path.replace("/", "_")
            #return renpy.loader.get_path(path)
            return renpy.config.savedir + "/" + path
        else:
            return renpy.loader.get_path(path)

    def get_path_if_exists(path):
        if not renpy.windows:
            path=path.replace("/", "_")
            #return renpy.loader.get_path(path)
            return renpy.config.savedir + "/" + path
        else:
            return renpy.loader.transfn(path)


    # Override music audio loader
    def SpheresLoadAudioFile(fn):
        """
        Returns a file-like object for the given filename.
        """

        try:
            fna = get_path_if_exists(fn)
            if not os.path.isfile(fna):
                raise Exception("Not a file")
            rv = renpy.loader.open_file(fna, "rb")
        except:
            rv = renpy.loader.load(fn)

        return rv

    renpy.audio.audio.load=SpheresLoadAudioFile

    ## Post setup
    if (persistent.summon is None):
        persistent.summon=ifte(config.developer, 15, 0)

    #############################################################################
    # URL3 Function
    def GAME_UPDATER():
        global tr_uptodate, tr_fatality
        tr_uptodate=False

        # If no version is provided, we are using default files
        # Default files version is "1" (Should never happen)
        if (persistent.version is None):
            persistent.version=1

        # Download upstream version
        x=requests.get("http://"+HOST+'/version.txt', verify=False)
        try:
            ver=int(x.text)
        except:
            stdout("IMPOSSIBLE TO DETERMINE VERSION")
            raise Exception("Could not estabilish a connection to update server:\n%s is not valid." % repr(x.text)) # TODO: Show this beautifully?
            # TODO: Should we set a "ver"?

        if (int(persistent.version) < ver):
          try:
            # TODO: Check if the server have SSL support
            stdout("Downloading updated game data...")

            # Download quests.json
            f=open(get_path("quests.json"), "w")
            stdout("Downloading quests.json")
            x=requests.get("http://"+HOST+'/quests.json', verify=False)
            f.write(x.text)
            f.close()

            # Download units.json
            f=open(get_path("units.json"), "w")
            stdout("Downloading units.json")
            x=requests.get("http://"+HOST+'/units.json', verify=False)
            f.write(x.text)
            f.close()

            # Download story.json
            f=open(get_path("story.json"), "w")
            stdout("Downloading story.json")
            x=requests.get("http://"+HOST+'/story.json', verify=False)
            f.write(x.text)
            f.close()

            # Download world.json
            f=open(get_path("world.json"), "w")
            stdout("Downloading world.json")
            x=requests.get("http://"+HOST+'/world.json', verify=False)
            f.write(x.text)
            f.close()

            # Download bar.json
            f=open(get_path("bar.json"), "w")
            stdout("Downloading bar.json")
            x=requests.get("http://"+HOST+'/bar.json', verify=False)
            f.write(x.text)
            f.close()

            # Download summons.json
            f=open(get_path("summons.json"), "w")
            stdout("Downloading summons.json")
            x=requests.get("http://"+HOST+'/summons.json', verify=False)
            f.write(x.text)
            f.close()

            persistent.version=ver
            stdout("Update complete")
          except:
            tr_fatality = False
            traceback.print_exc()
            stdout("[FATAL] Unable to update JSON files; Aborted")

        # Download server news
        # Handled by GAME_LOADER

        tr_uptodate=True
        return tr_load