Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

json.gno

2.65 Kb · 98 lines
 1package game
 2
 3import "strings"
 4
 5// The JSON documents are built by hand. That is safe because every string
 6// that reaches them was validated against a JSON-safe charset when it was
 7// written (see validate.gno): ids, names, models, colors and bech32 addresses
 8// need no escaping. The one string that is not under the realm's control, an
 9// address typed into a query, goes through quote.
10//
11// Ordering is deterministic everywhere: params follow the registry and the
12// leaderboard is best first.
13
14// StateJSON returns everything the game needs from the chain, as one JSON
15// object:
16//
17//	{
18//	  "version": 12,
19//	  "treasury": "g1...",
20//	  "params": { "plane_speed": 70, "boost_speed": 130 }
21//	}
22//
23// The output has no whitespace. It only changes when Version does. The skins
24// are in their own realm, gnofly/nfts/skins.
25func StateJSON() string {
26	var b strings.Builder
27
28	b.WriteString(`{"version":`)
29	b.WriteString(itoa(version))
30	b.WriteString(`,"treasury":"`)
31	b.WriteString(treasury.String())
32
33	b.WriteString(`","params":{`)
34	for i, p := range params {
35		if i > 0 {
36			b.WriteByte(',')
37		}
38		b.WriteByte('"')
39		b.WriteString(p.key)
40		b.WriteString(`":`)
41		b.WriteString(itoa(p.value))
42	}
43
44	b.WriteString(`}}`)
45	return b.String()
46}
47
48// PlayerJSON returns one player as a JSON object:
49//
50//	{ "address": "g1...", "kills": 17 }
51//
52// The output has no whitespace. An unknown address has zero kills. The skins
53// and planes a player owns are read from their realms (SkinsOf, PlanesOf).
54func PlayerJSON(addr address) string {
55	var b strings.Builder
56	b.WriteString(`{"address":`)
57	b.WriteString(quote(addr.String()))
58	b.WriteString(`,"kills":`)
59	b.WriteString(itoa(recordedKills(addr)))
60	b.WriteByte('}')
61	return b.String()
62}
63
64// KillLeaderboardJSON returns the top players by kills recorded on-chain as
65// a JSON array, best first, at most leaderboard_size entries:
66//
67//	[ { "address": "g1...", "kills": 17 } ]
68//
69// The output has no whitespace. With equal kills, the player who got there
70// first stays ahead.
71func KillLeaderboardJSON() string {
72	var b strings.Builder
73	writeRanking(&b, killers, "kills")
74	return b.String()
75}
76
77// quote returns s as a JSON string literal, quotes included. It is for the
78// strings the realm did not validate. Quotes and backslashes are escaped and
79// anything outside printable ASCII is replaced by "?", so the result is
80// valid JSON whatever s holds.
81func quote(s string) string {
82	var b strings.Builder
83	b.WriteByte('"')
84	for i := 0; i < len(s); i++ {
85		c := s[i]
86		switch {
87		case c == '"' || c == '\\':
88			b.WriteByte('\\')
89			b.WriteByte(c)
90		case c < 0x20 || c > 0x7e:
91			b.WriteByte('?')
92		default:
93			b.WriteByte(c)
94		}
95	}
96	b.WriteByte('"')
97	return b.String()
98}