Skip to content

Commit d02c009

Browse files
committed
Separate parts of modlib into two files. See #3
1 parent f819b00 commit d02c009

File tree

2 files changed

+142
-146
lines changed

2 files changed

+142
-146
lines changed

modloader/modast.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
This file is free software under the GPLv3 license
44
"""
55
import os
6+
import string
67

78
import renpy
89
from renpy import ast
@@ -204,3 +205,140 @@ def find_python_statement(statement):
204205
if isinstance(node, ast.Python) and node.code.source == statement:
205206
return node
206207
return None
208+
209+
ROT13 = string.maketrans(
210+
"NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm",
211+
"ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz")
212+
213+
class ASTHook(ast.Node):
214+
"""A custom :class:`renpy.ast.Node` that acts as a hook between
215+
other node objects.
216+
217+
Note:
218+
Don't instantiate this class directly. Ren'Py uses an
219+
internal serial for the call stack and other uses. This
220+
class emulates that at the base class.
221+
222+
Attributes:
223+
hook_func: A function that's called when the node is executed.
224+
If the function returns a non-None value, the next
225+
node will be skipped.
226+
fromOp: Unknown
227+
__oldNext: The original next node before hooking was done
228+
"""
229+
def __init__(self, loc, hook_func=None, from_op=None):
230+
#TODO: Understand fromOp and __oldNext
231+
super(ASTHook, self).__init__(loc)
232+
233+
self.hook_func = hook_func
234+
self.from_op = from_op
235+
self.old_next = None
236+
237+
def execute(self):
238+
"""Execute hook after node is called"""
239+
ast.statement_name("hook")
240+
ret = None
241+
if self.hook_func:
242+
ret = self.hook_func(self)
243+
if not ret:
244+
self.exec_continue()
245+
246+
def exec_continue(self):
247+
"""Continue"""
248+
ast.next_node(self.next)
249+
250+
def unhook(self):
251+
"""Remove the hook"""
252+
self.from_op.next = self.old_next
253+
254+
255+
class MenuHook(object):
256+
"""A hook class for editing a specific menu"""
257+
258+
def __init__(self, menu_, base_):
259+
"""Make a hook class for the specific ``menu_`` object
260+
261+
Args:
262+
menu_ (renpy.ast.Menu): The Menu node to be hooked
263+
base_ (AWSWModBase): An instance of the mod base class
264+
"""
265+
if not isinstance(menu_, ast.Menu):
266+
raise AssertionError("MenuHook not instantiated with a Menu node!")
267+
268+
self.menu = menu_
269+
self.base = base_
270+
# Copy the menu.items list, not a reference to it
271+
self.old_items = menu_.items[:]
272+
273+
def delete_item(self, item):
274+
"""Delete an item from the menu"""
275+
# TODO: Describe what the hell is happening here.
276+
self.get_items()[:] = [(lab, cond, block) for _, (lab, cond, block)
277+
in enumerate(self.get_items()) if lab != item]
278+
return None
279+
280+
def get_item(self, item):
281+
"""Get an item from the menu"""
282+
for obj in self.get_items():
283+
if obj[0] == item:
284+
return obj
285+
286+
def get_option_code(self, item):
287+
"""Get an item's SL code from the menu"""
288+
obj = self.get_item(item)
289+
return obj[2]
290+
291+
def get_items(self):
292+
"""Get all the items in the menu"""
293+
return self.menu.items
294+
295+
def set_conditional(self, item, new_cond):
296+
"""Change the conditional statement for ``item``
297+
298+
Returns:
299+
True if successful and False if not
300+
"""
301+
for i, (lab, _, block) in enumerate(self.get_items()):
302+
if lab == item:
303+
self.menu.items[i] = (lab, new_cond, block)
304+
return True
305+
return False
306+
307+
def add_item(self, label, hook, condition="True"):
308+
"""Add a new item to the menu
309+
310+
Args:
311+
label (str): The option's label
312+
313+
hook: Either a :class:`renpy.ast.Node` or a function to be
314+
executed after the menu choice has been selected
315+
316+
condition (str): A Python string to evaluate to determine
317+
whether or not the choice should be shown
318+
319+
Returns:
320+
None if ``hook`` is a :class:`renpy.ast.Node` or a
321+
:class:`ASTHook` if ``hook`` is a function
322+
"""
323+
if isinstance(hook, ast.Node):
324+
self.get_items().append((label, condition, [hook])) # Adding a dialogue option.
325+
return None
326+
else:
327+
node = ASTHook(("AWSWMod", 1))
328+
node.from_op = self.menu
329+
node.hook_func = hook
330+
node.name = "AWSWModOp_" + str(self.base.name_serial)
331+
self.base.name_serial += 1
332+
self.get_items().append((label, condition, [node]))
333+
return node
334+
335+
def add_item_call(self, label, usr_hook, condition="True"):
336+
#TODO: Determine what this does
337+
# pylint: disable=missing-docstring, invalid-name
338+
hook = self.add_item(label, None, condition)
339+
340+
def call_func(hook):
341+
rv = renpy.game.context().call(usr_hook.name, return_site=self.menu.next.name)
342+
hook.chain(rv)
343+
344+
hook.hook_func = call_func

modloader/modlib.py renamed to modloader/modgame.py

Lines changed: 4 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -13,61 +13,10 @@
1313
import modloader
1414
from modloader import modast
1515

16-
def sprnt(str_):
17-
"""Print an encoded string to stdout
18-
19-
Encode the string in UTF-8 before printing it out to stdout
20-
This helps avoid Unicode errors
21-
22-
Args:
23-
string (str): The string to be printed
24-
"""
25-
print str_.encode('utf-8')
26-
2716
ROT13 = string.maketrans(
2817
"NOPQRSTUVWXYZnopqrstuvwxyzABCDEFGHIJKLMabcdefghijklm",
2918
"ABCDEFGHIJKLMabcdefghijklmNOPQRSTUVWXYZnopqrstuvwxyz")
3019

31-
class ASTHook(ast.Node):
32-
"""A custom :class:`renpy.ast.Node` that acts as a hook between
33-
other node objects.
34-
35-
Note:
36-
Don't instantiate this class directly. Ren'Py uses an
37-
internal serial for the call stack and other uses. This
38-
class emulates that at the base class.
39-
40-
Attributes:
41-
hook_func: A function that's called when the node is executed.
42-
If the function returns a non-None value, the next
43-
node will be skipped.
44-
fromOp: Unknown
45-
__oldNext: The original next node before hooking was done
46-
"""
47-
def __init__(self, loc, hook_func=None, from_op=None):
48-
#TODO: Understand fromOp and __oldNext
49-
super(ASTHook, self).__init__(loc)
50-
51-
self.hook_func = hook_func
52-
self.from_op = from_op
53-
self.old_next = None
54-
55-
def execute(self):
56-
"""Execute hook after node is called"""
57-
ast.statement_name("hook")
58-
ret = None
59-
if self.hook_func:
60-
ret = self.hook_func(self)
61-
if not ret:
62-
self.exec_continue()
63-
64-
def exec_continue(self):
65-
"""Continue"""
66-
ast.next_node(self.next)
67-
68-
def unhook(self):
69-
"""Remove the hook"""
70-
self.from_op.next = self.old_next
7120

7221
class AWSWEndingHooks(object):
7322
"""The ending hooks for the game"""
@@ -132,97 +81,6 @@ def get_ending_picker_menu(self):
13281
return menu_hooks
13382

13483

135-
class AWSWMenuHook(object):
136-
"""A hook class for editing a specific menu"""
137-
138-
def __init__(self, menu_, base_):
139-
"""Make a hook class for the specific ``menu_`` object
140-
141-
Args:
142-
menu_ (renpy.ast.Menu): The Menu node to be hooked
143-
base_ (AWSWModBase): An instance of the mod base class
144-
"""
145-
if not isinstance(menu_, ast.Menu):
146-
raise AssertionError("MenuHook not instantiated with a Menu node!")
147-
148-
self.menu = menu_
149-
self.base = base_
150-
# Copy the menu.items list, not a reference to it
151-
self.old_items = menu_.items[:]
152-
153-
def delete_item(self, item):
154-
"""Delete an item from the menu"""
155-
# TODO: Describe what the hell is happening here.
156-
self.get_items()[:] = [(lab, cond, block) for _, (lab, cond, block)
157-
in enumerate(self.get_items()) if lab != item]
158-
return None
159-
160-
def get_item(self, item):
161-
"""Get an item from the menu"""
162-
for obj in self.get_items():
163-
if obj[0] == item:
164-
return obj
165-
166-
def get_option_code(self, item):
167-
# pylint: disable=missing-docstring
168-
obj = self.get_item(item)
169-
return obj[2]
170-
171-
def get_items(self):
172-
"""Get all the items in the menu"""
173-
return self.menu.items
174-
175-
def set_conditional(self, item, new_cond):
176-
"""Change the conditional statement for ``item``
177-
178-
Returns:
179-
True if successful and False if not
180-
"""
181-
for i, (lab, _, block) in enumerate(self.get_items()):
182-
if lab == item:
183-
self.menu.items[i] = (lab, new_cond, block)
184-
return True
185-
return False
186-
187-
def add_item(self, label, hook, condition="True"):
188-
"""Add a new item to the menu
189-
190-
Args:
191-
label (str): The option's label
192-
193-
hook: Either a :class:`renpy.ast.Node` or a function to be
194-
executed after the menu choice has been selected
195-
196-
condition (str): A Python string to evaluate to determine
197-
whether or not the choice should be shown
198-
199-
Returns:
200-
None if ``hook`` is a :class:`renpy.ast.Node` or a
201-
:class:`ASTHook` if ``hook`` is a function
202-
"""
203-
if isinstance(hook, ast.Node):
204-
self.get_items().append((label, condition, [hook])) # Adding a dialogue option.
205-
return None
206-
else:
207-
node = ASTHook(("AWSWMod", 1))
208-
node.from_op = self.menu
209-
node.hook_func = hook
210-
node.name = "AWSWModOp_" + str(self.base.name_serial)
211-
self.base.name_serial += 1
212-
self.get_items().append((label, condition, [node]))
213-
return node
214-
215-
def add_item_call(self, label, usr_hook, condition="True"):
216-
#TODO: Determine what this does
217-
# pylint: disable=missing-docstring, invalid-name
218-
hook = self.add_item(label, None, condition)
219-
220-
def call_func(hook):
221-
rv = renpy.game.context().call(usr_hook.name, return_site=self.menu.next.name)
222-
hook.chain(rv)
223-
224-
hook.hook_func = call_func
225-
22684
class AWSWHomeHook(object):
22785
"""Hook the menu found in the player's apartment."""
22886

@@ -417,7 +275,7 @@ def hook_opcode(self, node, func):
417275
"""
418276
next_statement = node.next
419277

420-
hook = ASTHook(("AWSWMod", 1)) # hooking hooks breaks
278+
hook = modast.ASTHook(("AWSWMod", 1)) # hooking hooks breaks
421279
hook.from_op = node
422280
node.next = hook
423281
hook.chain(next_statement)
@@ -495,7 +353,7 @@ def unhooklabel(self, label):
495353
#TODO: Determine if method should be a static function
496354
# pylint: disable=no-self-use
497355
found_node = modast.find_label(label)
498-
if isinstance(found_node, ASTHook):
356+
if isinstance(found_node, modast.ASTHook):
499357
found_node.from_op.next = found_node.next
500358

501359
def disable_slast_cache(self):
@@ -518,7 +376,7 @@ def get_menu_hook(self, menu):
518376
"""
519377
#TODO: Determine whether method should be static function
520378
# pylint: disable=no-self-use
521-
return AWSWMenuHook(menu, base)
379+
return modast.MenuHook(menu, base)
522380

523381
def get_home_hook(self):
524382
"""Get the home hook class
@@ -547,7 +405,7 @@ def get_node_from_location(self, node, location):
547405
node = node.next
548406

549407
# Effectively skip the ASTHook nodes by continuing on
550-
while node and isinstance(node, ASTHook):
408+
while node and isinstance(node, modast.ASTHook):
551409
node = node.next
552410
return node
553411

0 commit comments

Comments
 (0)