aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_option.go
blob: 9302baa1b86c4ea112ea60182aa84e907a856649 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package game

import (
	"fmt"
	"strconv"
	"strings"

	"thirdcollapse/internal/net"
	"thirdcollapse/internal/player"
)

func (g *Game) doOption(sess *net.Session, input string) {
	p := sess.Player.(*player.Player)

	if input == "" {
		sess.WriteLine("")
		table := &Table{
			Columns: []string{"Option", "Value", "Valid", "Description"},
		}
		for _, def := range player.OptionDefs {
			val := formatOptionValue(p, &def)
			valid := formatValidValues(&def)
			table.Rows = append(table.Rows, []string{def.Name, val, valid, def.Description})
		}
		for _, line := range table.Render(p.OptionBool("unicode")) {
			sess.WriteLine(line)
		}
		return
	}

	parts := strings.Fields(input)
	name := strings.ToLower(parts[0])
	def := player.GetOptionDef(name)
	if def == nil {
		sess.WriteLine(fmt.Sprintf("\nUnknown option: %s", name))
		return
	}

	if len(parts) == 1 {
		val := formatOptionValue(p, def)
		valid := formatValidValues(def)
		sess.WriteLine(fmt.Sprintf("\n%s = %s  [%s]", def.Name, val, valid))
		sess.WriteLine(fmt.Sprintf("  %s", def.Description))
		return
	}

	value := strings.ToLower(parts[1])
	parsed, ok := parseOptionValue(def, value)
	if !ok {
		valid := formatValidValues(def)
		sess.WriteLine(fmt.Sprintf("\nInvalid value for %s: %s  [%s]", def.Name, value, valid))
		return
	}

	if p.Options == nil {
		p.Options = make(map[string]any)
	}
	p.Options[def.Name] = parsed
	g.AccountStore.SaveCharacter(p)
	sess.WriteLine(fmt.Sprintf("\n%s set to %s.", def.Name, formatOptionValue(p, def)))
}

func formatOptionValue(p *player.Player, def *player.OptionDef) string {
	switch def.Type {
	case player.OptBool:
		if p.OptionBool(def.Name) {
			return "on"
		}
		return "off"
	case player.OptString:
		return p.OptionString(def.Name)
	case player.OptInt:
		return strconv.Itoa(p.OptionInt(def.Name))
	}
	return ""
}

func formatValidValues(def *player.OptionDef) string {
	switch def.Type {
	case player.OptBool:
		return "on/off"
	case player.OptString:
		if len(def.ValidValues) > 0 {
			return strings.Join(def.ValidValues, "/")
		}
		return "string"
	case player.OptInt:
		return "num"
	}
	return ""
}

func parseOptionValue(def *player.OptionDef, input string) (any, bool) {
	switch def.Type {
	case player.OptBool:
		switch input {
		case "on", "true", "yes", "1":
			return true, true
		case "off", "false", "no", "0":
			return false, true
		}
		return nil, false
	case player.OptString:
		if len(def.ValidValues) == 0 {
			return input, true
		}
		for _, v := range def.ValidValues {
			if strings.EqualFold(v, input) {
				return v, true
			}
		}
		return nil, false
	case player.OptInt:
		n, err := strconv.Atoi(input)
		if err != nil {
			return nil, false
		}
		return n, true
	}
	return nil, false
}