package game import ( "fmt" "strings" "unicode/utf8" "thehouseoficarus/internal/color" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" ) func (g *Game) executeSymbol(sess *net.Session, args []string, rawInput string) { p := sess.Player if len(args) == 0 { data, ok := p.MapSymbols[p.RoomID] if !ok { sess.WriteLine("No custom symbol set for this room.") return } msg := fmt.Sprintf("Custom symbol: %s", data.Char) if data.Color != "" { spec := color.Parse(data.Color) colored := color.Render(g.colorMode(sess), spec, data.Char) msg = fmt.Sprintf("Custom symbol: %s (%s)", colored, data.Color) } sess.WriteLine(msg) return } // extract symbol char from rawInput to preserve case, since // handleGameCommand lowercases args before dispatch (same pattern as say). char := args[0] if idx := strings.Index(strings.ToLower(rawInput), "symbol"); idx >= 0 { rest := strings.TrimSpace(rawInput[idx+6:]) if space := strings.Index(rest, " "); space >= 0 { char = rest[:space] } else { char = rest } } cleared := false if strings.EqualFold(char, "reset") || strings.EqualFold(char, "remove") { delete(p.MapSymbols, p.RoomID) if err := g.AccountStore.SaveCharacter(p); err != nil { sess.WriteLine("Error saving: " + err.Error()) return } sess.WriteLine("Custom symbol reset for this room.") cleared = true } if !cleared { r, size := utf8.DecodeRuneInString(char) if size == 0 || size != len(char) || r == utf8.RuneError { // color-only mode — args are a color spec, keep existing char colorSpec := strings.Join(args, " ") spec := color.Parse(colorSpec) if spec.Empty() { sess.WriteLine("Invalid color spec. Use a hex color code like FF and/or bold/dim/underline.") return } existing, ok := p.MapSymbols[p.RoomID] if !ok { existing = player.MapSymbolData{Char: "■"} } existing.Color = colorSpec p.MapSymbols[p.RoomID] = existing if err := g.AccountStore.SaveCharacter(p); err != nil { sess.WriteLine("Error saving: " + err.Error()) return } colored := color.Render(g.colorMode(sess), spec, existing.Char) sess.WriteLine(fmt.Sprintf("Map symbol color set to: %s (%s)", colored, colorSpec)) return } colorSpec := "" if len(args) > 1 { colorSpec = strings.Join(args[1:], " ") if colorSpec != "" { spec := color.Parse(colorSpec) if spec.Empty() { sess.WriteLine("Invalid color spec. Use a hex color code like FF and/or bold/dim/underline.") return } } } p.MapSymbols[p.RoomID] = player.MapSymbolData{ Char: char, Color: colorSpec, } if err := g.AccountStore.SaveCharacter(p); err != nil { sess.WriteLine("Error saving: " + err.Error()) return } msg := fmt.Sprintf("Map symbol set to: %s", char) if colorSpec != "" { spec := color.Parse(colorSpec) colored := color.Render(g.colorMode(sess), spec, char) msg = fmt.Sprintf("Map symbol set to: %s", colored) } sess.WriteLine(msg) } }