Page 1 of 2

SourceTV Listener

Posted: Thu Jul 07, 2016 1:19 pm
by decompile
Hello, is there something like SourceTV listener?

Would be great to use OnBroadcastActive or OnBroadcastEnd,

Im currently using tv_autorecord and creating a system behind it.

When an autorecord demo ends, it prints "Completed SourceTV demo "auto-20160707-1514-de_dust2.dem", recording time 22.3"

When an autorecord demo starts, it prints "SourceTV broadcast active."

It would be nice to get like the demo name, timestamp when it start, recording time etc.

The only way to get its timestamp is by using this:

Syntax: Select all

demoname = 'auto-20160707-1514-de_dust2.dem'
timepart = "-".join(basename.split("-")[1:3])
savetime = time.mktime(time.strptime(timepart,"%Y%m%d-%H%M"))

Re: SourceTV Listener

Posted: Sat Jul 09, 2016 9:58 pm
by La Muerte
I can't answer your question, but it'd be damn nice if you could implement a way to automatically upload said demo's to a webserver so that people can download, review and give feedback on them.

Re: SourceTV Listener

Posted: Sun Jul 10, 2016 4:17 am
by L'In20Cible
I didn't dig into the binaries but, there is certainly a way to hook those. For now, you could simply add your own callbacks to those specific commands and listen to them doing whatever you need to do.

Re: SourceTV Listener

Posted: Sun Jul 10, 2016 9:50 am
by decompile
La Muerte wrote:I can't answer your question, but it'd be damn nice if you could implement a way to automatically upload said demo's to a webserver so that people can download, review and give feedback on them.


Syntax: Select all

from ftplib import FTP

USER = ''
PASS = ''
SERVER = ''
PORT = 21

def connect_ftp():
ftp = FTP()
ftp.connect(SERVER, PORT)
ftp.login(USER, PASS)
return ftp

def upload_file(ftp_connetion, upload_file_path):

#Open the file
try:
upload_file = open(upload_file_path, 'r')

#get the name
path_split = upload_file_path.split('/')
final_file_name = path_split[len(path_split)-1]

#transfer the file
print('Uploading ' + final_file_name + '...')

ftp_connetion.storbinary('STOR '+ final_file_name, upload_file)

print('Upload finished.')

except IOError:
print ("File not found")
ftp_conn = connect_ftp()

demo_file_path = "E:\\GameServers\\css\cstrike\\demo1.dem"
upload_file(ftp_conn, demo_file_path)

Re: SourceTV Listener

Posted: Sun Jul 10, 2016 9:54 am
by decompile
L'In20Cible wrote:I didn't dig into the binaries but, there is certainly a way to hook those. For now, you could simply add your own callbacks to those specific commands and listen to them doing whatever you need to do.


Yes, just wrote my own listener, which just "manually" records the demos instead of using tv_autorecord.
Simply tv_record "xxxxxxx" and when the map ends it just executes tv_stoprecord. Atleast you have the demo name & the start time and endtime if needed.

Re: SourceTV Listener

Posted: Sun Jul 10, 2016 10:01 am
by iPlayer
decompile wrote:Yes, just wrote my own listener, which just "manually" records the demos instead of using tv_autorecord.
Simply tv_record "xxxxxxx" and when the map ends it just executes tv_stoprecord. Atleast you have the demo name & the start time and endtime if needed.

That's neat. As far as I can remember, demos are a bit broken in CS:S, you can't skip back and forth them that easy. With your manual approach, it's possible to make smaller demos, say, every 10 minutes.

Re: SourceTV Listener

Posted: Mon Jul 11, 2016 7:23 pm
by Ayuto
Tested with CS:S on Windows:

Syntax: Select all

# =============================================================================
# >> IMPORTS
# =============================================================================
# Python
import time

# Source.Python
import memory

from memory import DataType

from memory.manager import CustomType
from memory.manager import manager

from memory.hooks import PostHook

from core import PLATFORM
from engines.server import global_vars

from listeners import ListenerManager
from listeners import ListenerManagerDecorator


# =============================================================================
# >> GLOBAL VARIABLES
# =============================================================================
engine = memory.find_binary('bin/engine')

if PLATFORM == 'windows':
DEMO_RECORDER_OFFSET = 19680
hltv_ptr = engine.find_pointer(
b'\x55\x8B\xEC\x81\xEC\x1C\x01\x00\x00\x8D\x85\xE4\xFE\xFF\xFF\x68\x04\x01\x00\x00',
33,
2
)
else:
DEMO_RECORDER_OFFSET = 19652
hltv_ptr = engine.find_pointer('hltv', level=1)

if not hltv_ptr:
# Can happen if tv_enable is not set to 1
raise ValueError('HLTV Server is NULL.')


# =============================================================================
# >> CLASSES
# =============================================================================
class CHLTVDemoRecorder(CustomType, metaclass=manager):
get_demo_file = manager.virtual_function(0, [], DataType.STRING)
get_recording_tick = manager.virtual_function(1, [], DataType.INT)
start_recording = manager.virtual_function(2, [DataType.STRING, DataType.BOOL])
set_signon_state = manager.virtual_function(3, [])
is_recording = manager.virtual_function(4, [], DataType.BOOL)
pause_recording = manager.virtual_function(5, [])
resume_recording = manager.virtual_function(6, [])
stop_recording = manager.virtual_function(7, [])
record_command = manager.virtual_function(8, [DataType.STRING])
record_user_input = manager.virtual_function(9, [DataType.INT])
record_messages = manager.virtual_function(10, [DataType.POINTER, DataType.INT])
record_packet = manager.virtual_function(11, [])
record_server_classes = manager.virtual_function(12, [DataType.POINTER])
record_string_tables = manager.virtual_function(13, [])
reset_demo_interpolation = manager.virtual_function(14, [])

@property
def recording_time(self):
"""Return the recording time in seconds."""
return self.get_recording_tick() * global_vars.interval_per_tick

@property
def start_time(self):
"""Return the time when the record has been started."""
return time.time() - self.recording_time

demo_recorder = memory.make_object(
CHLTVDemoRecorder, hltv_ptr + DEMO_RECORDER_OFFSET)


class OnDemoStarted(ListenerManagerDecorator):
manager = ListenerManager()

class OnDemoStopped(ListenerManagerDecorator):
manager = ListenerManager()


# =============================================================================
# >> HOOKS
# =============================================================================
@PostHook(demo_recorder.start_recording)
def pre_start_recording(args, return_value):
OnDemoStarted.manager.notify()

@PostHook(demo_recorder.stop_recording)
def pre_stop_recording(args, return_value):
OnDemoStopped.manager.notify()


# =============================================================================
# >> TESTS
# =============================================================================
if not demo_recorder.is_recording():
raise ValueError('SourceTV is not recording.')

print('Demo file :', demo_recorder.get_demo_file())
print('Recording time:', divmod(demo_recorder.recording_time, 60))
print('Start time :', time.ctime(demo_recorder.start_time))

@OnDemoStarted
def on_demo_started():
print('Demo started:', demo_recorder.get_demo_file())

@OnDemoStopped
def on_demo_stopped():
print('Demo stopped:', demo_recorder.get_demo_file())

Edit: Added OnDemoStarted and OnDemoStopped decorators.
Edit2: Fixed plugin for Linux.

Re: SourceTV Listener

Posted: Fri Jul 15, 2016 7:00 pm
by decompile
Thank you Ayuto!!

Just noticed that OnDemoStarted isnt working, is it just me or someone else has it too?

Re: SourceTV Listener

Posted: Fri Jul 15, 2016 7:03 pm
by L'In20Cible
Why you remove your post to repost them few hours later?

Re: SourceTV Listener

Posted: Sat Jul 16, 2016 11:06 am
by decompile
L'In20Cible wrote:Why you remove your post to repost them few hours later?


When I posted it I wasnt sure if it was the official code which wasn't working, so I thought maybe I changed something to make it not work, but in the end I tested it only with the code from above and it doesnt work either

Re: SourceTV Listener

Posted: Sat Jul 16, 2016 2:27 pm
by Ayuto
When I tested it OnDemoStarted was working fine. Can you provide the steps to reproduce the issue?

Re: SourceTV Listener

Posted: Sat Jul 16, 2016 3:33 pm
by decompile
Problem solved, my srcds forced 'sv_autorecord 0' after mapchange, checked all cvars server.cfg/autoexec.cfg/srcds parameter + and after I removed them and put them only in autoexec.cfg it worked finally.

Re: SourceTV Listener

Posted: Sun Jul 24, 2016 11:46 pm
by decompile
Hey, would this work for cs:go windows/linux too?
Im using this for both games

Re: SourceTV Listener

Posted: Mon Jul 25, 2016 12:46 am
by L'In20Cible
This will most likely requires another signatures for CS:GO running on windows.

Re: SourceTV Listener

Posted: Sat Apr 21, 2018 1:25 pm
by decompile
Can someone maybe check the offsets/signatures for CS:S Windows/Linux and CS:GO Windows/Linux?

Additionally how are you doing that? Is there any program for that?

Re: SourceTV Listener

Posted: Mon Apr 23, 2018 6:08 am
by 12jdlovins
decompile wrote:Can someone maybe check the offsets/signatures for CS:S Windows/Linux and CS:GO Windows/Linux?

Additionally how are you doing that? Is there any program for that?


https://asherkin.github.io/vtable/

this might help? I'm unsure though, that stuff is beyond me at the moment.

Re: SourceTV Listener

Posted: Mon Apr 23, 2018 5:47 pm
by decompile
How would that work, also for CS:GO for example?

I tried to choose CS:S for now, and entered CHLTVDemoRecorder, found actually something but how do I get the offset?

Re: SourceTV Listener

Posted: Mon Apr 23, 2018 6:57 pm
by Ayuto
That tool is able to dump virtual function offsets/indexes, so you would be able to use it to update the "manager.virtual_function(...)" parts. However, that is only a part of the solution, because you also need to retrieve the pointer to the instance of CHLTVDemoRecorder. Moreover, symbols have been stripped from the CS:GO binaries, so actually you can't use that tool for CS:GO at all.

I'm using IDA Pro to retrieve this information.

I hope to find some time at the weekend to provide the necessarry information for CS:GO (CS:S should be up to date).

Re: SourceTV Listener

Posted: Mon Apr 23, 2018 11:44 pm
by 12jdlovins
I'm actually really interested in making a sourceTV recordinger & uploader however is using the pointers and such needed? Could i just start recording on map start and upload on map end basically with like tv_record mapname-date and such?

Re: SourceTV Listener

Posted: Tue Apr 24, 2018 12:29 am
by decompile
You dont need it, but its the official way to also hook auto-created demos, or user generated ones.