-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathregistry.py
228 lines (171 loc) · 6.55 KB
/
registry.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import inspect
import sys
from ast import literal_eval
from csv import DictReader
from enum import Enum, unique
from functools import partial
import effects
import behavior
from backpack import Backpack
from entities import Actor, Item
from misc import Singleton
@unique
class Actors(Enum):
HERO = 0
ORC = 1
DRAKE = 2
POOPY = 3
@unique
class Items(Enum):
CANDY = 1
AIR = 2
class RegistryError(NameError):
def __init__(self, message):
super().__init__(message)
class RegistryNotInitializedError(RegistryError):
def __init__(self):
super().__init__("The registry hasn't been initialized yet.")
class BehaviorNotFoundError(RegistryError):
def __init__(self, behavior):
super().__init__(f"The behavior '{behavior}' was not found in the registry.")
class EffectNotFoundError(RegistryError):
def __init__(self, effect):
super().__init__(f"The effect '{effect}' was not found in the registry.")
class ActorNotFoundError(RegistryError):
def __init__(self, actor):
super().__init__(f"The actor '{actor}' was not found in the registry.")
class ItemNotFoundError(RegistryError):
def __init__(self, item):
super().__init__(f"The item '{item}' was not found in the registry.")
class Registry(metaclass=Singleton):
"""
The registry contains info about most classes in the game, serving as a factory for things like actors and items.
The registry is a singleton, and loads all the needed information from json files upon creation. All data remains
loaded in the registry until the game is closed.
"""
behaviors = {}
effect = {}
actors = {}
items = {}
loaded = False
def __init__(cls):
"""
Load all data upon creation.
"""
cls.load()
# Initialize other variables stored in the registry
cls.backpack = Backpack(cls)
cls.loaded = True
@staticmethod
def _load_module(module_name):
def predicate(obj):
return (inspect.isclass(obj) or inspect.isfunction(obj)) and obj.__module__ == module_name
return inspect.getmembers(sys.modules[module_name], predicate)
def _load_behaviors(cls):
cls.behaviors = dict(cls._load_module('behavior'))
def _load_effects(cls):
cls.effect = dict(cls._load_module('effects'))
def _load_actors(cls):
with open('actors.csv', 'r') as f:
reader = DictReader(f, delimiter=';')
for actor in reader:
str_behavior = actor.get('behavior')
# If no behavior is specified, default to null behavior
real_behavior = None
if str_behavior != '':
real_behavior = cls.behaviors.get(str_behavior)
# Convert datatypes to the right ones
actor['key'] = Actors(int(actor.get('key')))
actor['behavior'] = real_behavior
to_literal = ['color']
for arg in to_literal:
actor[arg] = literal_eval(actor.get(arg))
cls.actors[actor['key']] = partial(Actor, **actor)
def _load_items(cls):
with open('items.csv', 'r') as f:
reader = DictReader(f, delimiter=';')
for item in reader:
str_effect = item.get('effect')
real_effect = None
effect_args = item.pop('effect_args')
if str_effect != '':
# Create the effect passing the required args
real_effect = partial(cls.effect.get(str_effect), *literal_eval(effect_args))
# Convert datatypes to the right ones
item['key'] = Items(int(item.get('key')))
item['effect'] = real_effect
to_literal = ['color', 'blocks', 'weight']
for arg in to_literal:
item[arg] = literal_eval(item.get(arg))
cls.items[item['key']] = partial(Item, **item)
def load(cls):
cls._load_behaviors()
cls._load_effects()
cls._load_actors()
cls._load_items()
def _get_behavior(cls, key):
"""
Retrieve the behavior corresponding to the key in the registry.
Args:
key (string): Name of the behavior class to retrieve.
Returns:
The behavior corresponding to the key, if found.
Raises:
BehaviorNotFoundError: If there's no behavior with the given key in the registry.
"""
if not cls.loaded:
raise RegistryNotInitializedError
behavior = cls.behaviors.get(key)
if behavior is None:
raise BehaviorNotFoundError(key)
return behavior
def _get_effect(cls, key):
"""
Retrieve the effect corresponding to the key in the registry.
Args:
key (string): Name of the effect class to retrieve.
Returns:
The effect corresponding to the key, if found, as a function with no args filled in yet.
Raises:
EffectNotFoundError: If there's no effect with the given key in the registry.
"""
if not cls.loaded:
raise RegistryNotInitializedError
effect = cls.effect.get(key)
if effect is None:
raise EffectNotFoundError(key)
return effect
def get_actor(cls, key):
"""
Return a new Actor object using the data in the registry corresponding to the given ID.
Args:
key (Actors): ID of the actor to get.
Returns:
Actor: An Actor with the information corresponding to the ID in the registry.
Raises:
ActorNotFoundError: If there's no actor with the given key in the registry.
"""
if not cls.loaded:
raise RegistryNotInitializedError
actor = cls.actors.get(key)
if actor is None:
raise ActorNotFoundError(key)
return actor()
def get_item(cls, key):
"""
Return a new Item object using the data in the registry corresponding to the given ID.
Args:
key (Items): ID of the item to get.
Returns:
Item: An Item with the information corresponding to the ID in the registry.
Raises:
ItemNotFoundError: If there's no item with the given key in the registry.
"""
if not cls.loaded:
raise RegistryNotInitializedError
item = cls.items.get(key)
if item is None:
raise ItemNotFoundError(key)
return item()