2025-06-28 11:24:06 +03:00
package command
import (
"code.haedhutner.dev/mvv/LastMUD/internal/game/logic/world"
2025-06-30 08:40:15 +03:00
"code.haedhutner.dev/mvv/LastMUD/internal/logging"
2025-06-29 18:21:22 +03:00
"regexp"
2025-06-28 11:24:06 +03:00
"time"
"code.haedhutner.dev/mvv/LastMUD/internal/ecs"
"code.haedhutner.dev/mvv/LastMUD/internal/game/data"
2025-06-30 08:40:15 +03:00
"golang.org/x/crypto/bcrypt"
2025-06-28 11:24:06 +03:00
)
func HandleSay ( w * ecs . World , _ time . Duration , player ecs . Entity , args data . ArgsMap ) ( err error ) {
playerRoom , ok := ecs . GetComponent [ data . InRoomComponent ] ( w , player )
if ! ok {
2025-06-29 18:21:22 +03:00
return createCommandError ( "You aren't in a room!" )
2025-06-28 11:24:06 +03:00
}
playerName , ok := ecs . GetComponent [ data . NameComponent ] ( w , player )
if ! ok {
2025-06-29 18:21:22 +03:00
return createCommandError ( "You have no name!" )
2025-06-28 11:24:06 +03:00
}
allPlayersInRoom := ecs . QueryEntitiesWithComponent ( w , func ( comp data . InRoomComponent ) bool {
return comp . Room == playerRoom . Room
} )
2025-06-28 21:45:52 +03:00
message , err := arg [ string ] ( args , data . ArgMessageContent )
2025-06-28 11:24:06 +03:00
2025-06-28 21:45:52 +03:00
if err != nil {
return err
2025-06-28 11:24:06 +03:00
}
if message == "" {
return nil
}
for p := range allPlayersInRoom {
2025-06-29 18:21:22 +03:00
world . SendMessageToPlayer ( w , p , playerName . Name + ": " + message )
2025-06-28 11:24:06 +03:00
}
return
}
func HandleQuit ( w * ecs . World , _ time . Duration , player ecs . Entity , _ data . ArgsMap ) ( err error ) {
connId , _ := ecs . GetComponent [ data . ConnectionIdComponent ] ( w , player )
world . CreateClosingGameOutput ( w , connId . ConnectionId , [ ] byte ( "Goodbye!" ) )
return
}
2025-06-30 08:40:15 +03:00
var usernameRegex = regexp . MustCompile ( ` ^[a-zA-Z0-9_-] { 1,16}$ ` )
var passwordRegex = regexp . MustCompile ( ` ^[a-zA-Z0-9!@#$%^&*()_+\-=\[\] { }|;:',.<>/?] { 6,12}$ ` )
2025-06-29 18:21:22 +03:00
func HandleRegister ( w * ecs . World , delta time . Duration , player ecs . Entity , args data . ArgsMap ) ( err error ) {
2025-06-28 21:45:52 +03:00
accountName , err := arg [ string ] ( args , data . ArgAccountName )
if err != nil {
return err
}
2025-06-29 18:21:22 +03:00
if ! usernameRegex . MatchString ( accountName ) {
2025-06-30 08:40:15 +03:00
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 )
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
2025-06-28 21:45:52 +03:00
}
2025-06-30 08:40:15 +03:00
// 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
}
2025-06-29 18:21:22 +03:00
2025-06-30 08:40:15 +03:00
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 } )
2025-06-28 21:45:52 +03:00
2025-06-28 11:24:06 +03:00
return
}