From: Jeremy Stanley Date: Sun, 18 Sep 2005 23:42:03 +0000 (+0000) Subject: Imported from archive. X-Git-Url: https://mudpy.org/gitweb?a=commitdiff_plain;ds=sidebyside;h=ab7fb385d9b58cd6ca9b0156e8f1780f5ce3e750;p=mudpy.git Imported from archive. * mudpy.py (User.negotiate_telnet_options): Added support for RFC 1184 linemode and RFC 858 go ahead suppression. Automated end of record/go ahead prompt terminator selection via Telnet option negotiation. Added support for Telnet suboption negotiation. Fixed a double-IAC escape matching error. (User.send): Refactored away some spaghetti logic for better readability. (log): Added syslog support. --- diff --git a/katarsis b/katarsis index 5c06393..4cb19de 100644 --- a/katarsis +++ b/katarsis @@ -1,38 +1,39 @@ -[location:101] -pickproof_n = yes -name = East Envy Avenue -closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Envy Avenue runs East and West here while a merchant's booth lies to the North. -terrain = city -link_e = location:102 -keywords_n = ['booth'] -description_n = This is a simple merchant's booth. -link_w = location:161 -link_n = location:159 - -[location:106] -keywords_e = ['shop'] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Gluttony Street runs North and South here while a storefront beckons to the East. +[location:127] +keywords_e = ['booth'] +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Lust Street runs North and South here while a merchant's booth lies to the East. closeable_e = yes pickproof_e = yes terrain = city -link_e = location:152 -name = North Gluttony Street -description_e = This is the entrance to a shop. -link_s = location:105 -link_n = location:107 +link_e = location:143 +link_n = location:128 +description_e = This is a simple merchant's booth. +link_s = location:126 +name = South Lust Street -[location:118] -pickproof_n = yes -name = East Avarice Avenue -closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Avarice Avenue runs East and West here while a merchant's booth lies to the North. +[location:120] +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West lies Avarice Avenue while Gluttony Street leads North. terrain = city -link_e = location:119 -keywords_n = ['booth'] -description_n = This is a simple merchant's booth. -link_w = location:116 -link_n = location:147 +name = The Corner of Gluttony and Avarice +link_w = location:119 +link_n = location:121 + +[location:143] +link_w = location:127 +terrain = inside +name = New BuildWalk Room +description = This unfinished room was created by Imp. + +[location:132] +keywords_e = ['booth'] +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Lust Street runs North and South here while a merchant's booth lies to the East. +closeable_e = yes +pickproof_e = yes +terrain = city +link_e = location:141 +link_n = location:133 +description_e = This is a simple merchant's booth. +link_s = location:131 +name = North Lust Street [location:159] link_s = location:101 @@ -49,16 +50,17 @@ link_s = location:129 pickproof_s = yes description = Shoes, shoes and more shoes... You need footwear, we have footwear. Look around, see what you like. Best prices in town! So you gonna buy something, stranger? -[location:104] -keywords_e = ['gate'] -name = East Market Gate +[location:122] +keywords_e = ['shop'] +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Gluttony Street runs North and South here while a storefront beckons to the East. closeable_e = yes pickproof_e = yes terrain = city -link_e = location:0 -description_e = This gate leads from the market to the city proper. -link_w = location:103 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West, Envy Avenue heads into the market while the rest of the city lies trough the gate to the East. +link_e = location:150 +link_n = location:103 +description_e = This is the entrance to a shop. +link_s = location:121 +name = South Gluttony Street [location:151] terrain = inside @@ -67,26 +69,26 @@ link_e = location:105 description = This unfinished room was created by Imp. [location:150] -terrain = inside link_w = location:122 +terrain = inside name = New BuildWalk Room description = This unfinished room was created by Imp. [location:153] -link_n = location:108 terrain = inside -description = This unfinished room was created by Imp. +link_n = location:108 name = New BuildWalk Room +description = This unfinished room was created by Imp. [location:152] -terrain = inside link_w = location:106 +terrain = inside name = New BuildWalk Room description = This unfinished room was created by Imp. [location:155] -terrain = inside link_w = location:114 +terrain = inside name = New BuildWalk Room description = This unfinished room was created by Imp. @@ -97,10 +99,10 @@ name = New BuildWalk Room description = This unfinished room was created by Imp. [location:157] -link_n = location:130 terrain = inside -description = This booth sells cloth garments of every description. Fine silks and linens line the walls, draped from every protrusion and stacked on every surface. +link_n = location:130 name = Tailor's Booth +description = This booth sells cloth garments of every description. Fine silks and linens line the walls, draped from every protrusion and stacked on every surface. [location:156] terrain = inside @@ -110,15 +112,15 @@ description = This unfinished room was created by Imp. [location:115] link_n = location:114 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Anger Street runs North and South here while a merchant's booth lies to the West. terrain = city -name = South Anger Street keywords_w = ['booth'] closeable_w = yes description_w = This is a simple merchant's booth. link_s = location:116 pickproof_w = yes link_w = location:156 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Anger Street runs North and South here while a merchant's booth lies to the West. +name = South Anger Street [location:114] keywords_e = ['booth'] @@ -127,62 +129,62 @@ closeable_e = yes pickproof_e = yes terrain = city link_e = location:155 -name = South Anger Street +link_n = location:161 description_e = This is a simple merchant's booth. link_s = location:115 -link_n = location:161 +name = South Anger Street [location:117] description_s = This gate leads from the market to the city proper. +link_n = location:116 description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the North, Anger Street heads into the market while the rest of the city lies trough the gate to the South. terrain = city -name = South Market Gate closeable_s = yes keywords_s = ['gate'] link_s = location:0 pickproof_s = yes -link_n = location:116 +name = South Market Gate [location:116] link_n = location:115 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Avarice Avenue while Anger Street runs North and South. terrain = city link_e = location:118 -name = South Anger and Avarice link_s = location:117 link_w = location:123 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Avarice Avenue while Anger Street runs North and South. +name = South Anger and Avarice [location:111] pickproof_n = yes name = North Market Gate closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the South, Anger Street heads into the market while the rest of the city lies trough the gate to the North. terrain = city +link_n = location:0 keywords_n = ['gate'] link_s = location:110 description_n = This gate leads from the market to the city proper. -link_n = location:0 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the South, Anger Street heads into the market while the rest of the city lies trough the gate to the North. [location:110] link_n = location:111 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sloth Avenue while Anger Street runs North and South. terrain = city link_e = location:109 -name = North Anger and Sloth link_s = location:112 link_w = location:135 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Sloth Avenue while Anger Street runs North and South. +name = North Anger and Sloth [location:113] link_n = location:112 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Anger Street runs North and South here while a merchant's booth lies to the West. terrain = city -name = North Anger Street keywords_w = ['booth'] closeable_w = yes description_w = This is a simple merchant's booth. link_s = location:161 pickproof_w = yes link_w = location:137 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Anger Street runs North and South here while a merchant's booth lies to the West. +name = North Anger Street [location:112] keywords_e = ['booth'] @@ -191,10 +193,10 @@ closeable_e = yes pickproof_e = yes terrain = city link_e = location:138 -name = North Anger Street +link_n = location:110 description_e = This is a simple merchant's booth. link_s = location:113 -link_n = location:110 +name = North Anger Street [location:137] terrain = inside @@ -204,14 +206,14 @@ description = This unfinished room was created by Imp. [location:136] description_w = This gate leads from the market to the city proper. +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East, Envy Avenue heads into the market while the rest of the city lies trough the gate to the West. terrain = city link_e = location:128 -name = West Market Gate keywords_w = ['gate'] closeable_w = yes pickproof_w = yes link_w = location:0 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East, Envy Avenue heads into the market while the rest of the city lies trough the gate to the West. +name = West Market Gate [location:135] description_s = This is a simple merchant's booth. @@ -229,13 +231,13 @@ description = You find the hustle and bustle of this place remarkably distractin pickproof_n = yes name = West Sloth Avenue closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sloth Avenue runs East and West here while a storefront beckons to the North. terrain = city link_e = location:135 +link_n = location:140 keywords_n = ['shop'] description_n = This is the entrance to a shop. link_w = location:133 -link_n = location:140 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sloth Avenue runs East and West here while a storefront beckons to the North. [location:119] description_s = This is the entrance to a shop. @@ -249,29 +251,29 @@ link_w = location:118 pickproof_s = yes description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Avarice Avenue runs East and West here while a storefront beckons to the South. -[location:132] -keywords_e = ['booth'] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Lust Street runs North and South here while a merchant's booth lies to the East. -closeable_e = yes -pickproof_e = yes +[location:118] +pickproof_n = yes +name = East Avarice Avenue +closeable_n = yes terrain = city -link_e = location:141 -name = North Lust Street -description_e = This is a simple merchant's booth. -link_s = location:131 -link_n = location:133 +link_e = location:119 +link_n = location:147 +keywords_n = ['booth'] +description_n = This is a simple merchant's booth. +link_w = location:116 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Avarice Avenue runs East and West here while a merchant's booth lies to the North. [location:131] link_n = location:132 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Lust Street runs North and South here while a storefront beckons to the West. terrain = city -name = North Lust Street keywords_w = ['shop'] closeable_w = yes description_w = This is the entrance to a shop. link_s = location:128 pickproof_w = yes link_w = location:142 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Lust Street runs North and South here while a storefront beckons to the West. +name = North Lust Street [location:130] description_s = This is a simple merchant's booth. @@ -285,29 +287,23 @@ link_w = location:129 pickproof_s = yes description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Envy Avenue runs East and West here while a merchant's booth lies to the South. -[location:105] -link_n = location:106 +[location:123] +description_s = This is the entrance to a shop. +name = West Avarice Avenue terrain = city -name = North Gluttony Street -keywords_w = ['booth'] -closeable_w = yes -description_w = This is a simple merchant's booth. -link_s = location:103 -pickproof_w = yes -link_w = location:151 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Gluttony Street runs North and South here while a merchant's booth lies to the West. - -[location:138] -terrain = inside -link_w = location:112 -name = New BuildWalk Room -description = This unfinished room was created by Imp. +link_e = location:116 +closeable_s = yes +keywords_s = ['shop'] +link_s = location:146 +link_w = location:124 +pickproof_s = yes +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Avarice Avenue runs East and West here while a storefront beckons to the South. [location:148] -link_n = location:119 terrain = inside -description = This unfinished room was created by Imp. +link_n = location:119 name = New BuildWalk Room +description = This unfinished room was created by Imp. [location:149] terrain = inside @@ -316,10 +312,10 @@ link_e = location:121 description = This unfinished room was created by Imp. [location:146] -link_n = location:123 terrain = inside -description = This unfinished room was created by Imp. +link_n = location:123 name = New BuildWalk Room +description = This unfinished room was created by Imp. [location:147] link_s = location:118 @@ -345,9 +341,9 @@ name = New BuildWalk Room link_e = location:131 description = This unfinished room was created by Imp. -[location:143] +[location:138] +link_w = location:112 terrain = inside -link_w = location:127 name = New BuildWalk Room description = This unfinished room was created by Imp. @@ -358,26 +354,26 @@ name = New BuildWalk Room description = This unfinished room was created by Imp. [location:141] -terrain = inside link_w = location:132 +terrain = inside name = New BuildWalk Room description = This unfinished room was created by Imp. [location:160] -link_n = location:102 terrain = inside -description = You find yourself amidst cold, hard steel and iron equipment of every possible description. A slight breeze brings tinkle and clank sounds from all around you. +link_n = location:102 name = Blacksmith's Booth +description = You find yourself amidst cold, hard steel and iron equipment of every possible description. A slight breeze brings tinkle and clank sounds from all around you. [location:161] link_n = location:113 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Envy Avenue while Anger Street runs North and South. A short flight of stairs leads up to the bandstand. terrain = city link_e = location:101 -name = Pride Square link_s = location:114 link_w = location:130 link_u = location:100 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Envy Avenue while Anger Street runs North and South. A short flight of stairs leads up to the bandstand. +name = Pride Square [location:108] description_s = This is a simple merchant's booth. @@ -395,28 +391,28 @@ description = You find the hustle and bustle of this place remarkably distractin pickproof_n = yes name = East Sloth Avenue closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sloth Avenue runs East and West here while a storefront beckons to the North. terrain = city link_e = location:108 +link_n = location:154 keywords_n = ['shop'] description_n = This is the entrance to a shop. link_w = location:110 -link_n = location:154 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Sloth Avenue runs East and West here while a storefront beckons to the North. [location:128] link_n = location:131 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Envy Avenue while Lust Street runs North and South. terrain = city link_e = location:129 -name = Lust and West Envy link_s = location:127 link_w = location:136 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Envy Avenue while Lust Street runs North and South. +name = Lust and West Envy [location:139] -link_n = location:135 terrain = inside -description = This unfinished room was created by Imp. +link_n = location:135 name = New BuildWalk Room +description = This unfinished room was created by Imp. [location:102] description_s = This is a simple merchant's booth. @@ -432,85 +428,89 @@ description = You find the hustle and bustle of this place remarkably distractin [location:103] link_n = location:105 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Envy Avenue while Gluttony Street runs North and South. terrain = city link_e = location:104 -name = Gluttony and East Envy link_s = location:122 link_w = location:102 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East and West lies Envy Avenue while Gluttony Street runs North and South. +name = Gluttony and East Envy [location:100] +link_d = location:161 terrain = inside description = The stand is currently not in use for a performance, but shoppers gather here to rest and chat with one another. A pleasantly cool breeze coupled with a nice view of the market make this a good place to relax and recover energy. name = The Bandstand -link_d = location:161 -[location:127] -keywords_e = ['booth'] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Lust Street runs North and South here while a merchant's booth lies to the East. -closeable_e = yes -pickproof_e = yes +[location:101] +pickproof_n = yes +name = East Envy Avenue +closeable_n = yes terrain = city -link_e = location:143 -name = South Lust Street -description_e = This is a simple merchant's booth. -link_s = location:126 -link_n = location:128 +link_e = location:102 +link_n = location:159 +keywords_n = ['booth'] +description_n = This is a simple merchant's booth. +link_w = location:161 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Envy Avenue runs East and West here while a merchant's booth lies to the North. -[location:120] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West lies Avarice Avenue while Gluttony Street leads North. +[location:106] +keywords_e = ['shop'] +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Gluttony Street runs North and South here while a storefront beckons to the East. +closeable_e = yes +pickproof_e = yes terrain = city -name = The Corner of Gluttony and Avarice -link_w = location:119 -link_n = location:121 +link_e = location:152 +link_n = location:107 +description_e = This is the entrance to a shop. +link_s = location:105 +name = North Gluttony Street [location:121] link_n = location:122 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Gluttony Street runs North and South here while a merchant's booth lies to the West. terrain = city -name = South Gluttony Street keywords_w = ['booth'] closeable_w = yes description_w = This is a simple merchant's booth. link_s = location:120 pickproof_w = yes link_w = location:149 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Gluttony Street runs North and South here while a merchant's booth lies to the West. +name = South Gluttony Street -[location:122] -keywords_e = ['shop'] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Gluttony Street runs North and South here while a storefront beckons to the East. +[location:104] +keywords_e = ['gate'] +name = East Market Gate closeable_e = yes pickproof_e = yes terrain = city -link_e = location:150 -name = South Gluttony Street -description_e = This is the entrance to a shop. -link_s = location:121 -link_n = location:103 +link_e = location:0 +description_e = This gate leads from the market to the city proper. +link_w = location:103 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the West, Envy Avenue heads into the market while the rest of the city lies trough the gate to the East. -[location:123] -description_s = This is the entrance to a shop. -name = West Avarice Avenue +[location:105] +link_n = location:106 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Gluttony Street runs North and South here while a merchant's booth lies to the West. terrain = city -link_e = location:116 -closeable_s = yes -keywords_s = ['shop'] -link_s = location:146 -link_w = location:124 -pickproof_s = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Avarice Avenue runs East and West here while a storefront beckons to the South. +keywords_w = ['booth'] +closeable_w = yes +description_w = This is a simple merchant's booth. +link_s = location:103 +pickproof_w = yes +link_w = location:151 +name = North Gluttony Street [location:124] pickproof_n = yes name = West Avarice Avenue closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Avarice Avenue runs East and West here while a merchant's booth lies to the North. terrain = city link_e = location:123 +link_n = location:145 keywords_n = ['booth'] description_n = This is a simple merchant's booth. link_w = location:125 -link_n = location:145 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Avarice Avenue runs East and West here while a merchant's booth lies to the North. [location:133] name = The Corner of Lust and Sloth @@ -523,20 +523,20 @@ description = You find the hustle and bustle of this place remarkably distractin pickproof_n = yes name = West Envy Avenue closeable_n = yes -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Envy Avenue runs East and West here while a merchant's booth lies to the North. terrain = city link_e = location:130 +link_n = location:158 keywords_n = ['booth'] description_n = This is a simple merchant's booth. link_w = location:128 -link_n = location:158 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Envy Avenue runs East and West here while a merchant's booth lies to the North. [location:125] -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East lies Avarice Avenue while Lust Street leads North. +link_n = location:126 terrain = city link_e = location:124 name = The Corner of Lust and Avarice -link_n = location:126 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. To the East lies Avarice Avenue while Lust Street leads North. [location:107] name = The Corner of Gluttony and Sloth @@ -547,13 +547,13 @@ description = You find the hustle and bustle of this place remarkably distractin [location:126] link_n = location:127 +description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Lust Street runs North and South here while a storefront beckons to the West. terrain = city -name = South Lust Street keywords_w = ['shop'] closeable_w = yes description_w = This is the entrance to a shop. link_s = location:125 pickproof_w = yes link_w = location:144 -description = You find the hustle and bustle of this place remarkably distracting. The streets are filled with people of all races, buying and selling goods of every variety. Lust Street runs North and South here while a storefront beckons to the West. +name = South Lust Street diff --git a/menu b/menu index bc443cd..eb1d270 100644 --- a/menu +++ b/menu @@ -95,6 +95,8 @@ error_weak = That is a weak password... Try something at least 7 characters long prompt = Enter a new password for "$(account)": error_differs = The two passwords did not match. Try again... +[menu:initial] + [menu:main_utility] action_c = user.new_avatar() branch_a = activate_avatar diff --git a/mudpy.py b/mudpy.py index 68bbd2b..af61429 100644 --- a/mudpy.py +++ b/mudpy.py @@ -11,7 +11,8 @@ from os.path import abspath, dirname, exists, isabs, join as path_join from random import choice, randrange from socket import AF_INET, SO_REUSEADDR, SOCK_STREAM, SOL_SOCKET, socket from stat import S_IMODE, ST_MODE -from telnetlib import DO, DONT, ECHO, EOR, IAC, WILL, WONT +from syslog import LOG_PID, LOG_INFO, LOG_DAEMON, closelog, openlog, syslog +from telnetlib import DO, DONT, ECHO, EOR, GA, IAC, LINEMODE, SB, SE, SGA, WILL, WONT from time import asctime, sleep class Element: @@ -199,13 +200,15 @@ class User: self.connection = None self.authenticated = False self.password_tries = 0 - self.state = "entering_account_name" + self.state = "initial" self.menu_seen = False self.error = "" self.input_queue = [] self.output_queue = [] self.partial_input = "" self.echoing = True + self.terminator = IAC+GA + self.negotiation_pause = 0 self.avatar = None self.account = None @@ -299,7 +302,7 @@ class User: """Send the user their current menu.""" if not self.menu_seen: self.menu_choices = get_menu_choices(self) - self.send(get_menu(self.state, self.error, self.echoing, self.menu_choices), "") + self.send(get_menu(self.state, self.error, self.echoing, self.terminator, self.menu_choices), "") self.menu_seen = True self.error = False self.adjust_echoing() @@ -313,31 +316,34 @@ class User: """Remove a user from the list of connected users.""" universe.userlist.remove(self) - def send(self, output, eol="$(eol)"): + def send(self, output, eol="$(eol)", raw=False): """Send arbitrary text to a connected user.""" - # start with a newline, append the message, then end - # with the optional eol string passed to this function - # and the ansi escape to return to normal text - output = "\r\n" + output + eol + chr(27) + "[0m" + # unless raw mode is on, clean it up all nice and pretty + if not raw: - # find and replace macros in the output - output = replace_macros(self, output) + # we'll take out GA or EOR and add them back on the end + if output.endswith(IAC+GA) or output.endswith(IAC+EOR): + terminate = True + output = output[:-2] + else: terminate = False - # wrap the text at 80 characters - output = wrap_ansi_text(output, 80) + # start with a newline, append the message, then end + # with the optional eol string passed to this function + # and the ansi escape to return to normal text + output = "\r\n" + output + eol + chr(27) + "[0m" - # drop the formatted output into the output queue - self.output_queue.append(output) + # find and replace macros in the output + output = replace_macros(self, output) - # try to send the last item in the queue and remove it - try: - self.connection.send(self.output_queue[0]) - del self.output_queue[0] + # wrap the text at 80 characters + output = wrap_ansi_text(output, 80) - # but if we can't, that's okay too - except: - pass + # tack the terminator back on + if terminate: output += self.terminator + + # drop the output into the user's output queue + self.output_queue.append(output) def pulse(self): """All the things to do to the user per increment.""" @@ -347,8 +353,13 @@ class User: self.state = "disconnecting" self.menu_seen = False + # if output is paused, decrement the counter + if self.state == "initial": + if self.negotiation_pause: self.negotiation_pause -= 1 + else: self.state = "entering_account_name" + # show the user a menu as needed - self.show_menu() + else: self.show_menu() # disconnect users with the appropriate state if self.state == "disconnecting": self.quit() @@ -356,6 +367,16 @@ class User: # the user is unique and not flagged to disconnect else: + # try to send the last item in the queue and remove it + if self.output_queue: + try: + self.connection.send(self.output_queue[0]) + del self.output_queue[0] + + # but if we can't, that's okay too + except: + pass + # check for input and add it to the queue self.enqueue_input() @@ -436,25 +457,51 @@ class User: # if there wasn't an IAC in the input, skip to the end if position < 0: position = len(text) - # replace a double (literal) IAC and move on + # replace a double (literal) IAC if there's an LF later elif len(text) > position+1 and text[position+1] == IAC: - text = text.replace(IAC+IAC, IAC) + if text.find("\n", position) > 0: text = text.replace(IAC+IAC, IAC) + else: position += 1 position += 1 # this must be an option negotiation elif len(text) > position+2 and text[position+1] in (DO, DONT, WILL, WONT): + negotiation = text[position+1:position+3] + # if we turned echo off, ignore the confirmation - if not self.echoing and text[position+1:position+3] == DO+ECHO: pass + if not self.echoing and negotiation == DO+ECHO: pass + + # allow LINEMODE + elif negotiation == WILL+LINEMODE: self.send(IAC+DO+LINEMODE, raw=True) + + # if the client likes EOR instead of GA, make a note of it + elif negotiation == DO+EOR: self.terminator = IAC+EOR + elif negotiation == DONT+EOR and self.terminator == IAC+EOR: + self.terminator = IAC+GA + + # if the client doesn't want GA, oblige + elif negotiation == DO+SGA and self.terminator == IAC+GA: + self.terminator = "" + self.send(IAC+WILL+SGA, raw=True) # we don't want to allow anything else - elif text[position+1] in (DO, WILL): self.send(IAC+WONT+text[position+2]) + elif text[position+1] == DO: self.send(IAC+WONT+text[position+2], raw=True) + elif text[position+1] == WILL: self.send(IAC+DONT+text[position+2], raw=True) # strip the negotiation from the input text = text.replace(text[position:position+3], "") + # get rid of IAC SB .* IAC SE + elif len(text) > position+4 and text[position:position+2] == IAC+SB: + end_subnegotiation = text.find(IAC+SE, position) + if end_subnegotiation > 0: text = text[:position] + text[end_subnegotiation+2:] + else: position += 1 + # otherwise, strip out a two-byte IAC command - else: text = text.replace(text[position:position+2], "") + elif len(text) > position+2: text = text.replace(text[position:position+2], "") + + # and this means we got the begining of an IAC + else: position += 1 # replace the input with our cleaned-up text self.partial_input = text @@ -527,6 +574,11 @@ def log(message): # send the timestamp and message to standard output print(timestamp + " " + message) + # send the message to the system log + openlog("mudpy", LOG_PID, LOG_INFO | LOG_DAEMON) + syslog(message) + closelog() + def wrap_ansi_text(text, width): """Wrap text with arbitrary width while ignoring ANSI colors.""" @@ -757,12 +809,19 @@ def check_for_connection(listening_socket): # set the user's ipa from the connection's ipa user.address = address[0] + # let the client know we WILL EOR + user.send(IAC+WILL+EOR, raw=True) + user.negotiation_pause = 2 + # return the new user object return user -def get_menu(state, error=None, echoing=True, choices={}): +def get_menu(state, error=None, echoing=True, terminator="", choices=None): """Show the correct menu text to a user.""" + # make sure we don't reuse a mutable sequence by default + if choices is None: choices = {} + # begin with a telnet echo command sequence if needed message = get_echo_sequence(state, echoing) @@ -781,8 +840,8 @@ def get_menu(state, error=None, echoing=True, choices={}): # display a message indicating if echo is off message += get_echo_message(state) - # tack on IAC EOR to indicate the prompt will not be followed by CRLF - message += IAC+EOR + # tack on EOR or GA to indicate the prompt will not be followed by CRLF + message += terminator # return the assembly of various strings defined above return message