FAQ or Documentation
                                    [ You decide ]

What is TeenyMUSH?
~~~~~~~~~~~~~~~~~~
        If you've seen a TinyMUSH server, then TeenyMUSH is a TinyMUSH like server writen from scratch from a different perspective. If you haven't seen a TinyMUSH server then TeenyMUSH is server which gives you a virtual blank piece of paper where you can make your own places or objects. When a person connects to a TeenyMUSH server, they might find themselves in a room with a description such as 'Cheers - A place where everyone knows your name'. It might contain a Bartender named Sam that responds to questions. There are even exits going to other places so that you might explore other parts of the world. If you don't like Cheers, maybe you'll open your own restaurant and call it Milliways. But either way, TeenyMUSH is the software that will make it happen.

How does TeenyMUSH differ from TinyMUSH?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	Built in web server with websocket support
	@telnet or url() for socket based communication via MushCode
	Automatic formatting of MushCode into multi-line readable code
	Attributes may span multiple lines via &&attribute command
	run() function to run @commands as functions
	@while loops
	Crash detection / resumption
	@reload - Code can be updated while running
	More understandable command execution order
	Written in Perl
        @dumps are incremental with daily full backups.
	Written in Perl


What does TeenyMUSH run on?
~~~~~~~~~~~~~~~~~~~~~~~~~~~
	TeenyMUSH should run about any computer that has perl 5 and the right modules. TeenyMUSH has been heavily tested on x86 Xubuntu 18.10 and initially a Raspberry Pi. The code has also been lightly tested on a Drobo 5n NAS and my Samsung S7 Edge running Android using Perl and Termux. I'd be happy to hear from anyone running TeenyMUSH on any odd hardware.

Where can TeenyMUSH be found?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	The source code can be found at https://github.com/c-hudson/teenymush. The development MUSH server can be found online at teenymush.dynu.net 4096. Its MUSH based web server can be found at http://ascii.dynu.net. The current version of this document can be found at http://ascii.dynu.net/faq. All are welcome.

What is TeenyMUSH's status?
~~~~~~~~~~~~~~~~~~~~~~~~~~~
	TeenyMUSH is a work in progress. It's development server has been up and running since 2016. As of the writing of this document, the server has been up for three month without crashing... even while implementing new code and debugging heavily. A few complicated games/objects have been ported over from TinyMUSH and run without problems. Not everything from TinyMUSH will run but hopefully it will as more of the internal @commands and @functions are written. Running TeenyMUSH will be an adventure for some and fun for others.

Installation
~~~~~~~~~~~~
	Download teenymush.pl and help.txt from git hub.

		wget https://github.com/c-hudson/teenymush/raw/master/teenymush.pl
		wget https://github.com/c-hudson/teenymush/raw/master/help.txt

	Run teenymush.pl script
		chmod u+x teenymush.pl
		./teenymush.pl

	Login as god on port 4096 with a password of portrzebie
		telnet localhost 4096


Configuration
~~~~~~~~~~~~~
   TeenyMUSH does not use a configuration file like TinyMUSH does. All configuration items are stored inside the database. Most options can be set from within the server or via the command line. The only options which may need to be initially set via the command line are the MUSH's ports that are used to listen for incoming connections. Examples of ports that are only used at startup are: port, httpd, and websocket.

Commandline Example:
   ./teenymush.pl -Dport=4201

Online Example
   &conf.port #0 = 4201
   &conf.master #0 = #3
                   
Option              |  Description
====================|=====================================================
badsite             | Login screen for banned sites
conlog              | yes/no - Log all non-web log to teenymush.log
createcost          | Quota cost of an object
digcost             | Quota cost of a room
dirty_single_file   | Dump the incremental data into a single file or
                    | multiple files.
dump_interval       | How often to do a full backup of the db in seconds
function_limit      | How many functions can be called [default 2500]
hostmask            |  Optionally hides full hostnames
                    |    mask      : domain name only
                    |    colormask : domain name w/colors
                    |    color     : colors for hostnames
host_filter         | Hide connect messages from hosts defined in
                    | this csv list. Useful for high volume sites that monitor
                    | stats. Hosts may include wild cards.
httpd               | Port to listen for web requests
httpd_invalid       | Invalid requests/hour before auto banning a site
httpd_template      | html to prefix before output via httpd
linkcost            | Quota cost of a link
login               | Login screen
logoff              | Log off screen
master              | dbref for the master room
master_overide      | yes/no. Run master room objects before any else
memory_prog_limit   | Defines the max number of bytes that setq(), @var, 
                    | %0 .. %9, etc can use. Default is 122880.
money_name_plural   | Singular form of money's name
money_name_singular | Plural form of money's name
motd                | Message of the day
mudname             | Your MUSH's name
paycheck            | Money received per day on connect by player
port                | Main port use to connect for the MUSH.
registration        | Login screen shown when registration is in effect
safemode            | Disables running/evaluation of any mushcode.
                    | If set to 2, the setting is persistant. If set to 1,
                    | it will be removed at startup.
show_offline_cmd    | Show commands from non-connected sessions to console
starting_money      | How much money does a player get on creation
starting_quota      | How many objects can a player create on creation
starting_room       | Starting location for new players
weblog              | yes/no - Log web requests to teenymush.web.log
websocket           | Port to listen for websocket connections
webuser             | Dbref of object that runs all code for httpd
====================|=====================================================

Web Server Support
~~~~~~~~~~~~~~~~~~
	TeenyMUSH has a built in web server that has full access to the MUSH engine, if you so wish it. Think about being able to use almost any @command or function to publish information about the goings on of your mush. This should make it rather trival to keep people informed about the inner workings of your MUSH via the web.
	TeenyMUSH supports a security model where only $commands in objects held by the webobject can be run. Any commands in the +who command will run normally as if the request was coming from a connected player.
Take the following bit of code '&who security_object=$+who:@pemit %#=[lwho()]'. If someone enters in the url of http://server_machine:8000/+who, it would match the +who command on the security_object. A similar command of 'http://server_machine:8000/@pemit/*adrick=foobar' would not work and would return a 'huh?' webpage. This assumes that the security_object is housed in the webobject's inventory. Arguments can also be passed via the same type of command. Keep in mind that any slashes will be converted to a space. I.E. 'http://server_machine:8000/+page/adrick=test' would run the '+page adrick=testing' command. 
	Configuration can be done with '@set #0/conf.httpd=<port>' and '@set #0/webobject=#dbref'. These control which port the mush listens to for httpd requests and which object the mush runs commands as. These can also be added to the teenymush.conf file. All http responces will be prefixed with the contents of the 'http_template.txt' file in the txt folder.
	

Websocket Support
~~~~~~~~~~~~~~~~~
	TeenyMUSH also supports web sockets. This allows real time two way communication between your web browser and the MUSH. Typically this is used to provide the user with a web based mudding client to access the MUSH without downloading any programs. Web sockets can provide access to MushCode in real time. For example, there is a connect 4 game that you may play against people logged into the MUSH. When a person makes a move, the results are sent in real time the web user and the MUSH player.
	Configuration and use of the websocket is a little tricky as it requires a corresponding set of html files for it to work. There's really too much to go into to describe it properly. Two examples are provided that are used by the interactive connect 4 game [sample_connect4.html] or grapenut's websocket client [wsclient.html]. The sample files will need to live in the txt folder. Grapenut's websocket client will need to be downloaded seperately at https://github.com/grapenut/websockclient and copied into the txt folder as well. Hopefully people will be able to figure out what needs to change to fit their website and environment. The 'conf.websocket=<port>' is required.

MushCode engine
~~~~~~~~~~~~~~~
	TeenyMUSH is different in that everything is run in the expected order. This eliminates the need for complicated code when you need to string bits of code together. For example a '@dolist lnum(2)=@pemit me=##;think done' would result in 'done' followed by 0 and 1 on standard TinyMUSH. In TeenyMUSH, the result would be 0, 1 and then the done. This is because TinyMUSH throws everything into a queue and does not preserve execution order. TeenyMUSH does preserve execution order.

Mush Sockets
~~~~~~~~~~~~
	TeenyMUSH supports sockets over the internet via @telnet or url(). The url() is for http/https connections and @telnet is more flexible and can be adapted to support multiple protocols. Url() puts received data into the %{data} variable. @telnet received data can be retrieved via a ^-listen style attribute or via the input() function depending upon if the object is set SOCKET_PUPPET or SOCKET_INPUT. The ^ character is replaced with a ! for socket listens.

Limitations:
	Any object wishing to use url() must be set SOCKET_INPUT by a wizard. @telnet requires an object be set SOCKET_PUPPET or SOCKET_INPUT by a wizard. An object may only have one socket open at any time.


url() example:

&&URL_LISTEN object=^*htt*://*":
   @switch 1=
      lt(strlen(%2),25),
         @@ ignore,
      DEFAULT,
         {  @while ( url(http://tinyurl.com/api-create.php?url=htt%1://%2)) {
               @switch %{data}=
                  #-1 CONNECTION FAILED,
                     say TinyURL is unavailable \[connection failed\],
                  #-1 PAGE LOAD FAILURE,
                     say Weather is unavailable \[page load failure\],
                  #-1 DATA PENDING,
                     @@ ignore,
                  http*tinyurl*,
                     :> %{data};
            }
         }

	This example waits and listens for someone to say a http://url longer then 25 characters. It then connects to tinyurl.com and spits out the shortened url from the website. The url function() returns only 1 until it has finished providing all data input via the %{data} variable. The MUSH also does not pause for this code to run. The socket is closed when all data is read, the execution of the attribute finishes, or when the other end closes the socket. @triggering another attribute will not any issues.

SOCKET_PUPPET example:

RESPONSE: !*link">*</a>*:say [edit(edit(%1,<p>,),</p>,)]
FORTUNE[C]: ^* says, "*FORTUNE*":
   @telnet www.fortunecookiemessage.com 80;
   @send GET / HTTP/1.1;
   @send Host: www.fortunecookiemessage.com;
   @send Connection: close;
   @send User-Agent: curl/7.52.1;
   @send Accept: */*;
   @send ;

	In this example, the code waits for someone to say fortune in uppercase. It then opens a connection to www.fortunecookiemessage.com and waits listens for a string that contains 'link">' followed by '</a>'. The "!" signifies that it is only listening (similar to ^-listen) for input from an open @telnet connection. The edits() remove the <p> and </p> that may or may not be part of %1.
	The advantage to using SOCKET_PUPPET verses SOCKET_INPUT is that it is a little more efficient. Code is only run when new input comes in. This doesn't mean that SOCKET_INPUT does a bad job of looking for input, but it will spin a few extra cycles if the network is slow. SOCKET_PUPPET is also handled more like standard MushCode and the code can be mush simpler. The downfall of SOCKET_PUPPET is that it is less flexible because it only has access to the current line of data at any particular time (outside of setting &attributes).

Multi-line Attributes
~~~~~~~~~~~~~~~~~~~~~
	TeenyMUSH supports a '&&attribute object=data' command. Once the command is started, it will not be finished till a blank line is received. A single period can be sent to indicate a blank line within the attribute. This allows the coder to format their attributes as desired for better readability. If you choose to use the MUSH's built in formatting, one can always @squish the attribute back into a more standard single line TinyMUSH format.

Code Readability
~~~~~~~~~~~~~~~~
	MushCode typically requires that all code is on one line. Good coders can get around some of this this by use of @trigger, u(), and careful crafting of code. One of TeenyMUSH's answers to this is by formatting Mush code for you. Any attribute that looks like it contains MushCode is automatically formatted into a multiple line code with indentation. Don't like how TeenyMUSH formated code? Attributes entered as multi-line attributes are never formatted.

Run() function
~~~~~~~~~~~~~~
	Mush code has traditionally had @commands and functions() that do the exact same thing. TeenyMUSH tries to get around the duplication of code by allowing @commands as functions. Certain looping commands may not be called as functions. Some examples of these would be @dolist, @wait, @find, and @while. 

Reloading of Code
~~~~~~~~~~~~~~~~~
	TeenyMUSH supports the reloading of code via the @reload command. When this command is issued, the server will check for any changes in the source that have happened since the last reload of code / startup. Sending the server a kill -HUP <PID> will also accomplish the same thing. This should prevent the need to restart the server for updates to the code.

single file mushcoded scripts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	TeenyMUSH can now be setup to run mushcode via the command line as a seperate standalone environment. The script does not connect to an existing instance, but instead reads the database data embeded at the script. A "__END__" must sperater the script and database. Changes to the database will be saved either via full @dumps or appending incremental dumps to the end of the script.

Example: 
   > cat __END__>>teenymush.pl
   > cat TeenyMUSH.xxx.tdb>>teenymush.pl
   > ./teenymush.pl "ex me"

   god(#0PGn)
   Type: PLAYER  Flags: GOD NO_COMMAND
   You see nothing special.
   Owner: god(#0PGn)  Key : god(#0PGn)  Pennies:
   Created: Tue Jul 14 11:59:30 2020
   Last: N/A
   Home: The Void(#1Rn)
   Location: The Void(#1Rn)
   > ./teenymush.pl "&foo me = bar"

   Set.
   > ./teenymush.pl "ex me"

   god(#0PGn)
   Type: PLAYER  Flags: GOD NO_COMMAND
   You see nothing special.
   Owner: god(#0PGn)  Key : god(#0PGn)  Pennies:
   Created: Tue Jul 14 11:59:30 2020
   Last: N/A
   FOO: bar
   Home: The Void(#1Rn)
   Location: The Void(#1Rn)

Database Backups
~~~~~~~~~~~~~~~~
        Database backups consist of a full backup and incremental additions. The format is ment to be as readable as possible. Readabilty should always be favored over reducing space. Editing by hand maybe done but only after the database format is properly documented.
        A full backup is done once a day and will always result in a new file. The full backup is a non-forked backup that is done in small segments without pausing the MUSH. Consistency is guaranteed by writing all changes to another location in memory while the backup is being written.
        A incremental backup of changes is written every 5 minutes but only if needed. This backup is always appended to the last full backup. This allows a restore to within 5 minutes of any point in time assuming one is willing to manually edit the database dump.