Skip to content

Compatibility Commands

Deliberate differences in the command table, the configuration and the objects the game starts with.

Added commands do not run UNIMPLEMENTED_COMMAND

Section titled “Added commands do not run UNIMPLEMENTED_COMMAND”

A choice.

PennMUSH runs a command made with @command/add and never @hooked through the UNIMPLEMENTED_COMMAND entry (command.c:1900-1903), so a hook on UNIMPLEMENTED_COMMAND changes what every such command does.
SharpMUSH has the added command print “This command has not been implemented.” itself. A hook on UNIMPLEMENTED_COMMAND changes only what typing UNIMPLEMENTED_COMMAND does, and that can be typed directly.
Why. Both print the same text, so only a hook on UNIMPLEMENTED_COMMAND can tell them apart. Re-entering hook dispatch by command name from inside a command body needs a mechanism only HUH_COMMAND has. (#1257)
Workaround. @hook the added command itself rather than UNIMPLEMENTED_COMMAND.

> @command/add foo
> foo
This command has not been implemented.

A choice.

PennMUSH changes the running value; the change is lost at restart unless it is also written to mush.cnf.
SharpMUSH keeps one stored configuration, which the portal also edits, and every /set is written to it and lasts across restarts. /save does the same and says so.
Why. There is no mush.cnf for a running game to fall back to.
Workaround. Set the value back when a change was meant to be temporary.
No example. The difference shows only after a restart, and the parity harness starts each server once per run.

command_restrictions reapplies without a restart

Section titled “command_restrictions reapplies without a restart”

A choice.

PennMUSH applies the restrict_command lines of mush.cnf at startup and restart (game.c:757, bsd.c:1284). @config/set restrict_command=<command> <restriction> applies one more while the game runs (cmds.c:334-335, conf.c:866-896). Each one replaces the command’s restriction (command.c:1752-1760). There is no list to take a line back out of, so nothing returns a command to the restriction it was made with.
SharpMUSH keeps the lines as one setting, command_restrictions. @config/set restrict_command adds a line to it, or replaces the line for that command, and applies it at once, as PennMUSH does. The setting is applied at startup, before @STARTUP runs, as PennMUSH does, and again whenever it is changed from the portal or @config/set, in both directions: a command the change no longer restricts goes back to the restriction it was made with, and is enabled again if the configuration had disabled it with nobody. Every command the old or the new setting names starts again from the restriction it was made with, so a live @command/restrict on one of those commands is lost. Commands the setting does not name, and changes to other options, leave live restrictions alone. (#1250) @config/set restrict_command with words that are neither restriction words nor a valid lock says Couldn't set that option.; PennMUSH says Option set. and leaves the command unlocked.
Why. The configuration can be changed while the game is running; a restriction that waits for a restart looks as if it had been ignored. A mistyped restriction is refused rather than leaving the command open to everyone.
Workaround. After changing command_restrictions, repeat any @command/restrict that should still apply to a command it names, or put the restriction in command_restrictions itself.
Example. The parity case choice.restrictions-reapply in tools/parity/scenarios/40-compat-choices.scn runs it on both servers.

A choice.

PennMUSH ships restrict.cnf and includes it from mush.cnf, so a stock game already applies 21 restrict_command lines at startup (game/restrictcnf.dst): a guest cannot @create, @dig, @open, @set, @link or @lock, a FIXED player’s home is refused with You can't do that IC!, and @destroy is noplayer with its own message, so a player who types @destroy <thing> is answered Use @recycle instead and the thing is not destroyed (game/restrictcnf.dst:86, sent by command.c:2336-2339).
SharpMUSH ships command_restrictions empty. Every command in a new game is open to whatever its own permission check allows: a player’s @destroy <thing> destroys the thing, and a guest can @create. An imported game keeps its own: reading a PennMUSH mush.cnf follows its include lines, as config_file_startup does, and carries each restrict_command line into command_restrictions and each restrict_function line into function_restrictions, and both are applied at startup, so an imported restrict_function lstats noguest answers a guest’s lstats() with #-1 PERMISSION DENIED as PennMUSH does. Only the restrict_function words that say who may call a function are applied (nobody, noguest, nogagged, nofixed, admin, wizard, god). A word that changes how it runs (nosidefx, logargs, noparse and the like), or a ! word that clears one of a built-in’s own restrictions, is kept but has no effect, and the import names it. A line that cannot be carried (an include that cannot be read, a restriction with no value, a restrict_attribute) is logged by name, and so is every include in a mush.cnf uploaded through the portal, which is not followed because it would name a file on the server.
Why. Those lines are one site’s policy, not the engine’s behaviour; restrict.cnf is a file the administrator edits, and two PennMUSH games rarely ship the same one. Taking @destroy away from ordinary players on a fresh install is the game’s decision to make, and SharpMUSH does not make it for a world nobody has configured yet.
Workaround. Put the lines back, in the words PennMUSH writes them: @config/set restrict_command=@destroy noplayer " Use @recycle instead, one per command, or set command_restrictions from the portal’s configuration page. noguest, nofixed, noplayer, nobody, a flag or power name, a lock and the " <message> suffix all mean there what they mean in restrict.cnf, and the restriction applies at once and lasts across restarts. The same goes for function_restrictions from the portal, with noguest, nogagged, nofixed, admin, wizard, god and nobody.
Example. The parity case obj.create in tools/parity/scenarios/10-player-commands.scn runs it on both servers.

PennMUSH’s file and allocator housekeeping answers NOT SUPPORTED

Section titled “PennMUSH’s file and allocator housekeeping answers NOT SUPPORTED”

A choice.

PennMUSH trims its own log files with @logwipe and reports its attribute-chunk allocator with @stats/chunks, /regions, /paging and /freespace.
SharpMUSH writes its logs to the sinks named in its configuration and stores attributes in its database, so it has neither. Those commands return #-1 NOT SUPPORTED, and @logwipe also records the attempt in the server log.
Why. Nothing in the game owns the resource those commands manage.
Workaround. Rotate logs where they are configured.
Example. The parity case choice.housekeeping in tools/parity/scenarios/40-compat-choices.scn runs it on both servers.

The HTTP and event handlers exist from the start

Section titled “The HTTP and event handlers exist from the start”

A choice.

PennMUSH has no HTTP or event handler until a wizard creates an object and points http_handler or event_handler at it.
SharpMUSH creates the HTTP Handler (#8) and the Event Handler (#9) in a new database, with the options already pointing at them and the default HTTP verb attributes installed.
Why. The web portal is built on handler routes and needs them present.
Workaround. Extend the shipped handlers rather than creating new ones. See help http and help event.

A new PennMUSH database has no #8 or #9, and answers #-1 NO SUCH OBJECT VISIBLE twice:

> think [name(#8)]|[name(#9)]
HTTP Handler|Event Handler

A drop-to move’s event names who caused it

Section titled “A drop-to move’s event names who caused it”

A choice.

PennMUSH reports the move of an object sent through a drop-to as caused by SYSEVENT (move.c:187).
SharpMUSH has no SYSEVENT object and passes on the enactor whose action caused the move. This shows only in the enactor of the OBJECT`MOVE event. (#1006 item 9)
Why. There is no SYSEVENT dbref to name.
Workaround. Do not rely on an OBJECT`MOVE handler’s enactor to tell a drop-to move from any other.
Example. The parity case choice.dropto in tools/parity/scenarios/40-compat-choices.scn runs it on both servers.

Typed input is bounded by a pending count, not a replenishing rate

Section titled “Typed input is bounded by a pending count, not a replenishing rate”

A choice.

PennMUSH keeps a typed line out of the queue entirely (run_user_input hands its QUEUE_SOCKET entry straight to do_entry (cque.c:1076-1088), so it never touches the tally queue_limit reads) and bounds it on the descriptor instead: a burst of COMMAND_BURST_SIZE commands that replenishes at COMMANDS_PER_SECOND (conf.h:99-100, bsd.c:197,1000-1004).
SharpMUSH also keeps typed input out of player_queue_limit, so a full owner queue never stops its owner typing and a typed line is never why another of that owner’s commands is refused. It bounds it by socket with command_burst_size, which defaults to the same 100 but caps the number of typed lines outstanding rather than the rate at which they start. A connection over that cap is told Queue admission rejected: ConnectionLimit. (#1320)
Why. SharpMUSH queues typed input rather than running it inside the network loop, so a pending count is the quantity it has; a replenishing rate would delay input the queue is already ready to run.
Workaround. None needed for softcode. Raise command_burst_size if a client that sends large scripted bursts is refused.

PennMUSH answers #-1 NO SUCH CONFIG OPTION:

> think config(command_burst_size)
100