bauiv1lib.profile.upgrade
UI for player profile upgrades.
1# Released under the MIT License. See LICENSE for details. 2# 3"""UI for player profile upgrades.""" 4 5from __future__ import annotations 6 7import time 8import weakref 9from typing import TYPE_CHECKING 10 11import bauiv1 as bui 12 13if TYPE_CHECKING: 14 from typing import Any 15 16 from bauiv1lib.profile.edit import EditProfileWindow 17 18 19class ProfileUpgradeWindow(bui.Window): 20 """Window for player profile upgrades to global.""" 21 22 def __init__( 23 self, 24 edit_profile_window: EditProfileWindow, 25 transition: str = 'in_right', 26 ): 27 if bui.app.classic is None: 28 raise RuntimeError('This requires classic.') 29 30 plus = bui.app.plus 31 assert plus is not None 32 33 self._r = 'editProfileWindow' 34 35 uiscale = bui.app.ui_v1.uiscale 36 self._width = 750 if uiscale is bui.UIScale.SMALL else 680 37 self._height = 350 38 assert bui.app.classic is not None 39 self._base_scale = ( 40 1.9 41 if uiscale is bui.UIScale.SMALL 42 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.2 43 ) 44 self._upgrade_start_time: float | None = None 45 self._name = edit_profile_window.getname() 46 self._edit_profile_window = weakref.ref(edit_profile_window) 47 48 top_extra = 15 if uiscale is bui.UIScale.SMALL else 15 49 super().__init__( 50 root_widget=bui.containerwidget( 51 size=(self._width, self._height + top_extra), 52 toolbar_visibility='menu_store_no_back', 53 transition=transition, 54 scale=self._base_scale, 55 stack_offset=( 56 (0, -30) if uiscale is bui.UIScale.SMALL else (0, 0) 57 ), 58 ) 59 ) 60 cancel_button = bui.buttonwidget( 61 parent=self._root_widget, 62 position=(52, 60), 63 size=(155, 60), 64 scale=0.8, 65 autoselect=True, 66 label=bui.Lstr(resource='cancelText'), 67 on_activate_call=self._cancel, 68 ) 69 self._upgrade_button = bui.buttonwidget( 70 parent=self._root_widget, 71 position=(self._width - 190, 60), 72 size=(155, 60), 73 scale=0.8, 74 autoselect=True, 75 label=bui.Lstr(resource='upgradeText'), 76 on_activate_call=self._on_upgrade_press, 77 ) 78 bui.containerwidget( 79 edit=self._root_widget, 80 cancel_button=cancel_button, 81 start_button=self._upgrade_button, 82 selected_child=self._upgrade_button, 83 ) 84 85 assert bui.app.classic is not None 86 bui.textwidget( 87 parent=self._root_widget, 88 position=(self._width * 0.5, self._height - 38), 89 size=(0, 0), 90 text=bui.Lstr(resource=f'{self._r}.upgradeToGlobalProfileText'), 91 color=bui.app.ui_v1.title_color, 92 maxwidth=self._width * 0.45, 93 scale=1.0, 94 h_align='center', 95 v_align='center', 96 ) 97 98 assert bui.app.classic is not None 99 bui.textwidget( 100 parent=self._root_widget, 101 position=(self._width * 0.5, self._height - 100), 102 size=(0, 0), 103 text=bui.Lstr(resource=f'{self._r}.upgradeProfileInfoText'), 104 color=bui.app.ui_v1.infotextcolor, 105 maxwidth=self._width * 0.8, 106 scale=0.7, 107 h_align='center', 108 v_align='center', 109 ) 110 111 self._status_text = bui.textwidget( 112 parent=self._root_widget, 113 position=(self._width * 0.5, self._height - 160), 114 size=(0, 0), 115 text=bui.Lstr( 116 resource=f'{self._r}.checkingAvailabilityText', 117 subs=[('${NAME}', self._name)], 118 ), 119 color=(0.8, 0.4, 0.0), 120 maxwidth=self._width * 0.8, 121 scale=0.65, 122 h_align='center', 123 v_align='center', 124 ) 125 126 self._price_text = bui.textwidget( 127 parent=self._root_widget, 128 position=(self._width * 0.5, self._height - 230), 129 size=(0, 0), 130 text='', 131 color=(0.2, 1, 0.2), 132 maxwidth=self._width * 0.8, 133 scale=1.5, 134 h_align='center', 135 v_align='center', 136 ) 137 138 self._tickets_text: bui.Widget | None 139 # if not bui.app.ui_v1.use_toolbars: 140 # self._tickets_text = bui.textwidget( 141 # parent=self._root_widget, 142 # position=(self._width * 0.9 - 5, self._height - 30), 143 # size=(0, 0), 144 # text=bui.charstr(bui.SpecialChar.TICKET) + '123', 145 # color=(0.2, 1, 0.2), 146 # maxwidth=100, 147 # scale=0.5, 148 # h_align='right', 149 # v_align='center', 150 # ) 151 # else: 152 self._tickets_text = None 153 154 bui.app.classic.master_server_v1_get( 155 'bsGlobalProfileCheck', 156 {'name': self._name, 'b': bui.app.env.engine_build_number}, 157 callback=bui.WeakCall(self._profile_check_result), 158 ) 159 self._cost = plus.get_v1_account_misc_read_val( 160 'price.global_profile', 500 161 ) 162 self._status: str | None = 'waiting' 163 self._update_timer = bui.AppTimer( 164 1.0, bui.WeakCall(self._update), repeat=True 165 ) 166 self._update() 167 168 def _profile_check_result(self, result: dict[str, Any] | None) -> None: 169 if result is None: 170 bui.textwidget( 171 edit=self._status_text, 172 text=bui.Lstr(resource='internal.unavailableNoConnectionText'), 173 color=(1, 0, 0), 174 ) 175 self._status = 'error' 176 bui.buttonwidget( 177 edit=self._upgrade_button, 178 color=(0.4, 0.4, 0.4), 179 textcolor=(0.5, 0.5, 0.5), 180 ) 181 else: 182 if result['available']: 183 bui.textwidget( 184 edit=self._status_text, 185 text=bui.Lstr( 186 resource=f'{self._r}.availableText', 187 subs=[('${NAME}', self._name)], 188 ), 189 color=(0, 1, 0), 190 ) 191 bui.textwidget( 192 edit=self._price_text, 193 text=bui.charstr(bui.SpecialChar.TICKET) + str(self._cost), 194 ) 195 self._status = None 196 else: 197 bui.textwidget( 198 edit=self._status_text, 199 text=bui.Lstr( 200 resource=f'{self._r}.unavailableText', 201 subs=[('${NAME}', self._name)], 202 ), 203 color=(1, 0, 0), 204 ) 205 self._status = 'unavailable' 206 bui.buttonwidget( 207 edit=self._upgrade_button, 208 color=(0.4, 0.4, 0.4), 209 textcolor=(0.5, 0.5, 0.5), 210 ) 211 212 def _on_upgrade_press(self) -> None: 213 # from bauiv1lib import gettickets 214 215 if self._status is None: 216 plus = bui.app.plus 217 assert plus is not None 218 219 # If it appears we don't have enough tickets, offer to buy more. 220 tickets = plus.get_v1_account_ticket_count() 221 if tickets < self._cost: 222 bui.getsound('error').play() 223 print('FIXME - show not-enough-tickets msg.') 224 # gettickets.show_get_tickets_prompt() 225 return 226 bui.screenmessage( 227 bui.Lstr(resource='purchasingText'), color=(0, 1, 0) 228 ) 229 self._status = 'pre_upgrading' 230 231 # Now we tell the original editor to save the profile, add an 232 # upgrade transaction, and then sit and wait for everything to 233 # go through. 234 edit_profile_window = self._edit_profile_window() 235 if edit_profile_window is None: 236 print('profile upgrade: original edit window gone') 237 return 238 success = edit_profile_window.save(transition_out=False) 239 if not success: 240 print('profile upgrade: error occurred saving profile') 241 bui.screenmessage( 242 bui.Lstr(resource='errorText'), color=(1, 0, 0) 243 ) 244 bui.getsound('error').play() 245 return 246 plus.add_v1_account_transaction( 247 {'type': 'UPGRADE_PROFILE', 'name': self._name} 248 ) 249 plus.run_v1_account_transactions() 250 self._status = 'upgrading' 251 self._upgrade_start_time = time.time() 252 else: 253 bui.getsound('error').play() 254 255 def _update(self) -> None: 256 plus = bui.app.plus 257 assert plus is not None 258 259 try: 260 t_str = str(plus.get_v1_account_ticket_count()) 261 except Exception: 262 t_str = '?' 263 if self._tickets_text is not None: 264 bui.textwidget( 265 edit=self._tickets_text, 266 text=bui.Lstr( 267 resource='getTicketsWindow.youHaveShortText', 268 subs=[ 269 ( 270 '${COUNT}', 271 bui.charstr(bui.SpecialChar.TICKET) + t_str, 272 ) 273 ], 274 ), 275 ) 276 277 # Once we've kicked off an upgrade attempt and all transactions go 278 # through, we're done. 279 if ( 280 self._status == 'upgrading' 281 and not plus.have_outstanding_v1_account_transactions() 282 ): 283 self._status = 'exiting' 284 bui.containerwidget(edit=self._root_widget, transition='out_right') 285 edit_profile_window = self._edit_profile_window() 286 if edit_profile_window is None: 287 print( 288 'profile upgrade transition out:' 289 ' original edit window gone' 290 ) 291 return 292 bui.getsound('gunCocking').play() 293 edit_profile_window.reload_window() 294 295 def _cancel(self) -> None: 296 # If we recently sent out an upgrade request, disallow canceling 297 # for a bit. 298 if ( 299 self._upgrade_start_time is not None 300 and time.time() - self._upgrade_start_time < 10.0 301 ): 302 bui.getsound('error').play() 303 return 304 bui.containerwidget(edit=self._root_widget, transition='out_right')
class
ProfileUpgradeWindow(bauiv1._uitypes.Window):
20class ProfileUpgradeWindow(bui.Window): 21 """Window for player profile upgrades to global.""" 22 23 def __init__( 24 self, 25 edit_profile_window: EditProfileWindow, 26 transition: str = 'in_right', 27 ): 28 if bui.app.classic is None: 29 raise RuntimeError('This requires classic.') 30 31 plus = bui.app.plus 32 assert plus is not None 33 34 self._r = 'editProfileWindow' 35 36 uiscale = bui.app.ui_v1.uiscale 37 self._width = 750 if uiscale is bui.UIScale.SMALL else 680 38 self._height = 350 39 assert bui.app.classic is not None 40 self._base_scale = ( 41 1.9 42 if uiscale is bui.UIScale.SMALL 43 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.2 44 ) 45 self._upgrade_start_time: float | None = None 46 self._name = edit_profile_window.getname() 47 self._edit_profile_window = weakref.ref(edit_profile_window) 48 49 top_extra = 15 if uiscale is bui.UIScale.SMALL else 15 50 super().__init__( 51 root_widget=bui.containerwidget( 52 size=(self._width, self._height + top_extra), 53 toolbar_visibility='menu_store_no_back', 54 transition=transition, 55 scale=self._base_scale, 56 stack_offset=( 57 (0, -30) if uiscale is bui.UIScale.SMALL else (0, 0) 58 ), 59 ) 60 ) 61 cancel_button = bui.buttonwidget( 62 parent=self._root_widget, 63 position=(52, 60), 64 size=(155, 60), 65 scale=0.8, 66 autoselect=True, 67 label=bui.Lstr(resource='cancelText'), 68 on_activate_call=self._cancel, 69 ) 70 self._upgrade_button = bui.buttonwidget( 71 parent=self._root_widget, 72 position=(self._width - 190, 60), 73 size=(155, 60), 74 scale=0.8, 75 autoselect=True, 76 label=bui.Lstr(resource='upgradeText'), 77 on_activate_call=self._on_upgrade_press, 78 ) 79 bui.containerwidget( 80 edit=self._root_widget, 81 cancel_button=cancel_button, 82 start_button=self._upgrade_button, 83 selected_child=self._upgrade_button, 84 ) 85 86 assert bui.app.classic is not None 87 bui.textwidget( 88 parent=self._root_widget, 89 position=(self._width * 0.5, self._height - 38), 90 size=(0, 0), 91 text=bui.Lstr(resource=f'{self._r}.upgradeToGlobalProfileText'), 92 color=bui.app.ui_v1.title_color, 93 maxwidth=self._width * 0.45, 94 scale=1.0, 95 h_align='center', 96 v_align='center', 97 ) 98 99 assert bui.app.classic is not None 100 bui.textwidget( 101 parent=self._root_widget, 102 position=(self._width * 0.5, self._height - 100), 103 size=(0, 0), 104 text=bui.Lstr(resource=f'{self._r}.upgradeProfileInfoText'), 105 color=bui.app.ui_v1.infotextcolor, 106 maxwidth=self._width * 0.8, 107 scale=0.7, 108 h_align='center', 109 v_align='center', 110 ) 111 112 self._status_text = bui.textwidget( 113 parent=self._root_widget, 114 position=(self._width * 0.5, self._height - 160), 115 size=(0, 0), 116 text=bui.Lstr( 117 resource=f'{self._r}.checkingAvailabilityText', 118 subs=[('${NAME}', self._name)], 119 ), 120 color=(0.8, 0.4, 0.0), 121 maxwidth=self._width * 0.8, 122 scale=0.65, 123 h_align='center', 124 v_align='center', 125 ) 126 127 self._price_text = bui.textwidget( 128 parent=self._root_widget, 129 position=(self._width * 0.5, self._height - 230), 130 size=(0, 0), 131 text='', 132 color=(0.2, 1, 0.2), 133 maxwidth=self._width * 0.8, 134 scale=1.5, 135 h_align='center', 136 v_align='center', 137 ) 138 139 self._tickets_text: bui.Widget | None 140 # if not bui.app.ui_v1.use_toolbars: 141 # self._tickets_text = bui.textwidget( 142 # parent=self._root_widget, 143 # position=(self._width * 0.9 - 5, self._height - 30), 144 # size=(0, 0), 145 # text=bui.charstr(bui.SpecialChar.TICKET) + '123', 146 # color=(0.2, 1, 0.2), 147 # maxwidth=100, 148 # scale=0.5, 149 # h_align='right', 150 # v_align='center', 151 # ) 152 # else: 153 self._tickets_text = None 154 155 bui.app.classic.master_server_v1_get( 156 'bsGlobalProfileCheck', 157 {'name': self._name, 'b': bui.app.env.engine_build_number}, 158 callback=bui.WeakCall(self._profile_check_result), 159 ) 160 self._cost = plus.get_v1_account_misc_read_val( 161 'price.global_profile', 500 162 ) 163 self._status: str | None = 'waiting' 164 self._update_timer = bui.AppTimer( 165 1.0, bui.WeakCall(self._update), repeat=True 166 ) 167 self._update() 168 169 def _profile_check_result(self, result: dict[str, Any] | None) -> None: 170 if result is None: 171 bui.textwidget( 172 edit=self._status_text, 173 text=bui.Lstr(resource='internal.unavailableNoConnectionText'), 174 color=(1, 0, 0), 175 ) 176 self._status = 'error' 177 bui.buttonwidget( 178 edit=self._upgrade_button, 179 color=(0.4, 0.4, 0.4), 180 textcolor=(0.5, 0.5, 0.5), 181 ) 182 else: 183 if result['available']: 184 bui.textwidget( 185 edit=self._status_text, 186 text=bui.Lstr( 187 resource=f'{self._r}.availableText', 188 subs=[('${NAME}', self._name)], 189 ), 190 color=(0, 1, 0), 191 ) 192 bui.textwidget( 193 edit=self._price_text, 194 text=bui.charstr(bui.SpecialChar.TICKET) + str(self._cost), 195 ) 196 self._status = None 197 else: 198 bui.textwidget( 199 edit=self._status_text, 200 text=bui.Lstr( 201 resource=f'{self._r}.unavailableText', 202 subs=[('${NAME}', self._name)], 203 ), 204 color=(1, 0, 0), 205 ) 206 self._status = 'unavailable' 207 bui.buttonwidget( 208 edit=self._upgrade_button, 209 color=(0.4, 0.4, 0.4), 210 textcolor=(0.5, 0.5, 0.5), 211 ) 212 213 def _on_upgrade_press(self) -> None: 214 # from bauiv1lib import gettickets 215 216 if self._status is None: 217 plus = bui.app.plus 218 assert plus is not None 219 220 # If it appears we don't have enough tickets, offer to buy more. 221 tickets = plus.get_v1_account_ticket_count() 222 if tickets < self._cost: 223 bui.getsound('error').play() 224 print('FIXME - show not-enough-tickets msg.') 225 # gettickets.show_get_tickets_prompt() 226 return 227 bui.screenmessage( 228 bui.Lstr(resource='purchasingText'), color=(0, 1, 0) 229 ) 230 self._status = 'pre_upgrading' 231 232 # Now we tell the original editor to save the profile, add an 233 # upgrade transaction, and then sit and wait for everything to 234 # go through. 235 edit_profile_window = self._edit_profile_window() 236 if edit_profile_window is None: 237 print('profile upgrade: original edit window gone') 238 return 239 success = edit_profile_window.save(transition_out=False) 240 if not success: 241 print('profile upgrade: error occurred saving profile') 242 bui.screenmessage( 243 bui.Lstr(resource='errorText'), color=(1, 0, 0) 244 ) 245 bui.getsound('error').play() 246 return 247 plus.add_v1_account_transaction( 248 {'type': 'UPGRADE_PROFILE', 'name': self._name} 249 ) 250 plus.run_v1_account_transactions() 251 self._status = 'upgrading' 252 self._upgrade_start_time = time.time() 253 else: 254 bui.getsound('error').play() 255 256 def _update(self) -> None: 257 plus = bui.app.plus 258 assert plus is not None 259 260 try: 261 t_str = str(plus.get_v1_account_ticket_count()) 262 except Exception: 263 t_str = '?' 264 if self._tickets_text is not None: 265 bui.textwidget( 266 edit=self._tickets_text, 267 text=bui.Lstr( 268 resource='getTicketsWindow.youHaveShortText', 269 subs=[ 270 ( 271 '${COUNT}', 272 bui.charstr(bui.SpecialChar.TICKET) + t_str, 273 ) 274 ], 275 ), 276 ) 277 278 # Once we've kicked off an upgrade attempt and all transactions go 279 # through, we're done. 280 if ( 281 self._status == 'upgrading' 282 and not plus.have_outstanding_v1_account_transactions() 283 ): 284 self._status = 'exiting' 285 bui.containerwidget(edit=self._root_widget, transition='out_right') 286 edit_profile_window = self._edit_profile_window() 287 if edit_profile_window is None: 288 print( 289 'profile upgrade transition out:' 290 ' original edit window gone' 291 ) 292 return 293 bui.getsound('gunCocking').play() 294 edit_profile_window.reload_window() 295 296 def _cancel(self) -> None: 297 # If we recently sent out an upgrade request, disallow canceling 298 # for a bit. 299 if ( 300 self._upgrade_start_time is not None 301 and time.time() - self._upgrade_start_time < 10.0 302 ): 303 bui.getsound('error').play() 304 return 305 bui.containerwidget(edit=self._root_widget, transition='out_right')
Window for player profile upgrades to global.
ProfileUpgradeWindow( edit_profile_window: bauiv1lib.profile.edit.EditProfileWindow, transition: str = 'in_right')
23 def __init__( 24 self, 25 edit_profile_window: EditProfileWindow, 26 transition: str = 'in_right', 27 ): 28 if bui.app.classic is None: 29 raise RuntimeError('This requires classic.') 30 31 plus = bui.app.plus 32 assert plus is not None 33 34 self._r = 'editProfileWindow' 35 36 uiscale = bui.app.ui_v1.uiscale 37 self._width = 750 if uiscale is bui.UIScale.SMALL else 680 38 self._height = 350 39 assert bui.app.classic is not None 40 self._base_scale = ( 41 1.9 42 if uiscale is bui.UIScale.SMALL 43 else 1.5 if uiscale is bui.UIScale.MEDIUM else 1.2 44 ) 45 self._upgrade_start_time: float | None = None 46 self._name = edit_profile_window.getname() 47 self._edit_profile_window = weakref.ref(edit_profile_window) 48 49 top_extra = 15 if uiscale is bui.UIScale.SMALL else 15 50 super().__init__( 51 root_widget=bui.containerwidget( 52 size=(self._width, self._height + top_extra), 53 toolbar_visibility='menu_store_no_back', 54 transition=transition, 55 scale=self._base_scale, 56 stack_offset=( 57 (0, -30) if uiscale is bui.UIScale.SMALL else (0, 0) 58 ), 59 ) 60 ) 61 cancel_button = bui.buttonwidget( 62 parent=self._root_widget, 63 position=(52, 60), 64 size=(155, 60), 65 scale=0.8, 66 autoselect=True, 67 label=bui.Lstr(resource='cancelText'), 68 on_activate_call=self._cancel, 69 ) 70 self._upgrade_button = bui.buttonwidget( 71 parent=self._root_widget, 72 position=(self._width - 190, 60), 73 size=(155, 60), 74 scale=0.8, 75 autoselect=True, 76 label=bui.Lstr(resource='upgradeText'), 77 on_activate_call=self._on_upgrade_press, 78 ) 79 bui.containerwidget( 80 edit=self._root_widget, 81 cancel_button=cancel_button, 82 start_button=self._upgrade_button, 83 selected_child=self._upgrade_button, 84 ) 85 86 assert bui.app.classic is not None 87 bui.textwidget( 88 parent=self._root_widget, 89 position=(self._width * 0.5, self._height - 38), 90 size=(0, 0), 91 text=bui.Lstr(resource=f'{self._r}.upgradeToGlobalProfileText'), 92 color=bui.app.ui_v1.title_color, 93 maxwidth=self._width * 0.45, 94 scale=1.0, 95 h_align='center', 96 v_align='center', 97 ) 98 99 assert bui.app.classic is not None 100 bui.textwidget( 101 parent=self._root_widget, 102 position=(self._width * 0.5, self._height - 100), 103 size=(0, 0), 104 text=bui.Lstr(resource=f'{self._r}.upgradeProfileInfoText'), 105 color=bui.app.ui_v1.infotextcolor, 106 maxwidth=self._width * 0.8, 107 scale=0.7, 108 h_align='center', 109 v_align='center', 110 ) 111 112 self._status_text = bui.textwidget( 113 parent=self._root_widget, 114 position=(self._width * 0.5, self._height - 160), 115 size=(0, 0), 116 text=bui.Lstr( 117 resource=f'{self._r}.checkingAvailabilityText', 118 subs=[('${NAME}', self._name)], 119 ), 120 color=(0.8, 0.4, 0.0), 121 maxwidth=self._width * 0.8, 122 scale=0.65, 123 h_align='center', 124 v_align='center', 125 ) 126 127 self._price_text = bui.textwidget( 128 parent=self._root_widget, 129 position=(self._width * 0.5, self._height - 230), 130 size=(0, 0), 131 text='', 132 color=(0.2, 1, 0.2), 133 maxwidth=self._width * 0.8, 134 scale=1.5, 135 h_align='center', 136 v_align='center', 137 ) 138 139 self._tickets_text: bui.Widget | None 140 # if not bui.app.ui_v1.use_toolbars: 141 # self._tickets_text = bui.textwidget( 142 # parent=self._root_widget, 143 # position=(self._width * 0.9 - 5, self._height - 30), 144 # size=(0, 0), 145 # text=bui.charstr(bui.SpecialChar.TICKET) + '123', 146 # color=(0.2, 1, 0.2), 147 # maxwidth=100, 148 # scale=0.5, 149 # h_align='right', 150 # v_align='center', 151 # ) 152 # else: 153 self._tickets_text = None 154 155 bui.app.classic.master_server_v1_get( 156 'bsGlobalProfileCheck', 157 {'name': self._name, 'b': bui.app.env.engine_build_number}, 158 callback=bui.WeakCall(self._profile_check_result), 159 ) 160 self._cost = plus.get_v1_account_misc_read_val( 161 'price.global_profile', 500 162 ) 163 self._status: str | None = 'waiting' 164 self._update_timer = bui.AppTimer( 165 1.0, bui.WeakCall(self._update), repeat=True 166 ) 167 self._update()
Inherited Members
- bauiv1._uitypes.Window
- get_root_widget