aboutsummaryrefslogtreecommitdiff
path: root/internal/game/session.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-11 04:46:27 -0400
committerhistoria <[not public]>2026-06-11 08:58:37 +0000
commit1b9e2da3b3c438d8dc53d3489725dd5ba0022777 (patch)
tree62264f24420bf4cfaa734942c65cc8dd45ba3d3b /internal/game/session.go
parent06c02a697e5daf8832a462de5970dd4c0e13a02c (diff)
downloadthehouseoficarus-1b9e2da3b3c438d8dc53d3489725dd5ba0022777.tar.gz
feat: web client, get/drop updates and fixes
Diffstat (limited to 'internal/game/session.go')
-rw-r--r--internal/game/session.go505
1 files changed, 0 insertions, 505 deletions
diff --git a/internal/game/session.go b/internal/game/session.go
deleted file mode 100644
index 7fe45e7..0000000
--- a/internal/game/session.go
+++ /dev/null
@@ -1,505 +0,0 @@
-package game
-
-import (
- "fmt"
- "os"
- "strings"
-
- "thirdcollapse/internal/net"
- "thirdcollapse/internal/player"
-)
-
-func (g *Game) handleAccountName(sess *net.Session, input string) {
- name := strings.TrimSpace(input)
- if name == "" {
- sess.Write("Account name: ")
- return
- }
- actualName, err := g.AccountStore.FindAccount(name)
- if err == nil {
- sess.Account = &net.AccountEntry{Name: actualName}
- sess.State = net.StatePassword
- sess.Write("Password: ")
- } else {
- sess.Account = &net.AccountEntry{Name: name}
- sess.State = net.StateNewAccountPass
- sess.Write("A new visitor to this rock!\nChoose password: ")
- }
-}
-
-func (g *Game) handlePassword(sess *net.Session, input string) {
- if input == "" {
- sess.Write("Password: ")
- return
- }
- acc, err := g.AccountStore.LoadAccount(sess.Account.Name)
- if err != nil {
- sess.WriteLine("Error loading account.")
- sess.State = net.StateAccountName
- sess.Write("Account name: ")
- return
- }
- if !player.CheckPassword(input, acc.PasswordHash) {
- sess.WriteLine("Wrong password.")
- sess.State = net.StateAccountName
- sess.Write("Account name: ")
- return
- }
- sess.Account = &net.AccountEntry{
- Name: acc.Name,
- PasswordHash: acc.PasswordHash,
- Characters: acc.Characters,
- Aliases: acc.Aliases,
- }
- if sess.Account.Aliases == nil {
- sess.Account.Aliases = make(map[string]string)
- }
- g.showMenu(sess)
-}
-
-func (g *Game) handleNewAccountPass(sess *net.Session, input string) {
- input = strings.TrimSpace(input)
- if input == "" {
- sess.Account = nil
- sess.State = net.StateAccountName
- sess.Write("Account name: ")
- return
- }
- sess.PendingPass = input
- sess.State = net.StateNewAccountConfirm
- sess.Write("Confirm password: ")
-}
-
-func (g *Game) handleNewAccountConfirm(sess *net.Session, input string) {
- input = strings.TrimSpace(input)
- if input == "" {
- sess.Account = nil
- sess.State = net.StateAccountName
- sess.Write("Account name: ")
- return
- }
- if input != sess.PendingPass {
- sess.WriteLine("Passwords do not match.")
- sess.Account = nil
- sess.State = net.StateAccountName
- sess.Write("Account name: ")
- return
- }
-
- hash, err := player.HashPassword(input)
- if err != nil {
- sess.WriteLine(fmt.Sprintf("Error creating account: %v", err))
- sess.Account = nil
- sess.State = net.StateAccountName
- sess.Write("Account name: ")
- return
- }
-
- acc := &player.Account{
- Name: sess.Account.Name,
- PasswordHash: hash,
- }
- if err := g.AccountStore.SaveAccount(acc); err != nil {
- sess.WriteLine(fmt.Sprintf("Error creating account: %v", err))
- sess.Account = nil
- sess.State = net.StateAccountName
- sess.Write("Account name: ")
- return
- }
-
- sess.Account = &net.AccountEntry{
- Name: acc.Name,
- PasswordHash: acc.PasswordHash,
- Aliases: make(map[string]string),
- }
- sess.PendingPass = ""
- g.showMenu(sess)
-}
-
-func (g *Game) showMenu(sess *net.Session) {
- sess.State = net.StateMenu
- lines := []string{
- "",
- fmt.Sprintf("SUCCESSFUL LOGIN as %s.", sess.Account.Name),
- "",
- }
- if len(sess.Account.Characters) > 0 {
- lines = append(lines,
- " (C)onnect character to TC",
- "",
- " (L)ist characters",
- " (R)ename character",
- " (D)elete character",
- )
- }
- lines = append(lines,
- " (N)ew character",
- " (P)urge account",
- " (A)ccount rename",
- " (Q)uit",
- "",
- "INPUT: ",
- )
- sess.WriteLines(lines...)
-}
-
-func (g *Game) handleMenu(sess *net.Session, input string) {
- switch strings.ToLower(strings.TrimSpace(input)) {
- case "":
- sess.Write("INPUT: ")
- case "c":
- if len(sess.Account.Characters) == 0 {
- sess.WriteLine("\nSYSTEM ERROR: Make a character with 'N' first!")
- sess.Write("\nINPUT: ")
- return
- }
- if len(sess.Account.Characters) == 1 {
- g.connectCharacter(sess, sess.Account.Characters[0])
- return
- }
- sess.WriteLine("\nSelect character:")
- for i, name := range sess.Account.Characters {
- sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, name))
- }
- sess.State = net.StateNewCharName
- sess.PendingChar = "connect"
- sess.Write("\nChoice: ")
-
- case "l":
- if len(sess.Account.Characters) == 0 {
- sess.WriteLine("\nSYSTEM ERROR: Zero characters on this account.\n(Make a character with 'N' first)")
- } else {
- sess.WriteLine("\nSELECT Humans FROM GaiaZeroFour:")
- for _, name := range sess.Account.Characters {
- sess.WriteLine(fmt.Sprintf(" - %s", name))
- }
- }
- sess.Write("\nINPUT: ")
-
- case "n":
- sess.State = net.StateNewCharName
- sess.PendingChar = ""
- sess.Write("What's your character name?: ")
-
- case "a":
- sess.State = net.StateRenameAccount
- sess.Write("New account name: ")
-
- case "r":
- if len(sess.Account.Characters) == 0 {
- sess.WriteLine("\nNo characters to rename.")
- sess.Write("\nChoice: ")
- return
- }
- if len(sess.Account.Characters) == 1 {
- sess.PendingChar = sess.Account.Characters[0]
- sess.State = net.StateRenameCharName
- sess.WriteLine(fmt.Sprintf("\nRenaming %s.", sess.PendingChar))
- sess.Write("New name: ")
- return
- }
- sess.State = net.StateRenameChar
- sess.WriteLine("\nRename which character?")
- for i, name := range sess.Account.Characters {
- sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, name))
- }
- sess.Write("\n> : ")
-
- case "d":
- if len(sess.Account.Characters) == 0 {
- sess.WriteLine("\nNo characters to delete.")
- sess.Write("\nINPUT: ")
- return
- }
- if len(sess.Account.Characters) == 1 {
- sess.PendingChar = sess.Account.Characters[0]
- } else {
- sess.State = net.StateDeleteChar
- sess.WriteLine("\nDelete which character?")
- for i, name := range sess.Account.Characters {
- sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, name))
- }
- sess.Write("\n>: ")
- return
- }
- g.showDeleteConfirm(sess)
-
- case "p":
- sess.State = net.StatePurgeAccount
- sess.WriteLine(fmt.Sprintf("\nPurge account %s and all characters?\nTo be clear you are about to PERMANENTLY DELETE EVERYTHING!\nType PURGE %s to confirm, or anything else to cancel.", sess.Account.Name, sess.Account.Name))
- sess.Write("\n> ")
-
- case "q":
- sess.WriteLine("Later.")
- sess.Conn.Close()
- return
-
- default:
- sess.Write("SYNTAX ERROR\nINPUT: ")
- }
-}
-
-func (g *Game) handleNewCharName(sess *net.Session, input string) {
- name := strings.TrimSpace(input)
-
- if sess.PendingChar == "connect" && len(sess.Account.Characters) > 0 {
- if idx, err := parseIndex(name); err == nil && idx > 0 && idx <= len(sess.Account.Characters) {
- sess.PendingChar = ""
- g.connectCharacter(sess, sess.Account.Characters[idx-1])
- return
- }
- sess.WriteLine("Invalid choice.")
- sess.Write("\nChoice: ")
- return
- }
-
- if name == "" {
- sess.Write("Character name: ")
- return
- }
-
- if g.AccountStore.CharacterExists(name) {
- sess.WriteLine("A character with that name already exists.")
- sess.Write("Character name: ")
- return
- }
-
- p := player.New(name)
- p.RoomID = 1
-
- if err := g.AccountStore.SaveCharacter(p); err != nil {
- sess.WriteLine(fmt.Sprintf("Error creating character: %v", err))
- sess.State = net.StateMenu
- g.showMenu(sess)
- return
- }
-
- acc, _ := g.AccountStore.LoadAccount(sess.Account.Name)
- acc.Characters = append(acc.Characters, name)
- g.AccountStore.SaveAccount(acc)
- sess.Account.Characters = acc.Characters
-
- g.connectCharacter(sess, name)
-}
-
-func (g *Game) connectCharacter(sess *net.Session, name string) {
- g.charsMu.Lock()
- if existing := g.loggedInChars[name]; existing != nil {
- g.charsMu.Unlock()
- sess.WriteLine("This character is logged in elsewhere.")
- sess.State = net.StateMenu
- g.showMenu(sess)
- return
- }
-
- p, err := g.AccountStore.LoadCharacter(name)
- if err != nil {
- g.charsMu.Unlock()
- sess.WriteLine(fmt.Sprintf("Error loading character: %v", err))
- sess.State = net.StateMenu
- g.showMenu(sess)
- return
- }
-
- sess.Player = p
- sess.State = net.StateGame
- g.loggedInChars[name] = sess
- g.charsMu.Unlock()
-
- g.World.SeedGroundItems(p.RoomID)
- g.seedRoomMobs(p.RoomID)
- g.ensureRoomObjects(p.RoomID)
-
- if g.Hub != nil {
- g.Hub.EnterRoom(sess, p.RoomID)
- }
-
- g.doLook(sess)
- sess.Write("\r\n> ")
-}
-
-func (g *Game) handleRenameAccount(sess *net.Session, input string) {
- newName := strings.TrimSpace(input)
- if newName == "" {
- sess.Write("New account name: ")
- return
- }
- oldName := sess.Account.Name
- if newName == oldName {
- sess.WriteLine("That's already your account name.")
- g.showMenu(sess)
- return
- }
- if g.AccountStore.AccountExists(newName) {
- sess.WriteLine("An account with that name already exists.")
- sess.Write("New account name: ")
- return
- }
-
- oldPath := g.AccountStore.AccountPath(oldName)
- newPath := g.AccountStore.AccountPath(newName)
- if err := os.Rename(oldPath, newPath); err != nil {
- sess.WriteLine(fmt.Sprintf("Error renaming account: %v", err))
- g.showMenu(sess)
- return
- }
-
- sess.Account.Name = newName
- sess.WriteLine(fmt.Sprintf("Account renamed to %s.", newName))
- g.showMenu(sess)
-}
-
-func (g *Game) handleRenameChar(sess *net.Session, input string) {
- name := strings.TrimSpace(input)
- if idx, err := parseIndex(name); err == nil && idx > 0 && idx <= len(sess.Account.Characters) {
- sess.PendingChar = sess.Account.Characters[idx-1]
- } else {
- sess.PendingChar = name
- }
-
- found := false
- for _, c := range sess.Account.Characters {
- if c == sess.PendingChar {
- found = true
- break
- }
- }
- if !found {
- sess.WriteLine(fmt.Sprintf("No character named %s on this account.", sess.PendingChar))
- g.showMenu(sess)
- return
- }
-
- sess.State = net.StateRenameCharName
- sess.WriteLine(fmt.Sprintf("Renaming %s.", sess.PendingChar))
- sess.Write("New name: ")
-}
-
-func (g *Game) handleRenameCharName(sess *net.Session, input string) {
- newName := strings.TrimSpace(input)
- oldName := sess.PendingChar
- if newName == "" {
- sess.Write("New name: ")
- return
- }
- if newName == oldName {
- sess.WriteLine("That's already the character's name.")
- g.showMenu(sess)
- return
- }
- if g.AccountStore.CharacterExists(newName) {
- sess.WriteLine("A character with that name already exists.")
- sess.Write("New name: ")
- return
- }
-
- oldPath := g.AccountStore.CharPath(oldName)
- newPath := g.AccountStore.CharPath(newName)
- if err := os.Rename(oldPath, newPath); err != nil {
- sess.WriteLine(fmt.Sprintf("Error renaming: %v", err))
- g.showMenu(sess)
- return
- }
-
- p, _ := g.AccountStore.LoadCharacter(newName)
- if p != nil {
- p.Name = newName
- g.AccountStore.SaveCharacter(p)
- }
-
- acc, _ := g.AccountStore.LoadAccount(sess.Account.Name)
- for i, c := range acc.Characters {
- if c == oldName {
- acc.Characters[i] = newName
- break
- }
- }
- g.AccountStore.SaveAccount(acc)
- sess.Account.Characters = acc.Characters
-
- sess.PendingChar = ""
- sess.WriteLine(fmt.Sprintf("%s renamed to %s.", oldName, newName))
- g.showMenu(sess)
-}
-
-func (g *Game) showDeleteConfirm(sess *net.Session) {
- sess.State = net.StateDeleteChar
- sess.WriteLine(fmt.Sprintf("\nDelete %s? Type DELETE %s to confirm, or anything else to cancel.", sess.PendingChar, sess.PendingChar))
-}
-
-func (g *Game) handleDeleteChar(sess *net.Session, input string) {
- if sess.PendingChar == "" {
- name := strings.TrimSpace(input)
- if idx, err := parseIndex(name); err == nil && idx > 0 && idx <= len(sess.Account.Characters) {
- sess.PendingChar = sess.Account.Characters[idx-1]
- } else {
- sess.PendingChar = name
- }
- found := false
- for _, c := range sess.Account.Characters {
- if c == sess.PendingChar {
- found = true
- break
- }
- }
- if !found {
- sess.WriteLine(fmt.Sprintf("No character named %s on this account.", sess.PendingChar))
- sess.PendingChar = ""
- g.showMenu(sess)
- return
- }
- g.showDeleteConfirm(sess)
- return
- }
-
- input = strings.TrimSpace(input)
- expected := "DELETE " + sess.PendingChar
- if strings.ToUpper(input) != strings.ToUpper(expected) {
- sess.WriteLine("Delete cancelled.")
- sess.PendingChar = ""
- g.showMenu(sess)
- return
- }
-
- charPath := g.AccountStore.CharPath(sess.PendingChar)
- if err := os.Remove(charPath); err != nil {
- sess.WriteLine(fmt.Sprintf("Error deleting: %v", err))
- sess.PendingChar = ""
- g.showMenu(sess)
- return
- }
-
- acc, _ := g.AccountStore.LoadAccount(sess.Account.Name)
- var newChars []string
- for _, c := range acc.Characters {
- if c != sess.PendingChar {
- newChars = append(newChars, c)
- }
- }
- acc.Characters = newChars
- g.AccountStore.SaveAccount(acc)
- sess.Account.Characters = newChars
-
- sess.WriteLine(fmt.Sprintf("%s has been deleted.", sess.PendingChar))
- sess.PendingChar = ""
- g.showMenu(sess)
-}
-
-func (g *Game) handlePurgeAccount(sess *net.Session, input string) {
- input = strings.TrimSpace(input)
- expected := "PURGE " + sess.Account.Name
- if strings.ToUpper(input) != strings.ToUpper(expected) {
- sess.WriteLine("Purge cancelled.")
- g.showMenu(sess)
- return
- }
-
- for _, name := range sess.Account.Characters {
- os.Remove(g.AccountStore.CharPath(name))
- }
-
- os.Remove(g.AccountStore.AccountPath(sess.Account.Name))
-
- sess.WriteLine(fmt.Sprintf("Account %s has been purged. Thanks for playing.", sess.Account.Name))
- sess.Conn.Close()
-}