bombsquad-plugin-manager/plugins/utilities/advanced_party_window.py

2174 lines
100 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
# ba_meta require api 9
2023-07-02 13:19:46 +05:30
'''
AdvancedPartyWindow by Mr.Smoothy
2023-07-02 13:19:46 +05:30
Updated to API 8 on 2nd July 2023 by Mr.Smoothy
2023-07-02 13:19:46 +05:30
build on base of plasma's modifypartywindow
2023-07-02 13:19:46 +05:30
discord mr.smoothy#5824
2023-07-02 13:19:46 +05:30
https://discord.gg/ucyaesh
2023-07-02 13:19:46 +05:30
Youtube : Hey Smoothy
Download more mods from
https://bombsquad-community.web.app/mods
'''
import threading
from _thread import start_new_thread
import urllib.parse
import urllib.request
from typing import TYPE_CHECKING, cast
import _babase
import bascenev1 as bs
import bauiv1 as bui
import babase
import time
import math
from dataclasses import dataclass
from bauiv1lib.confirm import ConfirmWindow
from bauiv1lib.colorpicker import ColorPickerExact
from typing import List, Sequence, Optional, Dict, Any, Union
import bauiv1lib.party as bascenev1lib_party
import ssl
import datetime
import base64
from babase._general import Call
from bauiv1lib.popup import PopupMenuWindow, PopupWindow
from bauiv1lib.account import viewer
import os
import urllib
import copy
import shutil
import sys
import re
import json
import codecs
import traceback
2026-04-06 00:18:59 +05:30
plugman = dict(
plugin_name="advanced_party_window",
description="Advanced your party window with lots of feature",
external_url="https://www.youtube.com/watch?v=QrES1jQGXF0",
authors=[
2026-04-06 00:18:59 +05:30
{"name": "Mr.Smoothy", "email": "", "discord": "mr.smoothy"},
],
version="2.1.7",
2026-04-06 00:18:59 +05:30
)
# added advanced ID revealer
2023-07-02 07:50:25 +00:00
# live ping
2022-09-17 16:39:03 +00:00
# Made by Mr.Smoothy - Plasma Boson
version_str = "7"
2025-10-28 12:49:26 +05:30
BCSSERVER = 'mods.ballistica.workers.dev'
2022-09-17 16:39:03 +00:00
cache_chat = []
2023-07-02 13:19:46 +05:30
connect = bs.connect_to_party
disconnect = bs.disconnect_from_host
2022-09-17 16:39:03 +00:00
unmuted_names = []
smo_mode = 3
f_chat = False
chatlogger = False
screenmsg = True
ip_add = "127.0.0.1"
p_port = 43210
p_name = "local"
current_ping = 0.0
enable_typing = False # this will prevent auto ping to update textwidget when user actually typing chat message
ssl._create_default_https_context = ssl._create_unverified_context
2022-09-17 16:39:03 +00:00
def newconnect_to_party(address, port=43210, print_progress=False):
global ip_add
global p_port
2023-11-12 17:30:32 +05:30
bs.chatmessage(" Joined IP "+ip_add+" PORT "+str(p_port))
2025-01-25 17:47:38 +05:30
dd = bs.get_connection_to_host_info_2()
2025-04-04 23:35:43 +00:00
title = getattr(dd, 'name', '')
2025-04-05 01:27:18 +02:00
bs.chatmessage(title) if dd and title else None
2025-01-25 17:47:38 +05:30
if (bool(dd)):
2023-07-02 13:19:46 +05:30
bs.disconnect_from_host()
2022-09-17 16:39:03 +00:00
ip_add = address
p_port = port
connect(address, port, print_progress)
else:
2022-09-17 16:39:03 +00:00
ip_add = address
p_port = port
# print(ip_add,p_port)
2022-09-17 16:39:03 +00:00
connect(ip_add, port, print_progress)
DEBUG_SERVER_COMMUNICATION = False
DEBUG_PROCESSING = False
2022-09-17 16:39:03 +00:00
class PingThread(threading.Thread):
"""Thread for sending out game pings."""
def __init__(self):
super().__init__()
def run(self) -> None:
# pylint: disable=too-many-branches
# pylint: disable=too-many-statements
2023-07-02 13:19:46 +05:30
bui.app.classic.ping_thread_count += 1
sock: Optional[socket.socket] = None
try:
import socket
2023-07-02 13:19:46 +05:30
from babase._net import get_ip_address_type
socket_type = get_ip_address_type(ip_add)
sock = socket.socket(socket_type, socket.SOCK_DGRAM)
2022-09-17 16:39:03 +00:00
sock.connect((ip_add, p_port))
accessible = False
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)
ping = (time.time() - starttime) * 1000.0
global current_ping
2022-09-17 16:39:03 +00:00
current_ping = round(ping, 2)
except ConnectionRefusedError:
# Fine, server; sorry we pinged you. Hmph.
pass
except OSError as exc:
import errno
# Ignore harmless errors.
if exc.errno in {
errno.EHOSTUNREACH, errno.ENETUNREACH, errno.EINVAL,
errno.EPERM, errno.EACCES
}:
pass
elif exc.errno == 10022:
# Windows 'invalid argument' error.
pass
elif exc.errno == 10051:
# Windows 'a socket operation was attempted
# to an unreachable network' error.
pass
elif exc.errno == errno.EADDRNOTAVAIL:
if self._port == 0:
# This has happened. Ignore.
pass
2023-07-02 13:19:46 +05:30
elif babase.do_once():
print(f'Got EADDRNOTAVAIL on gather ping'
f' for addr {self._address}'
f' port {self._port}.')
else:
2023-07-02 13:19:46 +05:30
babase.print_exception(
f'Error on gather ping '
f'(errno={exc.errno})', once=True)
except Exception:
2023-07-02 13:19:46 +05:30
babase.print_exception('Error on gather ping', once=True)
finally:
try:
if sock is not None:
sock.close()
except Exception:
2023-07-02 13:19:46 +05:30
babase.print_exception('Error on gather ping cleanup', once=True)
2023-07-02 13:19:46 +05:30
bui.app.classic.ping_thread_count -= 1
time.sleep(4)
self.run()
2023-07-02 13:19:46 +05:30
RecordFilesDir = os.path.join(_babase.env()["python_directory_user"], "Configs" + os.sep)
2022-09-17 16:39:03 +00:00
if not os.path.exists(RecordFilesDir):
os.makedirs(RecordFilesDir)
version_str = "3.0.1"
Current_Lang = None
SystemEncode = sys.getfilesystemencoding()
2022-09-17 16:39:03 +00:00
if not isinstance(SystemEncode, str):
SystemEncode = "utf-8"
2022-09-17 16:39:03 +00:00
PingThread().start()
2023-07-02 13:19:46 +05:30
class chatloggThread():
"""Thread for sending out game pings."""
2022-09-17 16:39:03 +00:00
def __init__(self):
super().__init__()
2022-09-17 16:39:03 +00:00
self.saved_msg = []
def run(self) -> None:
# pylint: disable=too-many-branches
# pylint: disable=too-many-statements
global chatlogger
2023-07-02 13:19:46 +05:30
self.timerr = babase.AppTimer(5.0, self.chatlogg, repeat=True)
2022-09-17 16:39:03 +00:00
def chatlogg(self):
2022-09-17 16:39:03 +00:00
global chatlogger
2023-07-02 13:19:46 +05:30
chats = bs.get_chat_messages()
2022-09-17 16:39:03 +00:00
for msg in chats:
if msg in self.saved_msg:
pass
else:
self.save(msg)
self.saved_msg.append(msg)
if len(self.saved_msg) > 45:
self.saved_msg.pop(0)
if chatlogger:
pass
else:
2022-09-17 16:39:03 +00:00
self.timerr = None
def save(self, msg):
x = str(datetime.datetime.now())
2023-07-02 13:19:46 +05:30
t = open(os.path.join(_babase.env()["python_directory_user"], "Chat logged.txt"), "a+")
2022-09-17 16:39:03 +00:00
t.write(x+" : " + msg + "\n")
t.close()
class mututalServerThread():
def run(self):
2023-07-02 13:19:46 +05:30
self.timer = babase.AppTimer(10, self.checkPlayers, repeat=True)
2022-09-17 16:39:03 +00:00
def checkPlayers(self):
2025-01-25 17:47:38 +05:30
if bool(bs.get_connection_to_host_info_2()):
server_name = bs.get_connection_to_host_info_2().name
2022-09-17 16:39:03 +00:00
players = []
2023-07-02 13:19:46 +05:30
for ros in bs.get_game_roster():
players.append(ros["display_string"])
2022-09-17 16:39:03 +00:00
start_new_thread(dump_mutual_servers, (players, server_name,))
2022-09-17 16:39:03 +00:00
def dump_mutual_servers(players, server_name):
filePath = os.path.join(RecordFilesDir, "players.json")
2022-09-17 16:39:03 +00:00
data = {}
if os.path.isfile(filePath):
2022-09-17 16:39:03 +00:00
f = open(filePath, "r")
data = json.load(f)
for player in players:
if player in data:
if server_name not in data[player]:
2022-09-17 16:39:03 +00:00
data[player].insert(0, server_name)
data[player] = data[player][:3]
else:
2022-09-17 16:39:03 +00:00
data[player] = [server_name]
f = open(filePath, "w")
json.dump(data, f)
mututalServerThread().run()
class customchatThread():
"""."""
def __init__(self):
super().__init__()
global cache_chat
2022-09-17 16:39:03 +00:00
self.saved_msg = []
2023-07-02 13:19:46 +05:30
try:
chats = bs.get_chat_messages()
for msg in chats: # fill up old chat , to avoid old msg popup
cache_chat.append(msg)
except:
pass
2022-09-17 16:39:03 +00:00
def run(self) -> None:
# pylint: disable=too-many-branches
# pylint: disable=too-many-statements
global chatlogger
2023-07-02 13:19:46 +05:30
self.timerr = babase.AppTimer(5.0, self.chatcheck, repeat=True)
def chatcheck(self):
2022-09-17 16:39:03 +00:00
global unmuted_names
global cache_chat
2023-07-02 13:19:46 +05:30
try:
chats = bs.get_chat_messages()
except:
chats = []
2022-09-17 16:39:03 +00:00
for msg in chats:
if msg in cache_chat:
pass
else:
if msg.split(":")[0] in unmuted_names:
2023-07-02 13:19:46 +05:30
bs.broadcastmessage(msg, color=(0.6, 0.9, 0.6))
2022-09-17 16:39:03 +00:00
cache_chat.append(msg)
if len(self.saved_msg) > 45:
cache_chat.pop(0)
2023-07-02 13:19:46 +05:30
if babase.app.config.resolve('Chat Muted'):
2022-09-17 16:39:03 +00:00
pass
else:
self.timerr = None
def chatloggerstatus():
2022-09-17 16:39:03 +00:00
global chatlogger
if chatlogger:
return "Turn off Chat Logger"
else:
return "Turn on chat logger"
2022-09-17 16:39:03 +00:00
def _getTransText(text, isBaLstr=False, same_fb=False):
global Current_Lang
global chatlogger
if Current_Lang != 'English':
Current_Lang = 'English'
global Language_Texts
Language_Texts = {
2022-09-17 16:39:03 +00:00
"Chinese": {
2022-09-17 16:39:03 +00:00
},
"English": {
"Add_a_Quick_Reply": "Add a Quick Reply",
"Admin_Command_Kick_Confirm": "Are you sure to use admin\
command to kick %s?",
2022-09-17 16:39:03 +00:00
"Ban_For_%d_Seconds": "Ban for %d second(s).",
"Ban_Time_Post": "Enter the time you want to ban(Seconds).",
"Credits_for_This": "Credits for This",
"Custom_Action": "Custom Action",
"Debug_for_Host_Info": "Host Info Debug",
"Game_Record_Saved": "Game replay %s is saved.",
"Kick_ID": "Kick ID:%d",
"Mention_this_guy": "Mention this guy",
"Modify_Main_Color": "Modify Main Color",
"No_valid_player_found": "Can't find a valid player.",
"No_valid_player_id_found": "Can't find a valid player ID.",
"Normal_kick_confirm": "Are you sure to kick %s?",
"Remove_a_Quick_Reply": "Remove a Quick Reply",
"Restart_Game_Record": "Save Recording",
"Restart_Game_Record_Confirm": "Are you sure to restart recording game stream?",
"Send_%d_times": "Send for %d times",
"Something_is_added": "'%s' is added.",
"Something_is_removed": "'%s' is removed.",
"Times": "Times",
"Translator": "Translator",
2022-09-17 16:39:03 +00:00
"chatloggeroff": "Turn off Chat Logger",
"chatloggeron": "Turn on Chat Logger",
"screenmsgoff": "Hide ScreenMessage",
"screenmsgon": "Show ScreenMessage",
"unmutethisguy": "unmute this guy",
"mutethisguy": "mute this guy",
"muteall": "Mute all",
2023-11-12 17:30:32 +05:30
"unmuteall": "Unmute all",
2023-11-12 12:01:30 +00:00
"copymsg": "copy"
2022-09-17 16:39:03 +00:00
}
}
Language_Texts = Language_Texts.get(Current_Lang)
try:
from Language_Packs import ModifiedPartyWindow_LanguagePack as ext_lan_pack
2022-09-17 16:39:03 +00:00
if isinstance(ext_lan_pack, dict) and isinstance(ext_lan_pack.get(Current_Lang), dict):
complete_Pack = ext_lan_pack.get(Current_Lang)
2022-09-17 16:39:03 +00:00
for key, item in complete_Pack.items():
Language_Texts[key] = item
except:
pass
2022-09-17 16:39:03 +00:00
return (Language_Texts.get(text, "#Unknown Text#" if not same_fb else text) if not isBaLstr else
2023-07-02 13:19:46 +05:30
babase.Lstr(resource="??Unknown??", fallback_value=Language_Texts.get(text, "#Unknown Text#" if not same_fb else text)))
2022-09-17 16:39:03 +00:00
def _get_popup_window_scale() -> float:
2023-07-02 13:19:46 +05:30
uiscale = bui.app.ui_v1.uiscale
return (2.3 if uiscale is babase.UIScale.SMALL else
1.65 if uiscale is babase.UIScale.MEDIUM else 1.23)
2022-09-17 16:39:03 +00:00
def _creat_Lstr_list(string_list: list = []) -> list:
2023-07-02 13:19:46 +05:30
return ([babase.Lstr(resource="??Unknown??", fallback_value=item) for item in string_list])
customchatThread().run()
2022-09-17 16:39:03 +00:00
2023-07-02 13:19:46 +05:30
class ModifiedPartyWindow(bascenev1lib_party.PartyWindow):
def __init__(self, origin: Sequence[float] = (0, 0)):
2025-10-28 12:49:26 +05:30
if _babase.env().get("build_number") >= 22597:
self._uiopenstate = bui.UIOpenState('classicparty')
else:
bui.set_party_window_open(True)
self._r = 'partyWindow'
2022-09-17 16:39:03 +00:00
self.msg_user_selected = ''
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
2023-07-02 13:19:46 +05:30
uiscale = bui.app.ui_v1.uiscale
self._height = (365 if uiscale is babase.UIScale.SMALL else
480 if uiscale is babase.UIScale.MEDIUM else 600)
2022-09-17 16:39:03 +00:00
# Custom color here
2023-07-02 13:19:46 +05:30
self._bg_color = babase.app.config.get("PartyWindow_Main_Color", (0.40, 0.55, 0.20)) if not isinstance(
2022-09-17 16:39:03 +00:00
self._getCustomSets().get("Color"), (list, tuple)) else self._getCustomSets().get("Color")
if not isinstance(self._bg_color, (list, tuple)) or not len(self._bg_color) == 3:
self._bg_color = (0.40, 0.55, 0.20)
2023-07-02 13:19:46 +05:30
bui.Window.__init__(self, root_widget=bui.containerwidget(
size=(self._width, self._height),
transition='in_scale',
color=self._bg_color,
2023-07-02 13:19:46 +05:30
parent=bui.get_special_widget('overlay_stack'),
on_outside_click_call=self.close_with_sound,
scale_origin_stack_offset=origin,
2023-07-02 13:19:46 +05:30
scale=(2.0 if uiscale is babase.UIScale.SMALL else
1.35 if uiscale is babase.UIScale.MEDIUM else 1.0),
stack_offset=(0, -10) if uiscale is babase.UIScale.SMALL else (
240, 0) if uiscale is babase.UIScale.MEDIUM else (330, 20)))
2023-07-02 13:19:46 +05:30
self._cancel_button = bui.buttonwidget(parent=self._root_widget,
2023-07-02 07:50:25 +00:00
scale=0.7,
position=(30, self._height - 47),
2022-09-17 16:39:03 +00:00
size=(50, 50),
2023-07-02 07:50:25 +00:00
label='',
on_activate_call=self.close,
2022-09-17 16:39:03 +00:00
autoselect=True,
color=(0.45, 0.63, 0.15),
2023-07-02 07:50:25 +00:00
icon=bui.gettexture('crossOut'),
2022-09-17 16:39:03 +00:00
iconscale=1.2)
2023-07-02 07:50:25 +00:00
self._smoothy_button = bui.buttonwidget(parent=self._root_widget,
scale=0.6,
position=(5, self._height - 47 - 40),
size=(50, 50),
label='69',
on_activate_call=self.smoothy_roster_changer,
autoselect=True,
color=(0.45, 0.63, 0.15),
icon=bui.gettexture('replayIcon'),
iconscale=1.2)
2023-07-02 13:19:46 +05:30
bui.containerwidget(edit=self._root_widget,
2023-07-02 07:50:25 +00:00
cancel_button=self._cancel_button)
2023-07-02 13:19:46 +05:30
self._menu_button = bui.buttonwidget(
parent=self._root_widget,
scale=0.7,
position=(self._width - 60, self._height - 47),
size=(50, 50),
label="\xee\x80\x90",
autoselect=True,
button_type='square',
2025-10-27 19:37:45 +05:30
on_activate_call=bs.WeakCallStrict(self._on_menu_button_press),
color=(0.55, 0.73, 0.25),
2023-07-02 13:19:46 +05:30
icon=bui.gettexture('menuButton'),
iconscale=1.2)
2026-04-05 23:22:03 +05:30
self._menu_popup: PopupMenuWindow | None = None
2025-01-25 17:47:38 +05:30
info = bs.get_connection_to_host_info_2()
if info != None:
title = info.name
else:
2023-07-02 13:19:46 +05:30
title = babase.Lstr(resource=self._r + '.titleText')
2023-07-02 13:19:46 +05:30
self._title_text = bui.textwidget(parent=self._root_widget,
2023-07-02 07:50:25 +00:00
scale=0.9,
color=(0.5, 0.7, 0.5),
text=title,
size=(120, 20),
position=(self._width * 0.5-60,
self._height - 29),
on_select_call=self.title_selected,
selectable=True,
maxwidth=self._width * 0.7,
h_align='center',
v_align='center')
2023-07-02 13:19:46 +05:30
self._empty_str = bui.textwidget(parent=self._root_widget,
2023-07-02 07:50:25 +00:00
scale=0.75,
size=(0, 0),
position=(self._width * 0.5,
self._height - 65),
maxwidth=self._width * 0.85,
text="no one",
h_align='center',
v_align='center')
self._scroll_width = self._width - 50
2023-07-02 13:19:46 +05:30
self._scrollwidget = bui.scrollwidget(parent=self._root_widget,
2023-07-02 07:50:25 +00:00
size=(self._scroll_width,
self._height - 200),
position=(30, 80),
color=(0.4, 0.6, 0.3))
2023-07-02 13:19:46 +05:30
self._columnwidget = bui.columnwidget(parent=self._scrollwidget,
2023-07-02 07:50:25 +00:00
border=2,
2023-11-12 17:30:32 +05:30
left_border=-200,
2023-07-02 07:50:25 +00:00
margin=0)
2023-07-02 13:19:46 +05:30
bui.widget(edit=self._menu_button, down_widget=self._columnwidget)
2023-07-02 13:19:46 +05:30
self._muted_text = bui.textwidget(
parent=self._root_widget,
position=(self._width * 0.5, self._height * 0.5),
size=(0, 0),
h_align='center',
v_align='center',
text="")
2023-07-02 13:19:46 +05:30
self._chat_texts: List[bui.Widget] = []
self._chat_texts_haxx: List[bui.Widget] = []
# add all existing messages if chat is not muted
# print("updates")
2022-09-17 16:39:03 +00:00
if True: # smoothy - always show chat in partywindow
2023-07-02 13:19:46 +05:30
msgs = bs.get_chat_messages()
for msg in msgs:
self._add_msg(msg)
# print(msg)
# else:
2023-07-02 13:19:46 +05:30
# msgs=_babase.get_chat_messages()
# for msg in msgs:
# print(msg);
2023-07-02 13:19:46 +05:30
# txt = bui.textwidget(parent=self._columnwidget,
# text=msg,
# h_align='left',
# v_align='center',
# size=(0, 13),
# scale=0.55,
# maxwidth=self._scroll_width * 0.94,
# shadow=0.3,
# flatness=1.0)
# self._chat_texts.append(txt)
# if len(self._chat_texts) > 40:
# first = self._chat_texts.pop(0)
# first.delete()
2023-07-02 13:19:46 +05:30
# bui.containerwidget(edit=self._columnwidget, visible_child=txt)
self.ping_widget = txt = bui.textwidget(
parent=self._root_widget,
2022-09-17 16:39:03 +00:00
scale=0.6,
size=(20, 5),
color=(0.45, 0.63, 0.15),
2022-09-17 16:39:03 +00:00
position=(self._width/2 - 20, 50),
text="Ping:"+str(current_ping)+" ms",
selectable=True,
autoselect=False,
v_align='center')
2023-07-02 13:19:46 +05:30
_babase.ping_widget = self.ping_widget
def enable_chat_mode():
pass
2023-07-02 13:19:46 +05:30
self._text_field = txt = bui.textwidget(
parent=self._root_widget,
editable=True,
size=(530-80, 40),
position=(44+60, 39),
text='',
maxwidth=494,
shadow=0.3,
flatness=1.0,
2023-07-02 13:19:46 +05:30
description=babase.Lstr(resource=self._r + '.chatMessageText'),
autoselect=True,
v_align='center',
corner_scale=0.7)
2023-07-02 13:19:46 +05:30
# for m in _babase.get_chat_messages():
# if m:
2023-07-02 13:19:46 +05:30
# ttchat=bui.textwidget(
# parent=self._columnwidget,
# size=(10,10),
# h_align='left',
# v_align='center',
# text=str(m),
# scale=0.6,
# flatness=0,
# color=(2,2,2),
# shadow=0,
# always_highlight=True
# )
2023-07-02 13:19:46 +05:30
bui.widget(edit=self._scrollwidget,
2023-07-02 07:50:25 +00:00
autoselect=True,
left_widget=self._cancel_button,
up_widget=self._cancel_button,
down_widget=self._text_field)
2023-07-02 13:19:46 +05:30
bui.widget(edit=self._columnwidget,
2023-07-02 07:50:25 +00:00
autoselect=True,
up_widget=self._cancel_button,
down_widget=self._text_field)
2023-07-02 13:19:46 +05:30
bui.containerwidget(edit=self._root_widget, selected_child=txt)
btn = bui.buttonwidget(parent=self._root_widget,
2023-07-02 07:50:25 +00:00
size=(50, 35),
label=babase.Lstr(resource=self._r + '.sendText'),
button_type='square',
autoselect=True,
position=(self._width - 70, 35),
on_activate_call=self._send_chat_message)
def _times_button_on_click():
# self._popup_type = "send_Times_Press"
2023-07-02 13:19:46 +05:30
# allow_range = 100 if _babase.get_foreground_host_session() is not None else 4
# PopupMenuWindow(position=self._times_button.get_screen_space_center(),
# scale=_get_popup_window_scale(),
# choices=[str(index) for index in range(1,allow_range + 1)],
# choices_display=_creat_Lstr_list([_getTransText("Send_%d_times")%int(index) for index in range(1,allow_range + 1)]),
# current_choice="Share_Server_Info",
# delegate=self)
Quickreply = self._get_quick_responds()
if len(Quickreply) > 0:
PopupMenuWindow(position=self._times_button.get_screen_space_center(),
2022-09-17 16:39:03 +00:00
scale=_get_popup_window_scale(),
choices=Quickreply,
choices_display=_creat_Lstr_list(Quickreply),
current_choice=Quickreply[0],
delegate=self)
self._popup_type = "QuickMessageSelect"
self._send_msg_times = 1
2023-07-02 13:19:46 +05:30
self._times_button = bui.buttonwidget(parent=self._root_widget,
2023-07-02 07:50:25 +00:00
size=(50, 35),
label="Quick",
button_type='square',
autoselect=True,
position=(30, 35),
on_activate_call=_times_button_on_click)
2023-07-02 13:19:46 +05:30
bui.textwidget(edit=txt, on_return_press_call=btn.activate)
self._name_widgets: List[bui.Widget] = []
self._roster: Optional[List[Dict[str, Any]]] = None
2022-09-17 16:39:03 +00:00
self.smoothy_mode = 1
self.full_chat_mode = False
2023-07-02 13:19:46 +05:30
self._update_timer = babase.AppTimer(1.0,
2025-10-27 19:37:45 +05:30
bs.WeakCallStrict(self._update),
2023-07-02 07:50:25 +00:00
repeat=True)
self._update()
2022-09-17 16:39:03 +00:00
def title_selected(self):
2022-09-17 16:39:03 +00:00
self.full_chat_mode = self.full_chat_mode == False
self._update()
2022-09-17 16:39:03 +00:00
def smoothy_roster_changer(self):
2022-09-17 16:39:03 +00:00
self.smoothy_mode = (self.smoothy_mode+1) % 3
2022-09-17 16:39:03 +00:00
self._update()
def on_chat_message(self, msg: str) -> None:
2022-09-17 16:39:03 +00:00
"""Called when a new chat message comes through."""
# print("on_chat"+msg)
if True:
self._add_msg(msg)
2023-11-12 17:30:32 +05:30
def _copy_msg(self, msg: str) -> None:
if bui.clipboard_is_supported():
bui.clipboard_set_text(msg)
bui.screenmessage(
bui.Lstr(resource='copyConfirmText'),
color=(0, 1, 0)
)
2023-11-12 17:30:32 +05:30
def _on_chat_press(self, msg, widget, showMute):
global unmuted_names
choices = ['copy']
choices_display = [_getTransText("copymsg", isBaLstr=True)]
if showMute:
if msg.split(":")[0].encode('utf-8') in unmuted_names:
choices.append('mute')
choices_display.append(_getTransText("mutethisguy", isBaLstr=True))
else:
choices.append('unmute')
choices_display.append(_getTransText("unmutethisguy", isBaLstr=True))
PopupMenuWindow(position=widget.get_screen_space_center(),
2022-09-17 16:39:03 +00:00
scale=_get_popup_window_scale(),
choices=choices,
choices_display=choices_display,
current_choice="@ this guy",
delegate=self)
2023-11-12 17:30:32 +05:30
self.msg_user_selected = msg
self._popup_type = "chatmessagepress"
2023-07-02 13:19:46 +05:30
# bs.chatmessage("pressed")
def _add_msg(self, msg: str) -> None:
2022-09-17 16:39:03 +00:00
try:
2023-11-12 17:30:32 +05:30
showMute = babase.app.config.resolve('Chat Muted')
if True:
2023-07-02 13:19:46 +05:30
txt = bui.textwidget(parent=self._columnwidget,
2023-07-02 07:50:25 +00:00
text=msg,
h_align='left',
v_align='center',
2023-11-12 17:30:32 +05:30
size=(900, 13),
2023-07-02 07:50:25 +00:00
scale=0.55,
position=(-0.6, 0),
selectable=True,
2023-11-12 17:30:32 +05:30
autoselect=True,
2023-07-02 07:50:25 +00:00
click_activate=True,
maxwidth=self._scroll_width * 0.94,
shadow=0.3,
flatness=1.0)
2023-07-02 13:19:46 +05:30
bui.textwidget(edit=txt,
2025-10-28 12:49:26 +05:30
on_activate_call=babase.CallPartial(
2023-07-02 07:50:25 +00:00
self._on_chat_press,
2023-11-12 17:30:32 +05:30
msg, txt, showMute))
2022-09-17 16:39:03 +00:00
2023-07-02 13:19:46 +05:30
# btn = bui.buttonwidget(parent=self._columnwidget,
2022-09-17 16:39:03 +00:00
# scale=0.7,
# size=(100,20),
# label="smoothy buttin",
2023-07-02 13:19:46 +05:30
# icon=bs.gettexture('replayIcon'),
2022-09-17 16:39:03 +00:00
# texture=None,
# )
self._chat_texts_haxx.append(txt)
if len(self._chat_texts_haxx) > 40:
first = self._chat_texts_haxx.pop(0)
first.delete()
2023-07-02 13:19:46 +05:30
bui.containerwidget(edit=self._columnwidget, visible_child=txt)
2022-09-17 16:39:03 +00:00
except Exception:
pass
def _add_msg_when_muted(self, msg: str) -> None:
2023-07-02 13:19:46 +05:30
txt = bui.textwidget(parent=self._columnwidget,
2023-07-02 07:50:25 +00:00
text=msg,
h_align='left',
v_align='center',
size=(0, 13),
scale=0.55,
maxwidth=self._scroll_width * 0.94,
shadow=0.3,
flatness=1.0)
2022-09-17 16:39:03 +00:00
self._chat_texts.append(txt)
if len(self._chat_texts) > 40:
first = self._chat_texts.pop(0)
first.delete()
2023-07-02 13:19:46 +05:30
bui.containerwidget(edit=self._columnwidget, visible_child=txt)
2022-09-17 16:39:03 +00:00
def color_picker_closing(self, picker) -> None:
2023-07-02 13:19:46 +05:30
babase._appconfig.commit_app_config()
2022-09-17 16:39:03 +00:00
def color_picker_selected_color(self, picker, color) -> None:
2022-09-17 16:39:03 +00:00
# bs.animateArray(self._root_widget,"color",3,{0:self._bg_color,1500:color})
2023-07-02 13:19:46 +05:30
bui.containerwidget(edit=self._root_widget, color=color)
self._bg_color = color
2023-07-02 13:19:46 +05:30
babase.app.config["PartyWindow_Main_Color"] = color
2022-09-17 16:39:03 +00:00
def _on_nick_rename_press(self, arg) -> None:
2023-07-02 13:19:46 +05:30
bui.containerwidget(edit=self._root_widget, transition='out_scale')
c_width = 600
c_height = 250
2023-07-02 13:19:46 +05:30
uiscale = bui.app.ui_v1.uiscale
self._nick_rename_window = cnt = bui.containerwidget(
2023-07-02 13:19:46 +05:30
scale=(1.8 if uiscale is babase.UIScale.SMALL else
1.55 if uiscale is babase.UIScale.MEDIUM else 1.0),
size=(c_width, c_height),
transition='in_scale')
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=cnt,
2023-07-02 07:50:25 +00:00
size=(0, 0),
h_align='center',
v_align='center',
text='Enter nickname',
maxwidth=c_width * 0.8,
position=(c_width * 0.5, c_height - 60))
2022-09-17 16:39:03 +00:00
id = self._get_nick(arg)
2023-07-02 13:19:46 +05:30
self._player_nick_text = txt89 = bui.textwidget(
parent=cnt,
size=(c_width * 0.8, 40),
h_align='left',
v_align='center',
text=id,
editable=True,
description='Players nick name',
position=(c_width * 0.1, c_height - 140),
autoselect=True,
maxwidth=c_width * 0.7,
max_chars=200)
2023-07-02 13:19:46 +05:30
cbtn = bui.buttonwidget(
parent=cnt,
2023-07-02 13:19:46 +05:30
label=babase.Lstr(resource='cancelText'),
2025-10-28 12:49:26 +05:30
on_activate_call=babase.CallPartial(
2023-07-02 13:19:46 +05:30
lambda c: bui.containerwidget(edit=c, transition='out_scale'),
cnt),
size=(180, 60),
position=(30, 30),
autoselect=True)
2023-07-02 13:19:46 +05:30
okb = bui.buttonwidget(parent=cnt,
2023-07-02 07:50:25 +00:00
label='Rename',
size=(180, 60),
position=(c_width - 230, 30),
2025-10-28 12:49:26 +05:30
on_activate_call=babase.CallPartial(
2023-07-02 07:50:25 +00:00
self._add_nick, arg),
autoselect=True)
2023-07-02 13:19:46 +05:30
bui.widget(edit=cbtn, right_widget=okb)
bui.widget(edit=okb, left_widget=cbtn)
bui.textwidget(edit=txt89, on_return_press_call=okb.activate)
bui.containerwidget(edit=cnt, cancel_button=cbtn, start_button=okb)
2022-09-17 16:39:03 +00:00
def _add_nick(self, arg):
2023-07-02 13:19:46 +05:30
config = babase.app.config
new_name_raw = cast(str, bui.textwidget(query=self._player_nick_text))
2022-09-17 16:39:03 +00:00
if arg:
if not isinstance(config.get('players nick'), dict):
config['players nick'] = {}
config['players nick'][arg] = new_name_raw
config.commit()
2023-07-02 13:19:46 +05:30
bui.containerwidget(edit=self._nick_rename_window,
2023-07-02 07:50:25 +00:00
transition='out_scale')
2023-07-02 13:19:46 +05:30
# bui.containerwidget(edit=self._root_widget,transition='in_scale')
2022-09-17 16:39:03 +00:00
def _get_nick(self, id):
2023-07-02 13:19:46 +05:30
config = babase.app.config
2022-09-17 16:39:03 +00:00
if not isinstance(config.get('players nick'), dict):
return "add nick"
elif id in config['players nick']:
return config['players nick'][id]
else:
return "add nick"
def _reset_game_record(self) -> None:
try:
2023-07-02 13:19:46 +05:30
dir_path = _babase.get_replays_dir()
2022-09-17 16:39:03 +00:00
curFilePath = os.path.join(dir_path+os.sep, "__lastReplay.brp").encode(SystemEncode)
2023-07-02 13:19:46 +05:30
newFileName = str(babase.Lstr(resource="replayNameDefaultText").evaluate(
2022-09-17 16:39:03 +00:00
)+" (%s)" % (datetime.datetime.strftime(datetime.datetime.now(), "%Y_%m_%d_%H_%M_%S"))+".brp")
newFilePath = os.path.join(dir_path+os.sep, newFileName).encode(SystemEncode)
2023-08-03 20:25:29 +05:30
# print(curFilePath, newFilePath)
2022-09-17 16:39:03 +00:00
# os.rename(curFilePath,newFilePath)
shutil.copyfile(curFilePath, newFilePath)
2023-07-02 13:19:46 +05:30
bs.broadcastmessage(_getTransText("Game_Record_Saved") % newFileName, color=(1, 1, 1))
2022-09-17 16:39:03 +00:00
except:
2023-07-02 13:19:46 +05:30
babase.print_exception()
bs.broadcastmessage(babase.Lstr(resource="replayWriteErrorText").evaluate() +
2023-07-02 07:50:25 +00:00
""+traceback.format_exc(), color=(1, 0, 0))
2022-09-17 16:39:03 +00:00
def _on_menu_button_press(self) -> None:
2023-07-02 13:19:46 +05:30
is_muted = babase.app.config.resolve('Chat Muted')
global chatlogger
2022-09-17 16:39:03 +00:00
choices = ["unmute" if is_muted else "mute", "screenmsg",
"addQuickReply", "removeQuickReply", "chatlogger", "credits"]
DisChoices = [_getTransText("unmuteall", isBaLstr=True) if is_muted else _getTransText("muteall", isBaLstr=True),
_getTransText("screenmsgoff", isBaLstr=True) if screenmsg else _getTransText(
"screenmsgon", isBaLstr=True),
_getTransText("Add_a_Quick_Reply", isBaLstr=True),
_getTransText("Remove_a_Quick_Reply", isBaLstr=True),
_getTransText("chatloggeroff", isBaLstr=True) if chatlogger else _getTransText(
"chatloggeron", isBaLstr=True),
_getTransText("Credits_for_This", isBaLstr=True)
]
choices.append("resetGameRecord")
2022-09-17 16:39:03 +00:00
DisChoices.append(_getTransText("Restart_Game_Record", isBaLstr=True))
if self._getCustomSets().get("Enable_HostInfo_Debug", False):
choices.append("hostInfo_Debug")
DisChoices.append(_getTransText("Debug_for_Host_Info", isBaLstr=True))
2026-04-05 23:22:03 +05:30
self._menu_popup = PopupMenuWindow(
position=self._menu_button.get_screen_space_center(),
scale=_get_popup_window_scale(),
choices=choices,
choices_display=DisChoices,
current_choice="unmute" if is_muted else "mute", delegate=self)
self._popup_type = "menu"
2022-09-17 16:39:03 +00:00
def _on_party_member_press(self, client_id: int, is_host: bool,
2023-07-02 13:19:46 +05:30
widget: bui.Widget) -> None:
# if we"re the host, pop up "kick" options for all non-host members
2023-07-02 13:19:46 +05:30
if bs.get_foreground_host_session() is not None:
kick_str = babase.Lstr(resource="kickText")
2022-09-17 16:39:03 +00:00
else:
2023-07-02 13:19:46 +05:30
kick_str = babase.Lstr(resource="kickVoteText")
2022-09-17 16:39:03 +00:00
choices = ["kick", "@ this guy", "info", "adminkick"]
2023-07-02 13:19:46 +05:30
choices_display = [kick_str, _getTransText("Mention_this_guy", isBaLstr=True), babase.Lstr(resource="??Unknown??", fallback_value="Info"),
babase.Lstr(resource="??Unknown??", fallback_value=_getTransText("Kick_ID") % client_id)]
try:
2022-09-17 16:39:03 +00:00
if len(self._getCustomSets().get("partyMemberPress_Custom") if isinstance(self._getCustomSets().get("partyMemberPress_Custom"), dict) else {}) > 0:
choices.append("customAction")
choices_display.append(_getTransText("Custom_Action", isBaLstr=True))
except:
2023-07-02 13:19:46 +05:30
babase.print_exception()
2026-04-05 23:22:03 +05:30
self._menu_popup = PopupMenuWindow(position=widget.get_screen_space_center(),
scale=_get_popup_window_scale(),
choices=choices,
choices_display=choices_display,
current_choice="@ this guy",
delegate=self)
self._popup_party_member_client_id = client_id
self._popup_party_member_is_host = is_host
self._popup_type = "partyMemberPress"
def _send_chat_message(self) -> None:
2023-07-02 13:19:46 +05:30
sendtext = bui.textwidget(query=self._text_field)
2022-09-17 16:39:03 +00:00
if sendtext == ".ip":
2023-07-02 13:19:46 +05:30
bs.chatmessage("IP "+ip_add+" PORT "+str(p_port))
2022-09-17 16:39:03 +00:00
2023-07-02 13:19:46 +05:30
bui.textwidget(edit=self._text_field, text="")
return
2022-09-17 16:39:03 +00:00
elif sendtext == ".info":
2025-01-25 17:47:38 +05:30
if bs.get_connection_to_host_info_2() == None:
2022-09-17 16:39:03 +00:00
s_build = 0
else:
2025-01-25 17:47:38 +05:30
s_build = bs.get_connection_to_host_info_2()['build_number']
2022-09-17 16:39:03 +00:00
s_v = "0"
if s_build <= 14365:
s_v = " 1.4.148 or below"
elif s_build <= 14377:
s_v = "1.4.148 < x < = 1.4.155 "
elif s_build >= 20001 and s_build < 20308:
s_v = "1.5"
elif s_build >= 20308 and s_build < 20591:
s_v = "1.6 "
else:
s_v = "1.7 and above "
2023-07-02 13:19:46 +05:30
bs.chatmessage("script version "+s_v+"- build "+str(s_build))
bui.textwidget(edit=self._text_field, text="")
2022-09-17 16:39:03 +00:00
return
elif sendtext == ".ping":
2023-07-02 13:19:46 +05:30
bs.chatmessage("My ping:"+str(current_ping))
bui.textwidget(edit=self._text_field, text="")
2022-09-17 16:39:03 +00:00
return
elif sendtext == ".save":
2025-01-25 17:47:38 +05:30
info = bs.get_connection_to_host_info_2()
2023-07-02 13:19:46 +05:30
config = babase.app.config
2025-01-25 17:47:38 +05:30
if info != None and info.get('name', '') != '':
2022-09-17 16:39:03 +00:00
title = info['name']
if not isinstance(config.get('Saved Servers'), dict):
config['Saved Servers'] = {}
config['Saved Servers'][f'{ip_add}@{p_port}'] = {
'addr': ip_add,
'port': p_port,
'name': title
}
config.commit()
2023-07-02 13:19:46 +05:30
bs.broadcastmessage("Server saved to manual")
bui.getsound('gunCocking').play()
bui.textwidget(edit=self._text_field, text="")
2022-09-17 16:39:03 +00:00
return
# elif sendtext != "":
# for index in range(getattr(self,"_send_msg_times",1)):
if '\\' in sendtext:
2022-09-17 16:39:03 +00:00
sendtext = sendtext.replace('\\d', ('\ue048'))
sendtext = sendtext.replace('\\c', ('\ue043'))
sendtext = sendtext.replace('\\h', ('\ue049'))
sendtext = sendtext.replace('\\s', ('\ue046'))
sendtext = sendtext.replace('\\n', ('\ue04b'))
sendtext = sendtext.replace('\\f', ('\ue04f'))
sendtext = sendtext.replace('\\g', ('\ue027'))
sendtext = sendtext.replace('\\i', ('\ue03a'))
sendtext = sendtext.replace('\\m', ('\ue04d'))
sendtext = sendtext.replace('\\t', ('\ue01f'))
sendtext = sendtext.replace('\\bs', ('\ue01e'))
sendtext = sendtext.replace('\\j', ('\ue010'))
sendtext = sendtext.replace('\\e', ('\ue045'))
sendtext = sendtext.replace('\\l', ('\ue047'))
sendtext = sendtext.replace('\\a', ('\ue020'))
sendtext = sendtext.replace('\\b', ('\ue00c'))
if sendtext == "":
sendtext = " "
msg = sendtext
msg1 = msg.split(" ")
ms2 = ""
if (len(msg1) > 11):
hp = int(len(msg1)/2)
for m in range(0, hp):
ms2 = ms2+" "+msg1[m]
2023-07-02 13:19:46 +05:30
bs.chatmessage(ms2)
2022-09-17 16:39:03 +00:00
ms2 = ""
for m in range(hp, len(msg1)):
ms2 = ms2+" "+msg1[m]
2023-07-02 13:19:46 +05:30
bs.chatmessage(ms2)
else:
2023-07-02 13:19:46 +05:30
bs.chatmessage(msg)
2023-07-02 13:19:46 +05:30
bui.textwidget(edit=self._text_field, text="")
# else:
# Quickreply = self._get_quick_responds()
# if len(Quickreply) > 0:
# PopupMenuWindow(position=self._text_field.get_screen_space_center(),
# scale=_get_popup_window_scale(),
# choices=Quickreply,
# choices_display=_creat_Lstr_list(Quickreply),
# current_choice=Quickreply[0],
# delegate=self)
# self._popup_type = "QuickMessageSelect"
# else:
2023-07-02 13:19:46 +05:30
# bs.chatmessage(sendtext)
# bui.textwidget(edit=self._text_field,text="")
2022-09-17 16:39:03 +00:00
def _get_quick_responds(self):
2022-09-17 16:39:03 +00:00
if not hasattr(self, "_caches") or not isinstance(self._caches, dict):
self._caches = {}
try:
2022-09-17 16:39:03 +00:00
filePath = os.path.join(RecordFilesDir, "Quickmessage.txt")
if os.path.exists(RecordFilesDir) is not True:
os.makedirs(RecordFilesDir)
if not os.path.isfile(filePath):
2022-09-17 16:39:03 +00:00
with open(filePath, "wb") as writer:
writer.write(({"Chinese": u"\xe5\x8e\x89\xe5\xae\xb3\xef\xbc\x8c\xe8\xbf\x98\xe6\x9c\x89\xe8\xbf\x99\xe7\xa7\x8d\xe9\xaa\x9a\xe6\x93\x8d\xe4\xbd\x9c!\
\xe4\xbd\xa0\xe2\x84\xa2\xe8\x83\xbd\xe5\x88\xab\xe6\x89\x93\xe9\x98\x9f\xe5\x8f\x8b\xe5\x90\x97\xef\xbc\x9f\
2023-07-02 13:19:46 +05:30
\xe5\x8f\xaf\xe4\xbb\xa5\xe5\x95\x8a\xe5\xb1\x85\xe7\x84\xb6\xe8\x83\xbd\xe8\xbf\x99\xe4\xb9\x88\xe7\x8e\xa9\xef\xbc\x9f"}.get(Current_Lang, "Thats Amazing !")).encode("UTF-8"))
if os.path.getmtime(filePath) != self._caches.get("Vertify_Quickresponse_Text"):
2023-07-02 13:19:46 +05:30
with open(filePath, "r+", encoding="utf-8") as Reader:
Text = Reader.read()
if Text.startswith(str(codecs.BOM_UTF8)):
Text = Text[3:]
self._caches["quickReplys"] = (Text).split("\\n")
self._caches["Vertify_Quickresponse_Text"] = os.path.getmtime(filePath)
2022-09-17 16:39:03 +00:00
return (self._caches.get("quickReplys", []))
except:
2023-07-02 13:19:46 +05:30
babase.print_exception()
bs.broadcastmessage(babase.Lstr(resource="errorText"), (1, 0, 0))
bui.getsound("error").play()
2022-09-17 16:39:03 +00:00
def _write_quick_responds(self, data):
try:
2022-09-17 16:39:03 +00:00
with open(os.path.join(RecordFilesDir, "Quickmessage.txt"), "wb") as writer:
writer.write("\\n".join(data).encode("utf-8"))
2022-09-17 16:39:03 +00:00
except:
2023-07-02 13:19:46 +05:30
babase.print_exception()
bs.broadcastmessage(babase.Lstr(resource="errorText"), (1, 0, 0))
bui.getsound("error").play()
2022-09-17 16:39:03 +00:00
def _getCustomSets(self):
try:
2022-09-17 16:39:03 +00:00
if not hasattr(self, "_caches") or not isinstance(self._caches, dict):
self._caches = {}
try:
from VirtualHost import MainSettings
2022-09-17 16:39:03 +00:00
if MainSettings.get("Custom_PartyWindow_Sets", {}) != self._caches.get("PartyWindow_Sets", {}):
self._caches["PartyWindow_Sets"] = MainSettings.get(
"Custom_PartyWindow_Sets", {})
except:
try:
2022-09-17 16:39:03 +00:00
filePath = os.path.join(RecordFilesDir, "Settings.json")
if os.path.isfile(filePath):
if os.path.getmtime(filePath) != self._caches.get("Vertify_MainSettings.json_Text"):
2023-07-02 13:19:46 +05:30
with open(filePath, "r+", encoding="utf-8") as Reader:
Text = Reader.read()
if Text.startswith(str(codecs.BOM_UTF8)):
Text = Text[3:]
2022-09-17 16:39:03 +00:00
self._caches["PartyWindow_Sets"] = json.loads(
Text.decode("utf-8")).get("Custom_PartyWindow_Sets", {})
self._caches["Vertify_MainSettings.json_Text"] = os.path.getmtime(
filePath)
except:
2023-07-02 13:19:46 +05:30
babase.print_exception()
2022-09-17 16:39:03 +00:00
return (self._caches.get("PartyWindow_Sets") if isinstance(self._caches.get("PartyWindow_Sets"), dict) else {})
except:
2023-07-02 13:19:46 +05:30
babase.print_exception()
2022-09-17 16:39:03 +00:00
def _getObjectByID(self, type="playerName", ID=None):
if ID is None:
ID = self._popup_party_member_client_id
type = type.lower()
output = []
for roster in self._roster:
if type.startswith("all"):
2022-09-17 16:39:03 +00:00
if type in ("roster", "fullrecord"):
output += [roster]
elif type.find("player") != -1 and roster["players"] != []:
2022-09-17 16:39:03 +00:00
if type.find("namefull") != -1:
output += [(i["name_full"]) for i in roster["players"]]
elif type.find("name") != -1:
output += [(i["name"]) for i in roster["players"]]
elif type.find("playerid") != -1:
output += [i["id"] for i in roster["players"]]
elif type.lower() in ("account", "displaystring"):
output += [(roster["display_string"])]
elif roster["client_id"] == ID and not type.startswith("all"):
try:
2022-09-17 16:39:03 +00:00
if type in ("roster", "fullrecord"):
return (roster)
elif type.find("player") != -1 and roster["players"] != []:
if len(roster["players"]) == 1 or type.find("singleplayer") != -1:
2022-09-17 16:39:03 +00:00
if type.find("namefull") != -1:
return ((roster["players"][0]["name_full"]))
elif type.find("name") != -1:
return ((roster["players"][0]["name"]))
elif type.find("playerid") != -1:
return (roster["players"][0]["id"])
else:
2022-09-17 16:39:03 +00:00
if type.find("namefull") != -1:
return ([(i["name_full"]) for i in roster["players"]])
elif type.find("name") != -1:
return ([(i["name"]) for i in roster["players"]])
elif type.find("playerid") != -1:
return ([i["id"] for i in roster["players"]])
elif type.lower() in ("account", "displaystring"):
return ((roster["display_string"]))
except:
2023-07-02 13:19:46 +05:30
babase.print_exception()
2022-09-17 16:39:03 +00:00
return (None if len(output) == 0 else output)
def _edit_text_msg_box(self, text, type="rewrite"):
if not isinstance(type, str) or not isinstance(text, str):
return
type = type.lower()
text = (text)
if type.find("add") != -1:
2023-07-02 13:19:46 +05:30
bui.textwidget(edit=self._text_field, text=bui.textwidget(query=self._text_field)+text)
2022-09-17 16:39:03 +00:00
else:
2023-07-02 13:19:46 +05:30
bui.textwidget(edit=self._text_field, text=text)
2022-09-17 16:39:03 +00:00
2023-07-02 13:19:46 +05:30
def _send_admin_kick_command(self): bs.chatmessage(
2022-09-17 16:39:03 +00:00
"/kick " + str(self._popup_party_member_client_id))
def new_input_window_callback(self, got_text, flag, code):
if got_text:
if flag.startswith("Host_Kick_Player:"):
try:
2023-07-02 13:19:46 +05:30
result = _babase.disconnect_client(
2022-09-17 16:39:03 +00:00
self._popup_party_member_client_id, ban_time=int(code))
if not result:
2023-07-02 13:19:46 +05:30
bui.getsound('error').play()
bs.broadcastmessage(
babase.Lstr(resource='getTicketsWindow.unavailableText'),
color=(1, 0, 0))
except:
2023-07-02 13:19:46 +05:30
bui.getsound('error').play()
print(traceback.format_exc())
def _kick_selected_player(self):
"""
2023-07-02 13:19:46 +05:30
result = _babase._disconnectClient(self._popup_party_member_client_id,banTime)
if not result:
2023-07-02 13:19:46 +05:30
bs.getsound("error").play()
bs.broadcastmessage(babase.Lstr(resource="getTicketsWindow.unavailableText"),color=(1,0,0))
"""
if self._popup_party_member_client_id != -1:
2023-07-02 13:19:46 +05:30
if bs.get_foreground_host_session() is not None:
self._popup_type = "banTimePress"
2022-09-17 16:39:03 +00:00
choices = [0, 30, 60, 120, 300, 600, 900, 1800, 3600, 7200, 99999999] if not (isinstance(self._getCustomSets().get("Ban_Time_List"), list)
and all([isinstance(item, int) for item in self._getCustomSets().get("Ban_Time_List")])) else self._getCustomSets().get("Ban_Time_List")
PopupMenuWindow(position=self.get_root_widget().get_screen_space_center(),
2022-09-17 16:39:03 +00:00
scale=_get_popup_window_scale(),
choices=[str(item) for item in choices],
choices_display=_creat_Lstr_list(
[_getTransText("Ban_For_%d_Seconds") % item for item in choices]),
current_choice="Share_Server_Info",
delegate=self)
"""
NewInputWindow(origin_widget = self.get_root_widget(),
delegate = self,post_text = _getTransText("Ban_Time_Post"),
default_code = "300",flag = "Host_Kick_Player:"+str(self._popup_party_member_client_id))
"""
else:
# kick-votes appeared in build 14248
2025-01-25 17:47:38 +05:30
info = bs.get_connection_to_host_info_2()
2025-03-25 22:09:18 +05:30
if bool(info) and (info.build_number <
2025-01-25 17:47:38 +05:30
14248):
2023-07-02 13:19:46 +05:30
bui.getsound('error').play()
bs.broadcastmessage(
babase.Lstr(resource='getTicketsWindow.unavailableText'),
color=(1, 0, 0))
else:
# Ban for 5 minutes.
2023-07-02 13:19:46 +05:30
result = bs.disconnect_client(
2022-09-17 16:39:03 +00:00
self._popup_party_member_client_id, ban_time=5 * 60)
if not result:
2023-07-02 13:19:46 +05:30
bui.getsound('error').play()
bs.broadcastmessage(
babase.Lstr(resource='getTicketsWindow.unavailableText'),
color=(1, 0, 0))
else:
2023-07-02 13:19:46 +05:30
bui.getsound('error').play()
bs.broadcastmessage(
babase.Lstr(resource='internal.cantKickHostError'),
color=(1, 0, 0))
2023-08-03 20:25:29 +05:30
# NewShareCodeWindow(origin_widget=self.get_root_widget(), delegate=None,code = "300",execText = u"_babase._disconnectClient(%d,{Value})"%self._popup_party_member_client_id)
def joinbombspot(self):
2023-07-02 07:50:25 +00:00
2023-07-02 13:19:46 +05:30
bui.open_url("https://discord.gg/ucyaesh")
2022-09-17 16:39:03 +00:00
def _update(self) -> None:
# pylint: disable=too-many-locals
# pylint: disable=too-many-branches
# pylint: disable=too-many-statements
# pylint: disable=too-many-nested-blocks
# # update muted state
2023-07-02 13:19:46 +05:30
# if babase.app.config.resolve('Chat Muted'):
# bui.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:
2023-07-02 13:19:46 +05:30
# bui.textwidget(edit=self._muted_text, color=(1, 1, 1, 0.0))
# update roster section
2023-07-02 13:19:46 +05:30
roster = bs.get_game_roster()
global f_chat
global smo_mode
2022-09-17 16:39:03 +00:00
if roster != self._roster or smo_mode != self.smoothy_mode or f_chat != self.full_chat_mode:
self._roster = roster
2022-09-17 16:39:03 +00:00
smo_mode = self.smoothy_mode
f_chat = self.full_chat_mode
# clear out old
for widget in self._name_widgets:
widget.delete()
self._name_widgets = []
2022-09-17 16:39:03 +00:00
if not self._roster:
top_section_height = 60
2023-07-02 13:19:46 +05:30
bui.textwidget(edit=self._empty_str,
2023-07-02 07:50:25 +00:00
text=babase.Lstr(resource=self._r + '.emptyText'))
2023-07-02 13:19:46 +05:30
bui.scrollwidget(edit=self._scrollwidget,
2023-07-02 07:50:25 +00:00
size=(self._width - 50,
self._height - top_section_height - 110),
position=(30, 80))
elif self.full_chat_mode:
top_section_height = 60
2023-07-02 13:19:46 +05:30
bui.scrollwidget(edit=self._scrollwidget,
2023-07-02 07:50:25 +00:00
size=(self._width - 50,
self._height - top_section_height - 75),
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:
2022-09-17 16:39:03 +00:00
if self.smoothy_mode == 1 and 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] + '...'
2022-09-17 16:39:03 +00:00
elif self.smoothy_mode == 0:
p_str = self._roster[index][
'display_string']
2022-09-17 16:39:03 +00:00
p_str = self._get_nick(p_str)
else:
2022-09-17 16:39:03 +00:00
p_str = self._roster[index][
'display_string']
except Exception:
2023-07-02 13:19:46 +05:30
babase.print_exception(
'Error calcing client name str.')
p_str = '???'
try:
2023-07-02 13:19:46 +05:30
widget = bui.textwidget(parent=self._root_widget,
2023-07-02 07:50:25 +00:00
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=babase.Lstr(value=p_str),
h_align='left',
v_align='center')
2022-09-17 16:39:03 +00:00
self._name_widgets.append(widget)
except Exception:
2022-09-17 16:39:03 +00:00
pass
# 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][
'client_id'] == -1
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).
try:
2023-07-02 13:19:46 +05:30
bui.textwidget(edit=widget,
2025-10-28 12:49:26 +05:30
on_activate_call=babase.CallPartial(
2023-07-02 07:50:25 +00:00
self._on_party_member_press,
self._roster[index]['client_id'],
is_host, widget))
except Exception:
2022-09-17 16:39:03 +00:00
pass
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,
2023-07-02 13:19:46 +05:30
_babase.get_string_width(
p_str, suppress_warning=True) *
t_scale)
try:
2022-09-17 16:39:03 +00:00
self._name_widgets.append(
2023-07-02 13:19:46 +05:30
bui.textwidget(
2022-09-17 16:39:03 +00:00
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),
2023-07-02 13:19:46 +05:30
text=babase.Lstr(resource=self._r +
2023-07-02 07:50:25 +00:00
'.hostText'),
2022-09-17 16:39:03 +00:00
scale=0.4,
shadow=0.1,
flatness=1.0))
except Exception:
2022-09-17 16:39:03 +00:00
pass
try:
2023-07-02 13:19:46 +05:30
bui.textwidget(edit=self._empty_str, text='')
bui.scrollwidget(edit=self._scrollwidget,
2023-07-02 07:50:25 +00:00
size=(self._width - 50,
max(100, self._height - 139 -
c_height_total)),
position=(30, 80))
except Exception:
2022-09-17 16:39:03 +00:00
pass
def hide_screen_msg(self):
2022-09-17 16:39:03 +00:00
file = open('ba_data/data/languages/english.json')
eng = json.loads(file.read())
file.close()
2022-09-17 16:39:03 +00:00
eng['internal']['playerJoinedPartyText'] = ''
eng['internal']['playerLeftPartyText'] = ''
eng['internal']['chatBlockedText'] = ''
eng['kickVoteStartedText'] = ''
# eng['kickVoteText']=''
2022-09-17 16:39:03 +00:00
eng['kickWithChatText'] = ''
eng['kickOccurredText'] = ''
eng['kickVoteFailedText'] = ''
eng['votesNeededText'] = ''
eng['playerDelayedJoinText'] = ''
eng['playerLeftText'] = ''
eng['kickQuestionText'] = ''
file = open('ba_data/data/languages/english.json', "w")
json.dump(eng, file)
file.close()
2023-07-02 13:19:46 +05:30
bs.app.lang.setlanguage(None)
def restore_screen_msg(self):
2022-09-17 16:39:03 +00:00
file = open('ba_data/data/languages/english.json')
eng = json.loads(file.read())
file.close()
2022-09-17 16:39:03 +00:00
eng['internal']['playerJoinedPartyText'] = "${NAME} joined the pawri!"
eng['internal']['playerLeftPartyText'] = "${NAME} left the pawri."
eng['internal']['chatBlockedText'] = "${NAME} is chat-blocked for ${TIME} seconds."
eng['kickVoteStartedText'] = "A kick vote has been started for ${NAME}."
# eng['kickVoteText']=''
2022-09-17 16:39:03 +00:00
eng['kickWithChatText'] = "Type ${YES} in chat for yes and ${NO} for no."
eng['kickOccurredText'] = "${NAME} was kicked."
eng['kickVoteFailedText'] = "Kick-vote failed."
eng['votesNeededText'] = "${NUMBER} votes needed"
eng['playerDelayedJoinText'] = "${PLAYER} will enter at the start of the next round."
eng['playerLeftText'] = "${PLAYER} left the game."
eng['kickQuestionText'] = "Kick ${NAME}?"
file = open('ba_data/data/languages/english.json', "w")
json.dump(eng, file)
file.close()
2023-07-02 13:19:46 +05:30
bs.app.lang.setlanguage(None)
def popup_menu_selected_choice(self, popup_window: PopupMenuWindow,
choice: str) -> None:
"""Called when a choice is selected in the popup."""
global unmuted_names
if self._popup_type == "banTimePress":
2023-07-02 07:50:25 +00:00
result = _babase.disconnect_client(
self._popup_party_member_client_id, ban_time=int(choice))
if not result:
2023-07-02 13:19:46 +05:30
bui.getsound('error').play()
bs.broadcastmessage(
babase.Lstr(resource='getTicketsWindow.unavailableText'),
color=(1, 0, 0))
elif self._popup_type == "send_Times_Press":
self._send_msg_times = int(choice)
2023-07-02 13:19:46 +05:30
bui.buttonwidget(edit=self._times_button, label="%s:%d" %
2023-07-02 07:50:25 +00:00
(_getTransText("Times"), getattr(self, "_send_msg_times", 1)))
elif self._popup_type == "chatmessagepress":
2022-09-17 16:39:03 +00:00
if choice == "mute":
2023-11-12 17:30:32 +05:30
unmuted_names.remove(self.msg_user_selected.split(":")[0].encode('utf-8'))
2022-09-17 16:39:03 +00:00
if choice == "unmute":
2023-11-12 17:30:32 +05:30
unmuted_names.append(self.msg_user_selected.split(":")[0].encode('utf-8'))
if choice == "copy":
self._copy_msg(self.msg_user_selected)
elif self._popup_type == "partyMemberPress":
if choice == "kick":
2022-09-17 16:39:03 +00:00
ConfirmWindow(text=_getTransText("Normal_kick_confirm") % self._getObjectByID("account"),
action=self._kick_selected_player, cancel_button=True, cancel_is_selected=True,
color=self._bg_color, text_scale=1.0,
origin_widget=self.get_root_widget())
2022-09-17 16:39:03 +00:00
elif choice == "info":
account = self._getObjectByID("account")
self.loading_widget = ConfirmWindow(text="Searching .....",
color=self._bg_color, text_scale=1.0, cancel_button=False,
origin_widget=self.get_root_widget())
start_new_thread(fetchAccountInfo, (account, self.loading_widget,))
elif choice == "adminkick":
2022-09-17 16:39:03 +00:00
ConfirmWindow(text=_getTransText("Admin_Command_Kick_Confirm") % self._getObjectByID("account"),
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 == "@ this guy":
2022-09-17 16:39:03 +00:00
ChoiceDis = []
NewChoices = []
account = self._getObjectByID("account")
ChoiceDis.append(account)
temp = self._getObjectByID("playerNameFull")
if temp is not None:
2022-09-17 16:39:03 +00:00
if isinstance(temp, str) and temp not in ChoiceDis:
ChoiceDis.append(temp)
elif isinstance(temp, (list, tuple)):
for item in temp:
2022-09-17 16:39:03 +00:00
if isinstance(item, str) and item not in ChoiceDis:
ChoiceDis.append(item)
# print("r\\""
for item in ChoiceDis:
2022-09-17 16:39:03 +00:00
NewChoices.append(u"self._edit_text_msg_box('%s','add')" %
(item.replace("'", r"'").replace('"', r'\\"')))
else:
2022-09-17 16:39:03 +00:00
nick = self._get_nick(account)
ChoiceDis.append(nick)
NewChoices.append(u"self._on_nick_rename_press('%s')" % (account))
p = PopupMenuWindow(position=popup_window.root_widget.get_screen_space_center(),
2022-09-17 16:39:03 +00:00
scale=_get_popup_window_scale(),
choices=NewChoices,
choices_display=_creat_Lstr_list(ChoiceDis),
current_choice=NewChoices[0],
delegate=self)
self._popup_type = "Custom_Exec_Choice"
elif choice == "customAction":
customActionSets = self._getCustomSets()
2022-09-17 16:39:03 +00:00
customActionSets = customActionSets.get("partyMemberPress_Custom") if isinstance(
customActionSets.get("partyMemberPress_Custom"), dict) else {}
ChoiceDis = []
NewChoices = []
for key, item in customActionSets.items():
ChoiceDis.append(key)
NewChoices.append(item)
if len(ChoiceDis) > 0:
p = PopupMenuWindow(position=popup_window.root_widget.get_screen_space_center(),
2022-09-17 16:39:03 +00:00
scale=_get_popup_window_scale(),
choices=NewChoices,
choices_display=_creat_Lstr_list(ChoiceDis),
current_choice=NewChoices[0],
delegate=self)
self._popup_type = "customAction_partyMemberPress"
2022-09-17 16:39:03 +00:00
else:
2023-07-02 13:19:46 +05:30
bui.getsound("error").play()
bs.broadcastmessage(
babase.Lstr(resource="getTicketsWindow.unavailableText"), color=(1, 0, 0))
elif self._popup_type == "menu":
if choice in ("mute", "unmute"):
2023-07-02 13:19:46 +05:30
cfg = babase.app.config
cfg['Chat Muted'] = (choice == 'mute')
cfg.apply_and_commit()
if cfg['Chat Muted']:
2022-09-17 16:39:03 +00:00
customchatThread().run()
self._update()
elif choice in ("credits",):
ConfirmWindow(text="AdvancePartyWindow by Mr.Smoothy \n extended version of ModifyPartyWindow(Plasma Boson) \n Version 5.3 \n Dont modify or release the source code \n Discord : \n mr.smoothy#5824 Plasma Boson#4104",
2022-09-17 16:39:03 +00:00
action=self.joinbombspot, width=420, height=200,
cancel_button=False, cancel_is_selected=False,
color=self._bg_color, text_scale=1.0, ok_text="More mods >", cancel_text=None,
origin_widget=self.get_root_widget())
elif choice == "chatlogger":
# ColorPickerExact(parent=self.get_root_widget(), position=self.get_root_widget().get_screen_space_center(),
# initial_color=self._bg_color, delegate=self, tag='')
global chatlogger
if chatlogger:
2022-09-17 16:39:03 +00:00
chatlogger = False
2023-07-02 13:19:46 +05:30
bs.broadcastmessage("Chat logger turned OFF")
else:
2022-09-17 16:39:03 +00:00
chatlogger = True
chatloggThread().run()
2023-07-02 13:19:46 +05:30
bs.broadcastmessage("Chat logger turned ON")
2022-09-17 16:39:03 +00:00
elif choice == 'screenmsg':
global screenmsg
if screenmsg:
2022-09-17 16:39:03 +00:00
screenmsg = False
self.hide_screen_msg()
else:
2022-09-17 16:39:03 +00:00
screenmsg = True
self.restore_screen_msg()
elif choice == "addQuickReply":
try:
2023-07-02 13:19:46 +05:30
newReply = bui.textwidget(query=self._text_field)
data = self._get_quick_responds()
data.append(newReply)
self._write_quick_responds(data)
2023-07-02 13:19:46 +05:30
bs.broadcastmessage(_getTransText("Something_is_added") %
2023-07-02 07:50:25 +00:00
newReply, color=(0, 1, 0))
2023-07-02 13:19:46 +05:30
bui.getsound("dingSmallHigh").play()
2022-09-17 16:39:03 +00:00
except:
2023-07-02 13:19:46 +05:30
babase.print_exception()
elif choice == "removeQuickReply":
Quickreply = self._get_quick_responds()
PopupMenuWindow(position=self._text_field.get_screen_space_center(),
2022-09-17 16:39:03 +00:00
scale=_get_popup_window_scale(),
choices=Quickreply,
choices_display=_creat_Lstr_list(Quickreply),
current_choice=Quickreply[0],
delegate=self)
self._popup_type = "removeQuickReplySelect"
2025-01-25 17:47:38 +05:30
elif choice in ("hostInfo_Debug",) and isinstance(bs.get_connection_to_host_info_2(), dict):
if bs.get_connection_to_host_info_2() != None:
2023-07-02 13:19:46 +05:30
# print(_babase.get_connection_to_host_info(),type(_babase.get_connection_to_host_info()))
2025-01-25 17:47:38 +05:30
ChoiceDis = list(bs.get_connection_to_host_info_2().keys())
NewChoices = ["bs.broadcastmessage(str(bs.get_connection_to_host_info_2().get('%s')))" % (
2022-09-17 16:39:03 +00:00
(str(i)).replace("'", r"'").replace('"', r'\\"')) for i in ChoiceDis]
PopupMenuWindow(position=popup_window.root_widget.get_screen_space_center(),
2022-09-17 16:39:03 +00:00
scale=_get_popup_window_scale(),
choices=NewChoices,
choices_display=_creat_Lstr_list(ChoiceDis),
current_choice=NewChoices[0],
delegate=self)
self._popup_type = "Custom_Exec_Choice"
2022-09-17 16:39:03 +00:00
else:
2023-07-02 13:19:46 +05:30
bui.getsound("error").play()
bs.broadcastmessage(
babase.Lstr(resource="getTicketsWindow.unavailableText"), color=(1, 0, 0))
elif choice == "translator":
2023-07-02 13:19:46 +05:30
chats = _babase._getChatMessages()
if len(chats) > 0:
choices = [(item) for item in chats[::-1]]
PopupMenuWindow(position=popup_window.root_widget.get_screen_space_center(),
2022-09-17 16:39:03 +00:00
scale=_get_popup_window_scale(),
choices=choices,
choices_display=_creat_Lstr_list(choices),
current_choice=choices[0],
delegate=self)
self._popup_type = "translator_Press"
2022-09-17 16:39:03 +00:00
else:
2023-07-02 13:19:46 +05:30
bui.getsound("error").play()
bs.broadcastmessage(
babase.Lstr(resource="getTicketsWindow.unavailableText"), color=(1, 0, 0))
elif choice == "resetGameRecord":
ConfirmWindow(text=_getTransText("Restart_Game_Record_Confirm"),
2022-09-17 16:39:03 +00:00
action=self._reset_game_record, cancel_button=True, cancel_is_selected=True,
color=self._bg_color, text_scale=1.0,
origin_widget=self.get_root_widget())
elif self._popup_type == "translator_Press":
2023-07-02 13:19:46 +05:30
pass
elif self._popup_type == "customAction_partyMemberPress":
try:
2022-09-17 16:39:03 +00:00
keyReplaceValue = (r"{$PlayerNameFull}", r"{$PlayerName}", r"{$PlayerID}",
r"{$AccountInfo}", r"{$AllPlayerName}", r"{$AllPlayerNameFull}")
pos = None
curKeyWord = None
for keyWord in keyReplaceValue:
CurPos = choice.find(keyWord)
if CurPos != -1 and (pos is None or CurPos < pos):
2022-09-17 16:39:03 +00:00
pos = CurPos
curKeyWord = keyWord
if isinstance(pos, int) and isinstance(curKeyWord, str):
if curKeyWord in (r"{$PlayerNameFull}", r"{$PlayerName}", r"{$AllPlayerName}", r"{$AllPlayerNameFull}"):
# if choice.count(curKeyWord) != 0:
playerName = self._getObjectByID(
curKeyWord.replace("{$", "").replace("}", ""))
if isinstance(playerName, (list, tuple)):
ChoiceDis = []
NewChoices = []
for i in playerName:
ChoiceDis.append(i)
2022-09-17 16:39:03 +00:00
NewChoices.append(choice.replace(
curKeyWord, (i.replace("'", r"'").replace('"', r'\\"')), 1))
p = PopupMenuWindow(position=popup_window.root_widget.get_screen_space_center(),
2022-09-17 16:39:03 +00:00
scale=_get_popup_window_scale(),
choices=NewChoices,
choices_display=_creat_Lstr_list(ChoiceDis),
current_choice=NewChoices[0],
delegate=self)
self._popup_type = "customAction_partyMemberPress"
2022-09-17 16:39:03 +00:00
elif isinstance(playerName, str):
self.popup_menu_selected_choice(popup_window, choice.replace(
curKeyWord, (playerName.replace("'", r"'").replace('"', r'\\"')), 1))
else:
2023-07-02 13:19:46 +05:30
bs.broadcastmessage(_getTransText("No_valid_player_found"), (1, 0, 0))
bui.getsound("error").play()
elif curKeyWord in (r"{$PlayerID}",) != 0:
playerID = self._getObjectByID("PlayerID")
playerName = self._getObjectByID("PlayerName")
2022-09-17 16:39:03 +00:00
# print(playerID,playerName)
if isinstance(playerID, (list, tuple)) and isinstance(playerName, (list, tuple)) and len(playerName) == len(playerID):
ChoiceDis = []
NewChoices = []
for i1, i2 in playerName, playerID:
ChoiceDis.append(i1)
NewChoices.append(choice.replace(r"{$PlayerID}", str(
i2).replace("'", r"'").replace('"', r'\\"')), 1)
p = PopupMenuWindow(position=popup_window.root_widget.get_screen_space_center(),
2022-09-17 16:39:03 +00:00
scale=_get_popup_window_scale(),
choices=NewChoices,
choices_display=_creat_Lstr_list(ChoiceDis),
current_choice=NewChoices[0],
delegate=self)
self._popup_type = "customAction_partyMemberPress"
2022-09-17 16:39:03 +00:00
elif isinstance(playerID, int):
self.popup_menu_selected_choice(popup_window, choice.replace(
r"{$PlayerID}", str(playerID).replace("'", r"'").replace('"', r'\\"')))
else:
2023-07-02 07:50:25 +00:00
bs.broadcastmessage(_getTransText(
"No_valid_player_id_found"), (1, 0, 0))
2023-07-02 13:19:46 +05:30
bui.getsound("error").play()
elif curKeyWord in (r"{$AccountInfo}",) != 0:
2022-09-17 16:39:03 +00:00
self.popup_menu_selected_choice(popup_window, choice.replace(
r"{$AccountInfo}", (str(self._getObjectByID("roster"))).replace("'", r"'").replace('"', r'\\"'), 1))
else:
exec(choice)
except Exception as e:
2023-07-02 13:19:46 +05:30
bs.broadcastmessage(repr(e), (1, 0, 0))
elif self._popup_type == "QuickMessageSelect":
2023-07-02 13:19:46 +05:30
# bui.textwidget(edit=self._text_field,text=self._get_quick_responds()[index])
2022-09-17 16:39:03 +00:00
self._edit_text_msg_box(choice, "add")
elif self._popup_type == "removeQuickReplySelect":
data = self._get_quick_responds()
if len(data) > 0 and choice in data:
data.remove(choice)
self._write_quick_responds(data)
2023-07-02 13:19:46 +05:30
bs.broadcastmessage(_getTransText("Something_is_removed") % choice, (1, 0, 0))
bui.getsound("shieldDown").play()
2022-09-17 16:39:03 +00:00
else:
2023-07-02 13:19:46 +05:30
bs.broadcastmessage(babase.Lstr(resource="errorText"), (1, 0, 0))
bui.getsound("error").play()
elif choice.startswith("custom_Exec_Choice_") or self._popup_type == "Custom_Exec_Choice":
2022-09-17 16:39:03 +00:00
exec(choice[len("custom_Exec_Choice_"):]
if choice.startswith("custom_Exec_Choice_") else choice)
else:
print("unhandled popup type: "+str(self._popup_type))
2022-09-17 16:39:03 +00:00
def fetchAccountInfo(account, loading_widget):
pbid = ""
account_data = []
servers = []
try:
filePath = os.path.join(RecordFilesDir, "players.json")
fdata = {}
if os.path.isfile(filePath):
f = open(filePath, "r")
fdata = json.load(f)
if account in fdata:
2022-09-17 16:39:03 +00:00
servers = fdata[account]
url = f'https://{BCSSERVER}/player?key={base64.b64encode(account.encode("utf-8")).decode("utf-8")}&base64=true'
2023-07-02 07:50:25 +00:00
req = urllib.request.Request(url, headers={
"User-Agent": f'BS{_babase.env().get("build_number", 0)}', "Accept-Language": "en-US,en;q=0.9", })
2023-07-02 13:19:46 +05:30
data = urllib.request.urlopen(req)
2022-09-17 16:39:03 +00:00
account_data = json.loads(data.read().decode('utf-8'))[0]
pbid = account_data["pbid"]
2023-07-02 13:19:46 +05:30
except Exception as e:
print(e)
pass
2023-07-02 13:19:46 +05:30
# _babase.pushcall(Call(updateAccountWindow,loading_widget,accounts[0]),from_other_thread=True)
_babase.pushcall(Call(CustomAccountViewerWindow, pbid, account_data,
2023-07-02 07:50:25 +00:00
servers, loading_widget), from_other_thread=True)
class CustomAccountViewerWindow(viewer.AccountViewerWindow):
2022-09-17 16:39:03 +00:00
def __init__(self, account_id, custom_data, servers, loading_widget):
super().__init__(account_id)
try:
loading_widget._cancel()
except:
pass
2022-09-17 16:39:03 +00:00
self.custom_data = custom_data
self.pb_id = account_id
self.servers = servers
def _copy_pb(self):
2023-07-02 13:19:46 +05:30
babase.clipboard_set_text(self.pb_id)
bs.broadcastmessage(babase.Lstr(resource='gatherWindow.copyCodeConfirmText'))
2022-09-17 16:39:03 +00:00
def _on_query_response(self, data):
if data is None:
2023-07-02 13:19:46 +05:30
bui.textwidget(edit=self._loading_text, text="")
bui.textwidget(parent=self._scrollwidget,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(170, 200),
flatness=1.0,
h_align='center',
v_align='center',
scale=0.5,
color=bui.app.ui_v1.infotextcolor,
text="Mutual servers",
maxwidth=300)
2022-09-17 16:39:03 +00:00
v = 200-21
for server in self.servers:
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._scrollwidget,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(170, v),
h_align='center',
v_align='center',
scale=0.55,
text=server,
maxwidth=300)
2022-09-17 16:39:03 +00:00
v -= 23
else:
for account in self.custom_data["accounts"]:
if account not in data["accountDisplayStrings"]:
data["accountDisplayStrings"].append(account)
try:
self._loading_text.delete()
trophystr = ''
try:
trophystr = data['trophies']
num = 10
chunks = [
trophystr[i:i + num]
for i in range(0, len(trophystr), num)
]
trophystr = ('\n\n'.join(chunks))
if trophystr == '':
trophystr = '-'
except Exception:
2023-07-02 13:19:46 +05:30
babase.print_exception('Error displaying trophies.')
account_name_spacing = 15
tscale = 0.65
2023-07-02 13:19:46 +05:30
ts_height = _babase.get_string_height(trophystr,
2023-07-02 07:50:25 +00:00
suppress_warning=True)
sub_width = self._width - 80
sub_height = 500 + ts_height * tscale + \
2022-09-17 16:39:03 +00:00
account_name_spacing * len(data['accountDisplayStrings'])
2023-07-02 13:19:46 +05:30
self._subcontainer = bui.containerwidget(
parent=self._scrollwidget,
size=(sub_width, sub_height),
background=False)
v = sub_height - 20
title_scale = 0.37
center = 0.3
maxwidth_scale = 0.45
showing_character = False
if data['profileDisplayString'] is not None:
tint_color = (1, 1, 1)
try:
if data['profile'] is not None:
profile = data['profile']
2023-07-02 13:19:46 +05:30
character = babase.app.spaz_appearances.get(
profile['character'], None)
if character is not None:
tint_color = (profile['color'] if 'color'
in profile else (1, 1, 1))
tint2_color = (profile['highlight']
if 'highlight' in profile else
(1, 1, 1))
icon_tex = character.icon_texture
tint_tex = character.icon_mask_texture
2023-07-02 13:19:46 +05:30
mask_texture = bui.gettexture(
'characterIconMask')
2023-07-02 13:19:46 +05:30
bui.imagewidget(
parent=self._subcontainer,
position=(sub_width * center - 40, v - 80),
size=(80, 80),
color=(1, 1, 1),
mask_texture=mask_texture,
2023-07-02 13:19:46 +05:30
texture=bui.gettexture(icon_tex),
tint_texture=bui.gettexture(tint_tex),
tint_color=tint_color,
tint2_color=tint2_color)
v -= 95
except Exception:
2023-07-02 13:19:46 +05:30
babase.print_exception('Error displaying character.')
bui.textwidget(
parent=self._subcontainer,
size=(0, 0),
position=(sub_width * center, v),
h_align='center',
v_align='center',
scale=0.9,
2023-07-02 13:19:46 +05:30
color=babase.safecolor(tint_color, 0.7),
shadow=1.0,
2023-07-02 13:19:46 +05:30
text=babase.Lstr(value=data['profileDisplayString']),
maxwidth=sub_width * maxwidth_scale * 0.75)
showing_character = True
v -= 33
center = 0.75 if showing_character else 0.5
maxwidth_scale = 0.45 if showing_character else 0.9
v = sub_height - 20
if len(data['accountDisplayStrings']) <= 1:
2023-07-02 13:19:46 +05:30
account_title = babase.Lstr(
resource='settingsWindow.accountText')
else:
2023-07-02 13:19:46 +05:30
account_title = babase.Lstr(
resource='accountSettingsWindow.accountsText',
fallback_resource='settingsWindow.accountText')
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
flatness=1.0,
h_align='center',
v_align='center',
scale=title_scale,
color=bui.app.ui_v1.infotextcolor,
text=account_title,
maxwidth=sub_width * maxwidth_scale)
draw_small = (showing_character
or len(data['accountDisplayStrings']) > 1)
v -= 14 if draw_small else 20
for account_string in data['accountDisplayStrings']:
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
h_align='center',
v_align='center',
scale=0.55 if draw_small else 0.8,
text=account_string,
maxwidth=sub_width * maxwidth_scale)
v -= account_name_spacing
v += account_name_spacing
v -= 25 if showing_character else 29
# =======================================================================
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
flatness=1.0,
h_align='center',
v_align='center',
scale=title_scale,
color=bui.app.ui_v1.infotextcolor,
text=str(self.pb_id),
maxwidth=sub_width * maxwidth_scale)
2023-07-02 13:19:46 +05:30
self._copy_btn = bui.buttonwidget(
parent=self._subcontainer,
2022-09-17 16:39:03 +00:00
position=(sub_width * center - 120, v - 9),
size=(60, 30),
scale=0.5,
label='copy',
color=(0.6, 0.5, 0.6),
on_activate_call=self._copy_pb,
autoselect=True)
2022-09-17 16:39:03 +00:00
v -= 24
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
flatness=1.0,
h_align='center',
v_align='center',
scale=title_scale,
color=bui.app.ui_v1.infotextcolor,
text="Name",
maxwidth=sub_width * maxwidth_scale)
2022-09-17 16:39:03 +00:00
v -= 26
for name in self.custom_data["names"]:
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
h_align='center',
v_align='center',
scale=0.51,
text=name,
maxwidth=sub_width * maxwidth_scale)
2022-09-17 16:39:03 +00:00
v -= 13
v -= 8
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
flatness=1.0,
h_align='center',
v_align='center',
scale=title_scale,
color=bui.app.ui_v1.infotextcolor,
text="Created On",
maxwidth=sub_width * maxwidth_scale)
2022-09-17 16:39:03 +00:00
v -= 19
d = self.custom_data["createdOn"]
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
h_align='center',
v_align='center',
scale=0.55,
text=d[:d.index("T")],
maxwidth=sub_width * maxwidth_scale)
2022-09-17 16:39:03 +00:00
v -= 29
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
flatness=1.0,
h_align='center',
v_align='center',
scale=title_scale,
color=bui.app.ui_v1.infotextcolor,
text="Discord",
maxwidth=sub_width * maxwidth_scale)
v -= 19
2022-09-17 16:39:03 +00:00
if len(self.custom_data["discord"]) > 0:
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
h_align='center',
v_align='center',
scale=0.55,
text=self.custom_data["discord"][0]["username"] +
","+self.custom_data["discord"][0]["id"],
maxwidth=sub_width * maxwidth_scale)
v -= 26
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
flatness=1.0,
h_align='center',
v_align='center',
scale=title_scale,
color=bui.app.ui_v1.infotextcolor,
text="Mutual servers",
maxwidth=sub_width * maxwidth_scale)
2022-09-17 16:39:03 +00:00
v = -19
v = 270
for server in self.servers:
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
h_align='center',
v_align='center',
scale=0.55,
text=server,
maxwidth=sub_width * maxwidth_scale)
2022-09-17 16:39:03 +00:00
v -= 13
2022-09-17 16:39:03 +00:00
v -= 16
# ==================================================================
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
flatness=1.0,
h_align='center',
v_align='center',
scale=title_scale,
color=bui.app.ui_v1.infotextcolor,
text=babase.Lstr(resource='rankText'),
maxwidth=sub_width * maxwidth_scale)
v -= 14
if data['rank'] is None:
rank_str = '-'
suffix_offset = None
else:
2023-07-02 13:19:46 +05:30
str_raw = babase.Lstr(
resource='league.rankInLeagueText').evaluate()
# FIXME: Would be nice to not have to eval this.
2023-07-02 13:19:46 +05:30
rank_str = babase.Lstr(
resource='league.rankInLeagueText',
subs=[('${RANK}', str(data['rank'][2])),
('${NAME}',
2023-07-02 13:19:46 +05:30
babase.Lstr(translate=('leagueNames',
2023-07-02 07:50:25 +00:00
data['rank'][0]))),
('${SUFFIX}', '')]).evaluate()
rank_str_width = min(
sub_width * maxwidth_scale,
2023-07-02 13:19:46 +05:30
_babase.get_string_width(rank_str, suppress_warning=True) *
0.55)
# Only tack our suffix on if its at the end and only for
# non-diamond leagues.
if (str_raw.endswith('${SUFFIX}')
and data['rank'][0] != 'Diamond'):
suffix_offset = rank_str_width * 0.5 + 2
else:
suffix_offset = None
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
h_align='center',
v_align='center',
scale=0.55,
text=rank_str,
maxwidth=sub_width * maxwidth_scale)
if suffix_offset is not None:
assert data['rank'] is not None
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center + suffix_offset,
v + 3),
h_align='left',
v_align='center',
scale=0.29,
flatness=1.0,
text='[' + str(data['rank'][1]) + ']')
v -= 14
2023-07-02 13:19:46 +05:30
str_raw = babase.Lstr(
resource='league.rankInLeagueText').evaluate()
old_offs = -50
prev_ranks_shown = 0
for prev_rank in data['prevRanks']:
2023-07-02 13:19:46 +05:30
rank_str = babase.Lstr(
value='${S}: ${I}',
subs=[
('${S}',
2023-07-02 13:19:46 +05:30
babase.Lstr(resource='league.seasonText',
2023-07-02 07:50:25 +00:00
subs=[('${NUMBER}', str(prev_rank[0]))])),
('${I}',
2023-07-02 13:19:46 +05:30
babase.Lstr(resource='league.rankInLeagueText',
2023-07-02 07:50:25 +00:00
subs=[('${RANK}', str(prev_rank[3])),
('${NAME}',
babase.Lstr(translate=('leagueNames',
prev_rank[1]))),
('${SUFFIX}', '')]))
]).evaluate()
rank_str_width = min(
sub_width * maxwidth_scale,
2023-07-02 13:19:46 +05:30
_babase.get_string_width(rank_str, suppress_warning=True) *
0.3)
# Only tack our suffix on if its at the end and only for
# non-diamond leagues.
if (str_raw.endswith('${SUFFIX}')
and prev_rank[1] != 'Diamond'):
suffix_offset = rank_str_width + 2
else:
suffix_offset = None
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center + old_offs, v),
h_align='left',
v_align='center',
scale=0.3,
text=rank_str,
flatness=1.0,
maxwidth=sub_width * maxwidth_scale)
if suffix_offset is not None:
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center + old_offs +
suffix_offset, v + 1),
h_align='left',
v_align='center',
scale=0.20,
flatness=1.0,
text='[' + str(prev_rank[2]) + ']')
prev_ranks_shown += 1
v -= 10
v -= 13
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
flatness=1.0,
h_align='center',
v_align='center',
scale=title_scale,
color=bui.app.ui_v1.infotextcolor,
text=babase.Lstr(resource='achievementsText'),
maxwidth=sub_width * maxwidth_scale)
v -= 14
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
h_align='center',
v_align='center',
scale=0.55,
text=str(data['achievementsCompleted']) + ' / ' +
str(len(bui.app.classic.ach.achievements)),
maxwidth=sub_width * maxwidth_scale)
v -= 25
if prev_ranks_shown == 0 and showing_character:
v -= 20
elif prev_ranks_shown == 1 and showing_character:
v -= 10
center = 0.5
maxwidth_scale = 0.9
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, 0),
position=(sub_width * center, v),
h_align='center',
v_align='center',
scale=title_scale,
color=bui.app.ui_v1.infotextcolor,
flatness=1.0,
text=babase.Lstr(resource='trophiesThisSeasonText',
fallback_resource='trophiesText'),
maxwidth=sub_width * maxwidth_scale)
v -= 19
2023-07-02 13:19:46 +05:30
bui.textwidget(parent=self._subcontainer,
2023-07-02 07:50:25 +00:00
size=(0, ts_height),
position=(sub_width * 0.5,
v - ts_height * tscale),
h_align='center',
v_align='top',
corner_scale=tscale,
text=trophystr)
except Exception:
2023-07-02 13:19:46 +05:30
babase.print_exception('Error displaying account info.')
2025-06-24 00:55:09 +05:30
# ba_meta export babase.Plugin
2025-06-23 19:27:10 +00:00
2023-07-02 13:19:46 +05:30
class bySmoothy(babase.Plugin):
def __init__(self):
2023-07-02 13:19:46 +05:30
bs.connect_to_party = newconnect_to_party
bascenev1lib_party.PartyWindow = ModifiedPartyWindow