Documentation ¶
Overview ¶
ANSI color related types and functions
commands.go handles the routing of commands.
When a player types a command, the cooresponding function is called from the commands map ¶
Note Commands are the primary place the "chain locking" pattern is used. If you get more than 1 setter at once, you MUST use this pattern to prevent deadlock and starvation. See the thing.go file comment for more details. Look at functions in this file which use NextChainTime for examples.
db.go handles database/persistence
initDb() creates and assigns the db to world, and launches saver goroutines.
These saver goroutines listen to the ThingManagers' saver chans, and save to the db when a change is made.
direction.go contains Direction types and functions
items.go contains Item types and funcs, along with an ItemManager type which provides item-related functions for ThingManager
Item implements the Thing interface. ItemManager is a ThingManager
listener.go handles tcp connections from clients.
It manages logins, calls commands that players type, etc.
main.go initializes the world and starts listening for connections
npc.go contains Npc types and func, along with an NpcManager type which provides npc-related funcs for ThingManager
Npc implements the Thing interface. NpcManager is a ThingManager
players.go contains Player types and funcs, along with an PlayerManager type which provides room-related functions for ThingManager
Player implements the Thing interface. PlayerManager is a ThingManager
players.go contains Room types and funcs, along with an RoomManager type which provides room-related functions for ThingManager
Room implements the Thing interface. RoomManager is a ThingManager
telnet.go has telnet-related types and funcs.
It negotiates telnet options, and handles telnet codes sent by clients ¶
thing.go handles the data management for gomud.
Thing is an interface, which data types implement.
Every Thing gets its own goroutine, with channels to get and set the value.
Getting is completely concurrent and never blocks. Setting can only be done by one goroutine at a time. There are convenience functions to set as if it were sequential.
Often, it must be guaranteed that certain Things don't change, when one is changed. For example, when a player picks up an item. We must guarantee that everyone in the room sees the message "Bill picks up a bowl." While at the same time, guaranteeing no one leaves the room, and then gets the message.
To provide this guarantee, gomud has an idiom whereby the setters of each Thing are requested, then the things in question are changed (bowl is in Bill's inventory, and out of the Room). Then, the "observer" Things have their current value written unchanged to their Setters (to release them).
Furthermore, to prevent deadlocks and starvation, when "chaining" setter requests, a StartTime is maintained, and if any Setter returns a AlreadyRequestedTime of older than our StartTime, we MUST release ALL Setters and start over (without resetting our StartTime).
This guarntees no goroutines deadlock waiting for eachother's setters, and guarntees no goroutines starves. You'll notice this solution bears a remarkable similarity to OS scheduling algorithms.
To see an example of the "chain locking" pattern, look at functions in commands.go, such as get and set.
You MUST implement this chaining pattern if you get more than 1 setter at once.