Improved server chat and screenmessage functionality

This commit is contained in:
Eric Froemling 2020-05-06 00:50:18 -07:00
parent 3872920093
commit c95357e3d0
10 changed files with 116 additions and 49 deletions

View File

@ -4132,16 +4132,16 @@
"assets/build/windows/x64/python.exe": "https://files.ballistica.net/cache/ba1/25/a7/dc87c1be41605eb6fefd0145144c",
"assets/build/windows/x64/python37.dll": "https://files.ballistica.net/cache/ba1/b9/e4/d912f56e42e9991bcbb4c804cfcb",
"assets/build/windows/x64/pythonw.exe": "https://files.ballistica.net/cache/ba1/6c/bb/b6f52c306aa4e88061510e96cefe",
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/8c/a0/002b38837d6d538912c7e3353d38",
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/c8/af/0f496b474262aea9ee0f91145177",
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/23/ff/2b90933ab022e851c9ee1885bd02",
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/2f/ee/38fac529e6e1fc418334e3c5a96f",
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/8d/99/1048ca7d9a3f8aabc7719399e996",
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/81/b5/72bb876e9a7e88cbd2c828b7b1a9",
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/3d/8b/ff95157b4e62b80210841a81594b",
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/80/b7/ac34c7c602b40a1f4f095b2bd5df",
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/c4/3b/8de9d3aa9d2bcfb7ad731b2243bc",
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/b9/e3/5f34b93ba4b62facbfea0a8dfde4",
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/a7/3e/65b9f907e53f753aa4178500cb2f",
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/58/1f/3241179955da91425342cea435a0"
"build/prefab/linux-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/6a/56/e48e9306428b4ae7b58225fce76c",
"build/prefab/linux-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/dd/2d/bdd22cbd39a9bb27a75302ef837a",
"build/prefab/linux/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/61/f2/a679c5a3c9113c7b7599a59415fb",
"build/prefab/linux/release/ballisticacore": "https://files.ballistica.net/cache/ba1/6c/21/c80e03031e6c5959140588d439bf",
"build/prefab/mac-server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/42/ff/6d9056500a768dae79ed44180796",
"build/prefab/mac-server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/58/d4/3f6d3cb75988db046f22bfb5c2a5",
"build/prefab/mac/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/a8/07/edf6360c8e5b824633bf55c97ed9",
"build/prefab/mac/release/ballisticacore": "https://files.ballistica.net/cache/ba1/27/cc/0ec7cab492f111923320dc165427",
"build/prefab/windows-server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/b2/b4/f68901c3dae4267a5640bf702d86",
"build/prefab/windows-server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/ae/b7/0400bd1021d0fc0c40d1c2149364",
"build/prefab/windows/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/ee/6e/8f88fef729d85a07910cbedbac31",
"build/prefab/windows/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/e1/90/4877825fb2d779bd7ac9704a1a4c"
}

View File

@ -275,6 +275,7 @@
<w>charmap</w>
<w>charname</w>
<w>charstr</w>
<w>chatmessage</w>
<w>checkarg</w>
<w>checkboxwidget</w>
<w>checkenv</w>
@ -316,6 +317,7 @@
<w>cnode</w>
<w>codecsmodule</w>
<w>codefilenames</w>
<w>codehash</w>
<w>codeop</w>
<w>collapsable</w>
<w>collidemodel</w>
@ -800,6 +802,7 @@
<w>halign</w>
<w>handlemessage</w>
<w>hant</w>
<w>hashfilename</w>
<w>hashlines</w>
<w>hashobj</w>
<w>hashopenssl</w>
@ -953,6 +956,7 @@
<w>langs</w>
<w>langtarget</w>
<w>langval</w>
<w>lasthash</w>
<w>lastline</w>
<w>lastplayer</w>
<w>lastpoweruptype</w>

View File

@ -34,7 +34,7 @@ NOTE: This file was autogenerated by gendummymodule; do not edit by hand.
"""
# (hash we can use to see if this file is out of date)
# SOURCES_HASH=244232883360612053934546020264848527679
# SOURCES_HASH=303806386736755003110818846527806768186
# I'm sorry Pylint. I know this file saddens you. Be strong.
# pylint: disable=useless-suppression
@ -1504,8 +1504,10 @@ def charstr(char_id: ba.SpecialChar) -> str:
return str()
def chat_message(message: Union[str, ba.Lstr]) -> None:
"""chat_message(message: Union[str, ba.Lstr]) -> None
def chatmessage(message: Union[str, ba.Lstr],
clients: Sequence[int] = None) -> None:
"""chatmessage(message: Union[str, ba.Lstr],
clients: Sequence[int] = None) -> None
(internal)
"""

View File

@ -31,8 +31,8 @@ from ba._freeforallsession import FreeForAllSession
from ba._dualteamsession import DualTeamSession
from bacommon.servermanager import (ServerCommand, StartServerModeCommand,
ShutdownCommand, ShutdownReason,
BroadcastCommand, ClientListCommand,
KickCommand)
ChatMessageCommand, ScreenMessageCommand,
ClientListCommand, KickCommand)
import _ba
if TYPE_CHECKING:
@ -58,9 +58,20 @@ def _cmd(command_data: bytes) -> None:
immediate=command.immediate)
return
if isinstance(command, BroadcastCommand):
if isinstance(command, ChatMessageCommand):
assert _ba.app.server is not None
_ba.app.server.broadcast_message(command.message)
_ba.chatmessage(command.message, clients=command.clients)
return
if isinstance(command, ScreenMessageCommand):
assert _ba.app.server is not None
# Note: we have to do transient messages if
# clients is specified, so they won't show up
# in replays.
_ba.screenmessage(command.message,
color=command.color,
clients=command.clients,
transient=command.clients is not None)
return
if isinstance(command, ClientListCommand):
@ -111,12 +122,6 @@ class ServerController:
timetype=TimeType.REAL,
repeat=True)
def broadcast_message(self, message: str) -> None:
"""Broadcast a message to all connected clients."""
# FIXME: Should add a proper call for this, which would allow
# us to use Lstr values and colors and whatnot.
_ba.chat_message(message)
def print_client_list(self) -> None:
"""Print info about all connected clients."""
import json
@ -184,13 +189,13 @@ class ServerController:
self._executing_shutdown = True
timestrval = time.strftime('%c')
if self._shutdown_reason is ShutdownReason.RESTARTING:
self.broadcast_message(
Lstr(resource='internal.serverRestartingText').evaluate())
_ba.screenmessage(Lstr(resource='internal.serverRestartingText'),
color=(1, 0.5, 0.0))
print(f'{Clr.SBLU}Exiting for server-restart'
f' at {timestrval}{Clr.RST}')
else:
self.broadcast_message(
Lstr(resource='internal.serverShuttingDownText').evaluate())
_ba.screenmessage(Lstr(resource='internal.serverShuttingDownText'),
color=(1, 0.5, 0.0))
print(f'{Clr.SBLU}Exiting for server-shutdown'
f' at {timestrval}{Clr.RST}')
with _ba.Context('ui'):

View File

@ -412,7 +412,7 @@ class PartyWindow(ba.Window):
self._popup_party_member_is_host = is_host
def _send_chat_message(self) -> None:
_ba.chat_message(cast(str, ba.textwidget(query=self._text_field)))
_ba.chatmessage(cast(str, ba.textwidget(query=self._text_field)))
ba.textwidget(edit=self._text_field, text='')
def close(self) -> None:

View File

@ -44,7 +44,7 @@ from efro.dataclassutils import dataclass_assign, dataclass_validate
from bacommon.servermanager import (ServerConfig, StartServerModeCommand)
if TYPE_CHECKING:
from typing import Optional, List, Dict, Union
from typing import Optional, List, Dict, Union, Tuple
from types import FrameType
from bacommon.servermanager import ServerCommand
@ -181,10 +181,31 @@ class ServerManagerApp:
# we'll hopefully still give it enough time to process/print.
time.sleep(0.1)
def broadcast(self, message: str) -> None:
"""Broadcast a message to all connected clients."""
from bacommon.servermanager import BroadcastCommand
self._enqueue_server_command(BroadcastCommand(message=message))
def screenmessage(self,
message: str,
color: Optional[Tuple[float, float, float]] = None,
clients: Optional[List[int]] = None) -> None:
"""Display a screen-message.
This will have no name attached and not show up in chat history.
They will show up in replays, however (unless clients is passed).
"""
from bacommon.servermanager import ScreenMessageCommand
self._enqueue_server_command(
ScreenMessageCommand(message=message, color=color,
clients=clients))
def chatmessage(self,
message: str,
clients: Optional[List[int]] = None) -> None:
"""Send a chat message from the server.
This will have the server's name attached and will be logged
in client chat windows, just like other chat messages.
"""
from bacommon.servermanager import ChatMessageCommand
self._enqueue_server_command(
ChatMessageCommand(message=message, clients=clients))
def clientlist(self) -> None:
"""Print a list of connected clients."""
@ -366,10 +387,16 @@ class ServerManagerApp:
# Watch for the process exiting.
code: Optional[int] = self._process.poll()
if code is not None:
print(f'{Clr.CYN}Server process exited'
if code == 0:
clr = Clr.CYN
slp = 0.0
else:
clr = Clr.SRED
slp = 5.0 # Avoid super fast death loops.
print(f'{clr}Server child-process exited'
f' with code {code}.{Clr.RST}')
time.sleep(1.0) # Keep things from moving too fast.
self._reset_process_vars()
time.sleep(slp)
break
time.sleep(0.25)

View File

@ -1,5 +1,5 @@
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
<h4><em>last updated on 2020-05-05 for Ballistica version 1.5.0 build 20002</em></h4>
<h4><em>last updated on 2020-05-06 for Ballistica version 1.5.0 build 20003</em></h4>
<p>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 <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
<hr>
@ -3988,17 +3988,11 @@ cause the powerup box to make a sound and disappear or whatnot.</p>
</p>
<h3>Methods:</h3>
<h5><a href="#method_ba_ServerController____init__">&lt;constructor&gt;</a>, <a href="#method_ba_ServerController__broadcast_message">broadcast_message()</a>, <a href="#method_ba_ServerController__handle_transition">handle_transition()</a>, <a href="#method_ba_ServerController__kick">kick()</a>, <a href="#method_ba_ServerController__print_client_list">print_client_list()</a>, <a href="#method_ba_ServerController__shutdown">shutdown()</a></h5>
<h5><a href="#method_ba_ServerController____init__">&lt;constructor&gt;</a>, <a href="#method_ba_ServerController__handle_transition">handle_transition()</a>, <a href="#method_ba_ServerController__kick">kick()</a>, <a href="#method_ba_ServerController__print_client_list">print_client_list()</a>, <a href="#method_ba_ServerController__shutdown">shutdown()</a></h5>
<dl>
<dt><h4><a name="method_ba_ServerController____init__">&lt;constructor&gt;</a></dt></h4><dd>
<p><span>ba.ServerController(config: ServerConfig)</span></p>
</dd>
<dt><h4><a name="method_ba_ServerController__broadcast_message">broadcast_message()</a></dt></h4><dd>
<p><span>broadcast_message(self, message: str) -&gt; None</span></p>
<p>Broadcast a message to all connected clients.</p>
</dd>
<dt><h4><a name="method_ba_ServerController__handle_transition">handle_transition()</a></dt></h4><dd>
<p><span>handle_transition(self) -&gt; bool</span></p>

View File

@ -26,7 +26,7 @@ from dataclasses import dataclass
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing import Optional
from typing import Optional, Tuple, List
@dataclass
@ -129,9 +129,18 @@ class ShutdownCommand(ServerCommand):
@dataclass
class BroadcastCommand(ServerCommand):
"""Broadcast a message to all clients."""
class ChatMessageCommand(ServerCommand):
"""Chat message from the server."""
message: str
clients: Optional[List[int]]
@dataclass
class ScreenMessageCommand(ServerCommand):
"""Screen-message from the server."""
message: str
color: Optional[Tuple[float, float, float]]
clients: Optional[List[int]]
@dataclass

View File

@ -149,7 +149,6 @@ def run(cmd: str) -> None:
subprocess.run(cmd, shell=True, check=True)
# 1
def get_files_hash(filenames: Sequence[Union[str, Path]],
extrahash: str = '',
int_only: bool = False,

View File

@ -547,5 +547,32 @@ def printcolors() -> None:
f'{TerminalColor.RESET.value}')
def lazy_increment_build() -> None:
"""Increment build number only if C++ sources have changed.
This is convenient to place in automatic commit/push scripts.
"""
import os
import subprocess
from efro.terminal import Clr
from efrotools import get_files_hash
from efrotools.code import get_code_filenames
codehash = get_files_hash(get_code_filenames(PROJROOT))
hashfilename = '.cache/lazy_increment_build'
try:
with open(hashfilename) as infile:
lasthash = infile.read()
except FileNotFoundError:
lasthash = ''
if codehash == lasthash:
pass
else:
print(f'{Clr.SMAG}Source(s) changed; incrementing build...{Clr.RST}')
subprocess.run(['tools/version_utils', 'incrementbuild'], check=True)
os.makedirs(os.path.dirname(hashfilename), exist_ok=True)
with open(hashfilename, 'w') as outfile:
outfile.write(codehash)
if __name__ == '__main__':
snippets_main(globals())