Пример #1
0
    def _update_linked_accounts_text(self) -> None:
        if self._linked_accounts_text is None:
            return

        # if this is not present, we haven't had contact from the server so
        # let's not proceed..
        if _ba.get_public_login_id() is None:
            num = int(time.time()) % 4
            accounts_str = num * '.' + (4 - num) * ' '
        else:
            accounts = _ba.get_account_misc_read_val_2('linkedAccounts', [])
            # our_account = _bs.get_account_display_string()
            # accounts = [a for a in accounts if a != our_account]
            # accounts_str = u', '.join(accounts) if accounts else
            # ba.Lstr(translate=('settingNames', 'None'))
            # UPDATE - we now just print the number here; not the actual
            # accounts
            # (they can see that in the unlink section if they're curious)
            accounts_str = str(max(0, len(accounts) - 1))
        ba.textwidget(edit=self._linked_accounts_text,
                      text=ba.Lstr(value='${L} ${A}',
                                   subs=[('${L}',
                                          ba.Lstr(resource=self._r +
                                                  '.linkedAccountsText')),
                                         ('${A}', accounts_str)]))
Пример #2
0
 def _have_unlinkable_accounts(self) -> bool:
     # if this is not present, we haven't had contact from the server so
     # let's not proceed..
     if _ba.get_public_login_id() is None:
         return False
     accounts = _ba.get_account_misc_read_val_2('linkedAccounts', [])
     return len(accounts) > 1
Пример #3
0
    def _update_field(self, response: dict[str, Any]) -> None:
        if self._angry_computer_image is None:
            self._angry_computer_image = ba.imagewidget(
                parent=self._root_widget,
                position=(self._width - 180, self._height * 0.5 - 65),
                size=(150, 150),
                texture=self.lineup_tex,
                model_transparent=self._angry_computer_transparent_model)
        if self._line_image is None:
            self._line_image = ba.imagewidget(
                parent=self._root_widget,
                color=(0.0, 0.0, 0.0),
                opacity=0.2,
                position=(self._line_left, self._line_bottom - 2.0),
                size=(self._line_width, 4.0),
                texture=self._white_tex)

        # now go through the data they sent, creating dudes for us and our
        # enemies as needed and updating target positions on all of them..

        # mark all as unclaimed so we know which ones to kill off..
        for dude in self._dudes:
            dude.claimed = False

        # always have a dude for ourself..
        if -1 not in self._dudes_by_id:
            dude = self.Dude(
                self, response['d'], self._initial_offset, True,
                _ba.get_account_misc_read_val_2('resolvedAccountID', None),
                _ba.get_account_display_string())
            self._dudes_by_id[-1] = dude
            self._dudes.append(dude)
        else:
            self._dudes_by_id[-1].set_target_distance(response['d'])
        self._dudes_by_id[-1].claimed = True

        # now create/destroy enemies
        for (enemy_id, enemy_distance, enemy_account_id,
             enemy_name) in response['e']:
            if enemy_id not in self._dudes_by_id:
                dude = self.Dude(self, enemy_distance, self._initial_offset,
                                 False, enemy_account_id, enemy_name)
                self._dudes_by_id[enemy_id] = dude
                self._dudes.append(dude)
            else:
                self._dudes_by_id[enemy_id].set_target_distance(enemy_distance)
            self._dudes_by_id[enemy_id].claimed = True

        # remove unclaimed dudes from both of our lists
        # noinspection PyUnresolvedReferences
        self._dudes_by_id = dict([
            item for item in list(self._dudes_by_id.items()) if item[1].claimed
        ])
        self._dudes = [dude for dude in self._dudes if dude.claimed]
Пример #4
0
def have_pro_options() -> bool:
    """Return whether pro-options are present.

    This is True for owners of Pro or old installs
    before Pro was a requirement for these.
    """

    # We expose pro options if the server tells us to
    # (which is generally just when we own pro),
    # or also if we've been grandfathered in or are using ballistica-core
    # builds.
    return have_pro() or bool(
        _ba.get_account_misc_read_val_2('proOptionsUnlocked', False)
        or _ba.app.config.get('lc14292', 0) > 1)
Пример #5
0
 def _do_purchase(self, item: str) -> None:
     if item == 'ad':
         import datetime
         # if ads are disabled until some time, error..
         next_reward_ad_time = _ba.get_account_misc_read_val_2(
             'nextRewardAdTime', None)
         if next_reward_ad_time is not None:
             next_reward_ad_time = datetime.datetime.utcfromtimestamp(
                 next_reward_ad_time)
         now = datetime.datetime.utcnow()
         if ((next_reward_ad_time is not None and next_reward_ad_time > now)
                 or self._ad_button_greyed):
             ba.playsound(ba.getsound('error'))
             ba.screenmessage(ba.Lstr(
                 resource='getTicketsWindow.unavailableTemporarilyText'),
                              color=(1, 0, 0))
         elif self._enable_ad_button:
             _ba.app.ads.show_ad('tickets')
     else:
         _ba.purchase(item)
Пример #6
0
    def _update(self) -> None:
        import datetime

        # if we somehow get signed out, just die..
        if _ba.get_account_state() != 'signed_in':
            self._back()
            return

        self._ticket_count = _ba.get_account_ticket_count()

        # update our incentivized ad button depending on whether ads are
        # available
        if self._ad_button is not None:
            next_reward_ad_time = _ba.get_account_misc_read_val_2(
                'nextRewardAdTime', None)
            if next_reward_ad_time is not None:
                next_reward_ad_time = datetime.datetime.utcfromtimestamp(
                    next_reward_ad_time)
            now = datetime.datetime.utcnow()
            if (_ba.have_incentivized_ad() and
                (next_reward_ad_time is None or next_reward_ad_time <= now)):
                self._ad_button_greyed = False
                ba.buttonwidget(edit=self._ad_button, color=(0.65, 0.5, 0.7))
                ba.textwidget(edit=self._ad_label, color=(0.7, 0.9, 0.7, 1.0))
                ba.textwidget(edit=self._ad_free_text, color=(1, 1, 0, 1))
                ba.imagewidget(edit=self._ad_image, opacity=0.6)
                ba.textwidget(edit=self._ad_time_text, text='')
            else:
                self._ad_button_greyed = True
                ba.buttonwidget(edit=self._ad_button, color=(0.5, 0.5, 0.5))
                ba.textwidget(edit=self._ad_label, color=(0.7, 0.9, 0.7, 0.2))
                ba.textwidget(edit=self._ad_free_text, color=(1, 1, 0, 0.2))
                ba.imagewidget(edit=self._ad_image, opacity=0.6 * 0.25)
                sval: Union[str, ba.Lstr]
                if (next_reward_ad_time is not None
                        and next_reward_ad_time > now):
                    sval = ba.timestring(
                        (next_reward_ad_time - now).total_seconds() * 1000.0,
                        centi=False,
                        timeformat=ba.TimeFormat.MILLISECONDS)
                else:
                    sval = ''
                ba.textwidget(edit=self._ad_time_text, text=sval)

        # if this is our first update, assign immediately; otherwise kick
        # off a smooth transition if the value has changed
        if self._smooth_ticket_count is None:
            self._smooth_ticket_count = float(self._ticket_count)
            self._smooth_update()  # will set the text widget

        elif (self._ticket_count != int(self._smooth_ticket_count)
              and self._smooth_update_timer is None):
            self._smooth_update_timer = ba.Timer(0.05,
                                                 ba.WeakCall(
                                                     self._smooth_update),
                                                 repeat=True,
                                                 timetype=ba.TimeType.REAL)
            diff = abs(float(self._ticket_count) - self._smooth_ticket_count)
            self._smooth_increase_speed = (diff /
                                           100.0 if diff >= 5000 else diff /
                                           50.0 if diff >= 1500 else diff /
                                           30.0 if diff >= 500 else diff /
                                           15.0)
Пример #7
0
    def update(self, index: int, party: PartyEntry, sub_scroll_width: float,
               sub_scroll_height: float, lineheight: float,
               columnwidget: ba.Widget, join_text: ba.Widget,
               filter_text: ba.Widget, existing_selection: Optional[Selection],
               tab: PublicGatherTab) -> None:
        """Update for the given data."""
        # pylint: disable=too-many-locals

        # Quick-out: if we've been marked clean for a certain index and
        # we're still at that index, we're done.
        if party.clean_display_index == index:
            return

        ping_good = _ba.get_account_misc_read_val('pingGood', 100)
        ping_med = _ba.get_account_misc_read_val('pingMed', 500)

        self._clear()
        hpos = 20
        vpos = sub_scroll_height - lineheight * index - 50
        self._name_widget = ba.textwidget(
            text=ba.Lstr(value=party.name),
            parent=columnwidget,
            size=(sub_scroll_width * 0.63, 20),
            position=(0 + hpos, 4 + vpos),
            selectable=True,
            on_select_call=ba.WeakCall(
                tab.set_public_party_selection,
                Selection(party.get_key(), SelectionComponent.NAME)),
            on_activate_call=ba.WeakCall(tab.on_public_party_activate, party),
            click_activate=True,
            maxwidth=sub_scroll_width * 0.45,
            corner_scale=1.4,
            autoselect=True,
            color=(1, 1, 1, 0.3 if party.ping is None else 1.0),
            h_align='left',
            v_align='center')
        ba.widget(edit=self._name_widget,
                  left_widget=join_text,
                  show_buffer_top=64.0,
                  show_buffer_bottom=64.0)
        if existing_selection == Selection(party.get_key(),
                                           SelectionComponent.NAME):
            ba.containerwidget(edit=columnwidget,
                               selected_child=self._name_widget)
        if party.stats_addr:
            url = party.stats_addr.replace(
                '${ACCOUNT}',
                _ba.get_account_misc_read_val_2('resolvedAccountID',
                                                'UNKNOWN'))
            self._stats_button = ba.buttonwidget(
                color=(0.3, 0.6, 0.94),
                textcolor=(1.0, 1.0, 1.0),
                label=ba.Lstr(resource='statsText'),
                parent=columnwidget,
                autoselect=True,
                on_activate_call=ba.Call(ba.open_url, url),
                on_select_call=ba.WeakCall(
                    tab.set_public_party_selection,
                    Selection(party.get_key(),
                              SelectionComponent.STATS_BUTTON)),
                size=(120, 40),
                position=(sub_scroll_width * 0.66 + hpos, 1 + vpos),
                scale=0.9)
            if existing_selection == Selection(
                    party.get_key(), SelectionComponent.STATS_BUTTON):
                ba.containerwidget(edit=columnwidget,
                                   selected_child=self._stats_button)

        self._size_widget = ba.textwidget(
            text=str(party.size) + '/' + str(party.size_max),
            parent=columnwidget,
            size=(0, 0),
            position=(sub_scroll_width * 0.86 + hpos, 20 + vpos),
            scale=0.7,
            color=(0.8, 0.8, 0.8),
            h_align='right',
            v_align='center')

        if index == 0:
            ba.widget(edit=self._name_widget, up_widget=filter_text)
            if self._stats_button:
                ba.widget(edit=self._stats_button, up_widget=filter_text)

        self._ping_widget = ba.textwidget(parent=columnwidget,
                                          size=(0, 0),
                                          position=(sub_scroll_width * 0.94 +
                                                    hpos, 20 + vpos),
                                          scale=0.7,
                                          h_align='right',
                                          v_align='center')
        if party.ping is None:
            ba.textwidget(edit=self._ping_widget,
                          text='-',
                          color=(0.5, 0.5, 0.5))
        else:
            ba.textwidget(edit=self._ping_widget,
                          text=str(int(party.ping)),
                          color=(0, 1, 0) if party.ping <= ping_good else
                          (1, 1, 0) if party.ping <= ping_med else (1, 0, 0))

        party.clean_display_index = index
Пример #8
0
    def _build_server_entry_lines(self, lineheight: float,
                                  ordered_parties: List[PartyEntry],
                                  sub_scroll_height: float,
                                  sub_scroll_width: float) -> None:
        existing_selection = self._selection
        columnwidget = self._join_list_column
        first = True
        assert columnwidget
        for i, party in enumerate(ordered_parties):
            hpos = 20
            vpos = sub_scroll_height - lineheight * i - 50
            party.name_widget = ba.textwidget(
                text=ba.Lstr(value=party.name),
                parent=columnwidget,
                size=(sub_scroll_width * 0.63, 20),
                position=(0 + hpos, 4 + vpos),
                selectable=True,
                on_select_call=ba.WeakCall(
                    self._set_public_party_selection,
                    Selection(party.index, SelectionComponent.NAME)),
                on_activate_call=ba.WeakCall(self._on_public_party_activate,
                                             party),
                click_activate=True,
                maxwidth=sub_scroll_width * 0.45,
                corner_scale=1.4,
                autoselect=True,
                color=(1, 1, 1, 0.3 if party.ping is None else 1.0),
                h_align='left',
                v_align='center')
            ba.widget(edit=party.name_widget,
                      left_widget=self._join_text,
                      show_buffer_top=64.0,
                      show_buffer_bottom=64.0)
            if existing_selection == Selection(party.index,
                                               SelectionComponent.NAME):
                ba.containerwidget(edit=columnwidget,
                                   selected_child=party.name_widget)
            if party.stats_addr:
                url = party.stats_addr.replace(
                    '${ACCOUNT}',
                    _ba.get_account_misc_read_val_2('resolvedAccountID',
                                                    'UNKNOWN'))
                party.stats_button = ba.buttonwidget(
                    color=(0.3, 0.6, 0.94),
                    textcolor=(1.0, 1.0, 1.0),
                    label=ba.Lstr(resource='statsText'),
                    parent=columnwidget,
                    autoselect=True,
                    on_activate_call=ba.Call(ba.open_url, url),
                    on_select_call=ba.WeakCall(
                        self._set_public_party_selection,
                        Selection(party.index,
                                  SelectionComponent.STATS_BUTTON)),
                    size=(120, 40),
                    position=(sub_scroll_width * 0.66 + hpos, 1 + vpos),
                    scale=0.9)
                if existing_selection == Selection(
                        party.index, SelectionComponent.STATS_BUTTON):
                    ba.containerwidget(edit=columnwidget,
                                       selected_child=party.stats_button)
            else:
                if party.stats_button:
                    party.stats_button.delete()
                    party.stats_button = None

            if first:
                if party.stats_button:
                    ba.widget(edit=party.stats_button,
                              up_widget=self._filter_text)
                if party.name_widget:
                    ba.widget(edit=party.name_widget,
                              up_widget=self._filter_text)
                first = False

            party.size_widget = ba.textwidget(
                text=str(party.size) + '/' + str(party.size_max),
                parent=columnwidget,
                size=(0, 0),
                position=(sub_scroll_width * 0.86 + hpos, 20 + vpos),
                scale=0.7,
                color=(0.8, 0.8, 0.8),
                h_align='right',
                v_align='center')
            party.ping_widget = ba.textwidget(
                parent=columnwidget,
                size=(0, 0),
                position=(sub_scroll_width * 0.94 + hpos, 20 + vpos),
                scale=0.7,
                h_align='right',
                v_align='center')
            if party.ping is None:
                ba.textwidget(edit=party.ping_widget,
                              text='-',
                              color=(0.5, 0.5, 0.5))
            else:
                ping_good = _ba.get_account_misc_read_val('pingGood', 100)
                ping_med = _ba.get_account_misc_read_val('pingMed', 500)
                ba.textwidget(edit=party.ping_widget,
                              text=str(party.ping),
                              color=(0, 1, 0) if party.ping <= ping_good else
                              (1, 1, 0) if party.ping <= ping_med else
                              (1, 0, 0))
    def __init__(self, origin_widget: ba.Widget = None):
        scale_origin: Optional[tuple[float, float]]
        if origin_widget is not None:
            self._transition_out = 'out_scale'
            scale_origin = origin_widget.get_screen_space_center()
            transition = 'in_scale'
        else:
            self._transition_out = 'out_right'
            scale_origin = None
            transition = 'in_right'
        bg_color = (0.4, 0.4, 0.5)
        self._width = 540
        self._height = 350
        self._scroll_width = 400
        self._scroll_height = 200
        uiscale = ba.app.ui.uiscale
        base_scale = (2.0 if uiscale is ba.UIScale.SMALL else
                      1.6 if uiscale is ba.UIScale.MEDIUM else 1.1)
        super().__init__(root_widget=ba.containerwidget(
            size=(self._width, self._height),
            transition=transition,
            scale=base_scale,
            scale_origin_stack_offset=scale_origin,
            stack_offset=(0, -10) if uiscale is ba.UIScale.SMALL else (0, 0)))
        self._cancel_button = ba.buttonwidget(parent=self._root_widget,
                                              position=(30, self._height - 50),
                                              size=(50, 50),
                                              scale=0.7,
                                              label='',
                                              color=bg_color,
                                              on_activate_call=self._cancel,
                                              autoselect=True,
                                              icon=ba.gettexture('crossOut'),
                                              iconscale=1.2)
        ba.textwidget(
            parent=self._root_widget,
            position=(self._width * 0.5, self._height * 0.88),
            size=(0, 0),
            text=ba.Lstr(
                resource='accountSettingsWindow.unlinkAccountsInstructionsText'
            ),
            maxwidth=self._width * 0.7,
            color=ba.app.ui.infotextcolor,
            h_align='center',
            v_align='center')
        ba.containerwidget(edit=self._root_widget,
                           cancel_button=self._cancel_button)

        self._scrollwidget = ba.scrollwidget(
            parent=self._root_widget,
            highlight=False,
            position=((self._width - self._scroll_width) * 0.5,
                      self._height - 85 - self._scroll_height),
            size=(self._scroll_width, self._scroll_height))
        ba.containerwidget(edit=self._scrollwidget, claims_left_right=True)
        self._columnwidget = ba.columnwidget(parent=self._scrollwidget,
                                             border=2,
                                             margin=0,
                                             left_border=10)

        our_login_id = _ba.get_public_login_id()
        if our_login_id is None:
            entries = []
        else:
            account_infos = _ba.get_account_misc_read_val_2(
                'linkedAccounts2', [])
            entries = [{
                'name': ai['d'],
                'id': ai['id']
            } for ai in account_infos if ai['id'] != our_login_id]

        # (avoid getting our selection stuck on an empty column widget)
        if not entries:
            ba.containerwidget(edit=self._scrollwidget, selectable=False)
        for i, entry in enumerate(entries):
            txt = ba.textwidget(parent=self._columnwidget,
                                selectable=True,
                                text=entry['name'],
                                size=(self._scroll_width - 30, 30),
                                autoselect=True,
                                click_activate=True,
                                on_activate_call=ba.Call(
                                    self._on_entry_selected, entry))
            ba.widget(edit=txt, left_widget=self._cancel_button)
            if i == 0:
                ba.widget(edit=txt, up_widget=self._cancel_button)