2022-09-30 15:18:39 +05:30
__author__ = ' Droopy '
__version__ = 4.0
# ba_meta require api 7
import datetime
import json
import math
import os
import pickle
import random
import time
import urllib . request
import weakref
from threading import Thread
from typing import List , Tuple , Sequence , Optional , Dict , Any , cast
from hashlib import md5
import _ba
import ba
import bastd . ui . party
from bastd . ui . colorpicker import ColorPickerExact
from bastd . ui . confirm import ConfirmWindow
from bastd . ui . mainmenu import MainMenuWindow
from bastd . ui . popup import PopupMenuWindow , PopupWindow , PopupMenu
_ip = ' 127.0.0.1 '
_port = 43210
_ping = ' - '
url = ' http://bombsquadprivatechat.ml '
last_msg = None
my_directory = _ba . env ( ) [ ' python_directory_user ' ] + ' /UltraPartyWindowFiles/ '
quick_msg_file = my_directory + ' QuickMessages.txt '
cookies_file = my_directory + ' cookies.txt '
saved_ids_file = my_directory + ' saved_ids.json '
my_location = my_directory
def initialize ( ) :
config_defaults = { ' Party Chat Muted ' : False ,
' Chat Muted ' : False ,
' ping button ' : True ,
' IP button ' : True ,
' copy button ' : True ,
' Direct Send ' : False ,
' Colorful Chat ' : True ,
' Custom Commands ' : [ ] ,
' Message Notification ' : ' bottom ' ,
' Self Status ' : ' online ' ,
' Translate Source Language ' : ' ' ,
' Translate Destination Language ' : ' en ' ,
' Pronunciation ' : True
}
config = ba . app . config
for key in config_defaults :
if key not in config :
config [ key ] = config_defaults [ key ]
if not os . path . exists ( my_directory ) :
os . makedirs ( my_directory )
if not os . path . exists ( cookies_file ) :
with open ( cookies_file , ' wb ' ) as f :
pickle . dump ( { } , f )
if not os . path . exists ( saved_ids_file ) :
with open ( saved_ids_file , ' w ' ) as f :
data = { }
json . dump ( data , f )
def display_error ( msg = None ) :
if msg :
ba . screenmessage ( msg , ( 1 , 0 , 0 ) )
else :
ba . screenmessage ( ' Failed! ' , ( 1 , 0 , 0 ) )
ba . playsound ( ba . getsound ( ' error ' ) )
def display_success ( msg = None ) :
if msg :
ba . screenmessage ( msg , ( 0 , 1 , 0 ) )
else :
ba . screenmessage ( ' Successful! ' , ( 0 , 1 , 0 ) )
2022-09-30 09:51:51 +00:00
2022-09-30 15:18:39 +05:30
class Translate ( Thread ) :
def __init__ ( self , data , callback ) :
super ( ) . __init__ ( )
self . data = data
self . _callback = callback
2022-09-30 09:51:51 +00:00
2022-09-30 15:18:39 +05:30
def run ( self ) :
_ba . pushcall ( ba . Call ( ba . screenmessage , ' Translating... ' ) , from_other_thread = True )
response = messenger . _send_request ( f ' { url } /translate ' , self . data )
if response :
_ba . pushcall ( ba . Call ( self . _callback , response ) , from_other_thread = True )
2022-09-30 09:51:51 +00:00
2022-09-30 15:18:39 +05:30
class ColorTracker :
def __init__ ( self ) :
self . saved = { }
def _get_safe_color ( self , sender ) :
while True :
color = ( random . random ( ) , random . random ( ) , random . random ( ) )
s = 0
background = ba . app . config . get ( ' PartyWindow Main Color ' , ( 0.5 , 0.5 , 0.5 ) )
for i , j in zip ( color , background ) :
s + = ( i - j ) * * 2
if s > 0.1 :
self . saved [ sender ] = color
if len ( self . saved ) > 20 :
self . saved . pop ( list ( self . saved . keys ( ) ) [ 0 ] )
break
time . sleep ( 0.1 )
def _get_sender_color ( self , sender ) :
if sender not in self . saved :
self . thread = Thread ( target = self . _get_safe_color , args = ( sender , ) )
self . thread . start ( )
return ( 1 , 1 , 1 )
else :
return self . saved [ sender ]
class PrivateChatHandler :
def __init__ ( self ) :
self . pvt_msgs = { }
self . login_id = None
self . last_msg_id = None
self . logged_in = False
self . cookieProcessor = urllib . request . HTTPCookieProcessor ( )
self . opener = urllib . request . build_opener ( self . cookieProcessor )
self . filter = ' all '
self . pending_messages = [ ]
self . friends_status = { }
self . error = ' '
Thread ( target = self . _ping ) . start ( )
def _load_ids ( self ) :
with open ( saved_ids_file , ' r ' ) as f :
saved = json . load ( f )
if self . myid in saved :
self . saved_ids = saved [ self . myid ]
else :
self . saved_ids = { ' all ' : ' <all> ' }
def _dump_ids ( self ) :
with open ( saved_ids_file , ' r ' ) as f :
saved = json . load ( f )
with open ( saved_ids_file , ' w ' ) as f :
saved [ self . myid ] = self . saved_ids
json . dump ( saved , f )
def _ping ( self ) :
self . server_online = False
response = self . _send_request ( url = f ' { url } ' )
if not response :
self . error = ' Server offline '
elif response :
try :
self . server_online = True
version = float ( response . replace ( ' v ' , ' ' ) )
except :
self . error = ' Server offline '
def _signup ( self , registration_key ) :
data = dict ( pb_id = self . myid , registration_key = registration_key )
response = self . _send_request ( url = f ' { url } /signup ' , data = data )
if response :
if response == ' successful ' :
display_success ( ' Account Created Successfully ' )
self . _login ( registration_key = registration_key )
return True
display_error ( response )
def _save_cookie ( self ) :
with open ( cookies_file , ' rb ' ) as f :
cookies = pickle . load ( f )
with open ( cookies_file , ' wb ' ) as f :
for c in self . cookieProcessor . cookiejar :
cookie = pickle . dumps ( c )
break
cookies [ self . myid ] = cookie
pickle . dump ( cookies , f )
def _cookie_login ( self ) :
self . myid = ba . internal . get_v1_account_misc_read_val_2 ( ' resolvedAccountID ' , ' ' )
try :
with open ( cookies_file , ' rb ' ) as f :
cookies = pickle . load ( f )
except :
return False
if self . myid in cookies :
cookie = pickle . loads ( cookies [ self . myid ] )
self . cookieProcessor . cookiejar . set_cookie ( cookie )
self . opener = urllib . request . build_opener ( self . cookieProcessor )
response = self . _send_request ( url = f ' { url } /login ' )
if response . startswith ( ' logged in as ' ) :
self . logged_in = True
self . _load_ids ( )
display_success ( response )
return True
def _login ( self , registration_key ) :
self . myid = ba . internal . get_v1_account_misc_read_val_2 ( ' resolvedAccountID ' , ' ' )
data = dict ( pb_id = self . myid , registration_key = registration_key )
response = self . _send_request ( url = f ' { url } /login ' , data = data )
if response == ' successful ' :
self . logged_in = True
self . _load_ids ( )
self . _save_cookie ( )
display_success ( ' Account Logged in Successfully ' )
return True
else :
display_error ( response )
def _query ( self , pb_id = None ) :
if not pb_id :
pb_id = self . myid
response = self . _send_request ( url = f ' { url } /query/ { pb_id } ' )
if response == ' exists ' :
return True
return False
def _send_request ( self , url , data = None ) :
try :
if not data :
response = self . opener . open ( url )
else :
response = self . opener . open ( url , data = json . dumps ( data ) . encode ( ) )
if response . getcode ( ) != 200 :
display_error ( response . read ( ) . decode ( ) )
return None
else :
return response . read ( ) . decode ( )
except :
return None
def _save_id ( self , account_id , nickname = ' <default> ' , verify = True ) :
# display_success(f'Saving {account_id}. Please wait...')
if verify :
url = ' http://bombsquadgame.com/accountquery?id= ' + account_id
response = json . loads ( urllib . request . urlopen ( url ) . read ( ) . decode ( ) )
if ' error ' in response :
display_error ( ' Enter valid account id ' )
return False
self . saved_ids [ account_id ] = { }
name = None
if nickname == ' <default> ' :
name_html = response [ ' name_html ' ]
name = name_html . split ( ' > ' ) [ 1 ]
nick = name if name else nickname
else :
nick = nickname
self . saved_ids [ account_id ] = nick
self . _dump_ids ( )
display_success ( f ' Account added: { nick } ( { account_id } ) ' )
return True
def _remove_id ( self , account_id ) :
removed = self . saved_ids . pop ( account_id )
self . _dump_ids ( )
ba . screenmessage ( f ' Removed successfully: { removed } ( { account_id } ) ' , ( 0 , 1 , 0 ) )
ba . playsound ( ba . getsound ( ' shieldDown ' ) )
def _format_message ( self , msg ) :
filter = msg [ ' filter ' ]
if filter in self . saved_ids :
if self . filter == ' all ' :
message = ' [ ' + self . saved_ids [ filter ] + ' ] ' + msg [ ' message ' ]
else :
message = msg [ ' message ' ]
else :
2022-09-30 09:51:51 +00:00
message = ' [ ' + msg [ ' filter ' ] + ' ]: ' + \
' Message from unsaved id. Save id to view message. '
2022-09-30 15:18:39 +05:30
return message
def _get_status ( self , id , type = ' status ' ) :
info = self . friends_status . get ( id , { } )
if not info :
return ' - '
if type == ' status ' :
return info [ ' status ' ]
else :
last_seen = info [ " last_seen " ]
last_seen = _get_local_time ( last_seen )
ba . screenmessage ( f ' Last seen on: { last_seen } ' )
def _get_local_time ( utctime ) :
d = datetime . datetime . strptime ( utctime , ' %d - % m- % Y % H: % M: % S ' )
d = d . replace ( tzinfo = datetime . timezone . utc )
d = d . astimezone ( )
return d . strftime ( ' % B %d , \t \t % H: % M: % S ' )
def update_status ( ) :
if messenger . logged_in :
if ba . app . config [ ' Self Status ' ] == ' online ' :
host = _ba . get_connection_to_host_info ( ) . get ( ' name ' , ' ' )
if host :
my_status = f ' Playing in { host } '
else :
my_status = ' in Lobby '
ids_to_check = [ i for i in messenger . saved_ids if i != ' all ' ]
response = messenger . _send_request ( url = f ' { url } /updatestatus ' ,
data = dict ( self_status = my_status , ids = ids_to_check ) )
if response :
messenger . friends_status = json . loads ( response )
else :
messenger . friends_status = { }
def messenger_thread ( ) :
counter = 0
while True :
counter + = 1
time . sleep ( 0.6 )
check_new_message ( )
if counter > 5 :
counter = 0
update_status ( )
def check_new_message ( ) :
if messenger . logged_in :
if messenger . login_id != messenger . myid :
response = messenger . _send_request ( f ' { url } /first ' )
if response :
messenger . pvt_msgs = json . loads ( response )
if messenger . pvt_msgs [ ' all ' ] :
messenger . last_msg_id = messenger . pvt_msgs [ ' all ' ] [ - 1 ] [ ' id ' ]
messenger . login_id = messenger . myid
else :
response = messenger . _send_request ( f ' { url } /new/ { messenger . last_msg_id } ' )
if response :
new_msgs = json . loads ( response )
if new_msgs :
for msg in new_msgs [ ' messages ' ] :
if msg [ ' id ' ] > messenger . last_msg_id :
messenger . last_msg_id = msg [ ' id ' ]
messenger . pvt_msgs [ ' all ' ] . append (
dict ( id = msg [ ' id ' ] , filter = msg [ ' filter ' ] , message = msg [ ' message ' ] , sent = msg [ ' sent ' ] ) )
if len ( messenger . pvt_msgs [ ' all ' ] ) > 40 :
messenger . pvt_msgs [ ' all ' ] . pop ( 0 )
if msg [ ' filter ' ] not in messenger . pvt_msgs :
messenger . pvt_msgs [ msg [ ' filter ' ] ] = [
dict ( id = msg [ ' id ' ] , filter = msg [ ' filter ' ] , message = msg [ ' message ' ] , sent = msg [ ' sent ' ] ) ]
else :
messenger . pvt_msgs [ msg [ ' filter ' ] ] . append (
dict ( id = msg [ ' id ' ] , filter = msg [ ' filter ' ] , message = msg [ ' message ' ] , sent = msg [ ' sent ' ] ) )
if len ( messenger . pvt_msgs [ msg [ ' filter ' ] ] ) > 20 :
messenger . pvt_msgs [ msg [ ' filter ' ] ] . pop ( 0 )
messenger . pending_messages . append (
( messenger . _format_message ( msg ) , msg [ ' filter ' ] , msg [ ' sent ' ] ) )
def display_message ( msg , msg_type , filter = None , sent = None ) :
flag = None
notification = ba . app . config [ ' Message Notification ' ]
if _ba . app . ui . party_window :
if _ba . app . ui . party_window ( ) :
if _ba . app . ui . party_window ( ) . _private_chat :
flag = 1
if msg_type == ' private ' :
if messenger . filter == filter or messenger . filter == ' all ' :
_ba . app . ui . party_window ( ) . on_chat_message ( msg , sent )
else :
if notification == ' top ' :
ba . screenmessage ( msg , ( 1 , 1 , 0 ) , True , ba . gettexture ( ' coin ' ) )
else :
ba . screenmessage ( msg , ( 1 , 1 , 0 ) , False )
else :
ba . screenmessage ( msg , ( 0.2 , 1.0 , 1.0 ) , True , ba . gettexture ( ' circleShadow ' ) )
else :
flag = 1
if msg_type == ' private ' :
if notification == ' top ' :
ba . screenmessage ( msg , ( 1 , 1 , 0 ) , True , ba . gettexture ( ' coin ' ) )
else :
ba . screenmessage ( msg , ( 1 , 1 , 0 ) , False )
if not flag :
if msg_type == ' private ' :
if notification == ' top ' :
ba . screenmessage ( msg , ( 1 , 1 , 0 ) , True , ba . gettexture ( ' coin ' ) )
else :
ba . screenmessage ( msg , ( 1 , 1 , 0 ) , False )
else :
ba . screenmessage ( msg , ( 0.2 , 1.0 , 1.0 ) , True , ba . gettexture ( ' circleShadow ' ) )
def msg_displayer ( ) :
for msg in messenger . pending_messages :
display_message ( msg [ 0 ] , ' private ' , msg [ 1 ] , msg [ 2 ] )
messenger . pending_messages . remove ( msg )
if ba . app . config [ ' Chat Muted ' ] and not ba . app . config [ ' Party Chat Muted ' ] :
global last_msg
last = _ba . get_chat_messages ( )
lm = last [ - 1 ] if last else None
if lm != last_msg :
last_msg = lm
display_message ( lm , ' public ' )
class SortQuickMessages :
def __init__ ( self ) :
uiscale = ba . app . ui . uiscale
bg_color = ba . app . config . get ( ' PartyWindow Main Color ' , ( 0.5 , 0.5 , 0.5 ) )
self . _width = 750 if uiscale is ba . UIScale . SMALL else 600
self . _height = ( 300 if uiscale is ba . UIScale . SMALL else
325 if uiscale is ba . UIScale . MEDIUM else 350 )
self . _root_widget = ba . containerwidget (
size = ( self . _width , self . _height ) ,
transition = ' in_right ' ,
on_outside_click_call = self . _save ,
color = bg_color ,
parent = _ba . get_special_widget ( ' overlay_stack ' ) ,
scale = ( 2.0 if uiscale is ba . UIScale . SMALL else
1.3 if uiscale is ba . UIScale . MEDIUM else 1.0 ) ,
stack_offset = ( 0 , - 16 ) if uiscale is ba . UIScale . SMALL else ( 0 , 0 ) )
ba . textwidget ( parent = self . _root_widget ,
position = ( - 10 , self . _height - 50 ) ,
size = ( self . _width , 25 ) ,
text = ' Sort Quick Messages ' ,
color = ba . app . ui . title_color ,
scale = 1.05 ,
h_align = ' center ' ,
v_align = ' center ' ,
maxwidth = 270 )
b_textcolor = ( 0.4 , 0.75 , 0.5 )
up_button = ba . buttonwidget ( parent = self . _root_widget ,
position = ( 10 , 170 ) ,
size = ( 75 , 75 ) ,
on_activate_call = self . _move_up ,
label = ba . charstr ( ba . SpecialChar . UP_ARROW ) ,
button_type = ' square ' ,
color = bg_color ,
textcolor = b_textcolor ,
autoselect = True ,
repeat = True )
down_button = ba . buttonwidget ( parent = self . _root_widget ,
position = ( 10 , 75 ) ,
size = ( 75 , 75 ) ,
on_activate_call = self . _move_down ,
label = ba . charstr ( ba . SpecialChar . DOWN_ARROW ) ,
button_type = ' square ' ,
color = bg_color ,
textcolor = b_textcolor ,
autoselect = True ,
repeat = True )
self . _scroll_width = self . _width - 150
self . _scroll_height = self . _height - 110
self . _scrollwidget = ba . scrollwidget (
parent = self . _root_widget ,
size = ( self . _scroll_width , self . _scroll_height ) ,
color = bg_color ,
position = ( 100 , 40 ) )
self . _columnwidget = ba . columnwidget (
parent = self . _scrollwidget ,
border = 2 ,
margin = 0 )
with open ( quick_msg_file , ' r ' ) as f :
self . msgs = f . read ( ) . split ( ' \n ' )
self . _msg_selected = None
self . _refresh ( )
ba . containerwidget ( edit = self . _root_widget ,
on_cancel_call = self . _save )
def _refresh ( self ) :
for child in self . _columnwidget . get_children ( ) :
child . delete ( )
for msg in enumerate ( self . msgs ) :
txt = ba . textwidget (
parent = self . _columnwidget ,
size = ( self . _scroll_width - 10 , 30 ) ,
selectable = True ,
always_highlight = True ,
on_select_call = ba . Call ( self . _on_msg_select , msg ) ,
text = msg [ 1 ] ,
h_align = ' left ' ,
v_align = ' center ' ,
maxwidth = self . _scroll_width )
if msg == self . _msg_selected :
ba . columnwidget ( edit = self . _columnwidget ,
selected_child = txt ,
visible_child = txt )
def _on_msg_select ( self , msg ) :
self . _msg_selected = msg
def _move_up ( self ) :
index = self . _msg_selected [ 0 ]
msg = self . _msg_selected [ 1 ]
if index :
self . msgs . insert ( ( index - 1 ) , self . msgs . pop ( index ) )
self . _msg_selected = ( index - 1 , msg )
self . _refresh ( )
def _move_down ( self ) :
index = self . _msg_selected [ 0 ]
msg = self . _msg_selected [ 1 ]
if index + 1 < len ( self . msgs ) :
self . msgs . insert ( ( index + 1 ) , self . msgs . pop ( index ) )
self . _msg_selected = ( index + 1 , msg )
self . _refresh ( )
def _save ( self ) - > None :
try :
with open ( quick_msg_file , ' w ' ) as f :
f . write ( ' \n ' . join ( self . msgs ) )
except :
ba . print_exception ( )
ba . screenmessage ( ' Error! ' , ( 1 , 0 , 0 ) )
ba . containerwidget (
edit = self . _root_widget ,
transition = ' out_right ' )
class TranslationSettings :
def __init__ ( self ) :
uiscale = ba . app . ui . uiscale
height = ( 300 if uiscale is ba . UIScale . SMALL else
350 if uiscale is ba . UIScale . MEDIUM else 400 )
width = ( 500 if uiscale is ba . UIScale . SMALL else
600 if uiscale is ba . UIScale . MEDIUM else 650 )
self . _transition_out : Optional [ str ]
scale_origin : Optional [ Tuple [ float , float ] ]
self . _transition_out = ' out_scale '
scale_origin = 10
transition = ' in_scale '
scale_origin = None
cancel_is_selected = False
cfg = ba . app . config
bg_color = cfg . get ( ' PartyWindow Main Color ' , ( 0.5 , 0.5 , 0.5 ) )
LANGUAGES = {
' ' : ' Auto-Detect ' ,
' af ' : ' afrikaans ' ,
' sq ' : ' albanian ' ,
' am ' : ' amharic ' ,
' ar ' : ' arabic ' ,
' hy ' : ' armenian ' ,
' az ' : ' azerbaijani ' ,
' eu ' : ' basque ' ,
' be ' : ' belarusian ' ,
' bn ' : ' bengali ' ,
' bs ' : ' bosnian ' ,
' bg ' : ' bulgarian ' ,
' ca ' : ' catalan ' ,
' ceb ' : ' cebuano ' ,
' ny ' : ' chichewa ' ,
' zh-cn ' : ' chinese (simplified) ' ,
' zh-tw ' : ' chinese (traditional) ' ,
' co ' : ' corsican ' ,
' hr ' : ' croatian ' ,
' cs ' : ' czech ' ,
' da ' : ' danish ' ,
' nl ' : ' dutch ' ,
' en ' : ' english ' ,
' eo ' : ' esperanto ' ,
' et ' : ' estonian ' ,
' tl ' : ' filipino ' ,
' fi ' : ' finnish ' ,
' fr ' : ' french ' ,
' fy ' : ' frisian ' ,
' gl ' : ' galician ' ,
' ka ' : ' georgian ' ,
' de ' : ' german ' ,
' el ' : ' greek ' ,
' gu ' : ' gujarati ' ,
' ht ' : ' haitian creole ' ,
' ha ' : ' hausa ' ,
' haw ' : ' hawaiian ' ,
' iw ' : ' hebrew ' ,
' he ' : ' hebrew ' ,
' hi ' : ' hindi ' ,
' hmn ' : ' hmong ' ,
' hu ' : ' hungarian ' ,
' is ' : ' icelandic ' ,
' ig ' : ' igbo ' ,
' id ' : ' indonesian ' ,
' ga ' : ' irish ' ,
' it ' : ' italian ' ,
' ja ' : ' japanese ' ,
' jw ' : ' javanese ' ,
' kn ' : ' kannada ' ,
' kk ' : ' kazakh ' ,
' km ' : ' khmer ' ,
' ko ' : ' korean ' ,
' ku ' : ' kurdish (kurmanji) ' ,
' ky ' : ' kyrgyz ' ,
' lo ' : ' lao ' ,
' la ' : ' latin ' ,
' lv ' : ' latvian ' ,
' lt ' : ' lithuanian ' ,
' lb ' : ' luxembourgish ' ,
' mk ' : ' macedonian ' ,
' mg ' : ' malagasy ' ,
' ms ' : ' malay ' ,
' ml ' : ' malayalam ' ,
' mt ' : ' maltese ' ,
' mi ' : ' maori ' ,
' mr ' : ' marathi ' ,
' mn ' : ' mongolian ' ,
' my ' : ' myanmar (burmese) ' ,
' ne ' : ' nepali ' ,
' no ' : ' norwegian ' ,
' or ' : ' odia ' ,
' ps ' : ' pashto ' ,
' fa ' : ' persian ' ,
' pl ' : ' polish ' ,
' pt ' : ' portuguese ' ,
' pa ' : ' punjabi ' ,
' ro ' : ' romanian ' ,
' ru ' : ' russian ' ,
' sm ' : ' samoan ' ,
' gd ' : ' scots gaelic ' ,
' sr ' : ' serbian ' ,
' st ' : ' sesotho ' ,
' sn ' : ' shona ' ,
' sd ' : ' sindhi ' ,
' si ' : ' sinhala ' ,
' sk ' : ' slovak ' ,
' sl ' : ' slovenian ' ,
' so ' : ' somali ' ,
' es ' : ' spanish ' ,
' su ' : ' sundanese ' ,
' sw ' : ' swahili ' ,
' sv ' : ' swedish ' ,
' tg ' : ' tajik ' ,
' ta ' : ' tamil ' ,
' te ' : ' telugu ' ,
' th ' : ' thai ' ,
' tr ' : ' turkish ' ,
' uk ' : ' ukrainian ' ,
' ur ' : ' urdu ' ,
' ug ' : ' uyghur ' ,
' uz ' : ' uzbek ' ,
' vi ' : ' vietnamese ' ,
' cy ' : ' welsh ' ,
' xh ' : ' xhosa ' ,
' yi ' : ' yiddish ' ,
' yo ' : ' yoruba ' ,
' zu ' : ' zulu ' }
self . root_widget = ba . containerwidget (
size = ( width , height ) ,
color = bg_color ,
transition = transition ,
toolbar_visibility = ' menu_minimal_no_back ' ,
parent = _ba . get_special_widget ( ' overlay_stack ' ) ,
on_outside_click_call = self . _cancel ,
scale = ( 2.1 if uiscale is ba . UIScale . SMALL else
1.5 if uiscale is ba . UIScale . MEDIUM else 1.0 ) ,
scale_origin_stack_offset = scale_origin )
ba . textwidget ( parent = self . root_widget ,
position = ( width * 0.5 , height - 45 ) ,
size = ( 20 , 20 ) ,
h_align = ' center ' ,
v_align = ' center ' ,
text = " Text Translation " ,
scale = 0.9 ,
color = ( 5 , 5 , 5 ) )
cbtn = btn = ba . buttonwidget ( parent = self . root_widget ,
autoselect = True ,
position = ( 30 , height - 60 ) ,
size = ( 30 , 30 ) ,
label = ba . charstr ( ba . SpecialChar . BACK ) ,
button_type = ' backSmall ' ,
on_activate_call = self . _cancel )
source_lang_text = ba . textwidget ( parent = self . root_widget ,
position = ( 40 , height - 110 ) ,
size = ( 20 , 20 ) ,
h_align = ' left ' ,
v_align = ' center ' ,
text = " Source Language : " ,
scale = 0.9 ,
color = ( 1 , 1 , 1 ) )
source_lang_menu = PopupMenu (
parent = self . root_widget ,
position = ( 330 if uiscale is ba . UIScale . SMALL else 400 , height - 115 ) ,
width = 200 ,
scale = ( 2.8 if uiscale is ba . UIScale . SMALL else
1.8 if uiscale is ba . UIScale . MEDIUM else 1.2 ) ,
current_choice = cfg [ ' Translate Source Language ' ] ,
choices = LANGUAGES . keys ( ) ,
choices_display = ( ba . Lstr ( value = i ) for i in LANGUAGES . values ( ) ) ,
button_size = ( 130 , 35 ) ,
on_value_change_call = self . _change_source )
destination_lang_text = ba . textwidget ( parent = self . root_widget ,
position = ( 40 , height - 165 ) ,
size = ( 20 , 20 ) ,
h_align = ' left ' ,
v_align = ' center ' ,
text = " Destination Language : " ,
scale = 0.9 ,
color = ( 1 , 1 , 1 ) )
destination_lang_menu = PopupMenu (
parent = self . root_widget ,
position = ( 330 if uiscale is ba . UIScale . SMALL else 400 , height - 170 ) ,
width = 200 ,
scale = ( 2.8 if uiscale is ba . UIScale . SMALL else
1.8 if uiscale is ba . UIScale . MEDIUM else 1.2 ) ,
current_choice = cfg [ ' Translate Destination Language ' ] ,
choices = list ( LANGUAGES . keys ( ) ) [ 1 : ] ,
choices_display = list ( ba . Lstr ( value = i ) for i in LANGUAGES . values ( ) ) [ 1 : ] ,
button_size = ( 130 , 35 ) ,
on_value_change_call = self . _change_destination )
try :
translation_mode_text = ba . textwidget ( parent = self . root_widget ,
2022-09-30 09:51:51 +00:00
position = ( 40 , height - 215 ) ,
size = ( 20 , 20 ) ,
h_align = ' left ' ,
v_align = ' center ' ,
text = " Translate Mode " ,
scale = 0.9 ,
color = ( 1 , 1 , 1 ) )
2022-09-30 15:18:39 +05:30
decoration = ba . textwidget ( parent = self . root_widget ,
2022-09-30 09:51:51 +00:00
position = ( 40 , height - 225 ) ,
size = ( 20 , 20 ) ,
h_align = ' left ' ,
v_align = ' center ' ,
text = " ________________ " ,
scale = 0.9 ,
color = ( 1 , 1 , 1 ) )
2022-09-30 15:18:39 +05:30
language_char_text = ba . textwidget ( parent = self . root_widget ,
2022-09-30 09:51:51 +00:00
position = ( 85 , height - 273 ) ,
size = ( 20 , 20 ) ,
h_align = ' left ' ,
v_align = ' center ' ,
text = ' Normal Translation ' ,
scale = 0.6 ,
color = ( 1 , 1 , 1 ) )
2022-09-30 15:18:39 +05:30
pronunciation_text = ba . textwidget ( parent = self . root_widget ,
2022-09-30 09:51:51 +00:00
position = ( 295 , height - 273 ) ,
size = ( 20 , 20 ) ,
h_align = ' left ' ,
v_align = ' center ' ,
text = " Show Prononciation " ,
scale = 0.6 ,
color = ( 1 , 1 , 1 ) )
2022-09-30 15:18:39 +05:30
from bastd . ui . radiogroup import make_radio_group
cur_val = ba . app . config . get ( ' Pronunciation ' , True )
cb1 = ba . checkboxwidget (
2022-09-30 09:51:51 +00:00
parent = self . root_widget ,
position = ( 250 , height - 275 ) ,
size = ( 20 , 20 ) ,
maxwidth = 300 ,
scale = 1 ,
autoselect = True ,
text = " " )
2022-09-30 15:18:39 +05:30
cb2 = ba . checkboxwidget (
2022-09-30 09:51:51 +00:00
parent = self . root_widget ,
position = ( 40 , height - 275 ) ,
size = ( 20 , 20 ) ,
maxwidth = 300 ,
scale = 1 ,
autoselect = True ,
text = " " )
2022-09-30 15:18:39 +05:30
make_radio_group ( ( cb1 , cb2 ) , ( True , False ) , cur_val ,
self . _actions_changed )
except Exception as e :
print ( e )
pass
ba . containerwidget ( edit = self . root_widget , cancel_button = btn )
def _change_source ( self , choice ) :
cfg = ba . app . config
cfg [ ' Translate Source Language ' ] = choice
cfg . apply_and_commit ( )
def _change_destination ( self , choice ) :
cfg = ba . app . config
cfg [ ' Translate Destination Language ' ] = choice
cfg . apply_and_commit ( )
def _actions_changed ( self , v : str ) - > None :
cfg = ba . app . config
cfg [ ' Pronunciation ' ] = v
cfg . apply_and_commit ( )
def _cancel ( self ) - > None :
ba . containerwidget ( edit = self . root_widget , transition = ' out_scale ' )
SettingsWindow ( )
class SettingsWindow :
def __init__ ( self ) :
uiscale = ba . app . ui . uiscale
height = ( 300 if uiscale is ba . UIScale . SMALL else
350 if uiscale is ba . UIScale . MEDIUM else 400 )
width = ( 500 if uiscale is ba . UIScale . SMALL else
600 if uiscale is ba . UIScale . MEDIUM else 650 )
scroll_h = ( 200 if uiscale is ba . UIScale . SMALL else
250 if uiscale is ba . UIScale . MEDIUM else 270 )
scroll_w = ( 450 if uiscale is ba . UIScale . SMALL else
550 if uiscale is ba . UIScale . MEDIUM else 600 )
self . _transition_out : Optional [ str ]
scale_origin : Optional [ Tuple [ float , float ] ]
self . _transition_out = ' out_scale '
scale_origin = 10
transition = ' in_scale '
scale_origin = None
cancel_is_selected = False
cfg = ba . app . config
bg_color = cfg . get ( ' PartyWindow Main Color ' , ( 0.5 , 0.5 , 0.5 ) )
self . root_widget = ba . containerwidget (
size = ( width , height ) ,
color = bg_color ,
transition = transition ,
toolbar_visibility = ' menu_minimal_no_back ' ,
parent = _ba . get_special_widget ( ' overlay_stack ' ) ,
on_outside_click_call = self . _cancel ,
scale = ( 2.1 if uiscale is ba . UIScale . SMALL else
1.5 if uiscale is ba . UIScale . MEDIUM else 1.0 ) ,
scale_origin_stack_offset = scale_origin )
ba . textwidget ( parent = self . root_widget ,
position = ( width * 0.5 , height - 45 ) ,
size = ( 20 , 20 ) ,
h_align = ' center ' ,
v_align = ' center ' ,
text = " Custom Settings " ,
scale = 0.9 ,
color = ( 5 , 5 , 5 ) )
cbtn = btn = ba . buttonwidget ( parent = self . root_widget ,
autoselect = True ,
position = ( 30 , height - 60 ) ,
size = ( 30 , 30 ) ,
label = ba . charstr ( ba . SpecialChar . BACK ) ,
button_type = ' backSmall ' ,
on_activate_call = self . _cancel )
scroll_position = ( 30 if uiscale is ba . UIScale . SMALL else
40 if uiscale is ba . UIScale . MEDIUM else 50 )
self . _scrollwidget = ba . scrollwidget ( parent = self . root_widget ,
position = ( 30 , scroll_position ) ,
simple_culling_v = 20.0 ,
highlight = False ,
size = ( scroll_w , scroll_h ) ,
selection_loops_to_parent = True )
ba . widget ( edit = self . _scrollwidget , right_widget = self . _scrollwidget )
self . _subcontainer = ba . columnwidget ( parent = self . _scrollwidget ,
selection_loops_to_parent = True )
ip_button = ba . checkboxwidget (
parent = self . _subcontainer ,
size = ( 300 , 30 ) ,
maxwidth = 300 ,
textcolor = ( ( 0 , 1 , 0 ) if cfg [ ' IP button ' ] else ( 0.95 , 0.65 , 0 ) ) ,
scale = 1 ,
value = cfg [ ' IP button ' ] ,
autoselect = True ,
text = " IP Button " ,
on_value_change_call = self . ip_button )
ping_button = ba . checkboxwidget (
parent = self . _subcontainer ,
size = ( 300 , 30 ) ,
maxwidth = 300 ,
textcolor = ( ( 0 , 1 , 0 ) if cfg [ ' ping button ' ] else ( 0.95 , 0.65 , 0 ) ) ,
scale = 1 ,
value = cfg [ ' ping button ' ] ,
autoselect = True ,
text = " Ping Button " ,
on_value_change_call = self . ping_button )
copy_button = ba . checkboxwidget (
parent = self . _subcontainer ,
size = ( 300 , 30 ) ,
maxwidth = 300 ,
textcolor = ( ( 0 , 1 , 0 ) if cfg [ ' copy button ' ] else ( 0.95 , 0.65 , 0 ) ) ,
scale = 1 ,
value = cfg [ ' copy button ' ] ,
autoselect = True ,
text = " Copy Text Button " ,
on_value_change_call = self . copy_button )
direct_send = ba . checkboxwidget (
parent = self . _subcontainer ,
size = ( 300 , 30 ) ,
maxwidth = 300 ,
textcolor = ( ( 0 , 1 , 0 ) if cfg [ ' Direct Send ' ] else ( 0.95 , 0.65 , 0 ) ) ,
scale = 1 ,
value = cfg [ ' Direct Send ' ] ,
autoselect = True ,
text = " Directly Send Custom Commands " ,
on_value_change_call = self . direct_send )
colorfulchat = ba . checkboxwidget (
parent = self . _subcontainer ,
size = ( 300 , 30 ) ,
maxwidth = 300 ,
textcolor = ( ( 0 , 1 , 0 ) if cfg [ ' Colorful Chat ' ] else ( 0.95 , 0.65 , 0 ) ) ,
scale = 1 ,
value = cfg [ ' Colorful Chat ' ] ,
autoselect = True ,
text = " Colorful Chat " ,
on_value_change_call = self . colorful_chat )
msg_notification_text = ba . textwidget ( parent = self . _subcontainer ,
scale = 0.8 ,
color = ( 1 , 1 , 1 ) ,
text = ' Message Notifcation: ' ,
size = ( 100 , 30 ) ,
h_align = ' left ' ,
v_align = ' center ' )
msg_notification_widget = PopupMenu (
parent = self . _subcontainer ,
position = ( 100 , height - 1200 ) ,
width = 200 ,
scale = ( 2.8 if uiscale is ba . UIScale . SMALL else
1.8 if uiscale is ba . UIScale . MEDIUM else 1.2 ) ,
choices = [ ' top ' , ' bottom ' ] ,
current_choice = ba . app . config [ ' Message Notification ' ] ,
button_size = ( 80 , 25 ) ,
on_value_change_call = self . _change_notification )
self_status_text = ba . textwidget ( parent = self . _subcontainer ,
scale = 0.8 ,
color = ( 1 , 1 , 1 ) ,
text = ' Self Status: ' ,
size = ( 100 , 30 ) ,
h_align = ' left ' ,
v_align = ' center ' )
self_status_widget = PopupMenu (
parent = self . _subcontainer ,
position = ( 50 , height - 1000 ) ,
width = 200 ,
scale = ( 2.8 if uiscale is ba . UIScale . SMALL else
1.8 if uiscale is ba . UIScale . MEDIUM else 1.2 ) ,
choices = [ ' online ' , ' offline ' ] ,
current_choice = ba . app . config [ ' Self Status ' ] ,
button_size = ( 80 , 25 ) ,
on_value_change_call = self . _change_status )
ba . containerwidget ( edit = self . root_widget , cancel_button = btn )
ba . containerwidget ( edit = self . root_widget ,
selected_child = ( cbtn if cbtn is not None
2022-09-30 09:51:51 +00:00
and cancel_is_selected else None ) ,
2022-09-30 15:18:39 +05:30
start_button = None )
self . _translation_btn = ba . buttonwidget ( parent = self . _subcontainer ,
scale = 1.2 ,
position = ( 100 , 1200 ) ,
size = ( 150 , 50 ) ,
label = ' Translate Settings ' ,
on_activate_call = self . _translaton_btn ,
autoselect = True )
def ip_button ( self , value : bool ) :
cfg = ba . app . config
cfg [ ' IP button ' ] = value
cfg . apply_and_commit ( )
if cfg [ ' IP button ' ] :
ba . screenmessage ( " IP Button is now enabled " , color = ( 0 , 1 , 0 ) )
else :
ba . screenmessage ( " IP Button is now disabled " , color = ( 1 , 0.7 , 0 ) )
def ping_button ( self , value : bool ) :
cfg = ba . app . config
cfg [ ' ping button ' ] = value
cfg . apply_and_commit ( )
if cfg [ ' ping button ' ] :
ba . screenmessage ( " Ping Button is now enabled " , color = ( 0 , 1 , 0 ) )
else :
ba . screenmessage ( " Ping Button is now disabled " , color = ( 1 , 0.7 , 0 ) )
def copy_button ( self , value : bool ) :
cfg = ba . app . config
cfg [ ' copy button ' ] = value
cfg . apply_and_commit ( )
if cfg [ ' copy button ' ] :
ba . screenmessage ( " Copy Text Button is now enabled " , color = ( 0 , 1 , 0 ) )
else :
ba . screenmessage ( " Copy Text Button is now disabled " , color = ( 1 , 0.7 , 0 ) )
def direct_send ( self , value : bool ) :
cfg = ba . app . config
cfg [ ' Direct Send ' ] = value
cfg . apply_and_commit ( )
def colorful_chat ( self , value : bool ) :
cfg = ba . app . config
cfg [ ' Colorful Chat ' ] = value
cfg . apply_and_commit ( )
def _change_notification ( self , choice ) :
cfg = ba . app . config
cfg [ ' Message Notification ' ] = choice
cfg . apply_and_commit ( )
def _change_status ( self , choice ) :
cfg = ba . app . config
cfg [ ' Self Status ' ] = choice
cfg . apply_and_commit ( )
def _translaton_btn ( self ) :
try :
ba . containerwidget ( edit = self . root_widget , transition = ' out_scale ' )
TranslationSettings ( )
except Exception as e :
print ( e )
pass
def _cancel ( self ) - > None :
ba . containerwidget ( edit = self . root_widget , transition = ' out_scale ' )
class PartyWindow ( ba . Window ) :
""" Party list/chat window. """
def __del__ ( self ) - > None :
_ba . set_party_window_open ( False )
def __init__ ( self , origin : Sequence [ float ] = ( 0 , 0 ) ) :
self . _private_chat = False
self . _firstcall = True
self . ping_server ( )
_ba . set_party_window_open ( True )
self . _r = ' partyWindow '
self . _popup_type : Optional [ str ] = None
self . _popup_party_member_client_id : Optional [ int ] = None
self . _popup_party_member_is_host : Optional [ bool ] = None
self . _width = 500
uiscale = ba . app . ui . uiscale
self . _height = ( 365 if uiscale is ba . UIScale . SMALL else
480 if uiscale is ba . UIScale . MEDIUM else 600 )
self . bg_color = ba . app . config . get ( ' PartyWindow Main Color ' , ( 0.5 , 0.5 , 0.5 ) )
self . ping_timer = ba . Timer ( 5 , ba . WeakCall ( self . ping_server ) , repeat = True )
ba . Window . __init__ ( self , root_widget = ba . containerwidget (
size = ( self . _width , self . _height ) ,
transition = ' in_scale ' ,
color = self . bg_color ,
parent = _ba . get_special_widget ( ' overlay_stack ' ) ,
on_outside_click_call = self . close_with_sound ,
scale_origin_stack_offset = origin ,
scale = ( 2.0 if uiscale is ba . UIScale . SMALL else
1.35 if uiscale is ba . UIScale . MEDIUM else 1.0 ) ,
stack_offset = ( 0 , - 10 ) if uiscale is ba . UIScale . SMALL else (
240 , 0 ) if uiscale is ba . UIScale . MEDIUM else ( 330 , 20 ) ) )
self . _cancel_button = ba . buttonwidget ( parent = self . _root_widget ,
scale = 0.7 ,
position = ( 30 , self . _height - 47 ) ,
size = ( 50 , 50 ) ,
label = ' ' ,
on_activate_call = self . close ,
autoselect = True ,
color = self . bg_color ,
icon = ba . gettexture ( ' crossOut ' ) ,
iconscale = 1.2 )
ba . containerwidget ( edit = self . _root_widget ,
cancel_button = self . _cancel_button )
self . _menu_button = ba . buttonwidget (
parent = self . _root_widget ,
scale = 0.7 ,
position = ( self . _width - 80 , self . _height - 47 ) ,
size = ( 50 , 50 ) ,
label = ' ... ' ,
autoselect = True ,
button_type = ' square ' ,
on_activate_call = ba . WeakCall ( self . _on_menu_button_press ) ,
color = self . bg_color ,
iconscale = 1.2 )
info = _ba . get_connection_to_host_info ( )
if info . get ( ' name ' , ' ' ) != ' ' :
self . title = ba . Lstr ( value = info [ ' name ' ] )
else :
self . title = ba . Lstr ( resource = self . _r + ' .titleText ' )
self . _title_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.9 ,
color = ( 0.5 , 0.7 , 0.5 ) ,
text = self . title ,
size = ( 0 , 0 ) ,
position = ( self . _width * 0.47 ,
self . _height - 29 ) ,
maxwidth = self . _width * 0.6 ,
h_align = ' center ' ,
v_align = ' center ' )
self . _empty_str = ba . textwidget ( parent = self . _root_widget ,
scale = 0.75 ,
size = ( 0 , 0 ) ,
position = ( self . _width * 0.5 ,
self . _height - 65 ) ,
maxwidth = self . _width * 0.85 ,
h_align = ' center ' ,
v_align = ' center ' )
self . _scroll_width = self . _width - 50
self . _scrollwidget = ba . scrollwidget ( parent = self . _root_widget ,
size = ( self . _scroll_width ,
self . _height - 200 ) ,
position = ( 30 , 80 ) ,
color = self . bg_color )
self . _columnwidget = ba . columnwidget ( parent = self . _scrollwidget ,
border = 2 ,
margin = 0 )
ba . widget ( edit = self . _menu_button , down_widget = self . _columnwidget )
self . _muted_text = ba . textwidget (
parent = self . _root_widget ,
position = ( self . _width * 0.5 , self . _height * 0.5 ) ,
size = ( 0 , 0 ) ,
h_align = ' center ' ,
v_align = ' center ' ,
text = ba . Lstr ( resource = ' chatMutedText ' ) )
self . _text_field = txt = ba . textwidget (
parent = self . _root_widget ,
editable = True ,
size = ( 500 , 40 ) ,
position = ( 54 , 39 ) ,
text = ' ' ,
maxwidth = 494 ,
shadow = 0.3 ,
flatness = 1.0 ,
description = ba . Lstr ( resource = self . _r + ' .chatMessageText ' ) ,
autoselect = True ,
v_align = ' center ' ,
corner_scale = 0.7 )
ba . widget ( edit = self . _scrollwidget ,
autoselect = True ,
left_widget = self . _cancel_button ,
up_widget = self . _cancel_button ,
down_widget = self . _text_field )
ba . widget ( edit = self . _columnwidget ,
autoselect = True ,
up_widget = self . _cancel_button ,
down_widget = self . _text_field )
ba . containerwidget ( edit = self . _root_widget , selected_child = txt )
self . _send_button = btn = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 50 , 35 ) ,
label = ba . Lstr ( resource = self . _r + ' .sendText ' ) ,
button_type = ' square ' ,
autoselect = True ,
color = self . bg_color ,
position = ( self . _width - 90 , 35 ) ,
on_activate_call = self . _send_chat_message )
ba . textwidget ( edit = txt , on_return_press_call = btn . activate )
self . _previous_button = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 30 , 30 ) ,
label = ba . charstr ( ba . SpecialChar . UP_ARROW ) ,
button_type = ' square ' ,
autoselect = True ,
position = ( 15 , 57 ) ,
color = self . bg_color ,
scale = 0.75 ,
on_activate_call = self . _previous_message )
self . _next_button = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 30 , 30 ) ,
label = ba . charstr ( ba . SpecialChar . DOWN_ARROW ) ,
button_type = ' square ' ,
autoselect = True ,
color = self . bg_color ,
scale = 0.75 ,
position = ( 15 , 28 ) ,
on_activate_call = self . _next_message )
self . _translate_button = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 55 , 47 ) ,
label = " Trans " ,
button_type = ' square ' ,
autoselect = True ,
color = self . bg_color ,
scale = 0.75 ,
position = ( self . _width - 28 , 35 ) ,
on_activate_call = self . _translate )
if ba . app . config [ ' copy button ' ] :
self . _copy_button = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 15 , 15 ) ,
label = ' © ' ,
button_type = ' backSmall ' ,
autoselect = True ,
color = self . bg_color ,
position = ( self . _width - 40 , 80 ) ,
on_activate_call = self . _copy_to_clipboard )
self . _ping_button = None
if info . get ( ' name ' , ' ' ) != ' ' :
if ba . app . config [ ' ping button ' ] :
self . _ping_button = ba . buttonwidget (
parent = self . _root_widget ,
scale = 0.7 ,
position = ( self . _width - 538 , self . _height - 57 ) ,
size = ( 75 , 75 ) ,
autoselect = True ,
button_type = ' square ' ,
label = f ' { _ping } ' ,
on_activate_call = self . _send_ping ,
color = self . bg_color ,
text_scale = 2.3 ,
iconscale = 1.2 )
if ba . app . config [ ' IP button ' ] :
self . _ip_port_button = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 30 , 30 ) ,
label = ' IP ' ,
button_type = ' square ' ,
autoselect = True ,
color = self . bg_color ,
2022-09-30 09:51:51 +00:00
position = ( self . _width - 530 ,
self . _height - 100 ) ,
2022-09-30 15:18:39 +05:30
on_activate_call = self . _ip_port_msg )
self . _settings_button = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 50 , 50 ) ,
scale = 0.5 ,
button_type = ' square ' ,
autoselect = True ,
color = self . bg_color ,
position = ( self . _width - 40 , self . _height - 47 ) ,
on_activate_call = self . _on_setting_button_press ,
icon = ba . gettexture ( ' settingsIcon ' ) ,
iconscale = 1.2 )
self . _privatechat_button = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 50 , 50 ) ,
scale = 0.5 ,
button_type = ' square ' ,
autoselect = True ,
color = self . bg_color ,
position = ( self . _width - 40 , self . _height - 80 ) ,
on_activate_call = self . _on_privatechat_button_press ,
icon = ba . gettexture ( ' ouyaOButton ' ) ,
iconscale = 1.2 )
self . _name_widgets : List [ ba . Widget ] = [ ]
self . _roster : Optional [ List [ Dict [ str , Any ] ] ] = None
self . _update_timer = ba . Timer ( 1.0 ,
ba . WeakCall ( self . _update ) ,
repeat = True ,
timetype = ba . TimeType . REAL )
self . _update ( )
def on_chat_message ( self , msg : str , sent = None ) - > None :
""" Called when a new chat message comes through. """
if ba . app . config [ ' Party Chat Muted ' ] and not _ba . app . ui . party_window ( ) . _private_chat :
return
if sent :
self . _add_msg ( msg , sent )
else :
self . _add_msg ( msg )
def _add_msg ( self , msg : str , sent = None ) - > None :
if ba . app . config [ ' Colorful Chat ' ] :
sender = msg . split ( ' : ' ) [ 0 ]
color = color_tracker . _get_sender_color ( sender ) if sender else ( 1 , 1 , 1 )
else :
color = ( 1 , 1 , 1 )
maxwidth = self . _scroll_width * 0.94
txt = ba . textwidget ( parent = self . _columnwidget ,
text = msg ,
h_align = ' left ' ,
v_align = ' center ' ,
size = ( 0 , 13 ) ,
scale = 0.55 ,
color = color ,
maxwidth = maxwidth ,
shadow = 0.3 ,
flatness = 1.0 )
if sent :
ba . textwidget ( edit = txt , size = ( 100 , 15 ) ,
selectable = True ,
click_activate = True ,
on_activate_call = ba . Call ( ba . screenmessage , f ' Message sent: { _get_local_time ( sent ) } ' ) )
self . _chat_texts . append ( txt )
if len ( self . _chat_texts ) > 40 :
first = self . _chat_texts . pop ( 0 )
first . delete ( )
ba . containerwidget ( edit = self . _columnwidget , visible_child = txt )
def _on_menu_button_press ( self ) - > None :
is_muted = ba . app . config [ ' Party Chat Muted ' ]
uiscale = ba . app . ui . uiscale
choices = [ ' muteOption ' , ' modifyColor ' , ' addQuickReply ' , ' removeQuickReply ' , ' credits ' ]
2022-09-30 09:51:51 +00:00
choices_display = [ ' Mute Option ' , ' Modify Main Color ' ,
' Add as Quick Reply ' , ' Remove a Quick Reply ' , ' Credits ' ]
2022-09-30 15:18:39 +05:30
if hasattr ( _ba . get_foreground_host_activity ( ) , ' _map ' ) :
choices . append ( ' manualCamera ' )
choices_display . append ( ' Manual Camera ' )
PopupMenuWindow (
position = self . _menu_button . get_screen_space_center ( ) ,
color = self . bg_color ,
scale = ( 2.3 if uiscale is ba . UIScale . SMALL else
1.65 if uiscale is ba . UIScale . MEDIUM else 1.23 ) ,
choices = choices ,
choices_display = self . _create_baLstr_list ( choices_display ) ,
current_choice = ' muteOption ' ,
delegate = self )
self . _popup_type = ' menu '
def _update ( self ) - > None :
if not self . _private_chat :
_ba . set_party_window_open ( True )
ba . textwidget ( edit = self . _title_text , text = self . title )
if self . _firstcall :
if hasattr ( self , ' _status_text ' ) :
self . _status_text . delete ( )
self . _roster = [ ]
self . _firstcall = False
self . _chat_texts : List [ ba . Widget ] = [ ]
if not ba . app . config [ ' Party Chat Muted ' ] :
msgs = _ba . get_chat_messages ( )
for msg in msgs :
self . _add_msg ( msg )
# update muted state
if ba . app . config [ ' Party Chat Muted ' ] :
ba . textwidget ( edit = self . _muted_text , color = ( 1 , 1 , 1 , 0.3 ) )
# clear any chat texts we're showing
if self . _chat_texts :
while self . _chat_texts :
first = self . _chat_texts . pop ( )
first . delete ( )
else :
ba . textwidget ( edit = self . _muted_text , color = ( 1 , 1 , 1 , 0.0 ) )
if self . _ping_button :
ba . buttonwidget ( edit = self . _ping_button ,
label = f ' { _ping } ' ,
textcolor = self . _get_ping_color ( ) )
# update roster section
roster = _ba . get_game_roster ( )
if roster != self . _roster or self . _firstcall :
self . _roster = roster
# clear out old
for widget in self . _name_widgets :
widget . delete ( )
self . _name_widgets = [ ]
if not self . _roster :
top_section_height = 60
ba . textwidget ( edit = self . _empty_str ,
text = ba . Lstr ( resource = self . _r + ' .emptyText ' ) )
ba . scrollwidget ( edit = self . _scrollwidget ,
size = ( self . _width - 50 ,
self . _height - top_section_height - 110 ) ,
position = ( 30 , 80 ) )
else :
columns = 1 if len (
self . _roster ) == 1 else 2 if len ( self . _roster ) == 2 else 3
rows = int ( math . ceil ( float ( len ( self . _roster ) ) / columns ) )
c_width = ( self . _width * 0.9 ) / max ( 3 , columns )
c_width_total = c_width * columns
c_height = 24
c_height_total = c_height * rows
for y in range ( rows ) :
for x in range ( columns ) :
index = y * columns + x
if index < len ( self . _roster ) :
t_scale = 0.65
pos = ( self . _width * 0.53 - c_width_total * 0.5 +
c_width * x - 23 ,
self . _height - 65 - c_height * y - 15 )
# if there are players present for this client, use
# their names as a display string instead of the
# client spec-string
try :
if self . _roster [ index ] [ ' players ' ] :
# if there's just one, use the full name;
# otherwise combine short names
if len ( self . _roster [ index ]
[ ' players ' ] ) == 1 :
p_str = self . _roster [ index ] [ ' players ' ] [
0 ] [ ' name_full ' ]
else :
p_str = ( ' / ' . join ( [
entry [ ' name ' ] for entry in
self . _roster [ index ] [ ' players ' ]
] ) )
if len ( p_str ) > 25 :
p_str = p_str [ : 25 ] + ' ... '
else :
p_str = self . _roster [ index ] [
' display_string ' ]
except Exception :
ba . print_exception (
' Error calcing client name str. ' )
p_str = ' ??? '
widget = ba . textwidget ( parent = self . _root_widget ,
position = ( pos [ 0 ] , pos [ 1 ] ) ,
scale = t_scale ,
size = ( c_width * 0.85 , 30 ) ,
maxwidth = c_width * 0.85 ,
color = ( 1 , 1 ,
1 ) if index == 0 else
( 1 , 1 , 1 ) ,
selectable = True ,
autoselect = True ,
click_activate = True ,
text = ba . Lstr ( value = p_str ) ,
h_align = ' left ' ,
v_align = ' center ' )
self . _name_widgets . append ( widget )
# in newer versions client_id will be present and
# we can use that to determine who the host is.
# in older versions we assume the first client is
# host
if self . _roster [ index ] [ ' client_id ' ] is not None :
is_host = self . _roster [ index ] [
2022-09-30 09:51:51 +00:00
' client_id ' ] == - 1
2022-09-30 15:18:39 +05:30
else :
is_host = ( index == 0 )
# FIXME: Should pass client_id to these sort of
# calls; not spec-string (perhaps should wait till
# client_id is more readily available though).
ba . textwidget ( edit = widget ,
on_activate_call = ba . Call (
self . _on_party_member_press ,
self . _roster [ index ] [ ' client_id ' ] ,
is_host , widget ) )
pos = ( self . _width * 0.53 - c_width_total * 0.5 +
c_width * x ,
self . _height - 65 - c_height * y )
# Make the assumption that the first roster
# entry is the server.
# FIXME: Shouldn't do this.
if is_host :
twd = min (
c_width * 0.85 ,
_ba . get_string_width (
p_str , suppress_warning = True ) *
t_scale )
self . _name_widgets . append (
ba . textwidget (
parent = self . _root_widget ,
position = ( pos [ 0 ] + twd + 1 ,
pos [ 1 ] - 0.5 ) ,
size = ( 0 , 0 ) ,
h_align = ' left ' ,
v_align = ' center ' ,
maxwidth = c_width * 0.96 - twd ,
color = ( 0.1 , 1 , 0.1 , 0.5 ) ,
text = ba . Lstr ( resource = self . _r +
2022-09-30 09:51:51 +00:00
' .hostText ' ) ,
2022-09-30 15:18:39 +05:30
scale = 0.4 ,
shadow = 0.1 ,
flatness = 1.0 ) )
ba . textwidget ( edit = self . _empty_str , text = ' ' )
ba . scrollwidget ( edit = self . _scrollwidget ,
size = ( self . _width - 50 ,
max ( 100 , self . _height - 139 -
c_height_total ) ) ,
position = ( 30 , 80 ) )
else :
_ba . set_party_window_open ( False )
for widget in self . _name_widgets :
widget . delete ( )
self . _name_widgets = [ ]
ba . textwidget ( edit = self . _title_text , text = ' Private Chat ' )
ba . textwidget ( edit = self . _empty_str , text = ' ' )
if self . _firstcall :
self . _firstcall = False
if hasattr ( self , ' _status_text ' ) :
self . _status_text . delete ( )
try :
msgs = messenger . pvt_msgs [ messenger . filter ]
except :
msgs = [ ]
if self . _chat_texts :
while self . _chat_texts :
first = self . _chat_texts . pop ( )
first . delete ( )
uiscale = ba . app . ui . uiscale
scroll_height = ( 165 if uiscale is ba . UIScale . SMALL else
280 if uiscale is ba . UIScale . MEDIUM else 400 )
ba . scrollwidget ( edit = self . _scrollwidget ,
size = ( self . _width - 50 , scroll_height ) )
for msg in msgs :
message = messenger . _format_message ( msg )
self . _add_msg ( message , msg [ ' sent ' ] )
self . _filter_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.6 ,
color = ( 0.9 , 1.0 , 0.9 ) ,
text = ' Filter: ' ,
size = ( 0 , 0 ) ,
position = ( self . _width * 0.3 ,
self . _height - 70 ) ,
h_align = ' center ' ,
v_align = ' center ' )
choices = [ i for i in messenger . saved_ids ]
2022-09-30 09:51:51 +00:00
choices_display = [ ba . Lstr ( value = messenger . saved_ids [ i ] )
for i in messenger . saved_ids ]
2022-09-30 15:18:39 +05:30
choices . append ( ' add ' )
choices_display . append ( ba . Lstr ( value = ' ***Add New*** ' ) )
filter_widget = PopupMenu (
parent = self . _root_widget ,
position = ( self . _width * 0.4 ,
self . _height - 80 ) ,
width = 200 ,
scale = ( 2.8 if uiscale is ba . UIScale . SMALL else
1.8 if uiscale is ba . UIScale . MEDIUM else 1.2 ) ,
choices = choices ,
choices_display = choices_display ,
current_choice = messenger . filter ,
button_size = ( 120 , 30 ) ,
on_value_change_call = self . _change_filter )
self . _popup_button = filter_widget . get_button ( )
if messenger . filter != ' all ' :
user_status = messenger . _get_status ( messenger . filter )
if user_status == ' Offline ' :
color = ( 1 , 0 , 0 )
elif user_status . startswith ( ( ' Playing in ' , ' in Lobby ' ) ) :
color = ( 0 , 1 , 0 )
else :
color = ( 0.9 , 1.0 , 0.9 )
self . _status_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.5 ,
color = color ,
2025-01-23 20:45:05 +00:00
text = f ' Status: \t { user_status } ' ,
2022-09-30 15:18:39 +05:30
size = ( 200 , 30 ) ,
position = ( self . _width * 0.3 ,
self . _height - 110 ) ,
h_align = ' center ' ,
v_align = ' center ' ,
autoselect = True ,
selectable = True ,
click_activate = True )
ba . textwidget ( edit = self . _status_text ,
on_activate_call = ba . Call ( messenger . _get_status , messenger . filter , ' last_seen ' ) )
def _change_filter ( self , choice ) :
if choice == ' add ' :
self . close ( )
AddNewIdWindow ( )
else :
messenger . filter = choice
self . _firstcall = True
self . _filter_text . delete ( )
self . _popup_button . delete ( )
if self . _chat_texts :
while self . _chat_texts :
first = self . _chat_texts . pop ( )
first . delete ( )
self . _update ( )
def popup_menu_selected_choice ( self , popup_window : PopupMenuWindow ,
choice : str ) - > None :
""" Called when a choice is selected in the popup. """
if self . _popup_type == ' partyMemberPress ' :
playerinfo = self . _get_player_info ( self . _popup_party_member_client_id )
if choice == ' kick ' :
name = playerinfo [ ' ds ' ]
ConfirmWindow ( text = f ' Are you sure to kick { name } ? ' ,
action = self . _vote_kick_player ,
cancel_button = True ,
cancel_is_selected = True ,
color = self . bg_color ,
text_scale = 1.0 ,
origin_widget = self . get_root_widget ( ) )
elif choice == ' mention ' :
players = playerinfo [ ' players ' ]
choices = [ ]
namelist = [ playerinfo [ ' ds ' ] ]
for player in players :
name = player [ ' name_full ' ]
if name not in namelist :
namelist . append ( name )
choices_display = self . _create_baLstr_list ( namelist )
for i in namelist :
i = i . replace ( ' " ' , ' \" ' )
i = i . replace ( " ' " , " \' " )
choices . append ( f ' self._edit_text_msg_box( " { i } " ) ' )
PopupMenuWindow ( position = popup_window . root_widget . get_screen_space_center ( ) ,
color = self . bg_color ,
scale = self . _get_popup_window_scale ( ) ,
choices = choices ,
choices_display = choices_display ,
current_choice = choices [ 0 ] ,
delegate = self )
self . _popup_type = " executeChoice "
elif choice == ' adminkick ' :
name = playerinfo [ ' ds ' ]
ConfirmWindow ( text = f ' Are you sure to use admin \n command to kick { name } ' ,
action = self . _send_admin_kick_command ,
cancel_button = True ,
cancel_is_selected = True ,
color = self . bg_color ,
text_scale = 1.0 ,
origin_widget = self . get_root_widget ( ) )
elif choice == ' customCommands ' :
choices = [ ]
choices_display = [ ]
playerinfo = self . _get_player_info ( self . _popup_party_member_client_id )
account = playerinfo [ ' ds ' ]
try :
name = playerinfo [ ' players ' ] [ 0 ] [ ' name_full ' ]
except :
name = account
for i in ba . app . config . get ( ' Custom Commands ' ) :
i = i . replace ( ' $c ' , str ( self . _popup_party_member_client_id ) )
i = i . replace ( ' $a ' , str ( account ) )
i = i . replace ( ' $n ' , str ( name ) )
if ba . app . config [ ' Direct Send ' ] :
choices . append ( f ' _ba.chatmessage( " { i } " ) ' )
else :
choices . append ( f ' self._edit_text_msg_box( " { i } " ) ' )
choices_display . append ( ba . Lstr ( value = i ) )
choices . append ( ' AddNewChoiceWindow() ' )
choices_display . append ( ba . Lstr ( value = ' ***Add New*** ' ) )
PopupMenuWindow ( position = popup_window . root_widget . get_screen_space_center ( ) ,
color = self . bg_color ,
scale = self . _get_popup_window_scale ( ) ,
choices = choices ,
choices_display = choices_display ,
current_choice = choices [ 0 ] ,
delegate = self )
self . _popup_type = ' executeChoice '
elif choice == ' addNew ' :
AddNewChoiceWindow ( )
elif self . _popup_type == ' menu ' :
if choice == ' muteOption ' :
current_choice = self . _get_current_mute_type ( )
PopupMenuWindow (
position = ( self . _width - 60 , self . _height - 47 ) ,
color = self . bg_color ,
scale = self . _get_popup_window_scale ( ) ,
choices = [ ' muteInGameOnly ' , ' mutePartyWindowOnly ' , ' muteAll ' , ' unmuteAll ' ] ,
choices_display = self . _create_baLstr_list (
[ ' Mute In Game Messages Only ' , ' Mute Party Window Messages Only ' , ' Mute all ' , ' Unmute All ' ] ) ,
current_choice = current_choice ,
delegate = self
)
self . _popup_type = ' muteType '
elif choice == ' modifyColor ' :
ColorPickerExact ( parent = self . get_root_widget ( ) ,
position = self . get_root_widget ( ) . get_screen_space_center ( ) ,
initial_color = self . bg_color ,
delegate = self , tag = ' ' )
elif choice == ' addQuickReply ' :
try :
newReply = ba . textwidget ( query = self . _text_field )
oldReplies = self . _get_quick_responds ( )
oldReplies . append ( newReply )
self . _write_quick_responds ( oldReplies )
ba . screenmessage ( f ' " { newReply } " is added. ' , ( 0 , 1 , 0 ) )
ba . playsound ( ba . getsound ( ' dingSmallHigh ' ) )
except :
ba . print_exception ( )
elif choice == ' removeQuickReply ' :
quick_reply = self . _get_quick_responds ( )
PopupMenuWindow ( position = self . _send_button . get_screen_space_center ( ) ,
color = self . bg_color ,
scale = self . _get_popup_window_scale ( ) ,
choices = quick_reply ,
choices_display = self . _create_baLstr_list ( quick_reply ) ,
current_choice = quick_reply [ 0 ] ,
delegate = self )
self . _popup_type = ' removeQuickReplySelect '
elif choice == ' credits ' :
ConfirmWindow (
text = u ' \ue043 Party Window Reloaded V3 \ue043 \n \n Credits - Droopy#3730 \n Special Thanks - BoTT-Vishah#4150 ' ,
action = self . join_discord ,
width = 420 ,
height = 230 ,
color = self . bg_color ,
text_scale = 1.0 ,
ok_text = " Join Discord " ,
origin_widget = self . get_root_widget ( ) )
elif choice == ' manualCamera ' :
ba . containerwidget ( edit = self . _root_widget , transition = ' out_scale ' )
Manual_camera_window ( )
elif self . _popup_type == ' muteType ' :
self . _change_mute_type ( choice )
elif self . _popup_type == ' executeChoice ' :
exec ( choice )
elif self . _popup_type == ' quickMessage ' :
if choice == ' *** EDIT ORDER *** ' :
SortQuickMessages ( )
else :
self . _edit_text_msg_box ( choice )
elif self . _popup_type == ' removeQuickReplySelect ' :
data = self . _get_quick_responds ( )
data . remove ( choice )
self . _write_quick_responds ( data )
ba . screenmessage ( f ' " { choice } " is removed. ' , ( 1 , 0 , 0 ) )
ba . playsound ( ba . getsound ( ' shieldDown ' ) )
else :
print ( f ' unhandled popup type: { self . _popup_type } ' )
del popup_window # unused
def _vote_kick_player ( self ) :
if self . _popup_party_member_is_host :
ba . playsound ( ba . getsound ( ' error ' ) )
ba . screenmessage (
ba . Lstr ( resource = ' internal.cantKickHostError ' ) ,
color = ( 1 , 0 , 0 ) )
else :
assert self . _popup_party_member_client_id is not None
# Ban for 5 minutes.
result = _ba . disconnect_client (
self . _popup_party_member_client_id , ban_time = 5 * 60 )
if not result :
ba . playsound ( ba . getsound ( ' error ' ) )
ba . screenmessage (
ba . Lstr ( resource = ' getTicketsWindow.unavailableText ' ) ,
color = ( 1 , 0 , 0 ) )
def _send_admin_kick_command ( self ) :
_ba . chatmessage ( ' /kick ' + str ( self . _popup_party_member_client_id ) )
def _translate ( self ) :
def _apply_translation ( translated ) :
if self . _text_field . exists ( ) :
ba . textwidget ( edit = self . _text_field , text = translated )
msg = ba . textwidget ( query = self . _text_field )
cfg = ba . app . config
if msg == ' ' :
ba . screenmessage ( ' Nothing to translate. ' , ( 1 , 0 , 0 ) )
ba . playsound ( ba . getsound ( ' error ' ) )
else :
data = dict ( message = msg )
if cfg [ ' Translate Source Language ' ] :
data [ ' src ' ] = cfg [ ' Translate Source Language ' ]
if cfg [ ' Translate Destination Language ' ] :
data [ ' dest ' ] = cfg [ ' Translate Destination Language ' ]
if cfg [ ' Pronunciation ' ] :
data [ ' type ' ] = ' pronunciation '
Translate ( data , _apply_translation ) . start ( )
def _copy_to_clipboard ( self ) :
msg = ba . textwidget ( query = self . _text_field )
if msg == ' ' :
ba . screenmessage ( ' Nothing to copy. ' , ( 1 , 0 , 0 ) )
ba . playsound ( ba . getsound ( ' error ' ) )
else :
ba . clipboard_set_text ( msg )
ba . screenmessage ( f ' " { msg } " is copied to clipboard. ' , ( 0 , 1 , 0 ) )
ba . playsound ( ba . getsound ( ' dingSmallHigh ' ) )
def _get_current_mute_type ( self ) :
cfg = ba . app . config
if cfg [ ' Chat Muted ' ] == True :
if cfg [ ' Party Chat Muted ' ] == True :
return ' muteAll '
else :
return ' muteInGameOnly '
else :
if cfg [ ' Party Chat Muted ' ] == True :
return ' mutePartyWindowOnly '
else :
return ' unmuteAll '
def _change_mute_type ( self , choice ) :
cfg = ba . app . config
if choice == ' muteInGameOnly ' :
cfg [ ' Chat Muted ' ] = True
cfg [ ' Party Chat Muted ' ] = False
elif choice == ' mutePartyWindowOnly ' :
cfg [ ' Chat Muted ' ] = False
cfg [ ' Party Chat Muted ' ] = True
elif choice == ' muteAll ' :
cfg [ ' Chat Muted ' ] = True
cfg [ ' Party Chat Muted ' ] = True
else :
cfg [ ' Chat Muted ' ] = False
cfg [ ' Party Chat Muted ' ] = False
cfg . apply_and_commit ( )
self . _update ( )
def popup_menu_closing ( self , popup_window : PopupWindow ) - > None :
""" Called when the popup is closing. """
def _on_party_member_press ( self , client_id : int , is_host : bool ,
widget : ba . Widget ) - > None :
# if we're the host, pop up 'kick' options for all non-host members
if _ba . get_foreground_host_session ( ) is not None :
kick_str = ba . Lstr ( resource = ' kickText ' )
else :
# kick-votes appeared in build 14248
if ( _ba . get_connection_to_host_info ( ) . get ( ' build_number ' , 0 ) <
14248 ) :
return
kick_str = ba . Lstr ( resource = ' kickVoteText ' )
uiscale = ba . app . ui . uiscale
choices = [ ' kick ' , ' mention ' , ' adminkick ' ]
2022-09-30 09:51:51 +00:00
choices_display = [ kick_str ] + \
list ( self . _create_baLstr_list ( [ ' Mention this guy ' , f ' Kick ID: { client_id } ' ] ) )
2022-09-30 15:18:39 +05:30
choices . append ( ' customCommands ' )
choices_display . append ( ba . Lstr ( value = ' Custom Commands ' ) )
PopupMenuWindow (
position = widget . get_screen_space_center ( ) ,
color = self . bg_color ,
scale = ( 2.3 if uiscale is ba . UIScale . SMALL else
1.65 if uiscale is ba . UIScale . MEDIUM else 1.23 ) ,
choices = choices ,
choices_display = choices_display ,
current_choice = ' mention ' ,
delegate = self )
self . _popup_type = ' partyMemberPress '
self . _popup_party_member_client_id = client_id
self . _popup_party_member_is_host = is_host
def _send_chat_message ( self ) - > None :
msg = ba . textwidget ( query = self . _text_field )
ba . textwidget ( edit = self . _text_field , text = ' ' )
if ' \\ ' in msg :
msg = msg . replace ( ' \\ d ' , ( ' \ue048 ' ) )
msg = msg . replace ( ' \\ c ' , ( ' \ue043 ' ) )
msg = msg . replace ( ' \\ h ' , ( ' \ue049 ' ) )
msg = msg . replace ( ' \\ s ' , ( ' \ue046 ' ) )
msg = msg . replace ( ' \\ n ' , ( ' \ue04b ' ) )
msg = msg . replace ( ' \\ f ' , ( ' \ue04f ' ) )
msg = msg . replace ( ' \\ g ' , ( ' \ue027 ' ) )
msg = msg . replace ( ' \\ i ' , ( ' \ue03a ' ) )
msg = msg . replace ( ' \\ m ' , ( ' \ue04d ' ) )
msg = msg . replace ( ' \\ t ' , ( ' \ue01f ' ) )
msg = msg . replace ( ' \\ bs ' , ( ' \ue01e ' ) )
msg = msg . replace ( ' \\ j ' , ( ' \ue010 ' ) )
msg = msg . replace ( ' \\ e ' , ( ' \ue045 ' ) )
msg = msg . replace ( ' \\ l ' , ( ' \ue047 ' ) )
msg = msg . replace ( ' \\ a ' , ( ' \ue020 ' ) )
msg = msg . replace ( ' \\ b ' , ( ' \ue00c ' ) )
if not msg :
choices = self . _get_quick_responds ( )
choices . append ( ' *** EDIT ORDER *** ' )
PopupMenuWindow ( position = self . _send_button . get_screen_space_center ( ) ,
scale = self . _get_popup_window_scale ( ) ,
color = self . bg_color ,
choices = choices ,
current_choice = choices [ 0 ] ,
delegate = self )
self . _popup_type = ' quickMessage '
return
elif msg . startswith ( ' /info ' ) :
account = msg . replace ( ' /info ' , ' ' )
if account :
from bastd . ui . account import viewer
viewer . AccountViewerWindow (
account_id = account )
ba . textwidget ( edit = self . _text_field , text = ' ' )
return
if not self . _private_chat :
if msg == ' /id ' :
myid = ba . internal . get_v1_account_misc_read_val_2 ( ' resolvedAccountID ' , ' ' )
2025-01-23 20:45:05 +00:00
_ba . chatmessage ( f " My Unique ID: { myid } " )
2022-09-30 15:18:39 +05:30
elif msg == ' /save ' :
info = _ba . get_connection_to_host_info ( )
config = ba . app . config
if info . get ( ' name ' , ' ' ) != ' ' :
title = info [ ' name ' ]
if not isinstance ( config . get ( ' Saved Servers ' ) , dict ) :
config [ ' Saved Servers ' ] = { }
config [ ' Saved Servers ' ] [ f ' { _ip } @ { _port } ' ] = {
' addr ' : _ip ,
' port ' : _port ,
' name ' : title
}
config . commit ( )
ba . screenmessage ( " Server Added To Manual " , color = ( 0 , 1 , 0 ) , transient = True )
ba . playsound ( ba . getsound ( ' gunCocking ' ) )
elif msg != ' ' :
_ba . chatmessage ( cast ( str , msg ) )
else :
receiver = messenger . filter
name = ba . internal . get_v1_account_display_string ( )
if not receiver :
display_error ( ' Choose a valid receiver id ' )
return
data = { ' receiver ' : receiver , ' message ' : f ' { name } : { msg } ' }
if msg . startswith ( ' /rename ' ) :
if messenger . filter != ' all ' :
nickname = msg . replace ( ' /rename ' , ' ' )
messenger . _save_id ( messenger . filter , nickname , verify = False )
self . _change_filter ( messenger . filter )
elif msg == ' /remove ' :
if messenger . filter != ' all ' :
messenger . _remove_id ( messenger . filter )
self . _change_filter ( ' all ' )
else :
display_error ( ' Cant delete this ' )
ba . textwidget ( edit = self . _text_field , text = ' ' )
return
ba . Call ( messenger . _send_request , url , data )
ba . Call ( check_new_message )
Thread ( target = messenger . _send_request , args = ( url , data ) ) . start ( )
Thread ( target = check_new_message ) . start ( )
ba . textwidget ( edit = self . _text_field , text = ' ' )
def _write_quick_responds ( self , data ) :
try :
with open ( quick_msg_file , ' w ' ) as f :
f . write ( ' \n ' . join ( data ) )
except :
ba . print_exception ( )
ba . screenmessage ( ' Error! ' , ( 1 , 0 , 0 ) )
ba . playsound ( ba . getsound ( ' error ' ) )
def _get_quick_responds ( self ) :
if os . path . exists ( quick_msg_file ) :
with open ( quick_msg_file , ' r ' ) as f :
return f . read ( ) . split ( ' \n ' )
else :
default_replies = [ ' What the hell? ' , ' Dude that \' s amazing! ' ]
self . _write_quick_responds ( default_replies )
return default_replies
def color_picker_selected_color ( self , picker , color ) - > None :
ba . containerwidget ( edit = self . _root_widget , color = color )
color = tuple ( round ( i , 2 ) for i in color )
self . bg_color = color
ba . app . config [ ' PartyWindow Main Color ' ] = color
def color_picker_closing ( self , picker ) - > None :
ba . app . config . apply_and_commit ( )
def _remove_sender_from_message ( self , msg = ' ' ) :
msg_start = msg . find ( " : " ) + 2
return msg [ msg_start : ]
def _previous_message ( self ) :
msgs = self . _chat_texts
if not hasattr ( self , ' msg_index ' ) :
self . msg_index = len ( msgs ) - 1
else :
if self . msg_index > 0 :
self . msg_index - = 1
else :
del self . msg_index
try :
msg_widget = msgs [ self . msg_index ]
msg = ba . textwidget ( query = msg_widget )
msg = self . _remove_sender_from_message ( msg )
if msg in ( ' ' , ' ' ) :
self . _previous_message ( )
return
except :
msg = ' '
self . _edit_text_msg_box ( msg , ' replace ' )
def _next_message ( self ) :
msgs = self . _chat_texts
if not hasattr ( self , ' msg_index ' ) :
self . msg_index = 0
else :
if self . msg_index < len ( msgs ) - 1 :
self . msg_index + = 1
else :
del self . msg_index
try :
msg_widget = msgs [ self . msg_index ]
msg = ba . textwidget ( query = msg_widget )
msg = self . _remove_sender_from_message ( msg )
if msg in ( ' ' , ' ' ) :
self . _next_message ( )
return
except :
msg = ' '
self . _edit_text_msg_box ( msg , ' replace ' )
def _ip_port_msg ( self ) :
try :
2025-01-23 20:45:05 +00:00
msg = f ' IP: { _ip } PORT: { _port } '
2022-09-30 15:18:39 +05:30
except :
msg = ' '
self . _edit_text_msg_box ( msg , ' replace ' )
def ping_server ( self ) :
info = _ba . get_connection_to_host_info ( )
if info . get ( ' name ' , ' ' ) != ' ' :
self . pingThread = PingThread ( _ip , _port )
self . pingThread . start ( )
def _get_ping_color ( self ) :
try :
if _ping < 100 :
return ( 0 , 1 , 0 )
elif _ping < 500 :
return ( 1 , 1 , 0 )
else :
return ( 1 , 0 , 0 )
except :
return ( 0.1 , 0.1 , 0.1 )
def _send_ping ( self ) :
if isinstance ( _ping , int ) :
_ba . chatmessage ( f ' My ping = { _ping } ms ' )
def close ( self ) - > None :
""" Close the window. """
ba . containerwidget ( edit = self . _root_widget , transition = ' out_scale ' )
def close_with_sound ( self ) - > None :
""" Close the window and make a lovely sound. """
ba . playsound ( ba . getsound ( ' swish ' ) )
self . close ( )
def _get_popup_window_scale ( self ) - > float :
uiscale = ba . app . ui . uiscale
return ( 2.4 if uiscale is ba . UIScale . SMALL else
1.5 if uiscale is ba . UIScale . MEDIUM else 1.0 )
def _create_baLstr_list ( self , list1 ) :
return ( ba . Lstr ( value = i ) for i in list1 )
def _get_player_info ( self , clientID ) :
info = { }
for i in _ba . get_game_roster ( ) :
if i [ ' client_id ' ] == clientID :
info [ ' ds ' ] = i [ ' display_string ' ]
info [ ' players ' ] = i [ ' players ' ]
info [ ' aid ' ] = i [ ' account_id ' ]
break
return info
def _edit_text_msg_box ( self , text , action = ' add ' ) :
if isinstance ( text , str ) :
if action == ' add ' :
2022-09-30 09:51:51 +00:00
ba . textwidget ( edit = self . _text_field , text = ba . textwidget (
query = self . _text_field ) + text )
2022-09-30 15:18:39 +05:30
elif action == ' replace ' :
ba . textwidget ( edit = self . _text_field , text = text )
def _on_setting_button_press ( self ) :
try :
SettingsWindow ( )
except Exception as e :
ba . print_exception ( )
pass
def _on_privatechat_button_press ( self ) :
try :
if messenger . logged_in :
self . _firstcall = True
if self . _chat_texts :
while self . _chat_texts :
first = self . _chat_texts . pop ( )
first . delete ( )
if not self . _private_chat :
self . _private_chat = True
else :
self . _filter_text . delete ( )
self . _popup_button . delete ( )
self . _private_chat = False
self . _update ( )
else :
if messenger . server_online :
if not messenger . _cookie_login ( ) :
if messenger . _query ( ) :
LoginWindow ( wtype = ' login ' )
else :
LoginWindow ( wtype = ' signup ' )
else :
display_error ( messenger . error )
except Exception as e :
ba . print_exception ( )
pass
def join_discord ( self ) :
ba . open_url ( " https://discord.gg/KvYgpEg2JR " )
class LoginWindow :
def __init__ ( self , wtype ) :
self . wtype = wtype
if self . wtype == ' signup ' :
title = ' Sign Up Window '
label = ' Sign Up '
else :
title = ' Login Window '
label = ' Log In '
uiscale = ba . app . ui . uiscale
bg_color = ba . app . config . get ( ' PartyWindow Main Color ' , ( 0.5 , 0.5 , 0.5 ) )
self . _root_widget = ba . containerwidget ( size = ( 500 , 250 ) ,
transition = ' in_scale ' ,
color = bg_color ,
toolbar_visibility = ' menu_minimal_no_back ' ,
parent = _ba . get_special_widget ( ' overlay_stack ' ) ,
on_outside_click_call = self . _close ,
scale = ( 2.1 if uiscale is ba . UIScale . SMALL else
1.5 if uiscale is ba . UIScale . MEDIUM else 1.0 ) ,
stack_offset = ( 0 , - 10 ) if uiscale is ba . UIScale . SMALL else (
240 , 0 ) if uiscale is ba . UIScale . MEDIUM else ( 330 , 20 ) )
self . _title_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.8 ,
color = ( 1 , 1 , 1 ) ,
text = title ,
size = ( 0 , 0 ) ,
position = ( 250 , 200 ) ,
h_align = ' center ' ,
v_align = ' center ' )
self . _id = ba . textwidget ( parent = self . _root_widget ,
scale = 0.5 ,
color = ( 1 , 1 , 1 ) ,
2022-09-30 09:51:51 +00:00
text = f ' Account: ' +
ba . internal . get_v1_account_misc_read_val_2 (
' resolvedAccountID ' , ' ' ) ,
2022-09-30 15:18:39 +05:30
size = ( 0 , 0 ) ,
position = ( 220 , 170 ) ,
h_align = ' center ' ,
v_align = ' center ' )
self . _registrationkey_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.5 ,
color = ( 1 , 1 , 1 ) ,
2025-01-23 20:45:05 +00:00
text = f ' Registration Key: ' ,
2022-09-30 15:18:39 +05:30
size = ( 0 , 0 ) ,
position = ( 100 , 140 ) ,
h_align = ' center ' ,
v_align = ' center ' )
self . _text_field = ba . textwidget (
parent = self . _root_widget ,
editable = True ,
size = ( 200 , 40 ) ,
position = ( 175 , 130 ) ,
text = ' ' ,
maxwidth = 410 ,
flatness = 1.0 ,
autoselect = True ,
v_align = ' center ' ,
corner_scale = 0.7 )
self . _connect_button = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 150 , 30 ) ,
color = ( 0 , 1 , 0 ) ,
label = ' Get Registration Key ' ,
button_type = ' square ' ,
autoselect = True ,
position = ( 150 , 80 ) ,
on_activate_call = self . _connect )
self . _confirm_button = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 50 , 30 ) ,
label = label ,
button_type = ' square ' ,
autoselect = True ,
position = ( 200 , 40 ) ,
on_activate_call = self . _confirmcall )
ba . textwidget ( edit = self . _text_field , on_return_press_call = self . _confirm_button . activate )
def _close ( self ) :
ba . containerwidget ( edit = self . _root_widget ,
transition = ( ' out_scale ' ) )
def _connect ( self ) :
try :
host = url . split ( ' http:// ' ) [ 1 ] . split ( ' : ' ) [ 0 ]
import socket
address = socket . gethostbyname ( host )
_ba . disconnect_from_host ( )
_ba . connect_to_party ( address , port = 11111 )
except Exception :
display_error ( ' Cant get ip from hostname ' )
def _confirmcall ( self ) :
if self . wtype == ' signup ' :
key = ba . textwidget ( query = self . _text_field )
answer = messenger . _signup ( registration_key = key ) if key else None
if answer :
self . _close ( )
else :
if messenger . _login ( registration_key = ba . textwidget ( query = self . _text_field ) ) :
self . _close ( )
class AddNewIdWindow :
def __init__ ( self ) :
uiscale = ba . app . ui . uiscale
bg_color = ba . app . config . get ( ' PartyWindow Main Color ' , ( 0.5 , 0.5 , 0.5 ) )
self . _root_widget = ba . containerwidget ( size = ( 500 , 250 ) ,
transition = ' in_scale ' ,
color = bg_color ,
toolbar_visibility = ' menu_minimal_no_back ' ,
parent = _ba . get_special_widget ( ' overlay_stack ' ) ,
on_outside_click_call = self . _close ,
scale = ( 2.1 if uiscale is ba . UIScale . SMALL else
1.5 if uiscale is ba . UIScale . MEDIUM else 1.0 ) )
self . _title_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.8 ,
color = ( 1 , 1 , 1 ) ,
text = ' Add New ID ' ,
size = ( 0 , 0 ) ,
position = ( 250 , 200 ) ,
h_align = ' center ' ,
v_align = ' center ' )
self . _accountid_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.6 ,
color = ( 1 , 1 , 1 ) ,
text = ' pb-id: ' ,
size = ( 0 , 0 ) ,
position = ( 50 , 155 ) ,
h_align = ' center ' ,
v_align = ' center ' )
self . _accountid_field = ba . textwidget (
parent = self . _root_widget ,
editable = True ,
size = ( 250 , 40 ) ,
position = ( 100 , 140 ) ,
text = ' ' ,
maxwidth = 410 ,
flatness = 1.0 ,
autoselect = True ,
v_align = ' center ' ,
corner_scale = 0.7 )
self . _nickname_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.5 ,
color = ( 1 , 1 , 1 ) ,
text = ' Nickname: ' ,
size = ( 0 , 0 ) ,
position = ( 50 , 115 ) ,
h_align = ' center ' ,
v_align = ' center ' )
self . _nickname_field = ba . textwidget (
parent = self . _root_widget ,
editable = True ,
size = ( 250 , 40 ) ,
position = ( 100 , 100 ) ,
text = ' <default> ' ,
maxwidth = 410 ,
flatness = 1.0 ,
autoselect = True ,
v_align = ' center ' ,
corner_scale = 0.7 )
self . _help_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.4 ,
color = ( 0.1 , 0.9 , 0.9 ) ,
text = ' Help: \n Enter pb-id of account you \n want to chat to \n Enter nickname of id to \n recognize id easily \n Leave nickname <default> \n to use their default name ' ,
size = ( 0 , 0 ) ,
position = ( 325 , 120 ) ,
h_align = ' left ' ,
v_align = ' center ' )
self . _add = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 50 , 30 ) ,
label = ' Add ' ,
button_type = ' square ' ,
autoselect = True ,
position = ( 100 , 50 ) ,
on_activate_call = ba . Call ( self . _relay_function ) )
ba . textwidget ( edit = self . _accountid_field , on_return_press_call = self . _add . activate )
self . _remove = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 75 , 30 ) ,
label = ' Remove ' ,
button_type = ' square ' ,
autoselect = True ,
position = ( 170 , 50 ) ,
on_activate_call = self . _remove_id )
ba . containerwidget ( edit = self . _root_widget ,
on_cancel_call = self . _close )
def _relay_function ( self ) :
account_id = ba . textwidget ( query = self . _accountid_field )
nickname = ba . textwidget ( query = self . _nickname_field )
try :
if messenger . _save_id ( account_id , nickname ) :
self . _close ( )
except :
display_error ( ' Enter valid pb-id ' )
def _remove_id ( self ) :
uiscale = ba . app . ui . uiscale
if len ( messenger . saved_ids ) > 1 :
choices = [ i for i in messenger . saved_ids ]
choices . remove ( ' all ' )
choices_display = [ ba . Lstr ( value = messenger . saved_ids [ i ] ) for i in choices ]
PopupMenuWindow ( position = self . _remove . get_screen_space_center ( ) ,
color = ba . app . config . get ( ' PartyWindow Main Color ' , ( 0.5 , 0.5 , 0.5 ) ) ,
scale = ( 2.4 if uiscale is ba . UIScale . SMALL else
1.5 if uiscale is ba . UIScale . MEDIUM else 1.0 ) ,
choices = choices ,
choices_display = choices_display ,
current_choice = choices [ 0 ] ,
delegate = self )
self . _popup_type = ' removeSelectedID '
def popup_menu_selected_choice ( self , popup_window : PopupMenuWindow ,
choice : str ) - > None :
""" Called when a choice is selected in the popup. """
if self . _popup_type == ' removeSelectedID ' :
messenger . _remove_id ( choice )
self . _close ( )
def popup_menu_closing ( self , popup_window : PopupWindow ) - > None :
""" Called when the popup is closing. """
def _close ( self ) :
ba . containerwidget ( edit = self . _root_widget ,
transition = ( ' out_scale ' ) )
class AddNewChoiceWindow :
def __init__ ( self ) :
uiscale = ba . app . ui . uiscale
bg_color = ba . app . config . get ( ' PartyWindow Main Color ' , ( 0.5 , 0.5 , 0.5 ) )
self . _root_widget = ba . containerwidget ( size = ( 500 , 250 ) ,
transition = ' in_scale ' ,
color = bg_color ,
toolbar_visibility = ' menu_minimal_no_back ' ,
parent = _ba . get_special_widget ( ' overlay_stack ' ) ,
on_outside_click_call = self . _close ,
scale = ( 2.1 if uiscale is ba . UIScale . SMALL else
1.5 if uiscale is ba . UIScale . MEDIUM else 1.0 ) ,
stack_offset = ( 0 , - 10 ) if uiscale is ba . UIScale . SMALL else (
240 , 0 ) if uiscale is ba . UIScale . MEDIUM else ( 330 , 20 ) )
self . _title_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.8 ,
color = ( 1 , 1 , 1 ) ,
text = ' Add Custom Command ' ,
size = ( 0 , 0 ) ,
position = ( 250 , 200 ) ,
h_align = ' center ' ,
v_align = ' center ' )
self . _text_field = ba . textwidget (
parent = self . _root_widget ,
editable = True ,
size = ( 500 , 40 ) ,
position = ( 75 , 140 ) ,
text = ' ' ,
maxwidth = 410 ,
flatness = 1.0 ,
autoselect = True ,
v_align = ' center ' ,
corner_scale = 0.7 )
self . _help_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.4 ,
color = ( 0.2 , 0.2 , 0.2 ) ,
text = ' Use \n $c = client id \n $a = account id \n $n = name ' ,
size = ( 0 , 0 ) ,
position = ( 70 , 75 ) ,
h_align = ' left ' ,
v_align = ' center ' )
self . _add = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 50 , 30 ) ,
label = ' Add ' ,
button_type = ' square ' ,
autoselect = True ,
position = ( 150 , 50 ) ,
on_activate_call = self . _add_choice )
ba . textwidget ( edit = self . _text_field , on_return_press_call = self . _add . activate )
self . _remove = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 50 , 30 ) ,
label = ' Remove ' ,
button_type = ' square ' ,
autoselect = True ,
position = ( 350 , 50 ) ,
on_activate_call = self . _remove_custom_command )
ba . containerwidget ( edit = self . _root_widget ,
on_cancel_call = self . _close )
def _add_choice ( self ) :
newCommand = ba . textwidget ( query = self . _text_field )
cfg = ba . app . config
if any ( i in newCommand for i in ( ' $c ' , ' $a ' , ' $n ' ) ) :
cfg [ ' Custom Commands ' ] . append ( newCommand )
cfg . apply_and_commit ( )
ba . screenmessage ( ' Added successfully ' , ( 0 , 1 , 0 ) )
ba . playsound ( ba . getsound ( ' dingSmallHigh ' ) )
self . _close ( )
else :
ba . screenmessage ( ' Use at least of these ($c, $a, $n) ' , ( 1 , 0 , 0 ) )
ba . playsound ( ba . getsound ( ' error ' ) )
def _remove_custom_command ( self ) :
uiscale = ba . app . ui . uiscale
commands = ba . app . config [ ' Custom Commands ' ]
PopupMenuWindow ( position = self . _remove . get_screen_space_center ( ) ,
color = ba . app . config . get ( ' PartyWindow Main Color ' , ( 0.5 , 0.5 , 0.5 ) ) ,
scale = ( 2.4 if uiscale is ba . UIScale . SMALL else
1.5 if uiscale is ba . UIScale . MEDIUM else 1.0 ) ,
choices = commands ,
current_choice = commands [ 0 ] ,
delegate = self )
self . _popup_type = ' removeCustomCommandSelect '
def popup_menu_selected_choice ( self , popup_window : PopupMenuWindow ,
choice : str ) - > None :
""" Called when a choice is selected in the popup. """
if self . _popup_type == ' removeCustomCommandSelect ' :
config = ba . app . config
config [ ' Custom Commands ' ] . remove ( choice )
config . apply_and_commit ( )
ba . screenmessage ( ' Removed successfully ' , ( 0 , 1 , 0 ) )
ba . playsound ( ba . getsound ( ' shieldDown ' ) )
def popup_menu_closing ( self , popup_window : PopupWindow ) - > None :
""" Called when the popup is closing. """
def _close ( self ) :
ba . containerwidget ( edit = self . _root_widget ,
transition = ( ' out_scale ' ) )
class Manual_camera_window :
def __init__ ( self ) :
self . _root_widget = ba . containerwidget (
on_outside_click_call = None ,
size = ( 0 , 0 ) )
button_size = ( 30 , 30 )
self . _title_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.9 ,
color = ( 1 , 1 , 1 ) ,
text = ' Manual Camera Setup ' ,
size = ( 0 , 0 ) ,
position = ( 130 , 153 ) ,
h_align = ' center ' ,
v_align = ' center ' )
self . _xminus = ba . buttonwidget ( parent = self . _root_widget ,
size = button_size ,
label = ba . charstr ( ba . SpecialChar . LEFT_ARROW ) ,
button_type = ' square ' ,
autoselect = True ,
position = ( 1 , 60 ) ,
on_activate_call = ba . Call ( self . _change_camera_position , ' x- ' ) )
self . _xplus = ba . buttonwidget ( parent = self . _root_widget ,
size = button_size ,
label = ba . charstr ( ba . SpecialChar . RIGHT_ARROW ) ,
button_type = ' square ' ,
autoselect = True ,
position = ( 60 , 60 ) ,
on_activate_call = ba . Call ( self . _change_camera_position , ' x ' ) )
self . _yplus = ba . buttonwidget ( parent = self . _root_widget ,
size = button_size ,
label = ba . charstr ( ba . SpecialChar . UP_ARROW ) ,
button_type = ' square ' ,
autoselect = True ,
position = ( 30 , 100 ) ,
on_activate_call = ba . Call ( self . _change_camera_position , ' y ' ) )
self . _yminus = ba . buttonwidget ( parent = self . _root_widget ,
size = button_size ,
label = ba . charstr ( ba . SpecialChar . DOWN_ARROW ) ,
button_type = ' square ' ,
autoselect = True ,
position = ( 30 , 20 ) ,
on_activate_call = ba . Call ( self . _change_camera_position , ' y- ' ) )
self . inwards = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 100 , 30 ) ,
label = ' INWARDS ' ,
button_type = ' square ' ,
autoselect = True ,
position = ( 120 , 90 ) ,
on_activate_call = ba . Call ( self . _change_camera_position , ' z- ' ) )
self . _outwards = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 100 , 30 ) ,
label = ' OUTWARDS ' ,
button_type = ' square ' ,
autoselect = True ,
position = ( 120 , 50 ) ,
on_activate_call = ba . Call ( self . _change_camera_position , ' z ' ) )
self . _step_text = ba . textwidget ( parent = self . _root_widget ,
scale = 0.5 ,
color = ( 1 , 1 , 1 ) ,
text = ' Step: ' ,
size = ( 0 , 0 ) ,
position = ( 1 , - 20 ) ,
h_align = ' center ' ,
v_align = ' center ' )
self . _text_field = ba . textwidget (
parent = self . _root_widget ,
editable = True ,
size = ( 100 , 40 ) ,
position = ( 26 , - 35 ) ,
text = ' ' ,
maxwidth = 120 ,
flatness = 1.0 ,
autoselect = True ,
v_align = ' center ' ,
corner_scale = 0.7 )
self . _reset = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 50 , 30 ) ,
label = ' Reset ' ,
button_type = ' square ' ,
autoselect = True ,
position = ( 120 , - 35 ) ,
on_activate_call = ba . Call ( self . _change_camera_position , ' reset ' ) )
self . _done = ba . buttonwidget ( parent = self . _root_widget ,
size = ( 50 , 30 ) ,
label = ' Done ' ,
button_type = ' square ' ,
autoselect = True ,
position = ( 180 , - 35 ) ,
on_activate_call = self . _close )
ba . containerwidget ( edit = self . _root_widget ,
cancel_button = self . _done )
def _close ( self ) :
ba . containerwidget ( edit = self . _root_widget ,
transition = ( ' out_scale ' ) )
def _change_camera_position ( self , direction ) :
activity = _ba . get_foreground_host_activity ( )
node = activity . globalsnode
aoi = list ( node . area_of_interest_bounds )
center = [ ( aoi [ 0 ] + aoi [ 3 ] ) / 2 ,
( aoi [ 1 ] + aoi [ 4 ] ) / 2 ,
( aoi [ 2 ] + aoi [ 5 ] ) / 2 ]
size = ( aoi [ 3 ] - aoi [ 0 ] ,
aoi [ 4 ] - aoi [ 1 ] ,
aoi [ 5 ] - aoi [ 2 ] )
try :
increment = float ( ba . textwidget ( query = self . _text_field ) )
except :
# ba.print_exception()
increment = 1
if direction == ' x ' :
center [ 0 ] + = increment
elif direction == ' x- ' :
center [ 0 ] - = increment
elif direction == ' y ' :
center [ 1 ] + = increment
elif direction == ' y- ' :
center [ 1 ] - = increment
elif direction == ' z ' :
center [ 2 ] + = increment
elif direction == ' z- ' :
center [ 2 ] - = increment
elif direction == ' reset ' :
2022-09-30 09:51:51 +00:00
node . area_of_interest_bounds = activity . _map . get_def_bound_box (
' area_of_interest_bounds ' )
2022-09-30 15:18:39 +05:30
return
aoi = ( center [ 0 ] - size [ 0 ] / 2 ,
center [ 1 ] - size [ 1 ] / 2 ,
center [ 2 ] - size [ 2 ] / 2 ,
center [ 0 ] + size [ 0 ] / 2 ,
center [ 1 ] + size [ 1 ] / 2 ,
center [ 2 ] + size [ 2 ] / 2 )
node . area_of_interest_bounds = tuple ( aoi )
def __popup_menu_window_init__ ( self ,
position : Tuple [ float , float ] ,
choices : Sequence [ str ] ,
current_choice : str ,
delegate : Any = None ,
width : float = 230.0 ,
maxwidth : float = None ,
scale : float = 1.0 ,
color : Tuple [ float , float , float ] = ( 0.35 , 0.55 , 0.15 ) ,
choices_disabled : Sequence [ str ] = None ,
choices_display : Sequence [ ba . Lstr ] = None ) :
# FIXME: Clean up a bit.
# pylint: disable=too-many-branches
# pylint: disable=too-many-locals
# pylint: disable=too-many-statements
if choices_disabled is None :
choices_disabled = [ ]
if choices_display is None :
choices_display = [ ]
# FIXME: For the moment we base our width on these strings so
# we need to flatten them.
choices_display_fin : List [ str ] = [ ]
for choice_display in choices_display :
choices_display_fin . append ( choice_display . evaluate ( ) )
if maxwidth is None :
maxwidth = width * 1.5
self . _transitioning_out = False
self . _choices = list ( choices )
self . _choices_display = list ( choices_display_fin )
self . _current_choice = current_choice
self . _color = color
self . _choices_disabled = list ( choices_disabled )
self . _done_building = False
if not choices :
raise TypeError ( ' Must pass at least one choice ' )
self . _width = width
self . _scale = scale
if len ( choices ) > 8 :
self . _height = 280
self . _use_scroll = True
else :
self . _height = 20 + len ( choices ) * 33
self . _use_scroll = False
self . _delegate = None # don't want this stuff called just yet..
# extend width to fit our longest string (or our max-width)
for index , choice in enumerate ( choices ) :
if len ( choices_display_fin ) == len ( choices ) :
choice_display_name = choices_display_fin [ index ]
else :
choice_display_name = choice
if self . _use_scroll :
self . _width = max (
self . _width ,
min (
maxwidth ,
_ba . get_string_width ( choice_display_name ,
suppress_warning = True ) ) + 75 )
else :
self . _width = max (
self . _width ,
min (
maxwidth ,
_ba . get_string_width ( choice_display_name ,
suppress_warning = True ) ) + 60 )
# init parent class - this will rescale and reposition things as
# needed and create our root widget
PopupWindow . __init__ ( self ,
position ,
size = ( self . _width , self . _height ) ,
bg_color = self . _color ,
scale = self . _scale )
if self . _use_scroll :
self . _scrollwidget = ba . scrollwidget ( parent = self . root_widget ,
position = ( 20 , 20 ) ,
highlight = False ,
color = ( 0.35 , 0.55 , 0.15 ) ,
size = ( self . _width - 40 ,
self . _height - 40 ) )
self . _columnwidget = ba . columnwidget ( parent = self . _scrollwidget ,
border = 2 ,
margin = 0 )
else :
self . _offset_widget = ba . containerwidget ( parent = self . root_widget ,
position = ( 30 , 15 ) ,
size = ( self . _width - 40 ,
self . _height ) ,
background = False )
self . _columnwidget = ba . columnwidget ( parent = self . _offset_widget ,
border = 2 ,
margin = 0 )
for index , choice in enumerate ( choices ) :
if len ( choices_display_fin ) == len ( choices ) :
choice_display_name = choices_display_fin [ index ]
else :
choice_display_name = choice
inactive = ( choice in self . _choices_disabled )
wdg = ba . textwidget ( parent = self . _columnwidget ,
size = ( self . _width - 40 , 28 ) ,
on_select_call = ba . Call ( self . _select , index ) ,
click_activate = True ,
color = ( 0.5 , 0.5 , 0.5 , 0.5 ) if inactive else
( ( 0.5 , 1 , 0.5 ,
1 ) if choice == self . _current_choice else
( 0.8 , 0.8 , 0.8 , 1.0 ) ) ,
padding = 0 ,
maxwidth = maxwidth ,
text = choice_display_name ,
on_activate_call = self . _activate ,
v_align = ' center ' ,
selectable = ( not inactive ) )
if choice == self . _current_choice :
ba . containerwidget ( edit = self . _columnwidget ,
selected_child = wdg ,
visible_child = wdg )
# ok from now on our delegate can be called
self . _delegate = weakref . ref ( delegate )
self . _done_building = True
original_connect_to_party = _ba . connect_to_party
original_sign_in = ba . internal . sign_in_v1
def modify_connect_to_party ( address : str , port : int = 43210 , print_progress : bool = True ) - > None :
global _ip , _port
_ip = address
_port = port
original_connect_to_party ( _ip , _port , print_progress )
temptimer = None
def modify_sign_in ( account_type : str ) - > None :
original_sign_in ( account_type )
if messenger . server_online :
messenger . logged_in = False
global temptimer
temptimer = ba . Timer ( 2 , messenger . _cookie_login )
class PingThread ( Thread ) :
""" Thread for sending out game pings. """
def __init__ ( self , address : str , port : int ) :
super ( ) . __init__ ( )
self . _address = address
self . _port = port
def run ( self ) - > None :
sock : Optional [ socket . socket ] = None
try :
import socket
from ba . internal import get_ip_address_type
socket_type = get_ip_address_type ( self . _address )
sock = socket . socket ( socket_type , socket . SOCK_DGRAM )
sock . connect ( ( self . _address , self . _port ) )
starttime = time . time ( )
# Send a few pings and wait a second for
# a response.
sock . settimeout ( 1 )
for _i in range ( 3 ) :
sock . send ( b ' \x0b ' )
result : Optional [ bytes ]
try :
# 11: BA_PACKET_SIMPLE_PING
result = sock . recv ( 10 )
except Exception :
result = None
if result == b ' \x0c ' :
# 12: BA_PACKET_SIMPLE_PONG
accessible = True
break
time . sleep ( 1 )
global _ping
_ping = int ( ( time . time ( ) - starttime ) * 1000.0 )
except Exception :
ba . print_exception ( ' Error on gather ping ' , once = True )
finally :
try :
if sock is not None :
sock . close ( )
except Exception :
ba . print_exception ( ' Error on gather ping cleanup ' , once = True )
def _get_store_char_tex ( self ) - > str :
_ba . set_party_icon_always_visible ( True )
return ( ' storeCharacterXmas ' if ba . internal . get_v1_account_misc_read_val (
' xmas ' , False ) else
2022-09-30 09:51:51 +00:00
' storeCharacterEaster ' if ba . internal . get_v1_account_misc_read_val (
' easter ' , False ) else ' storeCharacter ' )
2022-09-30 15:18:39 +05:30
# ba_meta export plugin
class InitalRun ( ba . Plugin ) :
def __init__ ( self ) :
if _ba . env ( ) . get ( " build_number " , 0 ) > = 20124 :
global messenger , listener , displayer , color_tracker
initialize ( )
messenger = PrivateChatHandler ( )
listener = Thread ( target = messenger_thread )
listener . start ( )
displayer = ba . Timer ( 0.4 , msg_displayer , True )
color_tracker = ColorTracker ( )
bastd . ui . party . PartyWindow = PartyWindow
PopupMenuWindow . __init__ = __popup_menu_window_init__
_ba . connect_to_party = modify_connect_to_party
ba . internal . sign_in_v1 = modify_sign_in
MainMenuWindow . _get_store_char_tex = _get_store_char_tex
else :
display_error ( " This Party Window only runs with BombSquad version higer than 1.6.0. " )