Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?xml version="1.0" encoding="iso-8859-1"?>
- <!DOCTYPE muclient [
- <!ENTITY show_vnums "true" >
- <!ENTITY show_timing "false" >
- <!ENTITY show_completed "false" >
- <!ENTITY show_database_mods "true" >
- <!ENTITY show_other_areas "false" >
- <!ENTITY show_area_exits "false" >
- <!ENTITY show_up_down "true" >
- <!ENTITY speedwalk_prefix "" >
- ]>
- <muclient>
- <plugin
- name="Materia_Magica_Mapper"
- author="Nick Gammon"
- id="1c17ac2c83b2b66c402c80c6"
- language="Lua"
- purpose="Mapper for Materia Magica"
- save_state="y"
- date_written="2010-10-12"
- date_modified="2010-10-18 07:05"
- requires="4.61"
- version="1.5"
- >
- <description trim="y">
- <![CDATA[
- AUTOMATIC MAPPER ... by Nick Gammon
- The window can be dragged to a new location by dragging the room name.
- Your current room is always in the center with a bolder border.
- LH-click on a room to speed-walk to it. RH-click on a room for options.
- LH-click on the "*" button on the bottom-left corner to configure it.
- ** WHY DOES THE MAP CHANGE? **
- The mapper draws from your room outwards - that is, it draws your room's exits
- first, then the rooms leading from those rooms, and so on.
- Eventually it finds an overlap, and draws a short "stub" line to indicate there
- is a room there which there isn't space to draw. If you get closer to that
- room the stub will disappear and the room(s) in question will be drawn.
- ACTIONS
- mapper help --> this help (or click the "?" button on the bottom right)
- mapper zoom out --> zoom out
- mapper zoom in --> zoom in
- mapper hide --> hide map
- mapper show --> show map
- FINDING THINGS
- mapper bookmarks --> show nearby rooms that you bookmarked
- mapper find <text> --> full-text search (eg. shop OR baker)
- mapper shop --> show nearby shops/banks etc.
- mapper train --> show nearby trainers
- mapper where <room> --> show directions to a room
- MOVING
- mapper goto <room> --> walk to a room by its room number (partial)
- mapper stop --> cancel any current speedwalk
- mapper resume --> resume last speedwalk or hyperlinked speedwalk
- ]]>
- </description>
- </plugin>
- <!-- Triggers -->
- <triggers>
- <trigger
- back_colour="8"
- bold="y"
- enabled="y"
- match="[Shop] *"
- match_back_colour="y"
- match_bold="y"
- match_inverse="y"
- match_italic="y"
- match_text_colour="y"
- name="Shop_Line"
- script="Shop_Line"
- sequence="200"
- text_colour="11"
- >
- </trigger>
- <trigger
- back_colour="8"
- bold="y"
- enabled="y"
- match="[Train] *"
- match_back_colour="y"
- match_bold="y"
- match_inverse="y"
- match_italic="y"
- match_text_colour="y"
- name="Train_Line"
- script="Train_Line"
- sequence="200"
- text_colour="11"
- >
- </trigger>
- <trigger
- enabled="y"
- match="kxwt_rshort *"
- name="process_room_name"
- sequence="100"
- send_to="14"
- >
- <send>name="%1"</send>
- </trigger>
- <trigger
- enabled="y"
- match="kxwt_rvnum *"
- name="process_room_desc"
- sequence="100"
- send_to="14"
- >
- <send>uid="%1"</send>
- </trigger>
- <trigger
- enabled="y"
- match="kxwt_terrain *"
- name="process_terrain"
- sequence="100"
- send_to="14"
- >
- <send>terrain="%1"</send>
- </trigger>
- <trigger
- enabled="y"
- match="kxwt_area * *"
- name="process_area"
- sequence="100"
- send_to="14"
- >
- <send>area="%2"</send>
- </trigger>
- <trigger
- enabled="y"
- match="[Exits: *]"
- name="Exits_Line"
- sequence="100"
- send_to="14"
- >
- <send>process_exits("%1")</send>
- </trigger>
- <trigger
- enabled="y"
- match="^The (door|gate) is closed\.$"
- regexp="y"
- name="Door_Closed"
- script="Door_Closed"
- sequence="100"
- >
- </trigger>
- <!-- various messages that cancel speedwalks -->
- <trigger
- enabled="y"
- match="You are too exhausted. Better rest for a bit."
- regexp="y"
- script="mapper.cancel_speedwalk"
- sequence="100"
- >
- </trigger>
- </triggers>
- <aliases>
- <!-- zooming aliases -->
- <alias
- match="mapper zoom out"
- enabled="y"
- sequence="100"
- omit_from_command_history="y"
- omit_from_output="y"
- script="mapper.zoom_out"
- >
- </alias>
- <alias
- match="mapper zoom in"
- enabled="y"
- sequence="100"
- omit_from_command_history="y"
- omit_from_output="y"
- script="mapper.zoom_in"
- >
- </alias>
- <alias
- match="mapper goto *"
- enabled="y"
- sequence="100"
- script="map_goto"
- >
- </alias>
- <!-- finding aliases -->
- <alias
- match="^mapper find ([\w* %d/"]+)$"
- enabled="y"
- sequence="100"
- script="map_find"
- regexp="y"
- >
- </alias>
- <alias
- match="^mapper book\w*$"
- regexp="y"
- enabled="y"
- sequence="100"
- script="map_bookmarks"
- >
- </alias>
- <alias
- match="mapper where *"
- enabled="y"
- sequence="100"
- script="map_where"
- >
- </alias>
- <alias
- match="mapper backup"
- enabled="y"
- sequence="100"
- omit_from_output="y"
- script="manual_backup"
- ></alias>
- <alias
- match="^mapper shops?$"
- regexp="y"
- enabled="y"
- sequence="100"
- script="map_shops"
- >
- </alias>
- <alias
- match="^mapper train\w*$"
- regexp="y"
- enabled="y"
- sequence="100"
- script="map_trainers"
- >
- </alias>
- <alias
- match="mapper resume"
- enabled="y"
- sequence="100"
- script="map_resume"
- >
- </alias>
- <alias
- script="OnHelp"
- match="mapper help"
- enabled="y"
- >
- </alias>
- <!-- cancel speedwalking -->
- <alias
- match="mapper stop"
- enabled="y"
- sequence="100"
- script="mapper.cancel_speedwalk"
- >
- </alias>
- <!-- show/hide mapper -->
- <alias
- match="mapper hide"
- enabled="y"
- sequence="100"
- script="mapper.hide"
- >
- </alias>
- <alias
- match="mapper show"
- enabled="y"
- sequence="100"
- script="mapper.show"
- >
- </alias>
- </aliases>
- <!-- Script -->
- <script>
- local show_vnums = &show_vnums;
- local show_timing = &show_timing;
- local show_completed = &show_completed;
- local show_database_mods = &show_database_mods;
- local show_other_areas = &show_other_areas;
- local show_up_down = &show_up_down;
- local show_area_exits = &show_area_exits;
- local speedwalk_prefix = "&speedwalk_prefix;"
- <![CDATA[
- mapper = require "altermapper"
- require "serialize"
- require "copytable"
- rooms = {}
- terrain = 0
- area = 0
- uid = 0
- current_room=0
- current_area = 0
- expected_exit=-666
- count = 0
- from_room=0
- last_direction_moved=0
- roomcount = 0
- exits_str = 0
- valid_direction = {
- n = "n",
- s = "s",
- e = "e",
- w = "w",
- u = "u",
- d = "d",
- ne = "ne",
- sw = "sw",
- nw = "nw",
- se = "se",
- north = "n",
- south = "s",
- east = "e",
- west = "w",
- up = "u",
- down = "d",
- northeast = "ne",
- northwest = "nw",
- southeast = "se",
- southwest = "sw",
- ['in'] = "in",
- out = "out",
- } -- end of valid_direction
- terrain_color = {}
- -- -----------------------------------------------------------------
- -- Here on white coloured line - this is a room name or room exits
- -- -----------------------------------------------------------------
- function Name_Or_Exits (name, line, wildcards)
- exits = string.match (line, "^Exits: (.*)")
- if exits then
- process_exits (exits)
- end -- if
- roomname = name
- end -- Name_Or_Exits
- function process_exits (exits_str)
- -- generate a "room ID" by hashing the room name, description and exits
- -- break up exits into individual directions
- exits = {}
- for exit in string.gmatch (exits_str, "%w+") do
- local ex = valid_direction [exit]
- if ex then
- exits [ex] = "-666" -- don't know where it goes yet
- end -- if
- end -- for
- if not rooms [current_room] then
- rooms [uid] = { name = name, roomdesc = uid, exits = exits, area=area, fillcolour=terrain_color[terrain], fillbrush=0, bordercolour=0xffffff }
- end -- if
- -- save so we know current room later on
- current_room = uid
- -- ColourNote ("rosybrown", "", roomdesc)
- -- ColourNote ("olive", "", uid)
- local room = rooms [current_room]
- -- not cached - see if in database
- if not room then
- -- print ("Loading room", current_room, "from database")
- room = load_room_from_database (current_room)
- end -- not in cache
- if not room then
- -- print ("Added room", uid) -- debugging
- -- print ("Name", name)
- -- ColourNote ("rosybrown", "", roomdesc)
- db:exec ("BEGIN TRANSACTION;")
- save_room_to_database (current_room, name, roomdesc)
- save_exits_to_database (current_room, exits)
- db:exec ("COMMIT;")
- -- get it back now
- room = load_room_from_database (current_room)
- end -- if room not there
- -- call mapper to draw this rom
- mapper.draw (uid) -- redraw room with name
- -- try to work out where previous room's exit led
- if expected_exit == "-666" and from_room then
- fix_up_exit ()
- end -- exit was wrong
- end -- process_exits
- function fix_up_exit ()
- -- where we were before
- local room = rooms [from_room]
- -- leads to here
- room.exits [last_direction_moved] = current_room
- -- clear for next time
- last_direction_moved = nil
- from_room = nil
- end -- fix_up_exit
- function Shop_Line (name, line, wildcards)
- -- location not known?
- if not current_room then
- return
- end -- if
- if rooms [current_room].shop then
- return
- end -- already a shop
- -- mark as shop
- rooms [current_room].shop = true
- -- update database
- dbcheck (db:execute (string.format (
- "UPDATE rooms SET shop = %i WHERE uid = %s;",
- fixbool (rooms [current_room].shop),
- fixsql (current_room)
- )))
- -- note it
- mapper.mapprint ("Room", current_room, "marked as a shop")
- -- redraw
- mapper.draw (current_room)
- end -- Shop_Line
- function Train_Line (name, line, wildcards)
- -- location not known?
- if not current_room then
- return
- end -- if
- if rooms [current_room].train then
- return
- end -- already a train
- -- mark as train
- rooms [current_room].train = true
- -- update database
- dbcheck (db:execute (string.format (
- "UPDATE rooms SET train = %i WHERE uid = %s;",
- fixbool (rooms [current_room].train),
- fixsql (current_room)
- )))
- -- note it
- mapper.mapprint ("Room", current_room, "marked as a training room")
- -- redraw
- mapper.draw (uid)
- end -- Train_Line
- -- -----------------------------------------------------------------
- -- mapper 'get_room' callback - it wants to know about room uid
- -- -----------------------------------------------------------------
- function get_room (uid)
- -- check we got room at all
- if not rooms [uid] then
- -- return nil
- end -- if
- -- look it up
- local ourroom = rooms [uid]
- -- not cached - see if in database
- if not ourroom then
- ourroom = load_room_from_database (uid)
- rooms [uid] = ourroom -- cache for later
- end -- not in cache
- if not ourroom then
- return nil
- end -- if
- local room = copytable.deep (ourroom)
- if uid == current_room then
- current_area = room.area
- end -- if
- -- build hover message
- local shop = ""
- if room.shop then
- shop = "\nRoom is shop"
- end -- if shop
- local train = ""
- if room.train then
- train = "\nRoom has trainer"
- end -- if train
- local notes = ""
- if room.notes then
- notes = "\nBookmark: " .. room.notes
- end -- if notes
- local texits = {}
- for dir in pairs (room.exits) do
- table.insert (texits, dir)
- end -- for
- table.sort (texits)
- room.hovermessage = string.format (
- "%s\tExits: %s\nRoom: %s%s%s%s",
- room.name,
- table.concat (texits, ", "),
- uid,
- shop,
- train,
- notes
- -- depth,
- -- table.concat (path, ",")
- )
- -- special room fill colours
- if room.shop then
- room.fillcolour = config.SHOP_FILL_COLOUR.colour
- room.fillbrush = 8
- end -- if
- if room.train then
- room.fillcolour = config.TRAINER_FILL_COLOUR.colour
- room.fillbrush = 8
- end -- if
- if uid == current_room then
- room.bordercolour = ColourNameToRGB "red"
- room.borderpenwidth = 2
- elseif room.area ~= current_area then
- room.bordercolour = config.DIFFERENT_AREA_COLOUR.colour
- end -- not in this area
- return room
- end -- get_room
- -- -----------------------------------------------------------------
- -- We have changed rooms - work out where the previous room led to
- -- -----------------------------------------------------------------
- function fix_up_exit ()
- -- where we were before
- local room = rooms [from_room]
- -- print ("Moved from", from_room, "to", current_room, "in direction", last_direction_moved)
- -- leads to here
- if from_room ~= current_room then
- dbcheck (db:execute (string.format ([[
- UPDATE exits SET touid = %s WHERE fromuid = %s AND dir = %s;
- ]],
- fixsql (current_room), -- destination room
- fixsql (from_room), -- from previous room
- fixsql (last_direction_moved) -- direction (eg. "n")
- )))
- if show_database_mods then
- mapper.mapprint ("Fixed exit", last_direction_moved, "from room", from_room, "to be to", current_room)
- end -- if
- room.exits [last_direction_moved] = current_room
- end -- if
- -- clear for next time
- last_direction_moved = nil
- from_room = nil
- end -- fix_up_exit
- -- -----------------------------------------------------------------
- -- try to detect when we send a movement command
- -- -----------------------------------------------------------------
- function OnPluginSent (sText)
- if valid_direction [sText] then
- last_direction_moved = valid_direction [sText]
- -- print ("Just moved", last_direction_moved)
- if current_room and rooms [current_room] then
- expected_exit = rooms [current_room].exits [last_direction_moved]
- if expected_exit then
- from_room = current_room
- end -- if
- -- print ("expected exit for this direction is to room", expected_exit)
- end -- if
- end -- if
- end -- function
- -- -----------------------------------------------------------------
- -- Plugin Install
- -- -----------------------------------------------------------------
- function OnPluginInstall ()
- config = {} -- in case not found
- setup_terrain_colors()
- -- get saved configuration
- assert (loadstring (GetVariable ("config") or "")) ()
- -- initialize mapper
- mapper.init { config = config,
- get_room = get_room,
- show_help = OnHelp, -- to show help
- room_click = room_click, -- called on RH click on room square
- timing = show_timing, -- want to see timing
- show_completed = show_completed, -- want to see "Speedwalk completed." message
- show_other_areas = show_other_areas, -- want to see areas other than the current one?
- show_up_down = show_up_down, -- want to follow up/down exits?
- show_area_exits = show_area_exits, -- want to see area exits?
- speedwalk_prefix = speedwalk_prefix, -- how to speedwalk
- }
- mapper.mapprint (string.format ("MUSHclient mapper installed, version %0.1f", mapper.VERSION))
- -- open databases on disk
- db = assert (sqlite3.open(GetInfo (66) .. Trim (WorldAddress ()) .. "_" .. WorldPort () .. ".db"))
- create_tables () -- create database structure if necessary
- end -- OnPluginInstall
- -- -----------------------------------------------------------------
- -- Plugin Save State
- -- -----------------------------------------------------------------
- function OnPluginSaveState ()
- mapper.save_state ()
- SetVariable ("config", "config = " .. serialize.save_simple (config))
- end -- OnPluginSaveState
- function map_resume (name, line, wildcards)
- local wanted = mapper.last_hyperlink_uid or mapper.last_speedwalk_uid
- if not wanted then
- mapper.print "No outstanding speedwalks or hyperlinks."
- return
- end -- if nothing to do
- -- find desired room
- mapper.find (
- function (uid)
- return uid == wanted, uid == wanted
- end, -- function
- show_vnums, -- show vnum?
- 1, -- how many to expect
- true -- just walk there
- )
- end -- map_resume
- function map_goto (name, line, wildcards)
- local wanted = wildcards [1]
- -- check valid string
- if string.match (wanted, "%X") then
- mapper.maperror ("Room number must be hex string (0-9, A-F), you entered: " .. wanted)
- return
- end -- if
- -- internally rooms are upper-case hex
- wanted = wanted:upper ()
- -- see if already there
- if current_room and string.match (current_room, "^" .. wanted) then
- mapper.mapprint ("You are already in that room.")
- return
- end -- if
- -- find desired room
- mapper.find (
- function (uid)
- local found = string.match (uid, "^" .. wanted)
- return found, found
- end, -- function
- show_vnums, -- show vnum?
- 1, -- how many to expect
- true -- just walk there
- )
- end -- map_goto
- function map_where (name, line, wildcards)
- if not mapper.check_we_can_find () then
- return
- end -- if
- local wanted = wildcards [1]
- if current_room and wanted == current_room then
- mapper.mapprint ("You are already in that room.")
- return
- end -- if
- local paths = mapper.find_paths (current_room,
- function (uid)
- return uid == wanted, -- wanted room?
- uid == wanted -- stop searching?
- end)
- local uid, item = next (paths, nil) -- extract first (only) path
- -- nothing? room not found
- if not item then
- mapper.mapprint (string.format ("Room %s not found", wanted))
- return
- end -- if
- -- turn into speedwalk
- local path = mapper.build_speedwalk (item.path)
- -- display it
- mapper.mapprint (string.format ("Path to %s is: %s", wanted, path))
- end -- map_where
- function OnHelp ()
- mapper.mapprint (string.format ("[MUSHclient mapper, version %0.1f]", mapper.VERSION))
- mapper.mapprint (world.GetPluginInfo (world.GetPluginID (), 3))
- end
- room_not_in_database = {}
- room_in_database = {}
- function dbcheck (code)
- if code ~= sqlite3.OK and -- no error
- code ~= sqlite3.ROW and -- completed OK with another row of data
- code ~= sqlite3.DONE then -- completed OK, no more rows
- local err = db:errmsg () -- the rollback will change the error message
- db:exec ("ROLLBACK") -- rollback any transaction to unlock the database
- error (err, 2) -- show error in caller's context
- end -- if
- end -- dbcheck
- function fixsql (s)
- if s then
- return "'" .. (string.gsub (s, "'", "''")) .. "'" -- replace single quotes with two lots of single quotes
- else
- return "NULL"
- end -- if
- end -- fixsql
- function fixbool (b)
- if b then
- return 1
- else
- return 0
- end -- if
- end -- fixbool
- function load_room_from_database (uid)
- local room
- assert (uid, "No UID supplied to load_room_from_database")
- -- if not in database, don't look again
- if room_not_in_database [uid] then
- return nil
- end -- no point looking
- for row in db:nrows(string.format ("SELECT * FROM rooms WHERE uid = %s", fixsql (uid))) do
- room = {
- name = row.name,
- area = row.area,
- description = row.description,
- shop = row.shop,
- train = row.train,
- notes = row.notes,
- exits = {} }
- for exitrow in db:nrows(string.format ("SELECT * FROM exits WHERE fromuid = %s", fixsql (uid))) do
- room.exits [exitrow.dir] = tostring (exitrow.touid)
- end -- for each exit
- end -- finding room
- if room then
- rooms [uid] = room
- return room
- end -- if found
- room_not_in_database [uid] = true
- return nil
- end -- load_room_from_database
- function save_room_to_database (uid, title, description)
- assert (uid, "No UID supplied to save_room_to_database")
- dbcheck (db:execute (string.format (
- "INSERT INTO rooms (uid, name, description, date_added) VALUES (%s, %s, %s, DATETIME('NOW'));",
- fixsql (uid),
- fixsql (title),
- fixsql (description)
- )))
- dbcheck (db:execute (string.format ([[
- INSERT INTO rooms_lookup (uid, name, description) VALUES (%s, %s, %s);
- ]], fixsql (uid),
- fixsql (title),
- fixsql (description)
- )))
- room_not_in_database [uid] = false
- if show_database_mods then
- mapper.mapprint ("Added room", uid, "to database. Name:", title)
- end -- if
- end -- function save_room_to_database
- function save_exits_to_database (uid, exits)
- for dir in string.gmatch (exits, "%a+") do
- -- fix up in and out
- dir = ({ ['i'] = "in", o = "out", }) [dir] or dir
- dbcheck (db:execute (string.format ([[
- INSERT INTO exits (dir, fromuid, touid, date_added)
- VALUES (%s, %s, %s, DATETIME('NOW'));
- ]], fixsql (dir), -- direction (eg. "n")
- fixsql (uid), -- from current room
- fixsql (-666) -- destination room (not known)
- )))
- if show_database_mods then
- -- mapper.mapprint ("Added unknown exit", dir, "from room", uid, "to database.")
- end -- if
- end -- for each exit
- end -- function save_exits_to_database
- function create_tables ()
- -- create rooms table
- dbcheck (db:execute[[
- PRAGMA foreign_keys = ON;
- PRAGMA journal_mode = WAL;
- CREATE TABLE IF NOT EXISTS rooms (
- roomid INTEGER PRIMARY KEY AUTOINCREMENT,
- uid TEXT NOT NULL, -- vnum or how the MUD identifies the room
- name TEXT, -- name of room
- description TEXT, -- description
- terrain TEXT, -- which building it is in
- shop INTEGER, -- 1 = shop here
- train INTEGER, -- 1 = trainer here
- notes TEXT, -- player notes
- date_added DATE, -- date added to database
- UNIQUE (uid)
- );
- CREATE INDEX IF NOT EXISTS shop_index ON rooms (shop);
- CREATE INDEX IF NOT EXISTS train_index ON rooms (train);
- CREATE TABLE IF NOT EXISTS exits (
- exitid INTEGER PRIMARY KEY AUTOINCREMENT,
- dir TEXT NOT NULL, -- direction, eg. "n", "s"
- fromuid TEXT NOT NULL, -- exit from which room (in rooms table)
- touid TEXT NOT NULL, -- exit to which room (in rooms table)
- date_added DATE, -- date added to database
- FOREIGN KEY(fromuid) REFERENCES rooms(uid)
- );
- CREATE INDEX IF NOT EXISTS fromuid_index ON exits (fromuid);
- CREATE INDEX IF NOT EXISTS touid_index ON exits (touid);
- ]])
- -- check if rooms_lookup table exists
- local table_exists
- for a in db:nrows "SELECT * FROM sqlite_master WHERE name = 'rooms_lookup' AND type = 'table'" do
- table_exists = true
- end -- for
- if not table_exists then
- dbcheck (db:execute "CREATE VIRTUAL TABLE rooms_lookup USING FTS3(uid, name, description);")
- -- in case we only deleted the rooms_lookup table to save space in the download
- dbcheck (db:execute "INSERT INTO rooms_lookup (uid, name, description) SELECT uid, name, description FROM rooms;")
- end -- if
- end -- function create_tables
- function room_edit_bookmark (room, uid)
- local notes = room.notes or ""
- if notes ~= "" then
- newnotes = utils.inputbox ("Modify room comment (clear it to delete from database)", room.name, notes)
- else
- newnotes = utils.inputbox ("Enter room comment (creates a bookmark for this room)", room.name, notes)
- end -- if
- if not newnotes then
- return
- end -- if cancelled
- if newnotes == "" then
- if notes == "" then
- mapper.mapprint ("No comment entered, bookmark not saved.")
- return
- else
- dbcheck (db:execute (string.format (
- "UPDATE rooms SET notes = NULL WHERE uid = %s;",
- fixsql (uid)
- )))
- mapper.mapprint ("Bookmark for room", uid, "deleted. Was previously:", notes)
- rooms [uid].notes = nil
- return
- end -- if
- end -- if
- if notes == newnotes then
- return -- no change made
- end -- if
- dbcheck (db:execute (string.format (
- "UPDATE rooms SET notes = %s WHERE uid = %s;",
- fixsql (newnotes),
- fixsql (uid)
- )))
- if notes ~= "" then
- mapper.mapprint ("Bookmark for room", uid, "changed to:", newnotes)
- else
- mapper.mapprint ("Bookmark added to room", uid, ":", newnotes)
- end -- if
- rooms [uid].notes = newnotes
- end -- room_edit_bookmark
- function room_toggle_shop (room, uid)
- rooms [uid].shop = not rooms [uid].shop
- dbcheck (db:execute (string.format (
- "UPDATE rooms SET shop = %i WHERE uid = %s;",
- fixbool (rooms [uid].shop),
- fixsql (uid)
- )))
- if rooms [uid].shop then
- mapper.mapprint ("Room", uid, "marked as a shop")
- else
- mapper.mapprint ("Room", uid, "not a shop any more")
- end
- mapper.draw (current_room)
- end -- room_toggle_shop
- function room_toggle_train (room, uid)
- rooms [uid].train = not rooms [uid].train
- dbcheck (db:execute (string.format (
- "UPDATE rooms SET train = %i WHERE uid = %s;",
- fixbool (rooms [uid].train),
- fixsql (uid)
- )))
- if rooms [uid].train then
- mapper.mapprint ("Room", uid, "marked as a training room")
- else
- mapper.mapprint ("Room", uid, "not a training room any more")
- end
- mapper.draw (current_room)
- end -- room_toggle_train
- function setup_terrain_colors()
- terrain_color["0"]=tonumber("0x000000")--NOTSET
- terrain_color["1"]=tonumber("0x606060")--Building
- terrain_color["2"]=tonumber("0x805a22")--Town
- terrain_color["3"]=tonumber("0x00ff00")--FIELD
- terrain_color["4"]=tonumber("0x00c000")--LFOREST
- terrain_color["5"]=tonumber("0x008000")--TFOREST
- terrain_color["6"]=tonumber("0x004000")--DFOREST
- terrain_color["7"]=tonumber("0x406080")--SWAMP
- terrain_color["8"]=tonumber("0x60a060")--PLATEAU
- terrain_color["9"]=tonumber("0x00ffff")--SANDY
- terrain_color["10"]=tonumber("0xc0c0c0")--MOUNTAIN
- terrain_color["11"]=tonumber("0x808080")--ROCK
- terrain_color["12"]=tonumber("0x00ffff")--DESERT
- terrain_color["13"]=tonumber("0x805080")--TUNDRA
- terrain_color["14"]=ColourNameToRGB("lightyellow")--BEACH
- terrain_color["15"]=tonumber("0x409040")--HILL
- terrain_color["16"]=tonumber("0xf0f080")--DUNES
- terrain_color["17"]=tonumber("0x20c040")--JUNGLE
- terrain_color["18"]=ColourNameToRGB("darkblue")--OCEAN
- terrain_color["19"]=tonumber("0x00f0f0")--STREAM
- terrain_color["20"]=ColourNameToRGB("blue")--RIVER
- terrain_color["21"]=tonumber("0x021e6c")--UNDERWATER
- terrain_color["22"]=tonumber("0x303030")--UNDERGROUND
- terrain_color["23"]=tonumber("0x000000")--AIR
- terrain_color["24"]=tonumber("0x82f8e6")--ICE
- terrain_color["25"]=ColourNameToRGB("red")--LAVA
- terrain_color["26"]=tonumber("0x806060")--RUINS
- terrain_color["27"]=tonumber("0x404040")--CAVE
- terrain_color["28"]=tonumber("0x907040")--CITY
- terrain_color["29"]=tonumber("0x20a060")--MARSH
- terrain_color["30"]=tonumber("0xf0f0a0")--WASTELAND
- terrain_color["31"]=tonumber("0xffffff")--CLOUD
- terrain_color["32"]=ColourNameToRGB("blue")--WATER
- terrain_color["33"]=tonumber("0x808080")--METAL
- terrain_color["34"]=tonumber("0x006000")--TAIGA
- terrain_color["35"]=tonumber("0x404040")--SEWER
- terrain_color["36"]=ColourNameToRGB("indigo")--SHADOW
- -- end of terrain_color
- end
- function room_add_exit (room, uid)
- local available = {
- n = "North",
- s = "South",
- e = "East",
- w = "West",
- u = "Up",
- d = "Down",
- ne = "Northeast",
- sw = "Southwest",
- nw = "Northwest",
- se = "Southeast",
- ['in'] = "In",
- out = "Out",
- } -- end of available
- -- remove existing exits
- for k in pairs (room.exits) do
- available [k] = nil
- end -- for
- if next (available) == nil then
- utils.msgbox ("All exits already used.", "No free exits!", "ok", "!", 1)
- return
- end -- not known
- local chosen_exit = utils.listbox ("Choose exit to add", "Exits ...", available )
- if not chosen_exit then
- return
- end
- exit_destination = utils.inputbox ("Enter destination room identifier (number) for " .. available [chosen_exit], room.name, "")
- if not exit_destination then
- return
- end -- cancelled
- -- look it up
- local dest_room = rooms [exit_destination]
- -- not cached - see if in database
- if not dest_room then
- dest_room = load_room_from_database (exit_destination)
- rooms [exit_destination] = dest_room -- cache for later
- end -- not in cache
- if not dest_room then
- utils.msgbox ("Room " .. exit_destination .. " does not exist.", "Room does not exist!", "ok", "!", 1)
- return
- end -- if still not there
- dbcheck (db:execute (string.format ([[
- INSERT INTO exits (dir, fromuid, touid, date_added)
- VALUES (%s, %s, %s, DATETIME('NOW'));
- ]], fixsql (chosen_exit), -- direction (eg. "n")
- fixsql (uid), -- from current room
- fixsql (exit_destination) -- destination room
- )))
- if show_database_mods then
- mapper.mapprint ("Added exit", available [chosen_exit], "from room", uid, "to room", exit_destination, "to database.")
- end -- if
- -- update in-memory table
- rooms [uid].exits [chosen_exit] = exit_destination
- mapper.draw (current_room)
- end -- room_add_exit
- function room_delete_exit (room, uid)
- local available = {
- n = "North",
- s = "South",
- e = "East",
- w = "West",
- u = "Up",
- d = "Down",
- ne = "Northeast",
- sw = "Southwest",
- nw = "Northwest",
- se = "Southeast",
- ['in'] = "In",
- out = "Out",
- } -- end of available
- -- remove non-existent exits
- for k in pairs (available) do
- if room.exits [k] then
- available [k] = available [k] .. " --> " .. room.exits [k]
- else
- available [k] = nil
- end -- if not a room exit
- end -- for
- if next (available) == nil then
- utils.msgbox ("There are no exits from this room.", "No exits!", "ok", "!", 1)
- return
- end -- not known
- local chosen_exit = utils.listbox ("Choose exit to delete", "Exits ...", available )
- if not chosen_exit then
- return
- end
- dbcheck (db:execute (string.format ([[
- DELETE FROM exits WHERE dir = %s AND fromuid = %s;
- ]], fixsql (chosen_exit), -- direction (eg. "n")
- fixsql (uid) -- from current room
- )))
- if show_database_mods then
- mapper.mapprint ("Deleted exit", available [chosen_exit], "from room", uid, "from database.")
- end -- if
- -- update in-memory table
- rooms [uid].exits [chosen_exit] = nil
- mapper.draw (current_room)
- end -- room_delete_exit
- function room_change_exit (room, uid)
- local available = {
- n = "North",
- s = "South",
- e = "East",
- w = "West",
- u = "Up",
- d = "Down",
- ne = "Northeast",
- sw = "Southwest",
- nw = "Northwest",
- se = "Southeast",
- ['in'] = "In",
- out = "Out",
- } -- end of available
- -- remove non-existent exits
- for k in pairs (available) do
- if room.exits [k] then
- available [k] = available [k] .. " --> " .. room.exits [k]
- else
- available [k] = nil
- end -- if not a room exit
- end -- for
- if next (available) == nil then
- utils.msgbox ("There are no exits from this room.", "No exits!", "ok", "!", 1)
- return
- end -- not known
- local chosen_exit = utils.listbox ("Choose exit to change destination of:", "Exits ...", available )
- if not chosen_exit then
- return
- end
- exit_destination = utils.inputbox ("Enter destination room identifier (number) for " .. available [chosen_exit], room.name, "")
- if not exit_destination then
- return
- end -- cancelled
- -- look it up
- local dest_room = rooms [exit_destination]
- -- not cached - see if in database
- if not dest_room then
- dest_room = load_room_from_database (exit_destination)
- rooms [exit_destination] = dest_room -- cache for later
- end -- not in cache
- if not dest_room then
- utils.msgbox ("Room " .. exit_destination .. " does not exist.", "Room does not exist!", "ok", "!", 1)
- return
- end -- if still not there
- dbcheck (db:execute (string.format ([[
- UPDATE exits SET touid = %s WHERE dir = %s AND fromuid = %s;
- ]], fixsql (exit_destination),
- fixsql (chosen_exit), -- direction (eg. "n")
- fixsql (uid) -- from current room
- )))
- if show_database_mods then
- mapper.mapprint ("Modified exit", available [chosen_exit], "from room", uid, "to be to room", exit_destination, "in database.")
- end -- if
- -- update in-memory table
- rooms [uid].exits [chosen_exit] = exit_destination
- mapper.draw (current_room)
- end -- room_change_exit
- function room_click (uid, flags)
- -- check we got room at all
- if not uid then
- return nil
- end -- if
- -- look it up
- local room = rooms [uid]
- -- not cached - see if in database
- if not room then
- room = load_room_from_database (uid)
- rooms [uid] = room -- cache for later
- end -- not in cache
- if not room then
- return
- end -- if still not there
- local handlers = {
- { name = "Edit bookmark", func = room_edit_bookmark} ,
- { name = "-", } ,
- { name = "Add Exit", func = room_add_exit} ,
- { name = "Change Exit", func = room_change_exit} ,
- { name = "Delete Exit", func = room_delete_exit} ,
- { name = "-", } ,
- { name = "Toggle Shop", func = room_toggle_shop } ,
- { name = "Toggle Trainer", func = room_toggle_train } ,
- } -- handlers
- local t, tf = {}, {}
- for _, v in pairs (handlers) do
- table.insert (t, v.name)
- tf [v.name] = v.func
- end -- for
- local choice = WindowMenu (mapper.win,
- WindowInfo (mapper.win, 14),
- WindowInfo (mapper.win, 15),
- table.concat (t, "|"))
- local f = tf [choice]
- if f then
- f (room, uid)
- end -- if handler found
- end -- room_click
- function map_find (name, line, wildcards)
- local rooms = {}
- local count = 0
- local snippets = {}
- local reset = ANSI (0)
- local bold = ANSI (1)
- local unbold = ANSI (22)
- function show_snippet (uid)
- AnsiNote (reset .. snippets [uid])
- end -- show_snippet
- -- find matching rooms using FTS3
- for row in db:nrows(string.format (
- [[
- SELECT uid, name, snippet(rooms_lookup, '%s', '%s', ' ... ', -1, -10) AS snippet
- FROM rooms_lookup
- WHERE rooms_lookup MATCH %s]],
- bold, unbold,
- fixsql (wildcards [1]))) do
- rooms [row.uid] = true
- snippets [row.uid] = row.snippet
- count = count + 1
- end -- finding room
- -- see if nearby
- mapper.find (
- function (uid)
- local room = rooms [uid]
- if room then
- rooms [uid] = nil
- end -- if
- return room, next (rooms) == nil
- end, -- function
- show_vnums, -- show vnum?
- count, -- how many to expect
- false, -- don't auto-walk
- show_snippet -- show find snippet
- )
- end -- map_find
- function map_bookmarks (name, line, wildcards)
- local rooms = {}
- local count = 0
- -- build table of special places (with info in them)
- for row in db:nrows(string.format ("SELECT uid, notes FROM rooms WHERE notes IS NOT NULL")) do
- rooms [row.uid] = capitalize (row.notes)
- count = count + 1
- end -- finding room
- -- find such places
- mapper.find (
- function (uid)
- local room = rooms [uid]
- if room then
- rooms [uid] = nil
- end -- if
- return room, next (rooms) == nil -- room will be type of info (eg. shop)
- end, -- function
- show_vnums, -- show vnum?
- count, -- how many to expect
- false -- don't auto-walk
- )
- end -- map_bookmarks
- function map_find_special (which)
- local rooms = {}
- local count = 0
- -- build table of special places (with info in them)
- for row in db:nrows(string.format ("SELECT uid, name FROM rooms WHERE %s = 1", which)) do
- rooms [row.uid] = true
- count = count + 1
- end -- finding room
- -- find such places
- mapper.find (
- function (uid)
- local room = rooms [uid]
- if room then
- rooms [uid] = nil
- end -- if
- return room, next (rooms) == nil -- room will be type of info (eg. shop)
- end, -- function
- show_vnums, -- show vnum?
- count, -- how many to expect
- false -- don't auto-walk
- )
- end -- map_find_special
- function map_shops (name, line, wildcards)
- map_find_special ("shop")
- end -- map_shops
- function map_trainers (name, line, wildcards)
- map_find_special ("train")
- end -- map_trainers
- function manual_backup()
- backup_databases(true)
- end
- function backup_databases(manual)
- wait.make(function()
- performing_maintenance = true
- local success = false
- maybe_Note("PERFORMING "..((manual and "MANUAL") or "AUTOMATIC").." DATABASE BACKUP. DON'T TOUCH ANYTHING!", manual)
- if not checkDatabaseIntegrity(true) then
- maybe_Note("ABORTING CURRENT BACKUP", manual)
- if not compact_mode then Note("") end
- Repaint()
- db = assert (sqlite3.open(worldPath..".db")) -- try to re-open the database anyway
- performing_maintenance = false
- satisfy_broadcast_queue()
- return
- end
- maybe_Note("BACKING UP DATABASE", manual)
- Repaint()
- backupPath = GetInfo(66).."db_backups\\"..sanitize_filename(WorldName())
- firstBackup = backupPath..".db.Backup"
- local ffi
- if type(jit) == 'table' then
- ffi = require("ffi")
- ffi.cdef[[
- bool CreateDirectoryA(const char *lpPathName, void *lpSecurityAttributes);
- bool CopyFileA(const char* lpExistingFileName, const char * lpNewFileName, bool bFailIfExists);
- unsigned long GetLastError(void);
- ]]
- succ = ffi.C.CreateDirectoryA(GetInfo(66).."db_backups\\", nil)
- err_no = ffi.C.GetLastError()
- else
- succ, err_no = utils.shellexecute("cmd", "/C mkdir db_backups", GetInfo(66), "open", 0)
- end
- if succ == false and err_no ~= 183 and err_no ~= 127 then
- -- error
- ColourNote("yellow","red", "ERROR ("..err_no..") trying to CreateDirectory: "..GetInfo(66).."db_backups\\\n")
- else
- -- successfully created the backup directory
- -- record when the backup occurs
- dbCheckExecute(string.format("INSERT OR REPLACE INTO storage (name, data) VALUES (%s,%s);", fixsql("backup_date"), fixsql(os.date("%b %d, %Y - %X"))))
- if db:isopen() then
- db:close() -- always close the database before copying
- end
- -- make new backup
- if use_compression == 1 then
- local tmp = GetInfo(66).."aard_package_temp_file.txt" -- temp file for recording output
- -- It's not so simple to catch errors from this, so record the output and look at it later.
- -- Use pushd/popd because cd can't @!#($$# access UNC paths.
- local execute_string = "pushd "..quote(GetInfo(66)).." & zip -j -v -T -lf "..quote(tmp).." "..quote(firstBackup..".zip").." "..quote(worldPath..".db").." & popd"
- function file_exists(name)
- local f=io.open(name,"r")
- if f~=nil then io.close(f) return true else return false end
- end
- function file_is_writable(name)
- local f=io.open(name,"w")
- if f~=nil then io.close(f) return true else return false end
- end
- if file_exists(tmp) and not file_is_writable(tmp) then
- ColourNote("yellow","red", "ERROR executing system command: "..execute_string.."\n")
- ColourNote("yellow", "red", "Log file "..quote(tmp).." is not writeable. Do you have write permission?") -- flaming output
- -- failure
- else
- utils.shellexecute("cmd", "/C "..execute_string, "", "open", 0)
- local zip_done = false
- local zip_error = false
- local zipstarttime = utils.timer()
- local zip_lines
- while not zip_done do
- zip_lines = {}
- if file_exists(tmp) then
- for line in io.lines(tmp) do
- table.insert(zip_lines, line)
- end
- os.remove(tmp) -- remove temp file
- end
- for _,line in ipairs(zip_lines) do
- if line:find("zip warning") or line:find("zip error") or line:find("zip I/O error") then
- zip_done = true
- zip_error = true
- end
- if line:find("zip OK") then
- zip_done = true
- end
- end
- if zip_done then break end
- if utils.timer() - zipstarttime > 30 then
- -- we have to give up EVENTUALLY
- break
- end
- wait.time(0.1)
- end
- if zip_error then
- -- something went wrong with the compression
- -- we expect to see some lines with the last line showing a passing test
- ColourNote("yellow","red", "ERROR executing system command: "..execute_string.."\n")
- for _,v in ipairs(zip_lines) do
- ColourNote("yellow", "red", v) -- flaming output
- end
- -- failure
- else
- for _,v in ipairs(zip_lines) do
- maybe_Note(v, manual) -- less intense output
- end
- success = true
- end
- end
- else
- -- no compression, just copy
- if type(jit) == 'table' then
- succ = ffi.C.CopyFileA(worldPath..".db", firstBackup, false)
- err_no = ffi.C.GetLastError()
- else
- -- succ, err_no = utils.shellexecute("cmd", "/C copy "..worldPath..".db "..firstBackup, "", "open", 0);
- local inp, outp, errmsg
- succ = false
- inp, errmsg, err_no = io.open(worldPath..".db", "rb")
- if err_no == nil then
- outp, errmsg, err_no = io.open(firstBackup, "wb")
- if err_no == nil then
- local data = inp:read("*all")
- outp:write(data)
- outp:close()
- inp:close()
- succ = true
- end
- end
- if succ == false then
- ColourNote("yellow","red", "ERROR: "..errmsg)
- end
- end
- if succ == false then
- ColourNote("yellow","red", "ERROR ("..err_no..") trying to copy database from '"..worldPath..".db' to '"..firstBackup.."'")
- else
- success = true
- end
- end
- end
- if success then
- rotate_backups(manual) -- rotate backup folders (obviously)
- maybe_Note("FINISHED DATABASE BACKUP. YOU MAY NOW GO BACK TO MUDDING.", manual)
- else
- Note("ABORTING BACKUP.")
- CorruptionAlert()
- end
- if not compact_mode then Note("") end
- db = assert (sqlite3.open(worldPath..".db")) -- re-open database
- Repaint()
- performing_maintenance = false
- satisfy_broadcast_queue()
- end)
- end
- function Door_Closed (name, line, wildcards)
- local dirs = {
- n = "north",
- s = "south",
- e = "east",
- w = "west",
- u = "up",
- d = "down",
- ne = "northeast",
- sw = "southwest",
- nw = "northwest",
- se = "southeast",
- ['in'] = "in",
- out = "out",
- } -- end of available
- if last_direction_moved then
- Send ("open " .. dirs [last_direction_moved])
- Send (dirs [last_direction_moved])
- end -- if
- end -- Door_Closed
- ]]>
- </script>
- </muclient>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement