data.gno
3.39 Kb ยท 142 lines
1package personal_world
2
3import (
4 "chain/runtime"
5
6 "gno.land/p/nt/avl"
7 "gno.land/p/nt/ufmt"
8)
9
10var (
11 verifierStore = avl.NewTree() // worldID -> map[chunkKey]verifier
12)
13
14func SetChunkVerifier(cur realm, worldID uint32, chunkKey string, verifier string) {
15 caller := runtime.PreviousRealm().Address()
16 assertIsAdminOrOperator(caller)
17
18 worldIDStr := ufmt.Sprintf("%d", worldID)
19 var chunkMap map[string]string
20
21 if value, exists := verifierStore.Get(worldIDStr); exists {
22 chunkMap = value.(map[string]string)
23 } else {
24 chunkMap = make(map[string]string)
25 verifierStore.Set(worldIDStr, chunkMap)
26 }
27
28 chunkMap[chunkKey] = verifier
29}
30
31// SetChunkVerifiers sets multiple chunk verifiers at once using direct string traversal.
32// chunkKeys and verifiers are comma-separated strings with matching item counts.
33// Example: chunkKeys="0_0,0_1,1_0", verifiers="hash1,hash2,hash3"
34func SetChunkVerifiers(cur realm, worldID uint32, chunkKeys string, verifiers string) {
35 caller := runtime.PreviousRealm().Address()
36 assertIsAdminOrOperator(caller)
37
38 if chunkKeys == "" {
39 panic("chunkKeys must not be empty")
40 }
41 if verifiers == "" {
42 panic("verifiers must not be empty")
43 }
44
45 worldIDStr := ufmt.Sprintf("%d", worldID)
46 var chunkMap map[string]string
47
48 if value, exists := verifierStore.Get(worldIDStr); exists {
49 chunkMap = value.(map[string]string)
50 } else {
51 chunkMap = make(map[string]string)
52 verifierStore.Set(worldIDStr, chunkMap)
53 }
54
55 // Direct string traversal parsing (no strings.Split)
56 keyStart, valStart := 0, 0
57 keyIdx, valIdx := 0, 0
58 count := 0
59
60 for {
61 // Find next delimiter or end for keys
62 for keyIdx < len(chunkKeys) && chunkKeys[keyIdx] != ',' {
63 keyIdx++
64 }
65 // Find next delimiter or end for values
66 for valIdx < len(verifiers) && verifiers[valIdx] != ',' {
67 valIdx++
68 }
69
70 // Extract key and value
71 key := chunkKeys[keyStart:keyIdx]
72 val := verifiers[valStart:valIdx]
73
74 // Validate: no empty keys or values allowed
75 if key == "" {
76 panic("empty chunkKey not allowed")
77 }
78 if val == "" {
79 panic("empty verifier not allowed")
80 }
81
82 chunkMap[key] = val
83 count++
84
85 // Check end conditions
86 keyEnd := keyIdx >= len(chunkKeys)
87 valEnd := valIdx >= len(verifiers)
88
89 // Validate: both must end at the same time (same item count)
90 if keyEnd != valEnd {
91 panic("chunkKeys and verifiers count mismatch")
92 }
93 if keyEnd {
94 break
95 }
96
97 // Move past the delimiter
98 keyIdx++
99 valIdx++
100 keyStart = keyIdx
101 valStart = valIdx
102 }
103}
104
105func GetChunkVerifier(worldID uint32, chunkKey string) string {
106 worldIDStr := ufmt.Sprintf("%d", worldID)
107
108 if value, exists := verifierStore.Get(worldIDStr); exists {
109 chunkMap := value.(map[string]string)
110 return chunkMap[chunkKey]
111 }
112
113 return ""
114}
115
116func ListChunkVerifiers(worldID uint32, chunkKeys ...string) []map[string]string {
117 if len(chunkKeys) > batchLimit {
118 panic("chunkKeys exceeds batchLimit")
119 }
120
121 result := make([]map[string]string, 0, len(chunkKeys))
122 if len(chunkKeys) == 0 {
123 return result
124 }
125
126 for _, chunkKey := range chunkKeys {
127 verifier := GetChunkVerifier(worldID, chunkKey)
128
129 if verifier != "" {
130 result = append(result, map[string]string{"chunkKey": chunkKey, "status": "found", "verifier": verifier})
131 } else {
132 result = append(result, map[string]string{"chunkKey": chunkKey, "status": "not_found"})
133 }
134 }
135
136 return result
137}
138
139func deleteWorldChunkVerifiers(worldID uint32) {
140 worldIDStr := ufmt.Sprintf("%d", worldID)
141 verifierStore.Remove(worldIDStr)
142}