… | |
… | |
81 | ); |
81 | ); |
82 | |
82 | |
83 | # read username |
83 | # read username |
84 | while () { |
84 | while () { |
85 | $user = query $ns, 0, "What is your name?\n:"; |
85 | $user = query $ns, 0, "What is your name?\n:"; |
86 | last if $user =~ /^[a-zA-Z0-9][a-zA-Z0-9\-_]{2,17}$/; |
86 | |
|
|
87 | if ($cf::LOGIN_LOCK{$user}) { |
87 | $ns->send_drawinfo ( |
88 | $ns->send_drawinfo ( |
|
|
89 | "That username is currently used in another login session. " |
|
|
90 | . "Chose another, or wait till the other session has ended.", |
|
|
91 | cf::NDI_RED |
|
|
92 | ); |
|
|
93 | } elsif ($user =~ /^[a-zA-Z0-9][a-zA-Z0-9\-_]{2,17}$/) { |
|
|
94 | last; |
|
|
95 | } else { |
|
|
96 | $ns->send_drawinfo ( |
88 | "Your username contains illegal characters " |
97 | "Your username contains illegal characters " |
89 | . "(only a-z, A-Z and 0-9 are allowed), " |
98 | . "(only a-z, A-Z and 0-9 are allowed), " |
90 | . "or is not between 3 and 18 characters in length.", |
99 | . "or is not between 3 and 18 characters in length.", |
91 | cf::NDI_RED |
100 | cf::NDI_RED |
92 | ); |
101 | ); |
|
|
102 | } |
93 | } |
103 | } |
94 | |
104 | |
95 | check_playing $ns, $user and next; |
105 | check_playing $ns, $user and next; |
96 | |
106 | |
97 | $ns->send_drawinfo ( |
107 | $ns->send_drawinfo ( |
… | |
… | |
110 | . "that cannot be too much to ask for :)", |
120 | . "that cannot be too much to ask for :)", |
111 | cf::NDI_RED |
121 | cf::NDI_RED |
112 | ); |
122 | ); |
113 | } |
123 | } |
114 | |
124 | |
115 | check_playing $ns, $user and next; |
|
|
116 | |
|
|
117 | my $dir = "$PLAYERDIR/$user"; |
125 | my $dir = "$PLAYERDIR/$user"; |
118 | my $plfile = "$dir/$user.pl"; |
126 | my $plfile = "$dir/$user.pl"; |
|
|
127 | |
|
|
128 | # lock this username for the remainder of this login session |
|
|
129 | if ($cf::LOGIN_LOCK{$user}) { |
|
|
130 | $ns->send_drawinfo ( |
|
|
131 | "That username is currently used in another login session. " |
|
|
132 | . "Chose another, or wait till the other session has ended.", |
|
|
133 | cf::NDI_RED |
|
|
134 | ); |
|
|
135 | next; |
|
|
136 | } |
|
|
137 | local $cf::LOGIN_LOCK{$user} = 1; |
|
|
138 | |
|
|
139 | check_playing $ns, $user and next; |
119 | |
140 | |
120 | # try to read the user file and check the password |
141 | # try to read the user file and check the password |
121 | if (my $fh = aio_open $plfile, O_RDONLY, 0) { |
142 | if (my $fh = aio_open $plfile, O_RDONLY, 0) { |
122 | my $mtime = (stat $fh)[9]; |
143 | my $mtime = (stat $fh)[9]; |
123 | |
144 | |
124 | 0 < aio_read $fh, 0, 16384, my $buf, 0 or next; |
145 | 0 < aio_read $fh, 0, 16384, my $buf, 0 or next; |
125 | $buf =~ /^password (\S+)$/m or next; |
146 | $buf =~ /^password (\S+)$/m or next; |
126 | my $hash = $1; |
147 | my $hash = $1; |
127 | |
|
|
128 | check_playing $ns, $user and next; |
|
|
129 | |
148 | |
130 | if ($hash eq crypt $pass, $hash) { |
149 | if ($hash eq crypt $pass, $hash) { |
131 | # password matches, wonderful |
150 | # password matches, wonderful |
132 | my $pl = cf::player::load $plfile or next; |
151 | my $pl = cf::player::load $plfile or next; |
133 | $pl->enable_save (1); |
152 | $pl->enable_save (1); |
134 | $pl->connect ($ns); |
153 | $pl->connect ($ns); |
135 | last; |
154 | last; |
136 | } |
|
|
137 | |
|
|
138 | if (can_cleanup $buf, $mtime) { |
155 | } elsif (can_cleanup $buf, $mtime) { |
139 | Coro::Timer::sleep 1; |
156 | Coro::Timer::sleep 1; |
140 | |
157 | |
141 | $ns->send_drawinfo ( |
158 | $ns->send_drawinfo ( |
142 | "Player exists, but password does not match. If this is you account, " |
159 | "Player exists, but password does not match. If this is your account, " |
143 | . "please try again. If not, you can now opt to take over this account " |
160 | . "please try again. If not, you can now decide to take over this account " |
144 | . "because it has not been in-use for some time.", |
161 | . "because it has not been in-use for some time.", |
145 | cf::NDI_RED |
162 | cf::NDI_RED |
146 | ); |
163 | ); |
147 | |
164 | |
148 | (query $ns, cf::CS_QUERY_SINGLECHAR, "Delete existing account and create a new one (Y/N)?") =~ /^[yY]/ |
165 | (query $ns, cf::CS_QUERY_SINGLECHAR, "Delete existing account and create a new one (Y/N)?") =~ /^[yY]/ |
149 | or next; |
166 | or next; |
150 | |
167 | |
151 | # check if the file hasn't changed |
168 | # check if the file hasn't changed |
152 | aio_stat $plfile or next; |
169 | aio_stat $plfile and next; |
153 | $mtime == (stat _)[9] or next; |
170 | $mtime == (stat _)[9] or next; |
154 | |
171 | |
155 | # nuke playerdir, this might block, but it needs to be atomic |
|
|
156 | nuke_playerdir $user; |
172 | nuke_playerdir $user; |
157 | |
173 | |
158 | # fall through to creation |
174 | # fall through to creation |
159 | } else { |
175 | } else { |
160 | Coro::Timer::sleep 1; |
176 | Coro::Timer::sleep 1; |
… | |
… | |
167 | next; |
183 | next; |
168 | } |
184 | } |
169 | } |
185 | } |
170 | |
186 | |
171 | # the rest of this function is character creation |
187 | # the rest of this function is character creation |
172 | check_playing $ns, $user and next; |
|
|
173 | |
188 | |
|
|
189 | # just to make sure nothing is left over |
174 | nuke_playerdir $user; |
190 | nuke_playerdir $user; |
|
|
191 | |
|
|
192 | my $pass2 = query $ns, cf::CS_QUERY_HIDEINPUT, "Please type your password again."; |
|
|
193 | |
|
|
194 | if ($pass2 ne $pass) { |
|
|
195 | $ns->send_drawinfo ( |
|
|
196 | "The passwords do not match, please try again.", |
|
|
197 | cf::NDI_RED |
|
|
198 | ); |
|
|
199 | next; |
|
|
200 | } |
175 | |
201 | |
176 | my $pl = cf::player::create; |
202 | my $pl = cf::player::create; |
177 | $pl->ob->name ($user); |
203 | $pl->ob->name ($user); |
178 | $pl->password (crypt $pass, join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]); |
204 | $pl->password (crypt $pass, join '', ('.', '/', 0..9, 'A'..'Z', 'a'..'z')[rand 64, rand 64]); |
179 | $pl->connect ($ns); |
205 | $pl->connect ($ns); |
|
|
206 | |
180 | my $ob = $pl->ob; |
207 | my $ob = $pl->ob; |
181 | |
208 | |
182 | while () { |
209 | while () { |
183 | $ob->update_stats; |
210 | $ob->update_stats; |
184 | $pl->save_stats; |
211 | $pl->save_stats; |
… | |
… | |
205 | $ns->send_drawinfo ($ob->msg, cf::NDI_BLUE); |
232 | $ns->send_drawinfo ($ob->msg, cf::NDI_BLUE); |
206 | $ns->send_packet (sprintf "query %d %s", cf::CS_QUERY_SINGLECHAR, |
233 | $ns->send_packet (sprintf "query %d %s", cf::CS_QUERY_SINGLECHAR, |
207 | "Now choose a character.\nPress any key to change outlook.\nPress `d' when you're pleased.\n"); |
234 | "Now choose a character.\nPress any key to change outlook.\nPress `d' when you're pleased.\n"); |
208 | |
235 | |
209 | $ns->state (cf::ST_CHANGE_CLASS); |
236 | $ns->state (cf::ST_CHANGE_CLASS); |
|
|
237 | $pl->enable_save (1);#d# too early |
210 | |
238 | |
211 | last; |
239 | last; |
212 | } |
240 | } |
213 | }); |
241 | }); |
214 | } |
242 | } |
… | |
… | |
218 | on_apply => sub { |
246 | on_apply => sub { |
219 | my ($bed, $ob) = @_; |
247 | my ($bed, $ob) = @_; |
220 | |
248 | |
221 | return cf::override 0 unless $ob->type == cf::PLAYER; |
249 | return cf::override 0 unless $ob->type == cf::PLAYER; |
222 | |
250 | |
223 | my $ns = $ob->contr->ns; |
|
|
224 | |
|
|
225 | # update respawn position |
251 | # update respawn position |
226 | $ob->contr->savebed ($bed->map->path, $bed->x, $bed->y); |
252 | $ob->contr->savebed ($bed->map->path, $bed->x, $bed->y); |
227 | |
253 | |
228 | #TODO? |
|
|
229 | #strcpy (pl->contr->killer, "left"); |
254 | $ob->contr->killer ("left"); |
230 | #check_score (pl); /* Always check score */ |
255 | $ob->check_score; |
231 | |
256 | |
232 | $ob->reply (undef, "In the future, you will wake up here when you die."); |
257 | $ob->reply (undef, "In the future, you will wake up here when you die."); |
233 | $ob->contr->save (); |
258 | $ob->contr->save (1); |
234 | |
259 | |
235 | $ns->query (cf::CS_QUERY_SINGLECHAR, "Do you want to continue playing (y/n)?", sub { |
260 | $ob->contr->ns->query (cf::CS_QUERY_SINGLECHAR, "Do you want to continue playing (y/n)?", sub { |
|
|
261 | $ob->contr->enable_save (1); |
236 | if ($_[0] !~ /^[yY]/) { |
262 | if ($_[0] !~ /^[yY]/) { |
237 | $ob->contr->save (1); |
263 | $ob->contr->save (1); |
238 | $ns->destroy (); |
264 | $ob->contr->ns->destroy; |
239 | } |
265 | } |
240 | }); |
266 | }); |
241 | }, |
267 | }, |
242 | ); |
268 | ); |
243 | |
269 | |
244 | cf::client->attach (package => __PACKAGE__); |
270 | cf::client->attach (package => __PACKAGE__); |