diff --git a/.efrocachemap b/.efrocachemap
index 6aa18ef9..ae2de923 100644
--- a/.efrocachemap
+++ b/.efrocachemap
@@ -3932,40 +3932,40 @@
"assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450",
"assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e",
"assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f",
- "build/prefab/full/linux_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/4d/69/2e4c0ba6b6a7f27c9754e6fa2028",
- "build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/54/e1/f8d826dfbe0ff9f192edc232857c",
- "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b1/fd/2258453c18672fd79398b0c2030c",
- "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/3e/74/9417d078cb0a0eaecdf30e531c4e",
- "build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b0/e8/495cc0e784c6b98d33ee8e83f922",
- "build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/7b/73/c72308a21aeb876e4192719f4445",
- "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/11/d4/474b2f2cf46689f7cb7733b66a10",
- "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/0e/d3/e1d791f6a6411c7acfdd72d2c75e",
- "build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/89/f9/7b3ec953d17beaa42560aa09bbdb",
- "build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/57/81/c00fc47949becf3fa7b8fda7737e",
- "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/63/87/4f12518d69e5974124744a99b9cc",
- "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/34/16/d383c070bc3ee1692f729d817ba5",
- "build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/0c/68/d5c5a2e2511e597ab13f0e23f62b",
- "build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/10/3a/e8cca189e72de469661306810f4e",
- "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/90/0a/621c8f2bc888e93581b4100ef857",
- "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2b/24/e9fd7c975d93ce57707b5ddd01f1",
- "build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a6/f8/3bcda19fe1c92de4114b0096a807",
- "build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d4/7b/22b7570f138f58ff88b219ff2586",
- "build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/99/54/0a026dbab2d2e6e44d89f8242f4f",
- "build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/79/63/76dd15496bdedc116a02fc7a5df3",
- "build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/95/48/ad90969b34d9166d32eae56ea9e4",
- "build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b4/5a/0515721b7e4ce334c0fabbeb4376",
- "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d5/7f/9d46d20545a97b9f3b65ce25880a",
- "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/66/bd/5b9723fab837270b875da9f9d91e",
- "build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/34/80/166ae132364a8d788ddc66b6b8fe",
- "build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/88/14/b63a6887474340f9ea5aecd861c7",
- "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/01/b8/9b18a2d624f5251c1d3d57a9abb8",
- "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/18/8a/d5f35a9938e4cfc21f26338b487a",
- "build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2f/c5/891774c681b68e350cca570a7936",
- "build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ef/96/a0e88328f90dc079c84bc0791f7f",
- "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c6/30/6446116fbb8ab3d97602a90ae99b",
- "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/40/75/633d1a8d826ecf7417519e7d39eb",
- "build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/81/da/43f897aec8a5140ac1ef35b193e9",
- "build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/94/90/fefc90daa043e388604ea79ef4f0",
- "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/12/cb/521fa56c5954c40be151704fd77e",
- "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/53/a7/da3c0ac70e103a8a3a31b50bc41e"
+ "build/prefab/full/linux_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/fe/8e/2d088fc700f5082e38c5905c62f9",
+ "build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/a3/bc/bbd49ff7fdc1e368e505fc13dc05",
+ "build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/15/90/aac271a2f2ce680065e77b004aef",
+ "build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/df/75/bfbb15dbb2e58d8b8417c916e8f4",
+ "build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b7/b3/2f36b4c8dfaf2d889ace6bed8997",
+ "build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/f8/0b/69392c0662bc27b261190f9b18c2",
+ "build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/23/55/3abe51e53f08d0c49d8cda499bd4",
+ "build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/94/e4/bf1c4727c463890db8c2370c9add",
+ "build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b5/cf/1c2eed82ae6a59caf38e0a99db3f",
+ "build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/a9/b5/938d8d57e898901dd09e01e0558e",
+ "build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/77/77/3a3be11fec9168018287cb8318e4",
+ "build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/9a/e4/2bf5b9b80d1a449f6615f567cb74",
+ "build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/be/d7/29cd656c83b4d0aaecda25f9ae71",
+ "build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/40/d4/4252bf6dc9ffefe8195c16a243fb",
+ "build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b6/e4/f8b2ccefb907c24fdae5a503687f",
+ "build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2b/41/03403d2112be6aa3c97ece97b6ad",
+ "build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/3e/32/5647116c2fdbdf9e7bf9c51a59c2",
+ "build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/d5/9d/f912c7a8b8297a63b5074f4611b6",
+ "build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/8e/a7/a65f979fb283ab33292bdff7c187",
+ "build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/65/fe/0eab9c08daeed85ba65020bb1497",
+ "build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/46/63/ddb89ceddbe7f7e0194686b1f9fd",
+ "build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8a/19/bff3a13ca376d9f3fe6c74be6655",
+ "build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/da/1b/0d4c818d4646a4bb7a37ab6201c8",
+ "build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/78/21/d2789bd9343f01b944d0246c43ef",
+ "build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f9/e5/602243f370562f553d1b7a8ea10f",
+ "build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1d/fd/1284817f08d90c2f9ddb6bea35a4",
+ "build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/84/00/da93ec1c6eb292ce0f914bae4c73",
+ "build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/fd/ce/f2d635f25f9af9b72b49f6bd7ac7",
+ "build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7f/ed/e915949aab7ff8f7751cea7e7c27",
+ "build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/cc/0e/9f736c2a548cdcc1d66e12df6989",
+ "build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/24/9d/8748b562e9534db9696227ce1f2d",
+ "build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/2b/24/7cb7aa32b353587b63c9a7094ad1",
+ "build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/01/b2/f50629fb6513240ef49b2ced2226",
+ "build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e8/b1/c5222a3c3d05614f175e3526a460",
+ "build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/41/0d/87732dd64bca0c72f16087864602",
+ "build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/9a/58/7363f022504a97b34e076f9eac53"
}
\ No newline at end of file
diff --git a/.idea/dictionaries/ericf.xml b/.idea/dictionaries/ericf.xml
index c7099f2d..1312a27e 100644
--- a/.idea/dictionaries/ericf.xml
+++ b/.idea/dictionaries/ericf.xml
@@ -165,6 +165,7 @@
ballisticacore
ballisticacorecb
bamaster
+ bamasteraddr
barcolor
barebones
baseh
@@ -205,6 +206,7 @@
bindvals
bisectmodule
bitcode
+ blarg
blas
blastos
bldtp
@@ -621,6 +623,7 @@
elapsedf
elementtree
elim
+ embconnect
emitfx
emoji
emojis
@@ -1906,6 +1909,7 @@
serverget
servermanager
servermode
+ servernodequery
servernodes
serverput
serverutils
diff --git a/assets/.asset_manifest_public.json b/assets/.asset_manifest_public.json
index c5603603..fd6e671c 100644
--- a/assets/.asset_manifest_public.json
+++ b/assets/.asset_manifest_public.json
@@ -40,7 +40,7 @@
"ba_data/python/ba/__pycache__/_meta.cpython-38.opt-1.pyc",
"ba_data/python/ba/__pycache__/_multiteamsession.cpython-38.opt-1.pyc",
"ba_data/python/ba/__pycache__/_music.cpython-38.opt-1.pyc",
- "ba_data/python/ba/__pycache__/_netutils.cpython-38.opt-1.pyc",
+ "ba_data/python/ba/__pycache__/_net.cpython-38.opt-1.pyc",
"ba_data/python/ba/__pycache__/_nodeactor.cpython-38.opt-1.pyc",
"ba_data/python/ba/__pycache__/_player.cpython-38.opt-1.pyc",
"ba_data/python/ba/__pycache__/_playlist.cpython-38.opt-1.pyc",
@@ -102,7 +102,7 @@
"ba_data/python/ba/_meta.py",
"ba_data/python/ba/_multiteamsession.py",
"ba_data/python/ba/_music.py",
- "ba_data/python/ba/_netutils.py",
+ "ba_data/python/ba/_net.py",
"ba_data/python/ba/_nodeactor.py",
"ba_data/python/ba/_player.py",
"ba_data/python/ba/_playlist.py",
diff --git a/assets/Makefile b/assets/Makefile
index ac33b73b..024edb6c 100644
--- a/assets/Makefile
+++ b/assets/Makefile
@@ -171,7 +171,7 @@ SCRIPT_TARGETS_PY_PUBLIC = \
build/ba_data/python/ba/_meta.py \
build/ba_data/python/ba/_multiteamsession.py \
build/ba_data/python/ba/_music.py \
- build/ba_data/python/ba/_netutils.py \
+ build/ba_data/python/ba/_net.py \
build/ba_data/python/ba/_nodeactor.py \
build/ba_data/python/ba/_player.py \
build/ba_data/python/ba/_playlist.py \
@@ -415,7 +415,7 @@ SCRIPT_TARGETS_PYC_PUBLIC = \
build/ba_data/python/ba/__pycache__/_meta.cpython-38.opt-1.pyc \
build/ba_data/python/ba/__pycache__/_multiteamsession.cpython-38.opt-1.pyc \
build/ba_data/python/ba/__pycache__/_music.cpython-38.opt-1.pyc \
- build/ba_data/python/ba/__pycache__/_netutils.cpython-38.opt-1.pyc \
+ build/ba_data/python/ba/__pycache__/_net.cpython-38.opt-1.pyc \
build/ba_data/python/ba/__pycache__/_nodeactor.cpython-38.opt-1.pyc \
build/ba_data/python/ba/__pycache__/_player.cpython-38.opt-1.pyc \
build/ba_data/python/ba/__pycache__/_playlist.cpython-38.opt-1.pyc \
diff --git a/assets/src/ba_data/python/_ba.py b/assets/src/ba_data/python/_ba.py
index 363d5302..01776ff3 100644
--- a/assets/src/ba_data/python/_ba.py
+++ b/assets/src/ba_data/python/_ba.py
@@ -2145,8 +2145,8 @@ def get_low_level_config_value(key: str, default_value: int) -> int:
return int()
-def get_master_server_address(source: int = -1) -> str:
- """get_master_server_address(source: int = -1) -> str
+def get_master_server_address(source: int = -1, version: int = 1) -> str:
+ """get_master_server_address(source: int = -1, version: int = 1) -> str
(internal)
diff --git a/assets/src/ba_data/python/ba/_apputils.py b/assets/src/ba_data/python/ba/_apputils.py
index f3698a4e..8e3767c6 100644
--- a/assets/src/ba_data/python/ba/_apputils.py
+++ b/assets/src/ba_data/python/ba/_apputils.py
@@ -56,7 +56,7 @@ def handle_log() -> None:
When this happens, we can upload our log to the server
after a short bit if desired.
"""
- from ba._netutils import master_server_post
+ from ba._net import master_server_post
from ba._enums import TimeType
app = _ba.app
app.log_have_new = True
@@ -121,7 +121,7 @@ def handle_leftover_log_file() -> None:
"""Handle an un-uploaded log from a previous run."""
try:
import json
- from ba._netutils import master_server_post
+ from ba._net import master_server_post
if os.path.exists(_ba.get_log_file_path()):
with open(_ba.get_log_file_path()) as infile:
diff --git a/assets/src/ba_data/python/ba/_assetmanager.py b/assets/src/ba_data/python/ba/_assetmanager.py
index 118f2306..c23624a4 100644
--- a/assets/src/ba_data/python/ba/_assetmanager.py
+++ b/assets/src/ba_data/python/ba/_assetmanager.py
@@ -158,6 +158,7 @@ def fetch_url(url: str, filename: Path, asset_gather: AssetGather) -> None:
"""Fetch a given url to a given filename for a given AssetGather.
"""
+ # pylint: disable=consider-using-with
import socket
diff --git a/assets/src/ba_data/python/ba/_netutils.py b/assets/src/ba_data/python/ba/_net.py
similarity index 62%
rename from assets/src/ba_data/python/ba/_netutils.py
rename to assets/src/ba_data/python/ba/_net.py
index 5f5e0883..39c3642d 100644
--- a/assets/src/ba_data/python/ba/_netutils.py
+++ b/assets/src/ba_data/python/ba/_net.py
@@ -15,7 +15,42 @@ if TYPE_CHECKING:
from typing import Any, Dict, Union, Callable, Optional
import socket
import ba
- ServerCallbackType = Callable[[Union[None, Dict[str, Any]]], None]
+ MasterServerCallback = Callable[[Union[None, Dict[str, Any]]], None]
+
+# Timeout for standard functions talking to the master-server/etc.
+DEFAULT_REQUEST_TIMEOUT_SECONDS = 60
+
+
+def is_urllib_network_error(exc: BaseException) -> bool:
+ """Is the provided exception a network-related error?
+
+ This should be passed any exception which resulted from opening or
+ reading a urllib Request. It should return True for any errors that
+ could conceivably arise due to unavailable/poor network connections,
+ firewall/connectivity issues, etc. These issues can often be safely
+ ignored or presented to the user as general 'network-unavailable'
+ states.
+ """
+ import urllib.request
+ import urllib.error
+ import http.client
+ import errno
+ import socket
+ if isinstance(
+ exc,
+ (urllib.error.URLError, ConnectionError, http.client.IncompleteRead,
+ http.client.BadStatusLine, socket.timeout)):
+ return True
+ if isinstance(exc, OSError):
+ if exc.errno == 10051: # Windows unreachable network error.
+ return True
+ if exc.errno in {
+ errno.ETIMEDOUT,
+ errno.EHOSTUNREACH,
+ errno.ENETUNREACH,
+ }:
+ return True
+ return False
def get_ip_address_type(addr: str) -> socket.AddressFamily:
@@ -42,26 +77,26 @@ def get_ip_address_type(addr: str) -> socket.AddressFamily:
return socket_type
-class ServerResponseType(Enum):
- """How to interpret responses from the server."""
+class MasterServerResponseType(Enum):
+ """How to interpret responses from the master-server."""
JSON = 0
-class ServerCallThread(threading.Thread):
- """Thread to communicate with the master server."""
+class MasterServerCallThread(threading.Thread):
+ """Thread to communicate with the master-server."""
def __init__(self, request: str, request_type: str,
data: Optional[Dict[str, Any]],
- callback: Optional[ServerCallbackType],
- response_type: ServerResponseType):
+ callback: Optional[MasterServerCallback],
+ response_type: MasterServerResponseType):
super().__init__()
self._request = request
self._request_type = request_type
- if not isinstance(response_type, ServerResponseType):
+ if not isinstance(response_type, MasterServerResponseType):
raise TypeError(f'Invalid response type: {response_type}')
self._response_type = response_type
self._data = {} if data is None else copy.deepcopy(data)
- self._callback: Optional[ServerCallbackType] = callback
+ self._callback: Optional[MasterServerCallback] = callback
self._context = _ba.Context('current')
# Save and restore the context we were created from.
@@ -87,11 +122,10 @@ class ServerCallThread(threading.Thread):
self._callback(arg)
def run(self) -> None:
- # pylint: disable=too-many-branches
+ # pylint: disable=too-many-branches, consider-using-with
import urllib.request
import urllib.error
import json
- import http.client
from ba import _general
try:
self._data = _general.utf8_all(self._data)
@@ -102,54 +136,43 @@ class ServerCallThread(threading.Thread):
urllib.request.Request(
(_ba.get_master_server_address() + '/' +
self._request + '?' + parse.urlencode(self._data)),
- None, {'User-Agent': _ba.app.user_agent_string}))
+ None, {'User-Agent': _ba.app.user_agent_string}),
+ timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS)
elif self._request_type == 'post':
response = urllib.request.urlopen(
urllib.request.Request(
_ba.get_master_server_address() + '/' + self._request,
parse.urlencode(self._data).encode(),
- {'User-Agent': _ba.app.user_agent_string}))
+ {'User-Agent': _ba.app.user_agent_string}),
+ timeout=DEFAULT_REQUEST_TIMEOUT_SECONDS)
else:
raise TypeError('Invalid request_type: ' + self._request_type)
# If html request failed.
if response.getcode() != 200:
response_data = None
- elif self._response_type == ServerResponseType.JSON:
+ elif self._response_type == MasterServerResponseType.JSON:
raw_data = response.read()
# Empty string here means something failed server side.
if raw_data == b'':
response_data = None
else:
- # Json.loads requires str in python < 3.6.
- raw_data_s = raw_data.decode()
- response_data = json.loads(raw_data_s)
+ response_data = json.loads(raw_data)
else:
raise TypeError(f'invalid responsetype: {self._response_type}')
except Exception as exc:
- import errno
do_print = False
response_data = None
# Ignore common network errors; note unexpected ones.
- if isinstance(
- exc,
- (urllib.error.URLError, ConnectionError,
- http.client.IncompleteRead, http.client.BadStatusLine)):
+ if is_urllib_network_error(exc):
pass
- elif isinstance(exc, OSError):
- if exc.errno == 10051: # Windows unreachable network error.
- pass
- elif exc.errno in [
- errno.ETIMEDOUT, errno.EHOSTUNREACH, errno.ENETUNREACH
- ]:
- pass
- else:
- do_print = True
- elif (self._response_type == ServerResponseType.JSON
+ elif (self._response_type == MasterServerResponseType.JSON
and isinstance(exc, json.decoder.JSONDecodeError)):
+ # FIXME: should handle this better; could mean either the
+ # server sent us bad data or it got corrupted along the way.
pass
else:
do_print = True
@@ -157,7 +180,7 @@ class ServerCallThread(threading.Thread):
if do_print:
# Any other error here is unexpected,
# so let's make a note of it,
- print(f'Error in ServerCallThread'
+ print(f'Error in MasterServerCallThread'
f' (response-type={self._response_type},'
f' response-data={response_data}):')
import traceback
@@ -169,18 +192,22 @@ class ServerCallThread(threading.Thread):
def master_server_get(
- request: str,
- data: Dict[str, Any],
- callback: Optional[ServerCallbackType] = None,
- response_type: ServerResponseType = ServerResponseType.JSON) -> None:
+ request: str,
+ data: Dict[str, Any],
+ callback: Optional[MasterServerCallback] = None,
+ response_type: MasterServerResponseType = MasterServerResponseType.JSON
+) -> None:
"""Make a call to the master server via a http GET."""
- ServerCallThread(request, 'get', data, callback, response_type).start()
+ MasterServerCallThread(request, 'get', data, callback,
+ response_type).start()
def master_server_post(
- request: str,
- data: Dict[str, Any],
- callback: Optional[ServerCallbackType] = None,
- response_type: ServerResponseType = ServerResponseType.JSON) -> None:
+ request: str,
+ data: Dict[str, Any],
+ callback: Optional[MasterServerCallback] = None,
+ response_type: MasterServerResponseType = MasterServerResponseType.JSON
+) -> None:
"""Make a call to the master server via a http POST."""
- ServerCallThread(request, 'post', data, callback, response_type).start()
+ MasterServerCallThread(request, 'post', data, callback,
+ response_type).start()
diff --git a/assets/src/ba_data/python/ba/_servermode.py b/assets/src/ba_data/python/ba/_servermode.py
index ec540d3b..245fd9e0 100644
--- a/assets/src/ba_data/python/ba/_servermode.py
+++ b/assets/src/ba_data/python/ba/_servermode.py
@@ -186,7 +186,7 @@ class ServerController:
def _run_access_check(self) -> None:
"""Check with the master server to see if we're likely joinable."""
- from ba._netutils import master_server_get
+ from ba._net import master_server_get
master_server_get(
'bsAccessCheck',
{
diff --git a/assets/src/ba_data/python/ba/internal.py b/assets/src/ba_data/python/ba/internal.py
index 1d852ee1..c2286f1c 100644
--- a/assets/src/ba_data/python/ba/internal.py
+++ b/assets/src/ba_data/python/ba/internal.py
@@ -25,8 +25,9 @@ from ba._campaign import getcampaign
from ba._messages import PlayerProfilesChangedMessage
from ba._multiteamsession import DEFAULT_TEAM_COLORS, DEFAULT_TEAM_NAMES
from ba._music import do_play_music
-from ba._netutils import (master_server_get, master_server_post,
- get_ip_address_type)
+from ba._net import (master_server_get, master_server_post,
+ get_ip_address_type, is_urllib_network_error,
+ DEFAULT_REQUEST_TIMEOUT_SECONDS)
from ba._powerup import get_default_powerup_distribution
from ba._profile import (get_player_profile_colors, get_player_profile_icon,
get_player_colors)
diff --git a/assets/src/ba_data/python/bastd/ui/confirm.py b/assets/src/ba_data/python/bastd/ui/confirm.py
index fc65aaf6..82e2ac48 100644
--- a/assets/src/ba_data/python/bastd/ui/confirm.py
+++ b/assets/src/ba_data/python/bastd/ui/confirm.py
@@ -34,8 +34,7 @@ class ConfirmWindow:
if cancel_text is None:
cancel_text = ba.Lstr(resource='cancelText')
height += 40
- if width < 360:
- width = 360
+ width = max(width, 360)
self._action = action
# if they provided an origin-widget, scale up from that
diff --git a/assets/src/ba_data/python/bastd/ui/gather/publictab.py b/assets/src/ba_data/python/bastd/ui/gather/publictab.py
index b1a326ba..fc07f836 100644
--- a/assets/src/ba_data/python/bastd/ui/gather/publictab.py
+++ b/assets/src/ba_data/python/bastd/ui/gather/publictab.py
@@ -1261,10 +1261,7 @@ class PublicGatherTab(GatherTab):
self._have_user_selected_row = True
def _on_max_public_party_size_minus_press(self) -> None:
- val = _ba.get_public_party_max_size()
- val -= 1
- if val < 1:
- val = 1
+ val = max(1, _ba.get_public_party_max_size() - 1)
_ba.set_public_party_max_size(val)
ba.textwidget(edit=self._host_max_party_size_value, text=str(val))
diff --git a/assets/src/server/ballisticacore_server.py b/assets/src/server/ballisticacore_server.py
index d2a7c53f..49101783 100755
--- a/assets/src/server/ballisticacore_server.py
+++ b/assets/src/server/ballisticacore_server.py
@@ -549,6 +549,7 @@ class ServerManagerApp:
def _run_server_cycle(self) -> None:
"""Spin up the server subprocess and run it until exit."""
+ # pylint: disable=consider-using-with
# Reload our config, and update our overall behavior based on it.
# We do non-strict this time to give the user repeated attempts if
diff --git a/ballisticacore-cmake/.idea/dictionaries/ericf.xml b/ballisticacore-cmake/.idea/dictionaries/ericf.xml
index c02c1bfa..2055a422 100644
--- a/ballisticacore-cmake/.idea/dictionaries/ericf.xml
+++ b/ballisticacore-cmake/.idea/dictionaries/ericf.xml
@@ -66,6 +66,7 @@
backtraces
ballistica
ballisticacore
+ bamasteraddr
barebones
basetype
basicsize
@@ -88,6 +89,7 @@
bitmask
bitpos
bitval
+ blarg
blitters
blitting
blockadr
@@ -271,6 +273,7 @@
elems
elevenbase
elevenbits
+ embconnect
emitfx
emojis
enablexinput
@@ -822,6 +825,7 @@
seqtypestr
serv
serverget
+ servernodequery
servernodes
serverput
sessiondata
diff --git a/docs/ba_module.md b/docs/ba_module.md
index 3d3a842e..e248e6bd 100644
--- a/docs/ba_module.md
+++ b/docs/ba_module.md
@@ -1,5 +1,5 @@
-
last updated on 2021-04-19 for Ballistica version 1.6.0 build 20347
+last updated on 2021-04-25 for Ballistica version 1.6.0 build 20349
This page documents the Python classes and functions in the 'ba' module,
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please let me know. Happy modding!
diff --git a/src/ballistica/ballistica.cc b/src/ballistica/ballistica.cc
index 252e796a..aa8029b7 100644
--- a/src/ballistica/ballistica.cc
+++ b/src/ballistica/ballistica.cc
@@ -21,7 +21,7 @@
namespace ballistica {
// These are set automatically via script; don't change here.
-const int kAppBuildNumber = 20347;
+const int kAppBuildNumber = 20349;
const char* kAppVersion = "1.6.0";
// Our standalone globals.
diff --git a/src/ballistica/config/config_common.h b/src/ballistica/config/config_common.h
index 664b7cb2..45764edd 100644
--- a/src/ballistica/config/config_common.h
+++ b/src/ballistica/config/config_common.h
@@ -10,9 +10,9 @@
// Universal sanity checks.
#if !BA_DEBUG_BUILD
-#if !NDEBUG
+#ifndef NDEBUG
#error NDEBUG should be defined for all non-debug builds.
-#endif // !NDEBUG
+#endif // NDEBUG
#endif // !BA_DEBUG_BUILD
// This header should be included at the very END of each platform config
diff --git a/tools/batools/build.py b/tools/batools/build.py
index cf7e7d09..7514b488 100644
--- a/tools/batools/build.py
+++ b/tools/batools/build.py
@@ -29,11 +29,11 @@ class PipRequirement:
PIP_REQUIREMENTS = [
- PipRequirement(modulename='pylint', minversion=[2, 7, 0]),
+ PipRequirement(modulename='pylint', minversion=[2, 8, 1]),
PipRequirement(modulename='mypy', minversion=[0, 812]),
- PipRequirement(modulename='yapf', minversion=[0, 30, 0]),
+ PipRequirement(modulename='yapf', minversion=[0, 31, 0]),
PipRequirement(modulename='cpplint', minversion=[1, 5, 4]),
- PipRequirement(modulename='pytest', minversion=[6, 2, 2]),
+ PipRequirement(modulename='pytest', minversion=[6, 2, 3]),
PipRequirement(modulename='typing_extensions'),
PipRequirement(modulename='pytz'),
PipRequirement(modulename='ansiwrap'),
diff --git a/tools/efro/entity/_entity.py b/tools/efro/entity/_entity.py
index 6a3d3942..b866964c 100644
--- a/tools/efro/entity/_entity.py
+++ b/tools/efro/entity/_entity.py
@@ -151,7 +151,7 @@ class EntityMixin:
cls=ExtendedJSONEncoder)
@staticmethod
- def json_loads(s: str) -> Any:
+ def json_loads(s: Union[str, bytes]) -> Any:
"""Load a json string using our special extended decoder.
Note that this simply returns loaded json data; no
@@ -159,7 +159,9 @@ class EntityMixin:
"""
return json.loads(s, cls=ExtendedJSONDecoder)
- def load_from_json_str(self, s: str, error: bool = True) -> None:
+ def load_from_json_str(self,
+ s: Union[str, bytes],
+ error: bool = True) -> None:
"""Set the entity's data in-place from a json string.
The 'error' argument determines whether Exceptions will be raised
@@ -171,7 +173,9 @@ class EntityMixin:
self.set_data(data, error=error)
@classmethod
- def from_json_str(cls: Type[T], s: str, error: bool = True) -> T:
+ def from_json_str(cls: Type[T],
+ s: Union[str, bytes],
+ error: bool = True) -> T:
"""Instantiate a new instance with provided json string.
The 'error' argument determines whether exceptions will be raised
diff --git a/tools/efrotools/code.py b/tools/efrotools/code.py
index 59531160..29c13fdb 100644
--- a/tools/efrotools/code.py
+++ b/tools/efrotools/code.py
@@ -629,6 +629,7 @@ def _run_idea_inspections(projroot: Path,
Throw an Exception if anything is found or goes wrong.
"""
# pylint: disable=too-many-locals
+ # pylint: disable=consider-using-with
import tempfile
import time
import datetime
@@ -778,22 +779,21 @@ def check_pycharm(projroot: Path, full: bool, verbose: bool) -> None:
# work that way.
if bool(False):
print('Launching GUI PyCharm to rebuild caches...', flush=True)
- process = subprocess.Popen(str(pycharmbin))
+ with subprocess.Popen(str(pycharmbin)) as process:
- # Wait a bit and ask it nicely to die.
- # We need to make sure it has enough time to do its cache updating
- # thing even if the system is fully under load.
- time.sleep(5 * 60)
+ # Wait a bit and ask it nicely to die.
+ # We need to make sure it has enough time to do its
+ # cache updating thing even if the system is fully under load.
+ time.sleep(5 * 60)
- # Seems killing it via applescript is more likely to leave it
- # in a working state for offline inspections than TERM signal..
- subprocess.run(
- "osascript -e 'tell application \"PyCharm CE\" to quit'",
- shell=True,
- check=False)
- # process.terminate()
- print('Waiting for GUI PyCharm to quit...', flush=True)
- process.wait()
+ # Seems killing it via applescript is more likely to leave it
+ # in a working state for offline inspections than TERM signal..
+ subprocess.run(
+ "osascript -e 'tell application \"PyCharm CE\" to quit'",
+ shell=True,
+ check=False)
+ print('Waiting for GUI PyCharm to quit...', flush=True)
+ process.wait()
_run_idea_inspections_cached(cachepath=cachepath,
filenames=filenames,
diff --git a/tools/efrotools/statictest.py b/tools/efrotools/statictest.py
index c2ed794b..8a9456a0 100644
--- a/tools/efrotools/statictest.py
+++ b/tools/efrotools/statictest.py
@@ -29,6 +29,7 @@ class StaticTestFile:
def __init__(self, filename: str):
# pylint: disable=global-statement, invalid-name
+ # pylint: disable=consider-using-with
global _tempdir, _nextfilenum
# pylint: enable=global-statement, invalid-name