rearrage_stuff
This commit is contained in:
79
scenes/playerCreation/createUasswprdPrompt.js
Normal file
79
scenes/playerCreation/createUasswprdPrompt.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import { Prompt } from "../prompt.js";
|
||||
import * as security from "../../utils/security.js";
|
||||
import { Config } from "../../config.js";
|
||||
|
||||
export class CreatePasswordPrompt extends Prompt {
|
||||
//
|
||||
promptText = ["Enter a password"];
|
||||
|
||||
//
|
||||
// Let the client know that we're asking for a password
|
||||
// so it can set <input type="password">
|
||||
promptOptions = { password: true };
|
||||
|
||||
get player() {
|
||||
return this.scene.player;
|
||||
}
|
||||
|
||||
onReply(text) {
|
||||
//
|
||||
// Check of the password is sane. This is both bad from a security point
|
||||
// of view, and technically not necessary as insane passwords couldn't
|
||||
// reside in the player lists. However, let's save some CPU cycles on
|
||||
// not hashing an insane password 1000+ times.
|
||||
// This is technically bad practice, but since this is just a game,
|
||||
// do it anyway.
|
||||
if (!security.isPasswordSane(text)) {
|
||||
this.sendError("Insane password");
|
||||
this.execute();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Block users who enter bad passwords too many times.
|
||||
if (this.player.failedPasswordsSinceLastLogin > Config.maxFailedLogins) {
|
||||
this.blockedUntil = Date.now() + Config.accountLockoutSeconds;
|
||||
this.calamity("You have been locked out for too many failed password attempts, come back later");
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle blocked users.
|
||||
// They don't even get to have their password verified.
|
||||
if (this.player.blockedUntil > Date.now()) {
|
||||
//
|
||||
// Try to re-login too soon, and your lockout lasts longer.
|
||||
this.blockedUntil += Config.accountLockoutSeconds;
|
||||
this.calamity("You have been locked out for too many failed password attempts, come back later");
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Verify the password against the hash we've stored.
|
||||
if (!security.verifyPassword(text, this.player.passwordHash)) {
|
||||
this.sendError("Incorrect password!");
|
||||
this.player.failedPasswordsSinceLastLogin++;
|
||||
|
||||
this.session.sendDebug(`Failed login attempt #${this.player.failedPasswordsSinceLastLogin}`);
|
||||
this.execute();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.player.lastSucessfulLoginAt = new Date();
|
||||
this.player.failedPasswordsSinceLastLogin = 0;
|
||||
|
||||
//
|
||||
// We do not allow a player to be logged in more than once!
|
||||
if (this.player.loggedIn) {
|
||||
this.calamity("This player is already logged in");
|
||||
return;
|
||||
}
|
||||
|
||||
this.scene.passwordAccepted();
|
||||
|
||||
//
|
||||
// Password was correct, go to main game
|
||||
this.session.setState(new JustLoggedInState(this.session));
|
||||
}
|
||||
}
|
||||
62
scenes/playerCreation/createUsernamePrompt.js
Executable file
62
scenes/playerCreation/createUsernamePrompt.js
Executable file
@@ -0,0 +1,62 @@
|
||||
import { Prompt } from "../prompt.js";
|
||||
import * as security from "../../utils/security.js";
|
||||
import { gGame } from "../../models/globals.js";
|
||||
import { PlayerCreationScene } from "./playerCreationSene.js";
|
||||
import { Config } from "../../config.js";
|
||||
|
||||
export class CreateUsernamePrompt extends Prompt {
|
||||
//
|
||||
promptText = [
|
||||
"Enter your username", //
|
||||
"((type *:help* for more info))", //
|
||||
];
|
||||
|
||||
//
|
||||
// When player types :help
|
||||
helpText = [
|
||||
"Your username.",
|
||||
"It's used, along with your password, when you log in.",
|
||||
"Other players can see it.",
|
||||
"Other players can use it to chat or trade with you",
|
||||
"It may only consist of the letters _a-z_, _A-Z_, _0-9_, and _underscore_",
|
||||
];
|
||||
|
||||
//
|
||||
// Let the client know that we're asking for a username
|
||||
promptOptions = { username: true };
|
||||
|
||||
/**
|
||||
* @returns {PlayerCreationScene}
|
||||
*/
|
||||
get scene() {
|
||||
return this._scene;
|
||||
}
|
||||
|
||||
onReply(username) {
|
||||
//
|
||||
// do basic syntax checks on usernames
|
||||
if (!security.isUsernameSane(username)) {
|
||||
console.info("Someone entered insane username: '%s'", username);
|
||||
this.sendError("Incorrect username, try again.");
|
||||
this.execute();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// try and fetch the player object from the game
|
||||
const player = gGame.getPlayer(username);
|
||||
|
||||
//
|
||||
// handle invalid username
|
||||
if (player) {
|
||||
console.info("Someone tried to create a user with an occupied username: '%s'", username);
|
||||
this.sendError("Occupied, try something else");
|
||||
this.execute();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Tell daddy that we're done
|
||||
this.scene.usernameAccepted(username);
|
||||
}
|
||||
}
|
||||
52
scenes/playerCreation/playerCreationSene.js
Executable file
52
scenes/playerCreation/playerCreationSene.js
Executable file
@@ -0,0 +1,52 @@
|
||||
import { Config } from "../../config.js";
|
||||
import { gGame } from "../../models/globals.js";
|
||||
import { Scene } from "../scene.js";
|
||||
import { CreateUsernamePrompt } from "./createUsernamePrompt.js";
|
||||
|
||||
export class PlayerCreationScene extends Scene {
|
||||
introText = "= Create Player";
|
||||
|
||||
/** @protected @type {Player} */
|
||||
player;
|
||||
|
||||
/** @protected @type {string} */
|
||||
password;
|
||||
|
||||
onReady() {
|
||||
//
|
||||
// If there are too many players, stop allowing new players in.
|
||||
if (gGame._players.size >= Config.maxPlayers) {
|
||||
this.session.calamity("Server is full, no more players can be created");
|
||||
}
|
||||
|
||||
this.showPrompt(new CreateUsernamePrompt(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the player has entered a valid and available username.
|
||||
*
|
||||
* @param {string} username
|
||||
*/
|
||||
usernameAccepted(username) {
|
||||
const player = gGame.createPlayer(username);
|
||||
this.player = player;
|
||||
|
||||
this.session.sendSystemMessage("salt", player.salt);
|
||||
this.session.sendText(`Username _*${username}*_ is available, and I've reserved it for you :)`);
|
||||
|
||||
//
|
||||
this.session.sendError("TODO: create a createPasswordPrompt and display it.");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Called when the player has entered a password and confirmed it.
|
||||
*
|
||||
* @param {string} password
|
||||
*/
|
||||
passwordAccepted(password) {
|
||||
this.password = password;
|
||||
this.session.sendText("*_Success_* ✅ You will now be asked to log in again, sorry for that ;)");
|
||||
this.player.setPasswordHash(security.generateHash(this.password));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user