diff --git a/evennia/commands/default/general.py b/evennia/commands/default/general.py index 6b739e022b..6e217d69ad 100644 --- a/evennia/commands/default/general.py +++ b/evennia/commands/default/general.py @@ -382,7 +382,7 @@ class CmdInventory(COMMAND_DEFAULT_CLASS): table = self.styled_table(border="header") for item in items: table.add_row(f"|C{item.name}|n", - "{}|n".format(utils.crop(raw_ansi(item.db.desc), width=50) or "")) + "{}|n".format(utils.crop(raw_ansi(item.db.desc or ""), width=50) or "")) string = f"|wYou are carrying:\n{table}" self.caller.msg(string) diff --git a/evennia/web/admin/accounts.py b/evennia/web/admin/accounts.py index 00f3f1beb7..bbff6d6131 100644 --- a/evennia/web/admin/accounts.py +++ b/evennia/web/admin/accounts.py @@ -6,7 +6,9 @@ from django import forms from django.conf import settings from django.contrib import admin, messages from django.contrib.admin.options import IS_POPUP_VAR +from django.contrib.admin.widgets import ForeignKeyRawIdWidget from django.contrib.auth.admin import UserAdmin as BaseUserAdmin +from django.utils.translation import gettext as _ from django.contrib.auth.forms import UserChangeForm, UserCreationForm from django.contrib.admin.utils import unquote from django.template.response import TemplateResponse @@ -18,6 +20,7 @@ from django.utils.html import escape from django.urls import path, reverse from django.contrib.auth import update_session_auth_hash +from evennia.objects.models import ObjectDB from evennia.accounts.models import AccountDB from evennia.utils import create from .attributes import AttributeInline @@ -240,11 +243,12 @@ class AccountAdmin(BaseUserAdmin): This is the main creation screen for Users/accounts """ + from .objects import ObjectInline list_display = ("username", "email", "is_staff", "is_superuser") form = AccountChangeForm add_form = AccountCreationForm - inlines = [AccountTagInline, AccountAttributeInline] + inlines = [AccountTagInline, AccountAttributeInline, ObjectInline] readonly_fields = ["db_date_created", "serialized_string"] fieldsets = ( ( diff --git a/evennia/web/admin/objects.py b/evennia/web/admin/objects.py index 118a0a51e9..722bce67dd 100644 --- a/evennia/web/admin/objects.py +++ b/evennia/web/admin/objects.py @@ -6,9 +6,11 @@ from django import forms from django.conf import settings from django.contrib import admin from django.contrib.admin.utils import flatten_fieldsets +from django.contrib.admin.widgets import ForeignKeyRawIdWidget from django.utils.translation import gettext as _ from evennia.objects.models import ObjectDB +from evennia.accounts.models import AccountDB from .attributes import AttributeInline from .tags import TagInline from . import utils as adminutils @@ -59,6 +61,14 @@ class ObjectCreateForm(forms.ModelForm): "as part of Evennia's startup.", choices=adminutils.get_and_load_typeclasses(parent=ObjectDB)) + db_lock_storage = forms.CharField( label="Locks", + required=False, + widget=forms.Textarea(attrs={"cols": "100", "rows": "2"}), + help_text="In-game lock definition string. If not given, defaults will be used. " + "This string should be on the form " + "type:lockfunction(args);type2:lockfunction2(args);...", + ) + db_cmdset_storage = forms.CharField( label="CmdSet", initial="", @@ -68,6 +78,15 @@ class ObjectCreateForm(forms.ModelForm): " and can leave this field blank.", ) + db_account = forms.ModelChoiceField( + AccountDB.objects.all(), + label="Controlling Account", + required=False, + widget=ForeignKeyRawIdWidget( + ObjectDB._meta.get_field('db_account').remote_field, admin.site), + help_text="Only needed for characters in MULTISESSION_MODE=1 or 2." + ) + raw_id_fields = ("db_destination", "db_location", "db_home") @@ -81,19 +100,32 @@ class ObjectEditForm(ObjectCreateForm): model = ObjectDB fields = "__all__" - db_lock_storage = forms.CharField( label="Locks", - required=False, - widget=forms.Textarea(attrs={"cols": "100", "rows": "2"}), - help_text="In-game lock definition string. If not given, defaults will be used. " - "This string should be on the form " - "type:lockfunction(args);type2:lockfunction2(args);...", + +class ObjectInline(admin.StackedInline): + """ + Inline creation of Object. + + """ + model = ObjectDB + # template = "admin/accounts/stacked.html" + form = ObjectCreateForm + fieldsets = ( + ( + None, + { + "fields": ( + ("db_key", "db_typeclass_path"), + ("db_location", "db_home", "db_destination", "db_account"), + "db_cmdset_storage", + "db_lock_storage", + ) + }, + ), ) - db_typeclass_path = forms.ChoiceField( - label="Typeclass", - help_text="This is the Python-path to the class implementing the actual object functionality. " - "
If your custom class is not found here, it may not be imported as part of Evennia's startup.", - choices=adminutils.get_and_load_typeclasses(parent=ObjectDB)) + extra = 1 + max_num = 1 + raw_id_fields = ("db_destination", "db_location", "db_home", "db_account") @admin.register(ObjectDB) @@ -108,7 +140,7 @@ class ObjectAdmin(admin.ModelAdmin): list_display_links = ("id", "db_key") ordering = ["db_account", "db_typeclass_path", "id"] search_fields = ["=id", "^db_key", "db_typeclass_path", "^db_account__db_key"] - raw_id_fields = ("db_destination", "db_location", "db_home") + raw_id_fields = ("db_destination", "db_location", "db_home", "db_account") readonly_fields = ("serialized_string", ) save_as = True @@ -125,7 +157,7 @@ class ObjectAdmin(admin.ModelAdmin): { "fields": ( ("db_key", "db_typeclass_path"), - ("db_location", "db_home", "db_destination"), + ("db_location", "db_home", "db_destination", "db_account"), "db_cmdset_storage", "db_lock_storage", "serialized_string" @@ -141,8 +173,7 @@ class ObjectAdmin(admin.ModelAdmin): { "fields": ( ("db_key", "db_typeclass_path"), - ("db_location", "db_home"), - "db_destination", + ("db_location", "db_home", "db_destination", "db_account"), "db_cmdset_storage", ) }, @@ -206,15 +237,17 @@ class ObjectAdmin(admin.ModelAdmin): change (bool): If this is a change or a new object. """ - obj.save() if not change: # adding a new object # have to call init with typeclass passed to it obj.set_class_from_typeclass(typeclass_path=obj.db_typeclass_path) + obj.save() obj.basetype_setup() obj.basetype_posthook_setup() obj.at_object_creation() - obj.at_init() + else: + obj.save() + obj.at_init() def response_add(self, request, obj, post_url_continue=None): from django.http import HttpResponseRedirect diff --git a/evennia/web/templates/admin/frontpage.html b/evennia/web/templates/admin/frontpage.html index 79a757e1dd..204408ba6a 100644 --- a/evennia/web/templates/admin/frontpage.html +++ b/evennia/web/templates/admin/frontpage.html @@ -54,6 +54,15 @@ making them very efficient.

+

+

ServerConfig

+ These are constants saved by the running server. While maybe interesting for + debugging, you should usually not modify these manually unless you + really know what you are doing. For example, the + BASE_*_TYPECLASS fields are stored in order to auto-update + when their setting changes; they must not be changed manually here. +

+

Website-only