Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,33 @@ Called when a map starts and the server is ready to accept clients.
pass


OnServerOutput
----------------

Called when something is printed to the console. You can decide whether the
message is logged/printed or not.

.. warning::

Be careful when printing something within this listener. It can easily
result into a recursion, which results into a crash of the server.


.. code-block:: python

from listeners import OnServerOutput
from core import OutputReturn

@OnServerOutput
def on_server_output(severity, msg):
# Block everything starting with 'sv_' or 'mp_' from being logged.
# This keeps the console clean in CS:GO.
if msg.startswith(('sv_', 'mp_')):
return OutputReturn.BLOCK

return OutputReturn.CONTINUE


OnTick
------

Expand Down
63 changes: 63 additions & 0 deletions addons/source-python/packages/source-python/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
# Core
from _core import console_message
from _core import get_interface
from _core import OutputReturn
from _core import SOURCE_ENGINE
from _core import SOURCE_ENGINE_BRANCH

Expand All @@ -58,6 +59,7 @@
'GameConfigObj',
'WeakAutoUnload',
'GAME_NAME',
'OutputReturn',
'PLATFORM',
'SOURCE_ENGINE',
'SOURCE_ENGINE_BRANCH',
Expand All @@ -66,6 +68,7 @@
'get_interface',
'get_public_ip',
'ignore_unicode_errors',
'server_output',
)


Expand Down Expand Up @@ -166,6 +169,7 @@ def echo_console(text):
for line in text.split('\n'):
console_message(line + '\n')


@contextmanager
def ignore_unicode_errors(errors='ignore'):
"""Overwrite the ``strict`` codecs error handler temporarily.
Expand Down Expand Up @@ -218,3 +222,62 @@ def get_public_ip():
This functions makes a call to http://ip.42.pl/raw to retrieve the public IP.
"""
return urlopen('http://ip.42.pl/raw').read().decode()


@contextmanager
def server_output(action=OutputReturn.CONTINUE):
"""Gather all server output sent during the execution of the with-statement.

:param OutputReturn action:
Determines what happens with the output.
:rtype: list
:return:
A list that will be filled with a tuple for every line that is being
logged. The tuple contains the severity and the message.

Example:

.. code:: python

from cvars import cvar
from core import server_output
from core import OutputReturn

status = cvar.find_command('status')

with server_output(OutputReturn.BLOCK) as output:
status()

# Print everything that was logged by the 'status' command
print(output)


Output:

.. code:: python

[(_core.MessageSeverity.MESSAGE, 'hostname: Counter-Strike: Global Offensive\\n'),
(_core.MessageSeverity.MESSAGE, 'version : 1.35.8.4/13584 513/6771 secure [A:1:2435270659:8640] \\n'),
(_core.MessageSeverity.MESSAGE, 'udp/ip : 192.168.178.60:27015 (public ip: 46.83.158.27)\\n'),
(_core.MessageSeverity.MESSAGE, 'os : Windows\\n'),
(_core.MessageSeverity.MESSAGE, 'type : community dedicated\\n'),
(_core.MessageSeverity.MESSAGE, 'players : 0 humans, 0 bots (20/0 max) (hibernating)\\n\\n'),
(_core.MessageSeverity.MESSAGE, '# userid name uniqueid connected ping loss state rate'),
(_core.MessageSeverity.MESSAGE, ' adr'),
(_core.MessageSeverity.MESSAGE, '\\n'),
(_core.MessageSeverity.MESSAGE, '#end\\n')]
"""
# Import this here to fix a cyclic import
from listeners import OnServerOutput

msg_buffer = []

def intercepter(severity, msg):
msg_buffer.append((severity, msg))
return action

OnServerOutput.manager.register_listener(intercepter)
try:
yield msg_buffer
finally:
OnServerOutput.manager.unregister_listener(intercepter)
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
from _listeners import on_query_cvar_value_finished_listener_manager
from _listeners import on_server_activate_listener_manager
from _listeners import on_tick_listener_manager
from _listeners import on_server_output_listener_manager
# Entity output
from listeners._entity_output import on_entity_output_listener_manager

Expand Down Expand Up @@ -103,6 +104,7 @@
'OnServerActivate',
'OnTick',
'OnVersionUpdate',
'OnServerOutput',
'get_button_combination_status',
'on_client_active_listener_manager',
'on_client_connect_listener_manager',
Expand Down Expand Up @@ -133,6 +135,7 @@
'on_server_activate_listener_manager',
'on_tick_listener_manager',
'on_version_update_listener_manager',
'on_server_output_listener_manager',
)


Expand Down Expand Up @@ -427,6 +430,12 @@ class OnButtonStateChanged(ListenerManagerDecorator):
manager = on_button_state_changed_listener_manager


class OnServerOutput(ListenerManagerDecorator):
"""Register/unregister a server output listener."""

manager = on_server_output_listener_manager


# =============================================================================
# >> FUNCTIONS
# =============================================================================
Expand Down
23 changes: 23 additions & 0 deletions src/core/modules/core/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,29 @@
#include "dynload.h"


//-----------------------------------------------------------------------------
// MessageSeverity
//-----------------------------------------------------------------------------
enum MessageSeverity
{
SEVERITY_MESSAGE = 0,
SEVERITY_WARNING,
SEVERITY_ASSERT,
SEVERITY_ERROR,
SEVERITY_LOG,
};


//-----------------------------------------------------------------------------
// OutputReturn
//-----------------------------------------------------------------------------
enum OutputReturn
{
OUTPUT_BLOCK = 0,
OUTPUT_CONTINUE
};


//-----------------------------------------------------------------------------
// ConMsg wrapper
//-----------------------------------------------------------------------------
Expand Down
31 changes: 31 additions & 0 deletions src/core/modules/core/core_wrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ extern CSourcePython g_SourcePythonPlugin;
// Forward declarations.
//-----------------------------------------------------------------------------
static void export_source_python_plugin(scope);
static void export_message_severity(scope);
static void export_output_return(scope);
static void export_constants(scope);
static void export_functions(scope);

Expand All @@ -52,6 +54,8 @@ static void export_functions(scope);
DECLARE_SP_MODULE(_core)
{
export_source_python_plugin(_core);
export_message_severity(_core);
export_output_return(_core);
export_constants(_core);
export_functions(_core);
}
Expand All @@ -69,6 +73,33 @@ void export_source_python_plugin(scope _core)
}


//-----------------------------------------------------------------------------
// Expose MessageSeverity.
//-----------------------------------------------------------------------------
void export_message_severity(scope _core)
{
enum_<MessageSeverity> _MessageSeverity("MessageSeverity");

_MessageSeverity.value("MESSAGE", SEVERITY_MESSAGE);
_MessageSeverity.value("WARNING", SEVERITY_WARNING);
_MessageSeverity.value("ASSERT", SEVERITY_ASSERT);
_MessageSeverity.value("ERROR", SEVERITY_ERROR);
_MessageSeverity.value("LOG", SEVERITY_LOG);
}


//-----------------------------------------------------------------------------
// Expose OutputReturn.
//-----------------------------------------------------------------------------
void export_output_return(scope _core)
{
enum_<OutputReturn> _OutputReturn("OutputReturn");

_OutputReturn.value("BLOCK", OUTPUT_BLOCK);
_OutputReturn.value("CONTINUE", OUTPUT_CONTINUE);
}


//-----------------------------------------------------------------------------
// Expose constants.
//-----------------------------------------------------------------------------
Expand Down
3 changes: 3 additions & 0 deletions src/core/modules/listeners/listeners_wrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ DEFINE_MANAGER_ACCESSOR(OnEntityDeleted)
DEFINE_MANAGER_ACCESSOR(OnDataLoaded)
DEFINE_MANAGER_ACCESSOR(OnCombinerPreCache)
DEFINE_MANAGER_ACCESSOR(OnDataUnloaded)
DEFINE_MANAGER_ACCESSOR(OnServerOutput)


//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -147,4 +148,6 @@ void export_listener_managers(scope _listeners)
_listeners.attr("on_data_loaded_listener_manager") = object(ptr(GetOnDataLoadedListenerManager()));
_listeners.attr("on_combiner_pre_cache_listener_manager") = object(ptr(GetOnCombinerPreCacheListenerManager()));
_listeners.attr("on_data_unloaded_listener_manager") = object(ptr(GetOnDataUnloadedListenerManager()));

_listeners.attr("on_server_output_listener_manager") = object(ptr(GetOnServerOutputListenerManager()));
}
Loading