Move olc to separate branch for now.
This is because it has increased in scope and would delay the release of the devel branch unnecessarily.
This commit is contained in:
parent
60fcb471ec
commit
ce57b52dcf
5 changed files with 0 additions and 775 deletions
|
|
@ -1,156 +0,0 @@
|
||||||
"""
|
|
||||||
OLC - On-Line Creation
|
|
||||||
|
|
||||||
This module is the core of the Evennia online creation helper system.
|
|
||||||
This is a resource intended for players with build privileges.
|
|
||||||
|
|
||||||
While the OLC command can be used to start the OLC "from the top", the
|
|
||||||
system is also intended to be plugged in to enhance existing build commands
|
|
||||||
with a more menu-like building style.
|
|
||||||
|
|
||||||
Functionality:
|
|
||||||
|
|
||||||
- Prototype management: Allows to create and edit Prototype
|
|
||||||
dictionaries. Can store such Prototypes on the Builder Player as an Attribute
|
|
||||||
or centrally on a central store that all builders can fetch prototypes from.
|
|
||||||
- Creates a new entity either from an existing prototype or by creating the
|
|
||||||
prototype on the fly for the sake of that single object (the prototype can
|
|
||||||
then also be saved for future use).
|
|
||||||
- Recording of session, for performing a series of recorded build actions in sequence.
|
|
||||||
Stored so as to be possible to reproduce.
|
|
||||||
- Export of objects created in recording mode to a batchcode file (Immortals only).
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
from time import time
|
|
||||||
from collections import OrderedDict
|
|
||||||
from evennia.utils.evmenu import EvMenu
|
|
||||||
from evennia.commands.command import Command
|
|
||||||
|
|
||||||
|
|
||||||
# OLC settings
|
|
||||||
_SHOW_PROMPT = True # settings.OLC_SHOW_PROMPT
|
|
||||||
_DEFAULT_PROMPT = "" # settings.OLC_DEFAULT_PROMPT
|
|
||||||
_LEN_HISTORY = 10 # settings.OLC_HISTORY_LENGTH
|
|
||||||
|
|
||||||
|
|
||||||
# OLC Session
|
|
||||||
|
|
||||||
def _new_session():
|
|
||||||
|
|
||||||
"""
|
|
||||||
This generates an empty olcsession structure, which is used to hold state
|
|
||||||
information in the olc but which can also be pickled.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
olcsession (dict): An empty OLCSession.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return {
|
|
||||||
# header info
|
|
||||||
"caller": None, # the current user of this session
|
|
||||||
"modified": time(),
|
|
||||||
"db_model": None, # currently unused, ObjectDB for now
|
|
||||||
"prompt_template": _DEFAULT_PROMPT, # prompt display
|
|
||||||
"olcfields": OrderedDict(), # registered OLCFields. Order matters
|
|
||||||
"prototype_key": "", # current active prototype key
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def _update_prompt(osession):
|
|
||||||
"""
|
|
||||||
Update the OLC status prompt.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
prompt (str): The prompt based on the
|
|
||||||
prompt template, populated with
|
|
||||||
the olcsession state.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
def search_entity(osession, query):
|
|
||||||
"""
|
|
||||||
Perform a query for a specified entity. Which type of entity is determined by the osession
|
|
||||||
state.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
query (str): This is a string, a #dbref or an extended search
|
|
||||||
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def display_prototype(osession):
|
|
||||||
"""
|
|
||||||
Display prototype fields according to the order of the registered olcfields.
|
|
||||||
|
|
||||||
"""
|
|
||||||
# TODO: Simple one column display to begin with - make multi-column later
|
|
||||||
pkey = osession['prototype_key']
|
|
||||||
outtxt = ["=== {pkey} ===".format(pkey=pkey)]
|
|
||||||
for field in osession['olcfields'].values():
|
|
||||||
fname, flabel, fvalue = field.name, field.label, field.display()
|
|
||||||
outtxt.append(" {fieldname} ({label}): {value}".format(fieldname=fname,
|
|
||||||
label=flabel, value=fvalue))
|
|
||||||
return '\n'.join(outtxt)
|
|
||||||
|
|
||||||
|
|
||||||
def display_field_value(osession, fieldname):
|
|
||||||
"""
|
|
||||||
Display info about a specific field.
|
|
||||||
"""
|
|
||||||
field = osession['olcfields'].get(fieldname, None)
|
|
||||||
if field:
|
|
||||||
return "{fieldname}: {value}".format(fieldname=field.name, value=field.display())
|
|
||||||
|
|
||||||
|
|
||||||
# Access function
|
|
||||||
|
|
||||||
from evennia.utils.olc import olc_pages
|
|
||||||
def display_obj(obj):
|
|
||||||
"""
|
|
||||||
Test of displaying object using fields and pages.
|
|
||||||
"""
|
|
||||||
olcsession = _new_session()
|
|
||||||
olcsession['caller'] = obj
|
|
||||||
page = olc_pages.OLCObjectPage(olcsession)
|
|
||||||
obj.msg(str(page))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def OLC(caller, target=None, startnode=None):
|
|
||||||
"""
|
|
||||||
This function is a common entry-point into the OLC menu system. It is used
|
|
||||||
by Evennia systems to jump into the different possible start points of the
|
|
||||||
OLC menu tree depending on what info is already available.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
caller (Object or Player): The one using the olc.
|
|
||||||
target (Object, optional): Object to operate on, if any is known.
|
|
||||||
startnode (str, optional): Where in the menu tree to start. If unset,
|
|
||||||
will be decided by whether target is given or not.
|
|
||||||
|
|
||||||
"""
|
|
||||||
startnode = startnode or (target and "node_edit_top") or "node_top"
|
|
||||||
EvMenu(caller, "evennia.utils.olc.olc_menu", startnode=startnode, target=target)
|
|
||||||
|
|
||||||
|
|
||||||
class CmdOLC(Command):
|
|
||||||
"""
|
|
||||||
Test OLC
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
olc [target]
|
|
||||||
|
|
||||||
Starts the olc to create a new object or to modify an existing one.
|
|
||||||
|
|
||||||
"""
|
|
||||||
key = "olc"
|
|
||||||
def func(self):
|
|
||||||
OLC(self.caller, target=self.args)
|
|
||||||
|
|
||||||
|
|
@ -1,523 +0,0 @@
|
||||||
"""
|
|
||||||
OLC fields describe how to edit and display a specific piece of data of a prototype within the OLC system.
|
|
||||||
|
|
||||||
The OLC system imports and adds these field classes to its prototype manipulation pages in order to
|
|
||||||
know what data to read and how to display it.
|
|
||||||
|
|
||||||
"""
|
|
||||||
from collections import deque
|
|
||||||
from evennia.utils.utils import to_str, to_unicode
|
|
||||||
from evennia.utils.olc import olc_utils
|
|
||||||
|
|
||||||
# from django.conf import settings
|
|
||||||
|
|
||||||
_OLC_VALIDATION_ERROR = """
|
|
||||||
Error storing data in {fieldname}:
|
|
||||||
{value}
|
|
||||||
The reported error was
|
|
||||||
{error}
|
|
||||||
"""
|
|
||||||
|
|
||||||
_LEN_HISTORY = 10 # settings.OLC_HISTORY_LENGTH
|
|
||||||
|
|
||||||
|
|
||||||
class InvalidActionError(RuntimeError):
|
|
||||||
"""
|
|
||||||
Raised when trying to perform a field action the field
|
|
||||||
does not support.
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ValidationError(RuntimeError):
|
|
||||||
"""
|
|
||||||
Raised when failing to validate new data being entered
|
|
||||||
into the field (from any source)
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class OLCField(object):
|
|
||||||
"""
|
|
||||||
This is the parent for all OLC fields. This docstring acts
|
|
||||||
as the help text for the field.
|
|
||||||
|
|
||||||
"""
|
|
||||||
# name of this field, for error reporting
|
|
||||||
key = "Empty field"
|
|
||||||
# if this field must have a value different than None
|
|
||||||
required = False
|
|
||||||
# used for displaying extra info in the OLC
|
|
||||||
label = "Empty field"
|
|
||||||
# initial value of field if not given
|
|
||||||
default = None
|
|
||||||
# actions available on this field. Available actions
|
|
||||||
# are replace, edit, append, remove, clear, help
|
|
||||||
actions = ['edit', 'clear', 'help']
|
|
||||||
|
|
||||||
def __init__(self, olcsession):
|
|
||||||
self._value_history = deque([self.default], _LEN_HISTORY)
|
|
||||||
self._history_pos = 0
|
|
||||||
self._has_changed = False
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return to_str(self.display())
|
|
||||||
|
|
||||||
def __unicode__(self):
|
|
||||||
return to_unicode(self.display())
|
|
||||||
|
|
||||||
# perform actions
|
|
||||||
# TODO - include editor in check!
|
|
||||||
def action_edit(self, *args):
|
|
||||||
"""
|
|
||||||
Edit field value.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
newval (any): New value to add/replace with.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
InvalidActionError: If editing is not allowed.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if args:
|
|
||||||
newval = args[0]
|
|
||||||
if 'edit' in self.actions:
|
|
||||||
self.value = newval
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
newval = "<Not given>"
|
|
||||||
raise InvalidActionError('Edit {value}->{newval}'.format(value=self.value, newval=newval))
|
|
||||||
|
|
||||||
def action_clear(self, *args):
|
|
||||||
"""
|
|
||||||
Clear field back to default.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
default (any): The field'd default value, now set.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
InvalidActionError: If clearing is not allowed.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if 'clear' in self.actions:
|
|
||||||
# don't validate this
|
|
||||||
object.__setattr__(self, 'value', self.default)
|
|
||||||
return self.value
|
|
||||||
raise InvalidActionError('Clear')
|
|
||||||
|
|
||||||
def action_help(self, *args):
|
|
||||||
"""
|
|
||||||
Get the help text for the field.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
help (str): Field help text.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
InvalidActionError: If help is not given for this field,
|
|
||||||
either becuase it's disallowed or unset.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if 'help' not in self.actions or not self.__doc__:
|
|
||||||
raise InvalidActioNError('Help')
|
|
||||||
return self.__doc__
|
|
||||||
|
|
||||||
# storing data to the field in a history-aware way
|
|
||||||
@property
|
|
||||||
def value(self):
|
|
||||||
return self._value_history[self._history_pos]
|
|
||||||
|
|
||||||
@value.setter
|
|
||||||
def value(self, value):
|
|
||||||
"""
|
|
||||||
Update field value by updating the history.
|
|
||||||
"""
|
|
||||||
original_value = value
|
|
||||||
try:
|
|
||||||
value = self.validate(value)
|
|
||||||
except Exception as err:
|
|
||||||
errtxt = _OLC_VALIDATION_ERROR.format(fieldname=self.key, value=original_value, error=err)
|
|
||||||
raise ValidationError(errtxt)
|
|
||||||
if (self._value_history and isinstance(value, (basestring, bool, int, float)) and
|
|
||||||
self._value_history[0] == value):
|
|
||||||
# don't change/update history if re-adding the same thing
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
self._has_changed = True
|
|
||||||
self._history_pos = 0
|
|
||||||
self._value_history.appendleft(value)
|
|
||||||
|
|
||||||
@value.deleter
|
|
||||||
def value(self):
|
|
||||||
self.history_pos = 0
|
|
||||||
self._value_history.appendleft(self.default)
|
|
||||||
|
|
||||||
def history(self, step):
|
|
||||||
"""
|
|
||||||
Change history position.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
step (int): Step in the history stack. Positive movement
|
|
||||||
means moving futher back in history (with a maximum
|
|
||||||
of `settings.OLC_HISTORY_LENGTH`, negative steps
|
|
||||||
moves towards recent history (with 0 being the latest
|
|
||||||
value).
|
|
||||||
|
|
||||||
"""
|
|
||||||
self._history_pos = min(len(self.value_history)-1, max(0, self._history_pos + step))
|
|
||||||
|
|
||||||
def has_changed(self):
|
|
||||||
"""
|
|
||||||
Check if this field has changed.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
changed (bool): If the field changed or not.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return bool(self._has_changed)
|
|
||||||
|
|
||||||
# overloadable methods
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
"""
|
|
||||||
Populate this field by retrieving data from an entity.
|
|
||||||
All fields on a page will have this called, so must
|
|
||||||
be able to handle also incompatible entities.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
entity (any): An object to use for
|
|
||||||
populating this field (like an Object).
|
|
||||||
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
"""
|
|
||||||
Store this field value in a prototype.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
prototype (dict): The prototype dict
|
|
||||||
to update with the value of this field.
|
|
||||||
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def validate(self, value, **kwargs):
|
|
||||||
"""
|
|
||||||
Validate/preprocess incoming data to store in this field.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value (any): An input value to
|
|
||||||
validate
|
|
||||||
|
|
||||||
Kwargs:
|
|
||||||
any (any): Optional info to send to field.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
validated_value (any): The value, correctly
|
|
||||||
validated and/or processed to store in this field.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
ValidateException: If the field was given an
|
|
||||||
invalid value to validate.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return str(value)
|
|
||||||
|
|
||||||
def display(self):
|
|
||||||
"""
|
|
||||||
How to display the field contents in the OLC display.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self.value
|
|
||||||
|
|
||||||
|
|
||||||
# OLCFields for all the standard model properties
|
|
||||||
# key, location, destination, home, aliases,
|
|
||||||
# permissions, tags, attributes ...
|
|
||||||
|
|
||||||
|
|
||||||
class OLCKeyField(OLCField):
|
|
||||||
"""
|
|
||||||
The name (key) of the object is its main identifier, used
|
|
||||||
throughout listings even if may not always be visible to
|
|
||||||
the end user.
|
|
||||||
"""
|
|
||||||
key = 'Name'
|
|
||||||
required = True
|
|
||||||
label = "The object's name"
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
self.value = entity.db_key
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
prototype['key'] = self.value
|
|
||||||
|
|
||||||
|
|
||||||
class OLCLocationField(OLCField):
|
|
||||||
"""
|
|
||||||
An object's location is usually a Room but could be any
|
|
||||||
other in-game entity. By convention, Rooms themselves have
|
|
||||||
a None location. Objects are otherwise only placed in a
|
|
||||||
None location to take them out of the game.
|
|
||||||
"""
|
|
||||||
key = 'Location'
|
|
||||||
required = False
|
|
||||||
label = "The object's current location"
|
|
||||||
|
|
||||||
def validate(self, value):
|
|
||||||
return olc_utils.search_by_string(self.olcsession, value)
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
self.value = entity.db_location
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
prototype['location'] = self.value
|
|
||||||
|
|
||||||
|
|
||||||
class OLCHomeField(OLCField):
|
|
||||||
"""
|
|
||||||
An object's home location acts as a fallback when various
|
|
||||||
extreme situations occur. An example is when a location is
|
|
||||||
deleted - all its content (except exits) are then not deleted
|
|
||||||
but are moved to each object's home location.
|
|
||||||
"""
|
|
||||||
key = 'Home'
|
|
||||||
required = True
|
|
||||||
label = "The object's home location"
|
|
||||||
|
|
||||||
def validate(self, value):
|
|
||||||
return olc_utils.search_by_string(self.olcsession, value)
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
self.value = entity.db_home
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
prototype['home'] = self.value
|
|
||||||
|
|
||||||
|
|
||||||
class OLCDestinationField(OLCField):
|
|
||||||
"""
|
|
||||||
An object's destination is usually not set unless the object
|
|
||||||
represents an exit between game locations. If set, the
|
|
||||||
destination should be set to the location you get to when
|
|
||||||
passing through this exit.
|
|
||||||
|
|
||||||
"""
|
|
||||||
key = 'Destination'
|
|
||||||
required = False
|
|
||||||
label = "The object's (usually exit's) destination"
|
|
||||||
|
|
||||||
def validate(self, value):
|
|
||||||
return olc_utils.search_by_string(self.olcsession, value)
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
self.value = entity.db_destination
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
prototype['destination'] = self.value
|
|
||||||
|
|
||||||
|
|
||||||
class OLCBatchField(OLCField):
|
|
||||||
"""
|
|
||||||
A field managing multiple values that can be appended to and
|
|
||||||
a given component popped out.
|
|
||||||
"""
|
|
||||||
actions = OLCField.actions + ['append', 'pop']
|
|
||||||
|
|
||||||
def action_append(self, value):
|
|
||||||
"""
|
|
||||||
Append a new value to this field.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
value (any): The value to append.
|
|
||||||
|
|
||||||
"""
|
|
||||||
value = self.value
|
|
||||||
value.append(value)
|
|
||||||
self.value = value
|
|
||||||
|
|
||||||
def action_pop(self, index=-1):
|
|
||||||
"""
|
|
||||||
Pop an element from the field.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
index (int, optional): Pop this index, otherwise pop the last
|
|
||||||
element in the field.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
element (any or None): The popped element or None.
|
|
||||||
|
|
||||||
"""
|
|
||||||
lst = self.value
|
|
||||||
try:
|
|
||||||
return lst.pop(int(index))
|
|
||||||
except IndexError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
# setting single Alias
|
|
||||||
class OLCAliasField(OLCField):
|
|
||||||
key = "Alias"
|
|
||||||
required = False
|
|
||||||
label = "An alternative name for the object"
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
if "index" in kwargs:
|
|
||||||
self.value = entity.aliases.all()[int(kwargs)]
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
if is_iter(prototype["aliases"]):
|
|
||||||
prototype["aliases"].append(self.value)
|
|
||||||
else:
|
|
||||||
prototype["aliases"] = [self.value]
|
|
||||||
|
|
||||||
|
|
||||||
# batch-setting aliases
|
|
||||||
class OLCAliasBatchField(OLCBatchField):
|
|
||||||
"""
|
|
||||||
Specify as a comma-separated list. Use quotes around the
|
|
||||||
alias if the alias itself contains a comma.
|
|
||||||
|
|
||||||
Aliases are alternate names for an object. An alias is just
|
|
||||||
as fast to search for as a key and two objects are assumed
|
|
||||||
to have the same name is *either* their name or any of their
|
|
||||||
aliases match.
|
|
||||||
|
|
||||||
"""
|
|
||||||
key = 'Aliases'
|
|
||||||
required = False
|
|
||||||
label = "The object's alternative name or names"
|
|
||||||
|
|
||||||
def validate(self, value):
|
|
||||||
return olc_utils.split_by_comma(value)
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
self.value = list(entity.aliases.all())
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
prototype['aliases'] = self.value
|
|
||||||
|
|
||||||
|
|
||||||
# setting single Tag
|
|
||||||
class OLCTagField(OLCField):
|
|
||||||
"""
|
|
||||||
Specify as tagname or tagname:category
|
|
||||||
|
|
||||||
Tags are used to identify groups of objects for later quick retrieval.
|
|
||||||
This is very useful for anything from creating zones of rooms to
|
|
||||||
easily find all Characters belonging a given group etc. A tag can also
|
|
||||||
have a category for a second level of grouping.
|
|
||||||
|
|
||||||
"""
|
|
||||||
key = "Tag"
|
|
||||||
required = False
|
|
||||||
label = "A single label for the object."
|
|
||||||
|
|
||||||
def validate(self, value):
|
|
||||||
category = None
|
|
||||||
if ':' in value:
|
|
||||||
value, category = value.rsplit(':', 1)
|
|
||||||
return (value, category)
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
if "index" in kwargs:
|
|
||||||
self.value = entity.tags.all()[int(kwargs)]
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
if is_iter(prototype["tags"]):
|
|
||||||
prototype["tags"].append(self.value)
|
|
||||||
else:
|
|
||||||
prototype["tags"] = [self.value]
|
|
||||||
|
|
||||||
|
|
||||||
# batch-setting Tags
|
|
||||||
class OLCTagBatchField(OLCBatchField):
|
|
||||||
"""
|
|
||||||
Specify as a comma-separated list of tagname or tagname:category.
|
|
||||||
|
|
||||||
Tags are used to identify groups of objects for later quick retrieval.
|
|
||||||
This is very useful for anything from creating zones of rooms to
|
|
||||||
easily find all Characters belonging a given group etc.
|
|
||||||
|
|
||||||
"""
|
|
||||||
key = 'Tags'
|
|
||||||
required = False
|
|
||||||
label = "Attach labels to objects to group and find them."
|
|
||||||
|
|
||||||
def validate(self, value):
|
|
||||||
if isinstance(value, basestring):
|
|
||||||
return [tuple(tagstr.split(':', 1)) if ':' in tagstr else (tagstr, None)
|
|
||||||
for tagstr in olc_utils.split_by_comma(value)]
|
|
||||||
else:
|
|
||||||
# assume a list of (key, category) - just let it pass
|
|
||||||
return value
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
self.value = entity.tags.all(return_key_and_category=True)
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
prototype['tags'] = self.value
|
|
||||||
|
|
||||||
def display(self):
|
|
||||||
outstr = []
|
|
||||||
for key, category in self.value:
|
|
||||||
outstr.append("{key}:{category}".format(key=key, category=category))
|
|
||||||
return '\n'.join(outstr)
|
|
||||||
|
|
||||||
|
|
||||||
# TODO fix this to correctly handle key, value, category
|
|
||||||
# setting single Attribute
|
|
||||||
class OLCAttributeField(OLCField):
|
|
||||||
key = "Attribute"
|
|
||||||
required = False
|
|
||||||
label = "An alternative name for the object"
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
if "index" in kwargs:
|
|
||||||
self.value = entity.attributes.all()[int(kwargs)]
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
if is_iter(prototype["attrs"]):
|
|
||||||
prototype["attrs"].append(self.value)
|
|
||||||
else:
|
|
||||||
prototype["attrs"] = [self.value]
|
|
||||||
|
|
||||||
|
|
||||||
# batch-setting attributes
|
|
||||||
class OLCAttributeBatchField(OLCBatchField):
|
|
||||||
"""
|
|
||||||
Specify as a comma-separated list of attrname=value or attrname:category=value.
|
|
||||||
|
|
||||||
Attributes are arbitrary pieces of data attached to an object. They can
|
|
||||||
contain references to other objects as well as simple Python structures such
|
|
||||||
as lists and dicts.
|
|
||||||
|
|
||||||
"""
|
|
||||||
key = 'Attributes'
|
|
||||||
required = False
|
|
||||||
label = "Additional data attached to this object."
|
|
||||||
actions = OLCField.actions + ['append']
|
|
||||||
|
|
||||||
def validate(self, value):
|
|
||||||
if isinstance(value, basestring):
|
|
||||||
return [tuple(lhs.split(':', 1) + [rhs]) if ':' in lhs else (lhs, None) + (rhs, )
|
|
||||||
for lhs, rhs in (attrstr.split('=', 1) if ':' in attrstr else ((attrstr, None),))
|
|
||||||
for attrstr in olc_utils.split_by_comma(value)]
|
|
||||||
else:
|
|
||||||
# we assume this is a list of Attributes
|
|
||||||
return [(attr.key, attr.category, attr.value) for attr in value]
|
|
||||||
|
|
||||||
def from_entity(self, entity, **kwargs):
|
|
||||||
self.value = entity.attributes.all()
|
|
||||||
|
|
||||||
def to_prototype(self, prototype):
|
|
||||||
for key, category, value in self.value:
|
|
||||||
prototype['attrs'] = (key, value, category)
|
|
||||||
|
|
||||||
def display(self):
|
|
||||||
outstr = []
|
|
||||||
for key, category, value in self.value:
|
|
||||||
outstr.append("{key}:{category} = {value}".format(key=key, category=category, value=value))
|
|
||||||
return '\n'.join(outstr)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
"""
|
|
||||||
This describes the menu structure/logic of the OLC system editor, using the EvMenu subsystem. The
|
|
||||||
various nodes are modular and will when possible make use of the various utilities of the OLC rather
|
|
||||||
than hard-coding things in each node.
|
|
||||||
|
|
||||||
Menu structure:
|
|
||||||
|
|
||||||
start:
|
|
||||||
new object
|
|
||||||
edit object <dbref>
|
|
||||||
manage prototypes
|
|
||||||
export session to batchcode file (immortals only)
|
|
||||||
|
|
||||||
new/edit object:
|
|
||||||
Protoype
|
|
||||||
Typeclass
|
|
||||||
Key
|
|
||||||
Location
|
|
||||||
Destination
|
|
||||||
PErmissions
|
|
||||||
LOcks
|
|
||||||
Attributes
|
|
||||||
TAgs
|
|
||||||
Scripts
|
|
||||||
|
|
||||||
create/update object
|
|
||||||
copy object
|
|
||||||
save prototype
|
|
||||||
save/delete object
|
|
||||||
update existing objects
|
|
||||||
|
|
||||||
manage prototypes
|
|
||||||
list prototype
|
|
||||||
search prototype
|
|
||||||
import prototype (from global store)
|
|
||||||
|
|
||||||
export session
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def node_top(caller, raw_input):
|
|
||||||
# top level node
|
|
||||||
# links to edit, manage, export
|
|
||||||
text = """OnLine Creation System"""
|
|
||||||
options = ({"key": ("|yN|new", "new", "n"),
|
|
||||||
"desc": "New object",
|
|
||||||
"goto": "node_new_top",
|
|
||||||
"exec": _obj_to_prototype},
|
|
||||||
{"key": ("|yE|ndit", "edit", "e", "m"),
|
|
||||||
"desc": "Edit existing object",
|
|
||||||
"goto": "node_edit_top",
|
|
||||||
"exec": _obj_to_prototype},
|
|
||||||
{"key": ("|yP|nrototype", "prototype", "manage", "p", "m"),
|
|
||||||
"desc": "Manage prototypes",
|
|
||||||
"goto": "node_prototype_top"},
|
|
||||||
{"key": ("E|yx|nport", "export", "x"),
|
|
||||||
"desc": "Export to prototypes",
|
|
||||||
"goto": "node_prototype_top"},
|
|
||||||
{"key": ("|yQ|nuit", "quit", "q"),
|
|
||||||
"desc": "Quit OLC",
|
|
||||||
"goto": "node_quit"},)
|
|
||||||
return text, options
|
|
||||||
|
|
||||||
def node_quit(caller, raw_input):
|
|
||||||
return 'Exiting.', None
|
|
||||||
|
|
||||||
def node_new_top(caller, raw_input):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def node_edit_top(caller, raw_input):
|
|
||||||
# edit top level
|
|
||||||
text = """Edit object"""
|
|
||||||
|
|
||||||
|
|
||||||
def node_prototype_top(caller, raw_input):
|
|
||||||
# manage prototypes
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def node_export_top(caller, raw_input):
|
|
||||||
# export top level
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
"""
|
|
||||||
Miscellaneous utilities for the OLC system.
|
|
||||||
|
|
||||||
"""
|
|
||||||
import csv
|
|
||||||
|
|
||||||
|
|
||||||
def search_by_string(olcsession, query):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def split_by_comma(string):
|
|
||||||
return csv.reader([string], skipinitialspace=True)
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue