Add registration
This commit is contained in:
parent
54121fc8ff
commit
1d10d963cd
10 changed files with 61 additions and 15 deletions
1
go.mod
1
go.mod
|
@ -9,5 +9,6 @@ require (
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/stretchr/objx v0.5.2 // indirect
|
github.com/stretchr/objx v0.5.2 // indirect
|
||||||
github.com/stretchr/testify v1.10.0 // indirect
|
github.com/stretchr/testify v1.10.0 // indirect
|
||||||
|
golang.org/x/crypto v0.39.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -10,6 +10,8 @@ github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||||
|
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||||
|
|
|
@ -11,7 +11,7 @@ func (ac AccountComponent) Type() ecs.ComponentType {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PasswordComponent struct {
|
type PasswordComponent struct {
|
||||||
EncryptedPassword string
|
EncryptedPassword []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pc PasswordComponent) Type() ecs.ComponentType {
|
func (pc PasswordComponent) Type() ecs.ComponentType {
|
||||||
|
|
|
@ -65,8 +65,8 @@ type ArgName = string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ArgMessageContent ArgName = "messageContent"
|
ArgMessageContent ArgName = "messageContent"
|
||||||
ArgAccountName = "accountName"
|
ArgAccountName ArgName = "accountName"
|
||||||
ArgAccountPassword = "accountPassword"
|
ArgAccountPassword ArgName = "accountPassword"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Arg struct {
|
type Arg struct {
|
||||||
|
@ -88,8 +88,6 @@ type Command string
|
||||||
const (
|
const (
|
||||||
CommandSay Command = "say"
|
CommandSay Command = "say"
|
||||||
CommandQuit = "quit"
|
CommandQuit = "quit"
|
||||||
CommandHelp = "help"
|
|
||||||
CommandSetName = "setname"
|
|
||||||
CommandLogin = "login"
|
CommandLogin = "login"
|
||||||
CommandRegister = "register"
|
CommandRegister = "register"
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,11 +2,14 @@ package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"code.haedhutner.dev/mvv/LastMUD/internal/game/logic/world"
|
"code.haedhutner.dev/mvv/LastMUD/internal/game/logic/world"
|
||||||
|
"code.haedhutner.dev/mvv/LastMUD/internal/logging"
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.haedhutner.dev/mvv/LastMUD/internal/ecs"
|
"code.haedhutner.dev/mvv/LastMUD/internal/ecs"
|
||||||
"code.haedhutner.dev/mvv/LastMUD/internal/game/data"
|
"code.haedhutner.dev/mvv/LastMUD/internal/game/data"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleSay(w *ecs.World, _ time.Duration, player ecs.Entity, args data.ArgsMap) (err error) {
|
func HandleSay(w *ecs.World, _ time.Duration, player ecs.Entity, args data.ArgsMap) (err error) {
|
||||||
|
@ -51,7 +54,8 @@ func HandleQuit(w *ecs.World, _ time.Duration, player ecs.Entity, _ data.ArgsMap
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var usernameRegex = regexp.MustCompile(`^[a-zA-Z0-9_-]{1,24}$`)
|
var usernameRegex = regexp.MustCompile(`^[a-zA-Z0-9_-]{1,16}$`)
|
||||||
|
var passwordRegex = regexp.MustCompile(`^[a-zA-Z0-9!@#$%^&*()_+\-=\[\]{}|;:',.<>/?]{6,12}$`)
|
||||||
|
|
||||||
func HandleRegister(w *ecs.World, delta time.Duration, player ecs.Entity, args data.ArgsMap) (err error) {
|
func HandleRegister(w *ecs.World, delta time.Duration, player ecs.Entity, args data.ArgsMap) (err error) {
|
||||||
accountName, err := arg[string](args, data.ArgAccountName)
|
accountName, err := arg[string](args, data.ArgAccountName)
|
||||||
|
@ -61,16 +65,42 @@ func HandleRegister(w *ecs.World, delta time.Duration, player ecs.Entity, args d
|
||||||
}
|
}
|
||||||
|
|
||||||
if !usernameRegex.MatchString(accountName) {
|
if !usernameRegex.MatchString(accountName) {
|
||||||
world.SendMessageToPlayer(w, player, "Registration: Username must only contain letters, numbers, dashes (-) and underscores (_), and be at most 24 characters in length.")
|
world.SendMessageToPlayer(w, player, "Registration: Username must only contain letters, numbers, dashes (-) and underscores (_), and be at most 16 characters in length.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//accountPassword, err := arg[string](args, data.ArgAccountPassword)
|
accountPassword, err := arg[string](args, data.ArgAccountPassword)
|
||||||
//
|
|
||||||
//if err != nil {
|
|
||||||
// return err
|
|
||||||
//}
|
|
||||||
|
|
||||||
// TODO: validate username and password, encrypt password, etc.
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !passwordRegex.MatchString(accountPassword) {
|
||||||
|
world.SendMessageToPlayer(w, player, "Registration: Password must be between 6 and 12 characters in length")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Validate username doesn't exist already
|
||||||
|
|
||||||
|
encryptedPassword, err := bcrypt.GenerateFromPassword([]byte(accountPassword), bcrypt.DefaultCost)
|
||||||
|
|
||||||
|
account := world.CreateAccount(w, accountName, encryptedPassword)
|
||||||
|
|
||||||
|
ecs.SetComponent(w, player, data.AccountComponent{Account: account})
|
||||||
|
|
||||||
|
world.SendMessageToPlayer(w, player, "Account created successfully! Welcome to LastMUD!")
|
||||||
|
|
||||||
|
defaultRoom, err := ecs.GetResource[ecs.Entity](w, data.ResourceDefaultRoom)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
logging.Error("Unable to locate default room")
|
||||||
|
world.SendMessageToPlayer(w, player, "Welcome to LastMUD! Your account was created, but you could not be joined to a room. Please try again later!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ecs.SetComponent(w, player, data.NameComponent{Name: accountName})
|
||||||
|
ecs.SetComponent(w, player, data.InRoomComponent{Room: defaultRoom})
|
||||||
|
ecs.SetComponent(w, player, data.PlayerStateComponent{State: data.PlayerStatePlaying})
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,6 @@ func CreateSystems() []*ecs.System {
|
||||||
// Command Handlers
|
// Command Handlers
|
||||||
ecs.CreateSystem("SayCommandHandler", CommandOffset+0, command.CreateHandler(data.CommandSay, command.HandleSay)),
|
ecs.CreateSystem("SayCommandHandler", CommandOffset+0, command.CreateHandler(data.CommandSay, command.HandleSay)),
|
||||||
ecs.CreateSystem("QuitCommandHandler", CommandOffset+10, command.CreateHandler(data.CommandQuit, command.HandleQuit)),
|
ecs.CreateSystem("QuitCommandHandler", CommandOffset+10, command.CreateHandler(data.CommandQuit, command.HandleQuit)),
|
||||||
// ecs.CreateSystem("RegisterCommandHandler", CommandOffset+20, command.CreateHandler(data.CommandRegister, command.HandleRegister)),
|
ecs.CreateSystem("RegisterCommandHandler", CommandOffset+60, command.CreateHandler(data.CommandRegister, command.HandleRegister)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"code.haedhutner.dev/mvv/LastMUD/internal/game/data"
|
"code.haedhutner.dev/mvv/LastMUD/internal/game/data"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateAccount(world *ecs.World, username, encryptedPassword string) ecs.Entity {
|
func CreateAccount(world *ecs.World, username string, encryptedPassword []byte) ecs.Entity {
|
||||||
account := ecs.NewEntity()
|
account := ecs.NewEntity()
|
||||||
|
|
||||||
ecs.SetComponent(world, account, data.NameComponent{Name: username})
|
ecs.SetComponent(world, account, data.NameComponent{Name: username})
|
||||||
|
|
|
@ -27,3 +27,13 @@ func SendMessageToPlayer(world *ecs.World, player ecs.Entity, message string) {
|
||||||
|
|
||||||
CreateGameOutput(world, connId.ConnectionId, message)
|
CreateGameOutput(world, connId.ConnectionId, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SendDisconnectMessageToPlayer(world *ecs.World, player ecs.Entity, message string) {
|
||||||
|
connId, ok := ecs.GetComponent[data.ConnectionIdComponent](world, player)
|
||||||
|
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateClosingGameOutput(world, connId.ConnectionId, []byte(message))
|
||||||
|
}
|
||||||
|
|
|
@ -19,3 +19,7 @@ func CreateRoom(
|
||||||
|
|
||||||
return entity
|
return entity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MovePlayerToRoom(world *ecs.World, player, room ecs.Entity) {
|
||||||
|
ecs.SetComponent(world, player, data.InRoomComponent{Room: room})
|
||||||
|
}
|
||||||
|
|
|
@ -119,6 +119,7 @@ func (srv *Server) consumeGameOutput() {
|
||||||
output := srv.lastmudgame.ConsumeNextOutput()
|
output := srv.lastmudgame.ConsumeNextOutput()
|
||||||
|
|
||||||
if output == nil {
|
if output == nil {
|
||||||
|
time.Sleep(20 * time.Millisecond)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue