From 6a0f3d7a252de4b1741cfe5e1c561412c602becc Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Tue, 9 Jun 2026 20:32:44 -0400 Subject: feat: better login screen --- README.md | 17 +++++++++++-- data/help/combat.yaml | 1 - data/players/accounts/di.yaml | 3 +++ data/players/accounts/ji.yaml | 3 +++ data/players/accounts/newguy.yaml | 3 +++ internal/game/game.go | 53 +++++++++++++++++++++------------------ internal/net/server.go | 23 +++++++++++++++-- internal/player/player.go | 4 ++- 8 files changed, 76 insertions(+), 31 deletions(-) create mode 100644 data/players/accounts/di.yaml create mode 100644 data/players/accounts/ji.yaml create mode 100644 data/players/accounts/newguy.yaml diff --git a/README.md b/README.md index 9dc51e2..109d435 100644 --- a/README.md +++ b/README.md @@ -10,12 +10,25 @@ - 600ms game ticks - Semi-AFK and active gameplay styles. - Classless. All attributes are skills that level 1-99 as you use them. -- Planned skills include Attack, Strength, Defense, Hitpoints, Ranged, Science, Technology, Fishing, Woodcutting, Mining, Hunter, Thieving, Scavenging, Cooking, Smithing, Crafting, Fletching, Alchemy, Construction, Agility. +- Planned skills include Attack, Strength, Defense, Hitpoints, Ranged, Science, Technology, Fishing, Woodcutting, Mining, Hunter, Thieving, Scavenging, Cooking, Smithing, Crafting, Fletching, Alchemy, Construction, Agility, Slayer. - A detailed casino for you to waste all the credits you grind up for. +# Building + +Install make and Go then + +``` +git clone https://codeberg.org/historia/thirdcollapse +cd thirdcollapse +make +./tc [port] +``` + +Then just telnet to the port. If no port is specified, the server will run on port 4000. + # Setting -TC is a low-tech sci-fi MUD. Computer systems are severely regulated following Earth's takeover of a benevolent dictator AI. Corrupt politicians were jailed. Harmful industries shuttered. Wealth and power were redistributed as the AI began to build Utopia. +TC is a low-tech sci-fi MUD. Computer systems are severely regulated following an attempted hostile takeover of Earth by a benevolent dictator AI. Corrupt politicians were jailed. Harmful industries shuttered. Wealth and power were redistributed as the AI began to build Utopia. The panicked ruling classes pooled their resources into an astroturfed revolution of Neoluddites who embrace techno-terrorism in the name of supposed freedom. It worked. Radio towers and data centers burn in a global wave of misplaced violence. The infrastructure of the internet is destroyed. Wireless networks are banned. A new, intentional Dark Age descends called the Second Collapse. Demagogues vow to never again let technology rule over mankind. diff --git a/data/help/combat.yaml b/data/help/combat.yaml index e2ccef6..6336fae 100644 --- a/data/help/combat.yaml +++ b/data/help/combat.yaml @@ -3,7 +3,6 @@ category: "Combat" description: | Combat basics. - Combat in Third Collapse follows Runescape Classic mechanics: - 600ms tick engine with per-weapon attack speeds - Attack, Strength, and Defense rolls determine hit/miss - Combat triangle: Melee > Ranged > Technology > Melee diff --git a/data/players/accounts/di.yaml b/data/players/accounts/di.yaml new file mode 100644 index 0000000..6f292bb --- /dev/null +++ b/data/players/accounts/di.yaml @@ -0,0 +1,3 @@ +name: di +password_hash: sha256:Pr1aiCjarQOsS8pdZwwAjg:c979628ddc5404361454eacdfd509c5bbd5f04cae60ff3a762335e44e4ecfe06 +characters: [] diff --git a/data/players/accounts/ji.yaml b/data/players/accounts/ji.yaml new file mode 100644 index 0000000..130c2c7 --- /dev/null +++ b/data/players/accounts/ji.yaml @@ -0,0 +1,3 @@ +name: ji +password_hash: sha256:GfCf3fMYkg89cJmJEF9lgg:33ef437cd7b9f2a64a55fa7819b21d2cf12cd19482ae4154fc330bd73f71ad48 +characters: [] diff --git a/data/players/accounts/newguy.yaml b/data/players/accounts/newguy.yaml new file mode 100644 index 0000000..b308084 --- /dev/null +++ b/data/players/accounts/newguy.yaml @@ -0,0 +1,3 @@ +name: newguy +password_hash: sha256:mPCmmVFAHRdjyZOj0+tQdQ:8c481b6748e8165388836b67c81e5be9f6f28cb5310654b776002483ae05cff3 +characters: [] diff --git a/internal/game/game.go b/internal/game/game.go index 0e1b82d..528c895 100644 --- a/internal/game/game.go +++ b/internal/game/game.go @@ -98,7 +98,7 @@ func (g *Game) handleAccountName(sess *net.Session, input string) { } else { sess.Account = &net.AccountEntry{Name: name} sess.State = net.StateNewAccountPass - sess.Write("Account not found. Enter a password to create it (or press enter to cancel): ") + sess.Write("A new visitor to this rock!\nChoose password: ") } } @@ -379,7 +379,7 @@ func (g *Game) handlePurgeAccount(sess *net.Session, input string) { // Delete account file os.Remove(g.AccountStore.AccountPath(sess.Account.Name)) - sess.WriteLine(fmt.Sprintf("Account %s has been purged.", sess.Account.Name)) + sess.WriteLine(fmt.Sprintf("Account %s has been purged. Thanks for playing.", sess.Account.Name)) sess.Conn.Close() } @@ -387,22 +387,25 @@ func (g *Game) showMenu(sess *net.Session) { sess.State = net.StateMenu lines := []string{ "", - fmt.Sprintf("Welcome, %s!", sess.Account.Name), + fmt.Sprintf("SUCCESSFUL LOGIN as %s.", sess.Account.Name), "", - "(C)onnect to character", } if len(sess.Account.Characters) > 0 { - lines = append(lines, "(L)ist characters") + lines = append(lines, + " (C)onnect character to TC", + "", + " (L)ist characters", + " (R)ename character", + " (D)elete character", + ) } lines = append(lines, - "(N)ew character", - "(R)ename character", - "(D)elete character", - "(P)urge account", - "(A)ccount rename", - "(Q)uit", + " (N)ew character", + " (P)urge account", + " (A)ccount rename", + " (Q)uit", "", - "Choice: ", + "INPUT: ", ) sess.WriteLines(lines...) } @@ -410,11 +413,11 @@ func (g *Game) showMenu(sess *net.Session) { func (g *Game) handleMenu(sess *net.Session, input string) { switch strings.ToLower(strings.TrimSpace(input)) { case "": - sess.Write("Choice: ") + sess.Write("INPUT: ") case "c": if len(sess.Account.Characters) == 0 { - sess.WriteLine("\nNo characters on this account.") - sess.Write("\nChoice: ") + sess.WriteLine("\nSYSTEM ERROR: Make a character with 'N' first!") + sess.Write("\nINPUT: ") return } if len(sess.Account.Characters) == 1 { @@ -431,19 +434,19 @@ func (g *Game) handleMenu(sess *net.Session, input string) { case "l": if len(sess.Account.Characters) == 0 { - sess.WriteLine("\nNo characters on this account.") + sess.WriteLine("\nSYSTEM ERROR: Zero characters on this account.\n(Make a character with 'N' first)") } else { - sess.WriteLine("\nCharacters:") + sess.WriteLine("\nSELECT Humans FROM GaiaZeroFour:") for _, name := range sess.Account.Characters { sess.WriteLine(fmt.Sprintf(" - %s", name)) } } - sess.Write("\nChoice: ") + sess.Write("\nINPUT: ") case "n": sess.State = net.StateNewCharName sess.PendingChar = "" - sess.Write("Character name: ") + sess.Write("What's your character name?: ") case "a": sess.State = net.StateRenameAccount @@ -467,12 +470,12 @@ func (g *Game) handleMenu(sess *net.Session, input string) { for i, name := range sess.Account.Characters { sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, name)) } - sess.Write("\nChoice: ") + sess.Write("\n> : ") case "d": if len(sess.Account.Characters) == 0 { sess.WriteLine("\nNo characters to delete.") - sess.Write("\nChoice: ") + sess.Write("\nINPUT: ") return } if len(sess.Account.Characters) == 1 { @@ -483,23 +486,23 @@ func (g *Game) handleMenu(sess *net.Session, input string) { for i, name := range sess.Account.Characters { sess.WriteLine(fmt.Sprintf(" %d) %s", i+1, name)) } - sess.Write("\nChoice: ") + sess.Write("\n>: ") return } g.showDeleteConfirm(sess) case "p": sess.State = net.StatePurgeAccount - sess.WriteLine(fmt.Sprintf("\nPurge account %s and all characters? Type PURGE %s to confirm, or anything else to cancel.", sess.Account.Name, sess.Account.Name)) + 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("Goodbye.") + sess.WriteLine("Later.") sess.Conn.Close() return default: - sess.Write("Invalid choice. Choice: ") + sess.Write("SYNTAX ERROR\nINPUT: ") } } diff --git a/internal/net/server.go b/internal/net/server.go index fa0b509..e5761a2 100644 --- a/internal/net/server.go +++ b/internal/net/server.go @@ -160,8 +160,27 @@ func (s *Server) handleSession(session *Session, handler func(*Session, string)) }() _, _ = session.Conn.Write([]byte("\033[2J\033[H")) // clear screen - session.Write("Welcome to Third Collapse!\r\n") - session.Write("Account name: ") + + welcomeart := ` + , 3333333 333 333 333 3333333 3333333 + | 33! 33! 333 33! 33! 333 33! 333 ':. + + -+- * 3!! 3!3!3!3! !!3 3!3!!3! 3!3 !3! '::._ * + | !!: !!: !!! !!: !!: :!! !!: !!! '._) + : : : : : : : : :: : : , + . * , + , welcome to third collapse . * + + 3333333 333333 333 , 333 333333 3333333 333333 33333333 + !33 33! 333 33! 33! 33! 333 33! 333 !33 33! + !3! 3!3 !3! 3!! 3!! + 3!3!3!3! 3!33!3! !33!! 3!!!:! + :!! !!: !!! !!: !!: !!: !!! !!: !:! !!: + :: :: : : :. : : ::.: : : ::.: : : : : : ::.: : : :: ::: + + +` + + session.Write(welcomeart) + session.Write("ACCOUNT NAME> ") for { line, err := session.Reader.ReadString('\n') diff --git a/internal/player/player.go b/internal/player/player.go index 581fc04..ad56923 100644 --- a/internal/player/player.go +++ b/internal/player/player.go @@ -25,12 +25,13 @@ const ( Construction SkillName = "construction" Scavenging SkillName = "scavenging" Hunter SkillName = "hunter" + Slayer SkillName = "slayer" ) var AllSkills = []SkillName{ Attack, Strength, Defense, Hitpoints, Ranged, Science, Technology, Fishing, Cooking, Woodcutting, Mining, Smithing, Crafting, Fletching, - Alchemy, Thieving, Agility, Construction, Scavenging, Hunter, + Alchemy, Thieving, Agility, Construction, Scavenging, Hunter, Slayer, } var SkillAbbr = map[SkillName]string{ @@ -54,6 +55,7 @@ var SkillAbbr = map[SkillName]string{ Construction: "con", Scavenging: "scv", Hunter: "hnt", + Slayer: "sly", } type AttackStyle string -- cgit v1.2.3