<?xml version='1.0' encoding='UTF-8'?> |
<!DOCTYPEmuclient [ |
<!ENTITYshow_vnums'true' > |
<!ENTITYshow_timing'false' > |
<!ENTITYshow_completed'false' > |
<!ENTITYshow_database_mods'true' > |
<!ENTITYshow_other_areas'false' > |
<!ENTITYshow_area_exits'true' > |
<!ENTITYshow_up_down'false' > |
<!ENTITYspeedwalk_prefix'' > |
]> |
<muclient> |
<plugin |
name='ATCP_Mapper' |
author='Nick Gammon' |
id='a80b38e2f618fbda79a6440c' |
language='Lua' |
purpose='Draws map for ATCP MUDs' |
date_written='2010-03-04' |
date_modified='2010-11-26' |
requires='4.51' |
version='1.6' |
save_state='y' |
> |
<descriptiontrim='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 (or use the mouse-wheel) |
mapper zoom in --> zoom in (or use the mouse-wheel) |
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 areas --> show path to nearby areas (zones) |
mapper heal --> show nearby healers |
mapper shop --> show nearby shops/banks etc. |
mapper train --> show nearby trainers |
mapper quest --> show nearby quest-givers |
mapper where <room> --> show directions to a room |
MOVING |
mapper goto <room> --> walk to a room by its room number |
mapper stop --> cancel any current speedwalk |
mapper resume --> resume last speedwalk or hyperlinked speedwalk |
]]> |
</description> |
</plugin> |
<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> |
<!-- finding aliases --> |
<alias |
match='^mapper find ([w* %d/"]+)$' |
enabled='y' |
sequence='100' |
script='map_find' |
regexp='y' |
> |
</alias> |
<alias |
match='mapper areas' |
enabled='y' |
sequence='100' |
script='map_areas' |
> |
</alias> |
<alias |
match='^mapper shops?$' |
regexp='y' |
enabled='y' |
sequence='100' |
script='map_shops' |
> |
</alias> |
<alias |
match='^mapper trainw*$' |
regexp='y' |
enabled='y' |
sequence='100' |
script='map_trainers' |
> |
</alias> |
<alias |
match='^mapper questw*$' |
regexp='y' |
enabled='y' |
sequence='100' |
script='map_quests' |
> |
</alias> |
<alias |
match='^mapper healw*$' |
regexp='y' |
enabled='y' |
sequence='100' |
script='map_healers' |
> |
</alias> |
<alias |
match='mapper goto *' |
enabled='y' |
sequence='100' |
script='map_goto' |
> |
</alias> |
<alias |
match='mapper where *' |
enabled='y' |
sequence='100' |
script='map_where' |
> |
</alias> |
<alias |
match='^mapper bookw*$' |
regexp='y' |
enabled='y' |
sequence='100' |
script='map_bookmarks' |
> |
</alias> |
<alias |
match='mapper resume' |
enabled='y' |
sequence='100' |
script='map_resume' |
> |
</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> |
<triggers> |
<!-- auto-swim --> |
<trigger |
enabled='y' |
match='There's water ahead of you. You'll have to * to make it through.' |
sequence='100' |
> |
<send>%1</send> |
</trigger> |
<trigger |
enabled='y' |
match='You'll have to swim to make it through the water in that direction.' |
send_to='12' |
sequence='100' |
> |
<send> |
if last_direction_moved then |
Send ('swim ' .. last_direction_moved) |
end -- if |
</send> |
</trigger> |
<!-- auto-open --> |
<trigger |
enabled='y' |
regexp='y' |
match='^There is a door in the way' |
send_to='12' |
sequence='100' |
> |
<send> |
if last_direction_moved then |
Send ('open door ' .. last_direction_moved) |
end -- if |
</send> |
</trigger> |
<!-- various messages that cancel speedwalks --> |
<trigger |
enabled='y' |
match='Now now, don't be so hasty!$' |
regexp='y' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='^You cannot walk through' |
regexp='y' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='As you stroll in, you feel your feet slipping on something slimy.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
<send>stand</send> |
</trigger> |
<trigger |
enabled='y' |
match='The door is locked.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='You are regaining balance and are unable to move.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='You are surrounded by a pocket of air and so must move normally through water.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='You fumble about drunkenly.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='You are asleep and can do nothing. WAKE will attempt to wake you.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='You must be standing first.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='You need to use a boat, fly, or swim underwater to go there.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='You can't * while sitting.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
regexp='y' |
match='^You dream about ' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='There is no exit in that direction.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
<trigger |
enabled='y' |
match='Alas, you cannot go that way.' |
script='mapper.cancel_speedwalk' |
sequence='100' |
> |
</trigger> |
</triggers> |
<!-- Plugin help --> |
<aliases> |
<alias |
script='OnHelp' |
match='mapper help' |
enabled='y' |
> |
</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[ |
require 'serialize' |
require 'checkplugin' |
mapper = require 'mapper' |
default_config = { |
-- assorted colours |
BACKGROUND_COLOUR = { name = 'Background', colour = ColourNameToRGB 'lightseagreen', }, |
ROOM_COLOUR = { name = 'Room', colour = ColourNameToRGB 'cyan', }, |
EXIT_COLOUR = { name = 'Exit', colour = ColourNameToRGB 'darkgreen', }, |
EXIT_COLOUR_UP_DOWN = { name = 'Exit up/down', colour = ColourNameToRGB 'darkmagenta', }, |
EXIT_COLOUR_IN_OUT = { name = 'Exit in/out', colour = ColourNameToRGB '#3775E8', }, |
OUR_ROOM_COLOUR = { name = 'Our room', colour = ColourNameToRGB 'black', }, |
UNKNOWN_ROOM_COLOUR = { name = 'Unknown room', colour = ColourNameToRGB '#00CACA', }, |
DIFFERENT_AREA_COLOUR = { name = 'Another area', colour = ColourNameToRGB '#009393', }, |
SHOP_FILL_COLOUR = { name = 'Shop', colour = ColourNameToRGB 'darkolivegreen', }, |
POSTOFFICE_FILL_COLOUR = { name = 'Post Office', colour = ColourNameToRGB 'yellowgreen', }, |
BANK_FILL_COLOUR = { name = 'Bank', colour = ColourNameToRGB 'gold', }, |
NEWSROOM_FILL_COLOUR = { name = 'Newsroom', colour = ColourNameToRGB 'lightblue', }, |
MAPPER_NOTE_COLOUR = { name = 'Messages', colour = ColourNameToRGB 'lightgreen' }, |
ROOM_NAME_TEXT = { name = 'Room name text', colour = ColourNameToRGB '#BEF3F1', }, |
ROOM_NAME_FILL = { name = 'Room name fill', colour = ColourNameToRGB '#105653', }, |
ROOM_NAME_BORDER = { name = 'Room name box', colour = ColourNameToRGB 'black', }, |
AREA_NAME_TEXT = { name = 'Area name text', colour = ColourNameToRGB '#BEF3F1',}, |
AREA_NAME_FILL = { name = 'Area name fill', colour = ColourNameToRGB '#105653', }, |
AREA_NAME_BORDER = { name = 'Area name box', colour = ColourNameToRGB 'black', }, |
FONT = { name = get_preferred_font {'Dina', 'Lucida Console', 'Fixedsys', 'Courier', 'Sylfaen',} , |
size = 8 |
} , |
-- size of map window |
WINDOW = { width = 400, height = 400 }, |
-- how far from where we are standing to draw (rooms) |
SCAN = { depth = 30 }, |
-- speedwalk delay |
DELAY = { time = 0.3 }, |
-- how many seconds to show 'recent visit' lines (default 3 minutes) |
LAST_VISIT_TIME = { time = 60 * 3 }, |
} |
local rooms = {} |
local areas = {} |
local environments = {} |
local user_terrain_colour = {} |
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 save_room_to_database (uid, title) |
assert (uid, 'No UID supplied to save_room_to_database') |
dbcheck (db:execute (string.format ( |
'INSERT INTO rooms (uid, name, area, date_added) VALUES (%s, %s, '0', DATETIME('NOW'));', |
fixsql (uid), |
fixsql (title) |
))) |
dbcheck (db:execute (string.format ([[ |
INSERT INTO rooms_lookup (uid, name) VALUES (%s, %s); |
]], fixsql (uid), |
fixsql (title) |
))) |
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) |
local room = rooms [uid] |
db:exec ('BEGIN TRANSACTION;') |
for dir in string.gmatch (exits, '[^,]+') 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 (0) -- destination room (not known) |
))) |
if show_database_mods then |
mapper.mapprint ('Added exit', dir, 'from room', uid, 'to database.') |
end -- if |
room.exits [dir] = '0' |
end -- for each exit |
db:exec ('COMMIT;') |
end -- function save_room_to_database |
function save_full_exits_to_database (uid, exits) |
local room = rooms [uid] |
db:exec ('BEGIN TRANSACTION;') |
for exit in string.gmatch (exits, '[^,]+') do |
dir, touid = string.match (exit, '^(%a+)%((%d+)%)$') |
if dir then |
-- 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 (touid) -- destination room |
))) |
if show_database_mods then |
mapper.mapprint ('Added exit', dir, 'from room', uid, 'to room', touid, 'to database.') |
end -- if |
room.exits [dir] = touid |
else |
mapper.maperror ('Cannot make sense of:', exit) |
end -- if can decode |
end -- for each exit |
db:exec ('COMMIT;') |
end -- function save_full_exits_to_database |
function fix_up_exit () |
local room = rooms [from_room] |
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 |
last_direction_moved = nil |
from_room = nil |
end -- fix_up_exit |
function save_environment_to_database (uid, s) |
local room = rooms [uid] |
dbcheck (db:execute (string.format ([[ |
UPDATE rooms SET terrain = %s WHERE uid = %s; |
]], |
fixsql (s), -- environment |
fixsql (uid) -- room |
))) |
room.terrain = s |
if show_database_mods then |
mapper.mapprint ('Fixed room', uid, 'to have environment:', s) |
end -- if |
end -- save_environment_to_database |
function save_info_to_database (uid, s) |
local room = rooms [uid] |
dbcheck (db:execute (string.format ([[ |
UPDATE rooms SET info = %s WHERE uid = %s; |
]], |
fixsql (s), -- info |
fixsql (uid) -- room |
))) |
room.info = s |
if show_database_mods then |
mapper.mapprint ('Fixed room', uid, 'to have info:', s) |
end -- if |
end -- save_info_to_database |
function save_coordinates_to_database (uid, s) |
local room = rooms [uid] |
local area, x, y, z = string.match (s, '^(.-),([%d-]+),([%d-]+),([%d-]+)') |
if x then |
dbcheck (db:execute (string.format ([[ |
UPDATE rooms SET x = %i, y = %i, z = %i, area = %s WHERE uid = %s; |
]], |
x, y, z, fixsql (area), -- coordinates, area |
fixsql (uid) -- room |
))) |
room.x = x |
room.y = y |
room.z = z |
room.area = area |
if show_database_mods then |
mapper.mapprint ('Fixed room', uid, 'to have coordinates:', x, y, z, 'and area', area) |
end -- if |
else |
mapper.maperror ('Cannot make sense of coordinates:', s) |
end -- if |
end -- save_coordinates_to_database |
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, |
building = row.building, |
terrain = row.terrain, |
info = row.info, |
notes = row.notes, |
x = row.x, |
y = row.y, |
z = row.z, |
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 |
for row in db_bm:nrows(string.format ('SELECT * FROM bookmarks WHERE uid = %s', fixsql (uid))) do |
rooms [uid].notes = row.notes |
end -- finding room |
return room |
end -- if found |
room_not_in_database [uid] = true |
return nil |
end -- load_room_from_database |
function create_tables () |
-- create rooms table |
dbcheck (db:execute[[ |
PRAGMA foreign_keys = ON; |
PRAGMA journal_mode = WAL; |
CREATE TABLE IF NOT EXISTS areas ( |
areaid INTEGER PRIMARY KEY AUTOINCREMENT, |
uid TEXT NOT NULL, -- vnum or how the MUD identifies the area |
name TEXT, -- name of area |
date_added DATE, -- date added to database |
UNIQUE (uid) |
); |
CREATE TABLE IF NOT EXISTS environments ( |
environmentid INTEGER PRIMARY KEY AUTOINCREMENT, |
uid TEXT NOT NULL, -- code for the environment |
name TEXT, -- name of environment |
color INTEGER, -- ANSI colour code |
date_added DATE, -- date added to database |
UNIQUE (uid) |
); |
CREATE INDEX IF NOT EXISTS name_index ON environments (name); |
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 |
area TEXT, -- which area |
building TEXT, -- which building it is in |
terrain TEXT, -- eg. road OR water |
info TEXT, -- eg. shop,postoffice |
notes TEXT, -- player notes |
x INTEGER, |
y INTEGER, |
z INTEGER, |
date_added DATE, -- date added to database |
UNIQUE (uid) |
); |
CREATE INDEX IF NOT EXISTS info_index ON rooms (info); |
CREATE INDEX IF NOT EXISTS terrain_index ON rooms (terrain); |
CREATE INDEX IF NOT EXISTS area_index ON rooms (area); |
CREATE TABLE IF NOT EXISTS exits ( |
exitid INTEGER PRIMARY KEY AUTOINCREMENT, |
dir TEXT NOT NULL, -- direction, eg. 'n', 's' |
fromuid STRING NOT NULL, -- exit from which room (in rooms table) |
touid STRING 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);') |
-- in case we only deleted the rooms_lookup table to save space in the download |
dbcheck (db:execute 'INSERT INTO rooms_lookup (uid, name) SELECT uid, name FROM rooms;') |
end -- if |
-- create bookmarks and terrain colours table in separate database |
dbcheck (db_bm:execute[[ |
PRAGMA foreign_keys = ON; |
CREATE TABLE IF NOT EXISTS bookmarks ( |
id INTEGER PRIMARY KEY AUTOINCREMENT, |
uid TEXT NOT NULL, -- vnum of room |
notes TEXT, -- user notes |
date_added DATE, -- date added to database |
UNIQUE (uid) |
); |
CREATE TABLE IF NOT EXISTS terrain ( |
id INTEGER PRIMARY KEY AUTOINCREMENT, |
name TEXT NOT NULL, -- terrain name |
color INTEGER, -- RGB code |
date_added DATE, -- date added to database |
UNIQUE (name) |
); |
]]) |
end -- function create_tables |
function get_room (uid) |
-- check we got room at all |
if not 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) |
room.area = areas [room.area] or string.format ('Area %s', room.area or '<unknown>') |
if uid current_room then |
current_area = room.area |
end -- if |
-- build hover message |
local environmentname = room.terrain |
if tonumber (environmentname) then |
environmentname = environments [tonumber (environmentname)] |
end -- convert to name |
local terrain = ' |
if environmentname then |
terrain = 'nTerrain: ' .. capitalize (environmentname) |
end -- if terrain known |
local info = ' |
if room.info then |
info = 'nInfo: ' .. capitalize (room.info) |
end -- if info known |
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) |
local areaname = room.area or 'Unknown' |
if tonumber (areaname) then |
areaname = areas [tonumber (areaname)] |
end -- convert to name |
room.hovermessage = string.format ( |
'%stExits: %snRoom: %snArea: %s%s%s%s', |
room.name, |
table.concat (texits, ', '), |
uid, |
areaname, |
terrain, |
info, |
notes |
-- depth, |
-- table.concat (path, ',') |
) |
room.bordercolour = config.ROOM_COLOUR.colour |
room.borderpen = 0 -- solid |
room.borderpenwidth = 1 |
room.fillcolour = 0xff0000 |
room.fillbrush = 1 -- no fill |
-- special room fill colours |
if room.info then |
if string.match (room.info, 'shop') then |
room.fillcolour = config.SHOP_FILL_COLOUR.colour |
room.fillbrush = 8 |
elseif string.match (room.info, 'postoffice') then |
room.fillcolour = config.POSTOFFICE_FILL_COLOUR.colour |
room.fillbrush = 8 |
elseif string.match (room.info, 'bank') then |
room.fillcolour = config.BANK_FILL_COLOUR.colour |
room.fillbrush = 8 |
elseif string.match (room.info, 'newsroom') then |
room.fillcolour = config.NEWSROOM_FILL_COLOUR.colour |
room.fillbrush = 8 |
end -- if |
else |
-- use terrain colour |
if environmentname then |
if user_terrain_colour [environmentname] then |
room.fillcolour = user_terrain_colour [environmentname] |
room.fillbrush = 0 -- solid |
elseif terrain_colours [environmentname] then |
room.fillcolour = colour_lookup [terrain_colours [environmentname]] |
room.fillbrush = 0 -- solid |
end |
end -- if environmentname |
end -- if |
if uid current_room then |
room.bordercolour = config.OUR_ROOM_COLOUR.colour |
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 |
function room_edit_bookmark (room, uid) |
local notes, found |
for row in db_bm:nrows(string.format ('SELECT * FROM bookmarks WHERE uid = %s', fixsql (uid))) do |
notes = row.notes |
found = true |
end -- finding room |
if found 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 not found then |
mapper.mapprint ('No comment entered, bookmark not saved.') |
return |
else |
dbcheck (db_bm:execute (string.format ( |
'DELETE FROM bookmarks 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 |
if found then |
dbcheck (db_bm:execute (string.format ( |
'UPDATE bookmarks SET notes = %s, date_added = DATETIME('NOW') WHERE uid = %s;', |
fixsql (newnotes), |
fixsql (uid) |
))) |
mapper.mapprint ('Bookmark for room', uid, 'changed to:', newnotes) |
else |
dbcheck (db_bm:execute (string.format ( |
'INSERT INTO bookmarks (uid, notes, date_added) VALUES (%s, %s, DATETIME('NOW'));', |
fixsql (uid), |
fixsql (newnotes) |
))) |
mapper.mapprint ('Bookmark added to room', uid, ':', newnotes) |
end -- if |
rooms [uid].notes = newnotes |
end -- room_edit_bookmark |
function room_edit_terrain_colour (room, uid) |
if not room.terrain then |
utils.msgbox ('This room does not have a terrain type', 'Unknown terrain!', 'ok', '!', 1) |
return |
end -- not known |
local environmentname = room.terrain |
if tonumber (environmentname) then |
environmentname = environments [tonumber (environmentname)] |
end -- convert to name |
local colour |
local colourtype = terrain_colours [environmentname] |
if colourtype then |
colour = colour_lookup [colourtype] |
end -- if type known |
if user_terrain_colour [environmentname] then |
colour = user_terrain_colour [environmentname] |
end -- if already have user colour |
local newcolour = PickColour (colour or 0x000000) |
if newcolour -1 or newcolour colour then |
return |
end -- cancelled |
if user_terrain_colour [environmentname] then |
dbcheck (db_bm:execute (string.format ( |
'UPDATE terrain SET color = %s, date_added = DATETIME('NOW') WHERE name = %s;', |
fixsql (newcolour), |
fixsql (environmentname) |
))) |
mapper.mapprint ('Colour for terrain ' .. environmentname .. ' changed to:', RGBColourToName (newcolour)) |
else |
dbcheck (db_bm:execute (string.format ( |
'INSERT INTO terrain (name, color, date_added) VALUES (%s, %s, DATETIME('NOW'));', |
fixsql (environmentname), |
fixsql (newcolour) |
))) |
mapper.mapprint ('Colour for terrain ' .. environmentname .. ' is now', RGBColourToName (newcolour)) |
end -- if |
user_terrain_colour [environmentname] = newcolour |
mapper.draw (current_room) |
end -- room_edit_terrain_colour |
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 change_room_area (room, uid) |
if next (areas) nil then |
mapper.maperror('There are no available areas to choose from.') |
return |
end -- if |
local chosen_area = utils.listbox ('Choose the area this room belongs to:', 'Areas ...', areas) |
if not chosen_area then |
return |
end -- if |
rooms[uid].area = chosen_area |
mapper.draw (current_room) |
dbcheck (db:execute (string.format ([[ |
UPDATE rooms SET area = %s WHERE uid = %s; |
]], fixsql (chosen_area), -- area (e.g. '1' for 'western ithmia') |
fixsql (uid) -- from current room |
))) |
end -- change_room_area |
function add_area (room, uid) |
local roomname |
local roomarea |
for row in db:nrows(string.format ('SELECT name, area FROM rooms WHERE uid = %s', fixsql (uid))) do |
roomname = row.name |
roomarea = row.area |
end -- finding room |
if roomname nil then |
mapper.maperror('Cannot find this room in the database') |
return |
end -- if |
local area_name = utils.inputbox ('Name for area: ' .. roomarea, |
'Choose the name for this area', |
areas [roomarea] ) |
if not area_name or area_name ' then |
return |
end -- if |
db:exec ('BEGIN TRANSACTION') |
-- get rid of old area description, if any |
local exists = db:execute (string.format ( |
'DELETE FROM areas WHERE uid = %s;', |
fixsql (roomarea) |
)) sqlite3.OK |
dbcheck (db:execute (string.format ( |
'INSERT INTO areas (uid, name, date_added) VALUES (%s, %s, DATETIME('NOW'));', |
fixsql (roomarea), |
fixsql (area_name) |
))) |
db:exec ('COMMIT') |
local action = 'Added' |
if exists then |
action = 'Changed' |
end -- if |
mapper.mapprint (string.format ('%s area '%s' with area code '%s', |
action, area_name, roomarea)) |
areas [roomarea] = area_name |
mapper.draw (current_room) |
end -- add_area |
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 = 'Edit terrain colour', func = room_edit_terrain_colour} , |
{ name = '-', } , |
-- { name = '^Exits', } , |
{ name = 'Add Exit', func = room_add_exit} , |
{ name = 'Change Exit', func = room_change_exit} , |
{ name = 'Delete Exit', func = room_delete_exit} , |
{ name = '-', } , |
{ name = 'Set area for room', func = change_room_area} , |
{ name = 'Update area name', func = add_area} , |
} -- 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 OnPluginInstall () |
config = {} -- in case not found |
-- get saved configuration |
assert (loadstring (GetVariable ('config') or ')) () |
-- allow for additions to config |
for k, v in pairs (default_config) do |
config [k] = config [k] or v |
end -- for |
-- initialize mapper engine |
mapper.init { config = config, -- colours, timing etc. |
get_room = get_room, -- get_room (uid) called to get room info |
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')) |
db_bm = assert (sqlite3.open(GetInfo (66) .. Trim (WorldAddress ()) .. '_' .. WorldPort () .. '_bookmarks.db')) |
create_tables () -- create database structure if necessary |
-- grab all area names |
for row in db:nrows('SELECT * FROM areas') do |
areas [row.uid] = row.name |
end -- finding areas |
-- grab all user terrain info |
for row in db_bm:nrows('SELECT * FROM terrain') do |
user_terrain_colour [row.name] = row.color |
end -- finding terrains |
-- grab all environment names |
for row in db:nrows('SELECT * FROM environments') do |
environments [tonumber (row.uid)] = row.name |
terrain_colours [row.name] = tonumber (row.color) |
end -- finding environments |
end -- OnPluginInstall |
function OnPluginEnable () |
mapper.show () |
end -- OnPluginDisable |
function OnPluginDisable () |
mapper.hide () |
end -- OnPluginDisable |
-- hide window on removal |
function OnPluginClose () |
mapper.hide () |
-- close databases |
db:close() |
db_bm:close() |
end -- OnPluginClose |
function OnPluginSaveState () |
mapper.save_state () |
SetVariable ('config', 'config = ' .. serialize.save_simple (config)) |
end -- OnPluginSaveState |
terrain_colours = {} |
-- ANSI colours lookup (for terrain_colours) |
colour_lookup = { |
[0] = ColourNameToRGB 'black', |
[1] = ColourNameToRGB 'maroon', |
[2] = ColourNameToRGB 'green', |
[3] = ColourNameToRGB 'olive', |
[4] = ColourNameToRGB 'navy', |
[5] = ColourNameToRGB 'purple', |
[6] = ColourNameToRGB 'teal', |
[7] = ColourNameToRGB 'silver', |
[8] = ColourNameToRGB 'gray', |
[9] = ColourNameToRGB 'red', |
[10] = ColourNameToRGB 'lime', |
[11] = ColourNameToRGB 'yellow', |
[12] = ColourNameToRGB 'blue', |
[13] = ColourNameToRGB 'magenta', |
[14] = ColourNameToRGB 'cyan', |
[15] = ColourNameToRGB 'white', |
} -- end of colour_lookup |
-- here when location changes, eg. : Room.Num 7476 |
function got_room_number (s) |
local room_number = s |
if not room_number then |
return |
end -- no room number |
current_room = room_number |
mapper.draw (room_number) |
if expected_exit '0' and from_room then |
fix_up_exit () |
end -- exit was wrong |
end -- got_room_number |
-- we got a room name, eg. : Room.Brief On the edge of a great plain |
function got_room_name (s) |
local brief = s |
if not current_room then |
return |
end -- don't have room |
local room = rooms [current_room] |
-- not cached - see if in database |
if not room then |
room = load_room_from_database (current_room) |
end -- not in cache |
if not room then |
save_room_to_database (current_room, brief) |
mapper.draw (current_room) -- redraw room with name |
end -- if room not there |
end -- got_room_name |
-- we got room exits, eg. : Room.Exits ne,sw,nw |
function got_room_exit (s) |
-- don't do if we are expecting full exits at some stage |
if full_exits_found then |
return |
end -- if |
local exits = string.match (s, '^([%a,]+)$') |
if not (current_room and exits) then |
return |
end -- if |
local room = rooms [current_room] |
-- not cached - see if in database |
if not room then |
room = load_room_from_database (current_room) |
end -- not in cache |
if room and next (room.exits) nil then |
save_exits_to_database (current_room, exits) |
mapper.draw (current_room) -- redraw room with exits |
end -- need to save exits |
end -- got_room_exit |
function got_vitals (s) |
-- ignore |
end -- function got_vitals |
-- we got room exits, eg. : Room.FullExits ne(8564),w(8428) |
function got_room_full_exits (s) |
full_exits_found = true |
local exits = string.match (s, '^([%a,(%d)]+)$') |
if not (current_room and exits) then |
return |
end -- if |
local room = rooms [current_room] |
-- not cached - see if in database |
if not room then |
room = load_room_from_database (current_room) |
end -- not in cache |
if room and next (room.exits) nil then |
save_full_exits_to_database (current_room, exits) |
mapper.draw (current_room) -- redraw room with exits |
end -- need to save exits |
end -- got_room_exit |
-- we got room environment, eg. : Urban |
function got_environment (s) |
if not current_room then |
return |
end -- if |
local room = rooms [current_room] |
-- not cached - see if in database |
if not room then |
room = load_room_from_database (current_room) |
end -- not in cache |
if room and room.terrain nil then |
save_environment_to_database (current_room, s) |
mapper.draw (current_room) -- redraw room with environment |
end -- need to save environment |
end -- got_environment |
-- we got room coordinates, eg. : '38,3,1,0' |
function got_coordinates (s) |
if not current_room then |
return |
end -- if |
local room = rooms [current_room] |
-- not cached - see if in database |
if not room then |
room = load_room_from_database (current_room) |
end -- not in cache |
if room and (room.area nil or tonumber (room.area) 0) then |
save_coordinates_to_database (current_room, s) |
mapper.draw (current_room) -- redraw room with area |
end -- need to save environment |
end -- got_coordinates |
-- we got room info, eg. : shops,postoffice |
function got_info (s) |
if not current_room then |
return |
end -- if |
local room = rooms [current_room] |
-- not cached - see if in database |
if not room then |
room = load_room_from_database (current_room) |
end -- not in cache |
if room and room.info nil then |
save_info_to_database (current_room, s) |
mapper.draw (current_room) -- redraw room with info |
end -- need to save environment |
end -- got_info |
handlers = { |
[1] = got_vitals, -- eg. 'H:496/496 M:412/412 E:1380/1380 W:960/960 NL:89/100' |
-- health mana endurance willpower experience |
[2] = got_room_name, -- eg. 'Continuing on the Parade of Zarathustra' |
[3] = got_room_exit, -- eg. 'n,s' |
[4] = got_room_number, -- eg. '401' |
[5] = got_room_full_exits, -- eg. 'ne(8564),w(8428)' |
[6] = got_environment, -- eg. 'Urban' |
[7] = got_coordinates, -- eg. '38,3,1,0' |
[8] = got_info, -- eg. 'shops,postoffice' |
} |
function OnPluginBroadcast (msg, id, name, text) |
if id '85f72d0e263d75df7bde6f00' then |
local f = handlers [msg] |
if f then |
f (text) |
end -- have handler |
end -- if ATCP message |
end |
function map_find (name, line, wildcards) |
local rooms = {} |
local count = 0 |
-- find matching rooms using FTS3 |
for row in db:nrows(string.format ('SELECT uid, name FROM rooms_lookup WHERE rooms_lookup MATCH %s', fixsql (wildcards [1]))) do |
rooms [row.uid] = true |
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 |
) |
end -- map_find |
function map_find_special (which_ones) |
local wanted_items = {} |
for _, v in ipairs (which_ones) do |
wanted_items [v:lower ()] = true |
end |
local rooms = {} |
local count = 0 |
-- build table of special places (with info in them) |
for row in db:nrows(string.format ('SELECT uid, name, info FROM rooms WHERE info IS NOT NULL')) do |
if row.info ~= ' then |
local wanted = false |
local t = {} |
for item in string.gmatch (row.info, '[^,]+') do |
if wanted_items [item:lower ()] then |
wanted = true |
table.insert (t, capitalize (item)) |
end -- if |
end -- for |
if wanted then |
rooms [row.uid] = table.concat(t, ', ') |
count = count + 1 |
end -- if |
end -- if |
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 |
--[[ |
for _, v in ipairs ({ |
-- 'guild', 'healer', 'trainer', 'questor', |
}) do wanted_items [v] = true end |
--]] |
function map_shops (name, line, wildcards) |
map_find_special { 'shop', 'postoffice', 'bank', 'newsroom', } |
end -- map_shops |
function map_trainers (name, line, wildcards) |
map_find_special { 'trainer', } |
end -- map_trainers |
function map_quests (name, line, wildcards) |
map_find_special { 'questor', } |
end -- map_quests |
function map_healers (name, line, wildcards) |
map_find_special { 'healers', } |
end -- map_healers |
function map_goto (name, line, wildcards) |
local wanted = wildcards [1] |
if current_room and wanted current_room then |
mapper.mapprint ('You are already in that room.') |
return |
end -- if |
-- 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_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 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_bookmarks (name, line, wildcards) |
local rooms = {} |
local count = 0 |
-- build table of special places (with info in them) |
for row in db_bm:nrows(string.format ('SELECT uid, notes FROM bookmarks')) 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_areas (name, line, wildcards) |
local wanted_areas = {} |
local count = 0 |
if next (areas) nil then |
mapper.maperror 'No areas known.' |
return |
end -- if |
-- build table of all areas, keyed by area code |
for k, v in pairs (areas) do |
wanted_areas [k] = v |
count = count + 1 |
end -- for |
-- find all areas |
mapper.find ( |
function (uid) |
local room = rooms [uid] |
local reason |
-- if this room is in the list of wanted areas then save its path |
if wanted_areas[room.area] then |
reason = wanted_areas [room.area] |
wanted_areas [room.area] = nil |
end -- found one! |
return reason, next (wanted_areas) nil |
end, -- function |
show_vnums, -- show vnum? |
count, -- how many to expect |
false -- don't auto-walk |
) |
end -- map_areas |
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 |
-- 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 |
function OnPluginConnect () |
mapper.cancel_speedwalk () |
-- DoAfter (3, 'look') -- force mapper update |
end -- OnPluginConnect |
function OnPluginDisconnect () |
mapper.cancel_speedwalk () |
end -- OnPluginConnect |
function OnHelp () |
mapper.mapprint (string.format ('[MUSHclient mapper, version %0.1f]', mapper.VERSION)) |
mapper.mapprint (world.GetPluginInfo (world.GetPluginID (), 3)) |
end |
function OnPluginListChanged () |
do_plugin_check_now ('85f72d0e263d75df7bde6f00', 'ATCP_NJG') -- check we have ATCP plugin |
end -- OnPluginListChanged |
]]> |
</script> |
</muclient> |
My application is running on Windows Platform and Linux Platform at the same time with Pair Mode, the windows platform is running with bind and linux with connect. After few hours, the application running on Windows abort with this error : (Unexpected action: state=2 source=1 action=5 (e:workspacenanomsg-1.1.4srctransportstcpatcp.c:228). |
I believe this problem is arising due to a potential 'race' relating to the close of the created socket. The code here is fragile, and has many assertions where the original author didn't think through all the cases. (The same is true of ZeroMQ as well.) . If you have a chance, I'd recommend giving NNG a shot (github.com/nanomsg/nng) which was designed to be robust from the first day. Having said that, if I find time to work on this I'll fix it. But right now nanomsg is definitely backburnered compared to NNG. (If you need support commercially, reach out to me separately -- we can work out a solution that should let you get a fix for this faster.) |