Kind Realm (renderable)
Name game_world
Namespace akkadia / beta
Exported functions 18
Module gno.land/r/akkadia/beta/game_world
gno 0.9 game_world.gno gno
⧉
1 package game_world 2 3 import ( 4 "chain" 5 "chain/banker" 6 "chain/runtime" 7 "chain/runtime/unsafe" 8 AddApprovedCreator (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, gameType string, creator string)
CreateGameWorld (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, gameType string) uint64
GetApprovedCreatorCount (gameType string) int
GetGameTypePolicy (gameType string) struct{CreationCost int64; CreationMode gno.land/r/akkadia/beta/game_world.CreationMode}
GetGameWorld (gameWorldID uint64) struct{ID uint64; Owner .uverse.address; GameType string; Status gno.land/r/akkadia/beta/game_world.GameWorldStatus; CreatedHeight int64; RestrictedHeight int64}
GetLatestGameWorldID () uint64
GetListLimit () int
GetRestrictedGameWorldCount () int
HasGameTypePolicy (gameType string) bool
HasGameWorld (gameWorldID uint64) bool
IsApprovedCreator (gameType string, creator string) bool
ListApprovedCreators (gameType string, offset int, count int) [].uverse.address
ListLatestGameWorldsByOwner (owner string) []gno.land/r/akkadia/beta/game_world.GameWorld
ListRestrictedGameWorldIDs (page int, count int) []uint64
RemoveApprovedCreator (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, gameType string, creator string)
RestrictGameWorld (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, gameWorldID uint64)
SetApprovedCreators (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, gameType string, creatorsCSV string, approved bool)
SetGameTypePolicy (cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, gameType string, creationCost int64, mode int)
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.
Render unavailable
rate limit exceeded — the render query is served by the Gnoland archive RPC.
vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.
"strconv"
9
10 "gno.land/p/akkadia/beta/accesscontrol"
11 "gno.land/r/akkadia/beta/admin"
12 )
13
14 const (
15 CreateGameWorldEvent = "CreateGameWorld"
16 RestrictGameWorldEvent = "RestrictGameWorld"
17 )
18
19 type CreationMode int
20
21 const (
22 CreationModeInvalid CreationMode = iota
23 CreationModeOperatorOnly
24 CreationModeApprovedCreator
25 CreationModePublicCreator
26 )
27
28 type GameWorldStatus int
29
30 const (
31 GameWorldStatusInvalid GameWorldStatus = iota
32 GameWorldStatusExists
33 GameWorldStatusRestricted
34 )
35
36 type GameWorld struct {
37 ID uint64
38 Owner address
39 GameType string
40 Status GameWorldStatus
41 CreatedHeight int64
42 RestrictedHeight int64
43 }
44
45 type GameTypePolicy struct {
46 CreationCost int64
47 CreationMode CreationMode
48 }
49
50 func CreateGameWorld(cur realm, gameType string ) uint64 {
51 owner := accesscontrol.MustGetUserCaller( 0 , cur)
52 policy := mustGetGameTypePolicy(gameType)
53 assertCreationAllowed(gameType, owner, policy.CreationMode)
54 assertExactUgnotPayment(policy.CreationCost)
55
56 id := createGameWorld(owner, gameType)
57 if policy.CreationCost > 0 {
58 bnk := banker.NewBanker(banker.BankerTypeRealmSend, cur)
59 bnk.SendCoins(cur.Address(), admin.GetFeeCollector(), chain.Coins{{ "ugnot" , policy.CreationCost}})
60 }
61 emitCreateGameWorld(owner, id, gameType, policy.CreationCost)
62 return id
63 }
64
65 func RestrictGameWorld(cur realm, gameWorldID uint64 ) {
66 executor := accesscontrol.MustGetAdminOrOperatorCaller( 0 , cur, admin.IsAdmin, admin.IsOperator)
67 world := GetGameWorld(gameWorldID)
68 if world.Status == GameWorldStatusRestricted {
69 return
70 }
71 world.Status = GameWorldStatusRestricted
72 world.RestrictedHeight = runtime.ChainHeight()
73 gameWorlds.Set(uint64Key(gameWorldID), world)
74 removeOwnerGameWorldID(world.Owner, gameWorldID)
75 restrictedGameWorldIDs.Set(uint64Key(gameWorldID), true )
76 chain.Emit(
77 RestrictGameWorldEvent,
78 "executor" , executor.String(),
79 "id" , strconv.FormatUint(gameWorldID, 10 ),
80 "oldStatus" , strconv.Itoa( int (GameWorldStatusExists)),
81 "newStatus" , strconv.Itoa( int (GameWorldStatusRestricted)),
82 "restrictedHeight" , strconv.FormatInt(world.RestrictedHeight, 10 ),
83 )
84 }
85
86 func HasGameWorld(gameWorldID uint64 ) bool { return gameWorlds.Has(uint64Key(gameWorldID)) }
87
88 func GetGameWorld(gameWorldID uint64 ) GameWorld {
89 value := gameWorlds.Get(uint64Key(gameWorldID))
90 if value == nil {
91 panic( "game world not found: " + strconv.FormatUint(gameWorldID, 10 ))
92 }
93 return value.(GameWorld)
94 }
95
96 func GetLatestGameWorldID() uint64 { return latestGameWorldID }
97
98 func GetListLimit() int { return gameWorldListLimit }
99
100 func GetRestrictedGameWorldCount() int { return restrictedGameWorldIDs.Size() }
101
102 func ListRestrictedGameWorldIDs(page, count int ) [] uint64 {
103 if page < 1 {
104 panic( "page must be at least 1" )
105 }
106 if count < 1 || count > gameWorldListLimit {
107 panic( "count must be between 1 and 100" )
108 }
109 result := [] uint64 {}
110 restrictedGameWorldIDs.IterateByOffset((page- 1 )*count, count, func (key string , _ any ) bool {
111 result = append(result, parseUint64Key(key))
112 return false
113 })
114 return result
115 }
116
117 func ListLatestGameWorldsByOwner(owner address) []GameWorld {
118 ids, found := getOwnerGameWorldIDs(owner)
119 if !found {
120 return []GameWorld{}
121 }
122 offset := ids.Size() - gameWorldListLimit
123 if offset < 0 {
124 offset = 0
125 }
126 result := []GameWorld{}
127 ids.IterateByOffset(offset, gameWorldListLimit, func (key string , _ any ) bool {
128 result = append(result, GetGameWorld(parseUint64Key(key)))
129 return false
130 })
131 return result
132 }
133
134 func createGameWorld(owner address, gameType string ) uint64 {
135 if latestGameWorldID == uint64 ( 18446744073709551615 ) {
136 panic( "game world id exhausted" )
137 }
138 latestGameWorldID++
139 id := latestGameWorldID
140 gameWorlds.Set(uint64Key(id), GameWorld{
141 ID: id,
142 Owner: owner,
143 GameType: gameType,
144 Status: GameWorldStatusExists,
145 CreatedHeight: runtime.ChainHeight(),
146 })
147 addOwnerGameWorldID(owner, id)
148 return id
149 }
150
151 func assertCreationAllowed(gameType string , creator address, mode CreationMode) {
152 switch mode {
153 case CreationModeOperatorOnly:
154 if !admin.IsAdmin(creator) && !admin.IsOperator(creator) {
155 panic( "game type creation is operator only" )
156 }
157 case CreationModeApprovedCreator:
158 if !isApprovedCreator(gameType, creator) {
159 panic( "creator is not approved for game type" )
160 }
161 case CreationModePublicCreator:
162 return
163 default :
164 panic( "invalid creation mode" )
165 }
166 }
167
168 func assertExactUgnotPayment(expected int64 ) {
169 coins := unsafe.OriginSend()
170 if expected == 0 {
171 if len(coins) != 0 {
172 panic( "exact payment required: expected no coins, got " + coins.String())
173 }
174 return
175 }
176 if len(coins) != 1 || coins[ 0 ].Denom != "ugnot" || coins[ 0 ].Amount != expected {
177 panic( "exact payment required: expected " + strconv.FormatInt(expected, 10 ) + "ugnot, got " + coins.String())
178 }
179 }
180
181 func emitCreateGameWorld(owner address, id uint64 , gameType string , creationCost int64 ) {
182 chain.Emit(
183 CreateGameWorldEvent,
184 "executor" , owner.String(),
185 "id" , strconv.FormatUint(id, 10 ),
186 "owner" , owner.String(),
187 "gameType" , gameType,
188 "creationCost" , strconv.FormatInt(creationCost, 10 ),
189 "createdHeight" , strconv.FormatInt(runtime.ChainHeight(), 10 ),
190 )
191 }
192