Project

Profile

Help

How to connect?
Download (6.13 KB) Statistics View on GitHub Reload from mirrored respository
| Branch: | Tag: | Revision:

github / src / game.py @ 96664dff

1
# Copyright (c) 2016, LE GOFF Vincent
2
# All rights reserved.
3

    
4
# Redistribution and use in source and binary forms, with or without
5
# modification, are permitted provided that the following conditions are met:
6

    
7
# * Redistributions of source code must retain the above copyright notice, this
8
#   list of conditions and the following disclaimer.
9

    
10
# * Redistributions in binary form must reproduce the above copyright notice,
11
#   this list of conditions and the following disclaimer in the documentation
12
#   and/or other materials provided with the distribution.
13

    
14
# * Neither the name of ytranslate nor the names of its
15
#   contributors may be used to endorse or promote products derived from
16
#   this software without specific prior written permission.
17

    
18
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28

    
29
"""This file contains the GameEngine class."""
30

    
31
import os
32

    
33
from enum import Enum
34
from twisted.internet import ssl, reactor
35

    
36
from client import CocoFactory
37
from config import Settings
38
from log import logger, begin
39
from sharp.engine import SharpScript
40
from world import World, MergingMethod
41

    
42
class Level(Enum):
43

    
44
    """Enumeration for a feature level.
45

46
    Features at the top level have the value "engine". They will be
47
    common across all worlds and characters. Features are often defined
48
    at the world level (common across characters) or at the character
49
    level (specific to this character).
50

51
    For instance, look at the macros, triggers and aliases.
52

53
    """
54

    
55
    engine = 1
56
    world = 2
57
    character = 3
58
    category = 4
59

    
60

    
61
class GameEngine:
62

    
63
    """A class representing the game engine.
64

65
    An instance of this class is to be created each time the program
66
    runs.  It doesn't handle thegraphical user interface, but centralizes
67
    about anything else:  the main configuration, world configuration
68
    of different games, aliases, macros, triggers and so on.  The
69
    GUI has a direct access to the engine and can therefore access it.
70

71
    """
72

    
73
    def __init__(self):
74
        self.logger = logger("")
75
        begin()
76
        self.settings = Settings(self)
77
        self.sounds = True
78
        self.worlds = {}
79
        self.default_world = None
80
        self.level = Level.engine
81
        self.logger.info("CocoMUD engine started")
82

    
83
    def load(self):
84
        """Load the configuration."""
85
        self.logger.info("Loading the user's configuration...")
86
        self.settings.load()
87
        self.TTS_on = self.settings["options.TTS.on"]
88
        self.TTS_outside = self.settings["options.TTS.outside"]
89

    
90
        # For each world, set the game engine
91
        for world in self.worlds.values():
92
            world.engine = self
93

    
94
    def open(self, host, port, world, panel=None):
95
        """Connect to the specified host and port.
96

97
        This method creates and returns a 'Factory' class initialized
98
        with the specified information.  It also tries to connect a
99
        client to this factory.
100

101
        """
102
        self.logger.info("Creating a client for {host}:{port}".format(
103
                host=host, port=port))
104

    
105
        self.prepare_world(world)
106
        factory = CocoFactory(world, panel)
107

    
108
        if world.protocol.lower() == "ssl":
109
            reactor.connectSSL(host, port, factory,
110
                    ssl.ClientContextFactory())
111
        else:
112
            reactor.connectTCP(host, port, factory)
113

    
114
        return factory
115

    
116
    def open_help(self, name):
117
        """Open the selected help file in HTML format.
118

119
        This method open the browser with the appropriate file.
120
        The file is the one in the user's language, unless it cannot
121
        be found.
122

123
        """
124
        lang = self.settings.get_language()
125
        filename = name + ".html"
126
        path = os.path.join("doc", lang, filename)
127
        if os.path.exists(path):
128
            self.logger.debug("Open the help file for {} (lang={})".format(
129
                    name, lang))
130
            os.startfile(path)
131
            return
132

    
133
        # Try English
134
        path = os.path.join("doc", "en", filename)
135
        if os.path.exists(path):
136
            self.logger.debug("Open the help file for {} (lang=en)".format(
137
                    name))
138
            os.startfile(path)
139
            return
140

    
141
        # Neither worked
142
        self.logger.debug("The documentation for the {} help file " \
143
                "cannot be found, either using lang={} or lang=en".format(
144
                name, lang))
145

    
146
    def get_world(self, name):
147
        """Return the selected world either by its name or location."""
148
        name = name.lower()
149
        for world in self.worlds.values():
150
            if world.name.lower() == name:
151
                return world
152
            elif world.location == name:
153
                return world
154

    
155
        return None
156

    
157
    def create_world(self, name):
158
        """Create a world."""
159
        world = World(name.lower())
160
        world.engine = self
161
        return world
162

    
163
    def prepare_world(self, world, merge=None):
164
        """Prepare the world, creating appropriate values."""
165
        if not world.sharp_engine:
166
            sharp_engine = SharpScript(self, None, world)
167
            world.sharp_engine = sharp_engine
168

    
169
        if merge is not None:
170
            if merge == "ignore":
171
                world.merging = MergingMethod.ignore
172
            elif merge == "replace":
173
                world.merging = MergingMethod.replace
174
            else:
175
                raise ValueError("unkwno merging method: {}".format(
176
                        merge))
177

    
178
    def stop(self):
179
        """Stop the game engine and close the sessions."""
180
        reactor.stop()
(9-9/19)