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

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

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}