AmigaMUD, Copyright 1997 by Chris Gray The 'MUDServ' Program MUDServ is the AmigaMUD server program. It is the largest and most complex part of the system, but it is quite easy to use. MUDServ runs all of the AmigaMUD scenario code, maintains the database files, responds to client requests, provides all of the builtin functions that can be used, provides for interaction between clients, runs the "machines", etc. A system is hosting an AmigaMUD if and only if it is running MUDServ. A system will normally only run one copy of AmigaMUD at a time, but it is possible to run more for testing purposes. This can be handy for having a production MUD as well as a development one. MUDServ expects the MUD database files to be present in the directory which it is run from, or in a directory specified in a tooltype or command line parameter. These are: MUD.data - the raw data of the scenario. This includes the data for characters, rooms, objects, monsters, etc. as well as the AmigaMUD code that governs them. The system should be able to support an arbitrary sized file, but so far, the standard scenario (30,000 lines of source yielding hundreds of locations, dozens of commands and objects, etc.) has not grown much over 500K bytes. MUD.index - this is an index into MUD.data which allows mapping from a unique constant identifier for something onto a perhaps changing position in the MUD.data file. MUDServ will also create and write a 'MUD.log' file. This file can be deleted at will, but most people running servers will want to scan through it before deleting it. It often contains some interesting information. Also, there are commands in the standard scenario, such as 'bug', 'gripe' and 'typo' which let players put short complaints about things into the MUD.log file. Valid database files are either copied from another source or are produced by the 'MUDCre' program and expanded via MUDServ. The files are in a binary format, and are not intended to be read by humans. Mess around editing them at your own risk. MUDServ assumes they are valid - it may crash your system if they are not, just like an invalid program might. MUDServ requires a stack size of 25000 bytes in order to run. It will exit right away if the stack is not at least that large. If running from a shell, you can use the 'Stack' command (perhaps from a shell- startup file) to set it. If running from the Workbench, you can use the "Icons"/"Information" menu item to set it. Warning MUDServ maintains an in-memory cache of the most recently used database items. When items are changed, as a result of player actions, machine actions or timed events, the changes are NOT immediately written out to the on-disk copy of the database. This behavior is required in order to get reasonable performance from the system without having continual disk I/O even on a fast hard drive. Without this, the system would be completely unusable on a floppy-based system. Because of this behavior, you must not simply shut off or reboot the host machine when you are through playing. You must properly flush the database and shut the server down. This can be done using the MUDShut program or a BREAK to the MUDServ process, as described later. If you wish to automate backups of the AmigaMUD database, the '-w' CLI option to MUDShut is useful. With this flag set, MUDShut will send a different type of request to MUDServ, and MUDServ will not reply until it has fully shut down. Thus, the MUDShut command will not return until the database has been fully written out and the files closed. The standard scenario included with AmigaMUD contains a SysAdmin-only command, "backup", which can be used to make automatic periodic (or one-shot) backups of the database. It will atomically flush the database and copy the database files to a "backup" directory within the directory containing the original database files. The scenario also contains code to recover from inconsistent situations created by running from such a backup, when the backup is taken while some characters, etc. are in non-normal states (such as entering a letter). This backup facility is strongly recommended. Workbench Tool Types When MUDServ is started from the Workbench, it accepts several tool- types in its icon. Some of these are boolean (true/false) values. For these, any of YES/yes/TRUE/true/Y/y/T/t or an empty value, are accepted as true, and any other value is accepted as false. Note that on early versions of the AmigaOS, empty values are not valid. The following Workbench tooltypes are accepted by MUDServ when it is started from the Workbench: PATH= - specify a path to the directory in which the AmigaMUD database files exist. The default is the directory from which MUDServ is run. MUDServ will change directories to that directory while it is running. PORTNAME= - specify the name of the Amiga OS Exec port name that MUDServ is to create and export. This is the port by which all clients connect to the server. The default name is "MUD port". TEST - useful for running a test AmigaMUD while a production one is running. Sets the port name to "MUD test port". WIZARD - any connections by "SysAdmin" (the AmigaMUD system administrator character) will be forced into "wizard" mode. This is useful if SysAdmin messes up and gets into a state where he can't otherwise get into wizard mode. This can happen if an invalid input handler is installed, or if SysAdmin ends up in an invalid room. QUIET - by default, MUDServ will open a console window and display occasional messages in that window, to allow interested MUD administrators to see what is happening. Specifying QUIET prevents the use of that window. The default state is to use the window, so that first-time users of AmigaMUD can get positive feedback that things are working. NORETRY - in some situations, such as not being able to allocate memory, the server cannot proceed normally. It will then put up a requester indicating the problem, and asking the user if it should try again. If the user can do something that can possibly fix the problem (such as shutting down other programs to free up memory), then they should do so, and answer in the affirmative. The server will then try again. If the user answers in the negative, then MUDServ will abort. Setting the NORETRY tooltype tells the server to abort immediately, without looking for help from the user. CACHE= - specifies the size of the in-memory database cache. This cache holds the most recently accessed or written parts of the database in memory, so that they can be accessed more quickly. Larger cache sizes reduce the amount of disk I/O needed during operation. The minimum cache size is 32768 bytes. The default cache size is 100000 bytes. I find a cache size of 500000 bytes to be quite adequate. Note that the cache must be available as a single contiguous region. The largest region a system has available is indicated by the 'Avail' shell command. Other needs may prevent the use of a cache that large, however. One disadvantage of a large cache is that it takes a while to flush it to disk, so players would notice a few seconds of non-responsiveness whenever it had to be flushed out. MEMORY= - specifies the amount of memory that the server should try to limit itself to. This does not include the cache, cache index data structures, the in-memory copy of the MUD.index file, or messages allocated to send to clients. It does include memory for AmigaMUD functions, in-memory copies of symbol tables and grammars, client structures, machine structures, a write-back use-count cache, etc. The value given is not a hard limit - the server will try to keep under it, but will often exceed it. Providing a small memory limit will require more database accesses, putting more stress on the database cache, and requiring more disk I/O operations. The default limit is 1000000000 bytes, which is effectively no limit. REQUEST= - specifies a limit on the number of requests (messages) that the server should observe. Requests are AmigaMUD messages between the server and the clients. When it needs to send a message, the server will try to get one from its pool of free ones. If the pool is empty, then it will allocate one from the system. When it receives a message that does not need a reply, the server adds the message to its pool of free messages. If that pool contains more than the given number of messages, it will free the new one back to the system. The expense of having a small limit is one of CPU time and not disk I/O. The default limit is 100. IGNORECTRLE - Normally, MUDServ can be interrupted from an infinite CPU loop (typically caused by running with a too- large "RunLimit" value) by sending a 'break e' signal to it. Specifying this tooltype tells MUDServ to ignore the signal. This shouldn't be needed, but I am leaving it in in case of troubles similar to those encountered when I was using the 'break f' signal for this purpose. Command Line Flags When MUDServ is started from a shell, the following flags can be given (see the above section for more detailed descriptions): -T - use "MUD test port" as the Amiga OS message port name -W - force SysAdmin to enter in wizard mode -Q - do not open and use the message window -N - do not retry in abort situations -P - use as the Amiga OS message port name -c - use as the database cache size -m - use as the maximum memory usage target -r - use as the free request limit -E - ignore 'break e' signals -M - do not activate any machines on startup, and do not let any machines operate by themselves. This is useful when some machine or machines have gotten out of hand, for example when running the "wanderers" on a system that just isn't fast enough to handle them. If a parameter without a leading '-' is given, then it is taken as a path to where the database files can be found, and MUDServ will change directories to that directory. Shutting MUDServ Down MUDServ uses write-back caching for the database. This means that changes made to the database are not immediately written to disk. Instead, the changes are kept in the in-memory cache, and only written to disk when that cache is "flushed". This flushing is done on shutdown, in response to running the 'MUDFlush' program, in response to calling the 'Flush' builtin, or whenever the database code cannot find a large enough slot for a new value. Because of this, the on-disk copy of the database is not accurate and consistent except immediately after a flush of the in-memory cache. This means that you cannot safely shut down MUDServ by simply rebooting or turning off your Amiga. Doing so will leave you with a scrambled database. Using write-through caching, where all changes are written to disk immediately, would be hopelessly slow - almost everything done in AmigaMUD changes the database, often in several ways. For example, a character walking from one room to another changes the record of which room the character is in. This is also true for 'machines', such as the randomly generated monsters in the standard scenario. There are three safe ways to shut down MUDServ. In all of these ways, it will not actually shut down until all clients have disconnected. It will, however, remember that it is supposed to shut down and do so as soon as it can. The program 'MUDShut' sends a special message to MUDServ, requesting that it shutdown. Running MUDShut multiple times will not speed the process up. When the special privileged character SysAdmin is connected and in "wizard" mode (working directly with the AmigaMUD programming language, rather than playing the scenario), he can enter a line reading "ShutDown(true).". This line is a call to the 'ShutDown' builtin function, and tells the server that it should shut down as soon as possible. Of course, it cannot do so until SysAdmin logs out. A line reading "ShutDown(false)." will cancel all previous requests to shut down. If MUDServ is started from a shell, it will have a CLI Process number. Sending a standard BREAK signal (using the 'Break' command) to that process will tell MUDServ to shut down. If the MUDShut program is run from a shell, it can be given the '-w' flag, which will cause it to use a special request to MUDServ, such that MUDShut will not exit until the server has written out and closed all of the database files. This can be used to allow automatic backups. It is possible for MUDServ to get into an inconsistent state where it cannot respond to a normal shutdown request. This could be, for example, when stuck in an infinite loop in AmigaMUD code, when SysAdmin has put in an extremely large execution time limit. In this situation, sending a 'BREAK E' signal to the MUDServ process will cause it to stop its current AmigaMUD code execution and return to its top level activity loop. Two such signals will cause it to abort immediately. Do not do this unless you really need to. If you do so, you will have to restore your database from a backup copy, and you may want to reboot your Amiga to recover memory that MUDServ was not able to free when it aborted. This facility can be disabled with the '-E' command-line flag, or the "IGNORECTRLE" tooltype, in case there is something in your system generating the signal when it isn't wanted. Remote Connections Also part of hosting AmigaMUD are possible copies of the MUDAgent program running on the host machine. These copies will run without the server being active if they are waiting for incoming calls, so they don't normally have to be shut down. If they are started from a shell, they can be shut down by doing a 'BREAK' on their process number. If they are started from the Workbench, they can be shut down by running the 'AgentKill' program, which will find their tasks and set the BREAK signal on them. Often, the MUDAgent copies are started on demand by some other program, such as a BBS or 'Getty'. In that situation, they exist only for the duration of one session, so there is nothing to shut down. A Few Basic Wizarding Procedures Repeated here for those who miss it in "Intro.txt", the default password for SysAdmin is "SysAdminPassword". The standard scenario contains a few commands that can be used by SysAdmin only. They are: 'backup' - discussed earlier in the "Warning" section 'shutdown' - this command sets the internal server flag indicating that the MUD is being shut down. It will no longer accept new client connections, and will terminate when the last current client goes away. The 'shutdown' command broadcasts a simple message to everyone on the MUD. If 'shutdown' is followed by some text, that text will accompany the message. E.g. shutdown System going down for harddrive replacement. would result in everyone connected to the MUD seeing: **** System going down for harddrive replacement. SysAdmin has started shutdown of the MUD. **** 'freeposes' - this command accepts a yes/no parameter, and will default to 'yes' if no parameter is given. The scenario has several built-in poses, such as "wave", which will appear directly on other player's screens. The generic pose command, however (abbreviated ':') by default puts a " => " between the name of the posing player and the pose itself. This lets other players know that the output they are seeing is a pose, and not some normal output from the system. E.g. if player "Sam" types :gives Fred 10000 blutos. other players would see: Sam => gives Fred 10000 blutos. Some players prefer to have free arbitrary poses, however. This can be globally enabled in the AmigaMUD scenario using the 'freeposes' command. The above example would then show: Sam gives Fred 10000 blutos. 'freebuilding' - this command can be used to allow all players to be builders, without SysAdmin having to enable them separately. Technically, if this command is in effect when a new player first enters the game, then that player will be made a full builder at that time. By default, players are not full builders, and can only build in the Playpen. 'makeapprentice ' - this command allows SysAdmin to make a given player an apprentice, thus having access to "wizard mode", and to programming within the AmigaMUD system. Use this command carefully, since an out-of-control apprentice can ruin your MUD, and make it unusable. 'cast makebuilder ' - this command allows SysAdmin to make an individual player a builder. The change will not take place until the player next connects to the MUD. 'cast unmakebuilder ' - make a player not a builder. SysAdmin, or any other wizard, can enter wizard mode from the standard scenario by typing the "wizard" command. In wizard mode, user input is not handled by the scenario, but is either one of a very few wizard- mode commands, or is a statement in the AmigaMUD programming language. For reference, the way for a wizard to get back into playing mode from wizard mode is to type the following: Normal()$ on an input line by itself, when the prompt is "> ". Note that this input line, as well as all of the following ones, ends in a dollar sign. This dollar sign is required, to indicate the end of the statement. If you forget it, the prompt will switch to ": ", and nothing will happen. You must then type the dollar sign to execute the statement. Note also that the capitalization of these input statements must be as shown. The standard scenario sets the "creation password" to an empty string. This means that no special password or permission is needed to create a new character. A creation password can be installed by using the following line while in wizard mode (only SysAdmin can do this): NewCreationPassword()$ The system will prompt for the new password. If the password begins with an asterisk ('*'), then automatic character creation is not allowed at all. In that case, SysAdmin will have to manually create all new characters. This is done in wizard mode as follows: CreateCharacter("characterName", "characterPassword")$ The character will be created with the given name and password. As usual, do not include spaces or punctuation in the name. A character can be removed from the system using: DestroyCharacter("characterName")$ Note that the above can leave unreachable junk in the database, if the character is carrying complicated objects such as containers. A character can be booted off of the system with: use Characters BootClient(characterName)$ If something prevents that from working, and it is truly necessary to get rid of the character right away, the following can be used: use Characters NukeClient(characterName)$ This is a rather drastic method, however, so avoid it whenever possible. When the character reconnects, he/she will likely have to move around a bit and do some "looks" to get the graphics to come back properly. This is because "NukeClient" is so abrupt that it does not allow the client to execute the scenario shutdown code. If SysAdmin wishes to make a character into a wizard or apprentice, this can be done in wizard mode as follows: use Characters MakeApprentice(CharacterName, false)$ or MakeWizard(CharacterName, false)$ The "use Characters" needs to be done only once per connection. Note that here the character name is not quoted - it is known directly because the "Characters" table is in-use. Note also that this method will not work if the character name has spaces or punctuation marks in it. The "false" in the above tells the system to not immediately change the mode of the player. If the player is currently connected and "true" is used instead, then the player will be immediately placed into wizard mode. A wizard or apprentice can be demoted back to a normal character using: MakeNormal(CharacterName)$ MUDServ places an execution time limit on the AmigaMUD code run in response to any input line or mouse-click. The execution is aborted if this limit is exceeded. The standard scenario sets this limit to 10 seconds. Other limits can be set as follows: RunLimit(new-limit)$ where 'new-limit' is the new execution time limit in seconds. The old limit will be printed out. Do not make the limit too large, as this can cause MUDServ to hang if erroneous wizard code is encountered. There is no command in the standard scenario to allow sending a message to all connected players. This can be done as follows: APrint("This is the message.")$ This can be used to announce system shutdowns, special events, etc. The standard scenario uses it to announce when a character completes a Quest. Messages in MUD.log Many different messages can appear in the MUD.log file. Some are just informational, but others can indicate problems, either with the system as a whole or with the scenario. I will attempt to explain some of them here, but there are many that are not explained, either because they are (hopefully) obvious, or because they are coming through some obscure path that I miss. Most lines in the log file will be prefixed by the date and time they are produced. _start = 0x07ccb890 lib = 0x07cbf554 This line is produced when the server starts up. The exact numbers will differ, often from run to run. They are useful only to the author of the system. If the system gets an "Enforcer" hit or other system problem in which the CPU program counter is available, these numbers are helpful in pinning down the location in the code of the problem. Player SysAdmin enters the game Player SysAdmin leaves the game Messages of this type are produced whenever a player enters or leaves the game. External programs can then be run to keep track of who is using the game and when, and perhaps to add up the amount of time various players are spending in the game. Setting WIZARD mode Clearing WIZARD mode These messages occur whenever a wizard or apprentice goes in or out of wizard (programming) mode. They can be useful in tracking down the causes of problems created in the scenario. expandIndexTable This message indicates than it was necessary for the database code to increase the size of its index array. A number of these will occur when compiling the standard scenario, and occasional ones can occur when running. They are indications of increasing memory usage. Server shutdown request via message - currently 0 clients Shutting down, 1 client serviced Machines: 11 created, 0 deleted Things: 785 created, 0 destroyed Messages: 27448 processed, 2174 sent Allocator: used: 2158592 limit: 1000000000 allocs: 187602 frees: 187602 reclaims: 0 panics: 0 cre 5819 del 5 rd 27117 rep 2371 shr 2 exp 8047 dir 6693 frd 446 fwt 1718 fsk 1976 MUD server V1.0 Copyright 1995 by Chris Gray shut down These messages are typical of shutting down the server. This particular set came after compiling the current version of the standard scenario. Normally, the memory usage figure will be much smaller. The server will not shut down when there are active clients, so the shutdown request (which can come via a message sent by the MUDShut program, a shell 'break' signal to the server process, or by SysAdmin calling the 'ShutDown(true)' builtin) can be quite a ways before the actual shutdown. Machines are the 'robots' or NPC's (Non-Player-Characters) in the AmigaMUD system. During active playing in the standard scenario's combat area, the number created and destroyed can be much higher, perhaps in the tens or hundreds of thousands. Things are the basic entities in the AmigaMUD system. They represent characters, machines, rooms, objects, etc. Messages are the means by which player input is sent to the server and player output is sent from the server. Again, the numbers would normally be quite a bit higher with active players. The memory used by the allocator does not include the database cache and an in-memory copy of the MUD.index file. It also does not include the various Exec messages that the server may have had to allocate. The next line gives some statistics on the database activities: cre: database entries (things, characters, strings, tables, machines, procedures, property structures, etc.) that were created in this run del: database entries deleted rd: database entries read (on long, intensive runs, I've seen this number over 20,000,000) rep: database entries replaced shr: database entries shrunk (e.g. when properties are removed from a thing, or elements are deleted from a list) exp: database entries expanded dir: database entries dirtied (a change made which doesn't involve changing the size of the entry) The next line indicates the number of actual disk I/O operations that the database code had to make. The ratio between the above numbers and these numbers is an indication of how effective the database cache has been: frd: number of actual file reads fwt: number of actual file writes fsk: number of file seeks DataSize 605678=>605678 IndexCurrent 7027=>7021 On occasions, the database code will scan through the highest indexed database entries, attempting to merge and free them. This line indicates the success of doing so. 'DataSize' indicates the total used size of the MUD.data file. 'IndexCurrent' indicates the total used size of the MUD.index file. Server flush request via message This message indicates that a request to flush the database to disk was received. This is generated by running the 'MUDFlush' program. BootClient for player SysAdmin This indicates that a request was generated to shut down the indicated client. The client will exit as soon as its current activity in the server is done. In this case, it was generated by the scenario calling the 'Quit' builtin as a result of the player entering the 'bye' command. Agent shutdown for player SysAdmin The MUDAgent program has shut down a connection for some reason. This could be loss of carrier, activity timeout, failure to communicate, etc. NukeClient for player SysAdmin This is a record of a more severe method of shutting down a given client. In this case, the system tries to shut the client down right away, and does not wait for anything. This is done by SysAdmin via the 'NukeClient' builtin. SysAdmin has set the shutdown flag. SysAdmin has cleared the shutdown flag. These appear in response to SysAdmin using the ShutDown builtin. Name1 changed name to Name2 A system administrator will sometimes want to keep track of which characters are played by which real people. This message helps by logging when a character changes name. It comes from the 'ChangeName' builtin. New player when no entry action! This message indicates that a person has tried to connect and create a new character when there is not yet an 'entry-action' routine in the scenario. This is the routine, set by the 'SetNewCharacterAction' builtin, which is called to setup a new character. no memory for server request This will be immediately followed by an abort. The server could not allocate memory for a message, and so cannot proceed. serverMessage: got unexpected type NN from server MUDState NNNN > 1000 Can't find local offset XXXXXXXX in 'readExec' can't find ref key in 'readExec' invalid request type client not found client already editing can't find name for builtin in subPublicProc can't find Characters in public symbol table can't find Builtin in public symbol table These should not happen, and will cause an abort. If they happen, something serious is wrong with your AmigaMUD system. This could be an invalid program, a damaged database, failing hardware, etc. You should not continue to run such a system, since it is possible that important data on your hard disk could be damaged. can't create MUD port can't allocate interrupt can't open timer device can't allocate timer request can't create timer port These messages indicate that MUDServ could not start up because it could not do all of its initialization. They usually indicate that they system does not have enough free memory. MUD port already exits This can happen if you try to start two servers using the same port name. If you get this message when you are sure that there is no other copy of MUDServ running, then you will have to reboot your system to clear the condition. Fail to seek to end to expand The database code needed to expand MUD.data, but could not seek to the current end of the file in order to write more to it. This should not happen. Fail to write NN bytes to expand Fail to write block to expand Fail to write NNN bytes to flush buffer can't write index to index file This can happen if your disk is full. In this case you will have to go back to a backup of your database files, since the current ones are no longer internally consistent. This kind of symptom can also happen if the disk or partition in use becomes write protected. Fail to seek to NNNNNN to flush buffer Fail to seek to write direct Fail to write NNN bytes direct This is a similar seek failure. It should not happen. If it does, there is something wrong with your system. Fail to seek to NNNNNN to read direct Fail to read NNN bytes direct Fail to seek to NNNNNN to fill buffer Fail to read enough into buffer This can indicate a filesystem failure or a corrupt database. In either case, you will need to restore from a backup. can't write XXXXX to index file can't open/create new index file The MUD.index file has several special values at its beginning. One of them couldn't be written when flushing the database. This will yield a corrupt set of database files. It is also possible that this kind of symptom could occur if the disk that AmigaMUD is running on becomes write protected. offset > SORT_BUCKETS XXXXXXXX CacheLRUHead ~= next in ioFlush No cache slot len NNN for item invalid type to ioCreate key XXXXXXXX not in cache for ioDirty key XXXXXXXX not in cache for ioExpand new len < oldlen on ioExpand of XXXXXXXX assumption failed in ioExpand! ioShrink, newLen 0 Key XXXXXXXX not in cache for 'ioShrink' new len > old len on ioShrink of XXXXXXXX ioReplace, newLen = 0 ioDelete(XXXXXXXX) - already deleted! I've got a bug. Let me know. If you get any of these, then the database code will have aborted. This leaves you with an inconsistent set of database files and you must go back to a backup of them. Cannot create cache slot len NNN for item The database code uses a non-write-through cache to hold the most recently referenced database items. This abort indicates that it needed to create such a cache slot for an item, and was not able to find a hole large enough (the items must be stored in one contiguous slot). In such cases it simply cannot continue executing, because it has no knowledge about the state of the upper-level code that is using it. Hence the abort. With this abort, like those listed above, the database files are now unusable. Run with a larger database cache to avoid this abort. Too few cache entries to make one for len NNN This abort is similar to the previous one, except that in this case, there are a small number of large entries that seem to be using up all of the space. Again, the database will be corrupt, and you should run with a larger database cache. database overflow - too many entries!!! The system thinks you have more than 2 ** 24 entries (over 16 million). I can't believe that! expansion failed An attempt was made to expand the in-memory copy of MUD.index. A region of memory big enough could not be allocated. You will have to restore from backup files, and attempt to make more free memory available for running. AmigaMUD code running in the scenario can also add lines to the log file. The content of those lines is entirely up to the scenario. In the standard scenario, they are user-generated comments about bugs or typos, or just plain complaints.