Skip to content

Commit e52fbb1

Browse files
committed
fix(TSimbaRecorder): read notes
The way @TazEQ originally made this followed my suggestion of using threads and it was a bad suggestion. When a script gets killed so is the thread the recorder was running on. So now it's running with `RunSimbaScript()` similar to what 1.4 did. So it can properly record clients being GPU rendered, the main process also passes plugin information to the subprocess which will setup it's target with a plugin as well if the main one is using one. TODO: stop recording and restart on target resizing, with Target.AddEvent() should be easy TODO: add blackout boxes for users RSNs. Ideally done better and more performant that how it was done on 1.4
1 parent d7af024 commit e52fbb1

10 files changed

Lines changed: 171 additions & 148 deletions

File tree

osrs.simba

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,10 @@ Summary: It includes this file until the current file is reached.
170170

171171

172172
{$IFNDEF WL_ANTIBAN_TASKS_INCLUDED} {$INCLUDE_ONCE osrs/antiban/antibantasks.simba}
173-
{$IFNDEF WL_ANTIBAN_FORM_INCLUDED} {$INCLUDE_ONCE osrs/antiban/antibanform.simba}
173+
{$IFNDEF WL_ANTIBAN_FORM_INCLUDED} {$INCLUDE_ONCE osrs/antiban/antibanform.simba}
174+
{$IFNDEF WL_RECORDER_INCLUDED} {$INCLUDE_ONCE osrs/recorder/recorder.simba}
174175
{$IFNDEF WL_MISC_FORM_INCLUDED} {$INCLUDE_ONCE osrs/miscform.simba}
175176

176-
177177
{$IFNDEF WL_SETUP_INCLUDED} {$INCLUDE_ONCE osrs/interfaces/setup.simba}
178178
{$IFNDEF WL_INTERFACE_DEBUGGING_INCLUDED} {$INCLUDE_ONCE osrs/interfaces/debugging.simba}
179179
{$IFNDEF WL_OVERRIDES_INCLUDED} {$INCLUDE_ONCE osrs/overrides.simba}
@@ -187,4 +187,4 @@ Summary: It includes this file until the current file is reached.
187187
{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}
188188
{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}
189189
{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}
190-
{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}
190+
{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}

osrs/fakeinput.simba

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Main record used to interact with the remote input plugin.
3434
*)
3535
TRemoteInput = record
3636
Target: Pointer;
37+
Window: TWindowHandle;
3738
end;
3839

3940
(*
@@ -47,19 +48,18 @@ This is automatically called for you on the {ref}`RemoteInput variable`.
4748
procedure TRemoteInput.Setup();
4849
var
4950
timer: TCountDown;
50-
window: TWindowHandle;
5151
pid: TProcessID;
5252
begin
5353
{$IFDEF SIMBAHEADLESS}
54-
window := StrToInt(Target.ToString().Between('Handle=', ','));
54+
Self.Window := StrToInt(Target.ToString().Between('Handle=', ','));
5555
{$ELSE}
56-
window := GetSimbaTargetWindow();
56+
Self.Window := GetSimbaTargetWindow();
5757
{$ENDIF}
5858

59-
if window.GetClassName() <> 'SunAwtCanvas' then
59+
if Self.Window.GetClassName() <> 'SunAwtCanvas' then
6060
Exit;
6161

62-
pid := window.GetPID();
62+
pid := Self.Window.GetPID();
6363

6464
try
6565
RIInject(pid);
@@ -129,6 +129,7 @@ Main record used to interact with the wasp input plugin.
129129
*)
130130
TWaspInput = record
131131
Target: Pointer;
132+
Window: TWindowHandle;
132133
end;
133134

134135
(*
@@ -141,19 +142,18 @@ This is automatically called for you on the {ref}`WaspInput variable`.
141142
*)
142143
procedure TWaspInput.Setup();
143144
var
144-
window: TWindowHandle;
145145
pid: TProcessID;
146146
begin
147147
{$IFDEF SIMBAHEADLESS}
148-
window := StrToInt(Target.ToString().Between('Handle=', ','));
148+
Self.Window := StrToInt(Target.ToString().Between('Handle=', ','));
149149
{$ELSE}
150-
window := GetSimbaTargetWindow();
150+
Self.Window := GetSimbaTargetWindow();
151151
{$ENDIF}
152152

153-
if window.GetClassName() <> 'JagRenderView' then
153+
if Self.Window.GetClassName() <> 'JagRenderView' then
154154
Exit;
155155

156-
pid := window.GetPID();
156+
pid := Self.Window.GetPID();
157157
Inject({$MACRO LOADEDLIB(waspinput)}, pid);
158158
Target.SetPlugin({$MACRO LOADEDLIB(waspinput)}, ToStr(pid), RSClient.Canvas);
159159
Self.Target := @pid;
@@ -356,3 +356,5 @@ begin
356356
WriteLn(GetDebugLn('RSClient', 'InjectInput method is not implemented without a fake input tool.', ELogLevel.WARN));
357357
{$ENDIF}
358358
end;
359+
360+

osrs/miscform.simba

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ begin
130130
Self.ClientPanel := TLazPanel.CreateEx(parent, TLazTabSheet(parent).Width div 2 - 240, 20, 480, 220);
131131
Self.ClientPanel.BevelWidth := 0;
132132

133-
WriteLn Self.ClientPanel.Width;
134133
Self.LoggedInInfo := TLazLabel.CreateEx(Self.ClientPanel, 'You are logged in as ' + WaspClient.User.Username, '', 80, 80, 0, 30);
135134
Self.LoggedInInfo.Font.Name := 'Courier New';
136135

osrs/overrides.simba

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,3 +370,19 @@ begin
370370
RSMouseZoom.ZoomLevel := RSMouseZoom.Slider2Level(level);
371371
end;
372372

373+
374+
(*
375+
## ScriptForm.OnStart override
376+
```pascal
377+
procedure TScriptForm.OnStart(sender: TLazObject); override;
378+
```
379+
Overrides TScriptForm.OnStart to perform certain tasks when the script starts
380+
running, e.g. start the `Simba Recorder`
381+
*)
382+
procedure TScriptForm.OnStart(sender: TLazObject); override;
383+
begin
384+
inherited();
385+
386+
if SimbaRecorder.Enabled then
387+
SimbaRecorder.Start();
388+
end;

osrs/recorder/recorder.simba

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
(*
2+
# Recorder
3+
Records video in separate thread for debugging script crashes and issues.
4+
5+
Basic usage:
6+
```pascal
7+
SimbaRecorder.Start(30); // Start recording with 30 second buffer
8+
SimbaRecorder.Start(30, 'MyVideos'); // Custom save directory
9+
// Videos are automatically saved on script end
10+
```
11+
*)
12+
13+
{$DEFINE WL_RECORDER_INCLUDED}
14+
{$INCLUDE_ONCE WaspLib/osrs.simba}
15+
16+
type
17+
(*
18+
## type TSimbaRecorder
19+
```pascal
20+
TSimbaRecorder = record
21+
Thread: TThread;
22+
IsRecording: Boolean;
23+
BufferSeconds: Integer;
24+
VideoPath: String;
25+
RecorderTarget: TTarget;
26+
end;
27+
```
28+
Manages video recording with buffered capture.
29+
*)
30+
TSimbaRecorder = record
31+
Enabled, IsRecording: Boolean;
32+
BufferSeconds: UInt64;
33+
end;
34+
(*
35+
## TSimbaRecorder.Start
36+
```pascal
37+
procedure TSimbaRecorder.Start(BufferSeconds: Integer = 30; VideoPath: String = 'Videos');
38+
```
39+
Starts recording with specified buffer duration and save path.
40+
*)
41+
procedure TSimbaRecorder.Start();
42+
var
43+
window, plugin: String;
44+
begin
45+
if not Self.Enabled or Self.IsRecording then
46+
Exit;
47+
48+
{$IFNDEF WL_DISABLE_FAKE_INPUT}
49+
case RSClient.Client of
50+
{$IFDEF WINDOWS}
51+
ERSClient.OFFICIAL:
52+
begin
53+
window := ToStr(WaspInput.Window);
54+
plugin := 'plugin=wasp-input';
55+
end;
56+
{$ENDIF}
57+
ERSClient.LEGACY, ERSClient.RUNELITE:
58+
begin
59+
window := ToStr(RemoteInput.Window);
60+
plugin := 'plugin=remote-input';
61+
end;
62+
end;
63+
{$ENDIF}
64+
65+
WriteLn {$MACRO DIR} + 'recorder_subprocess.simba';
66+
RunSimbaScript({$MACRO DIR} + 'recorder_subprocess.simba',
67+
[
68+
'script=' + ToStr(GetProcessID()),
69+
'target=' + window,
70+
'time=' + ToStr(Self.BufferSeconds),
71+
plugin,
72+
'path=' + WLEnv.VideosDir
73+
]
74+
);
75+
Self.IsRecording := True;
76+
end;
77+
78+
var
79+
SimbaRecorder: TSimbaRecorder;
80+
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
(*
2+
# Recorder SubProcess
3+
Standalone script meant to be ran by WaspLib to record a target
4+
*)
5+
{$loadlib Plugins/wasp-plugins/librecorder/librecorder}
6+
{$loadlib Plugins/wasp-plugins/libremoteinput/libremoteinput}
7+
{$loadlib Plugins/wasp-plugins/waspinput/waspinput}
8+
9+
var
10+
Process: TProcessID;
11+
Frame: TImage;
12+
13+
{$H-}
14+
function GetFrame(sender: TRecorder): Pointer;
15+
begin
16+
Frame := Target.GetImage();
17+
Result := Frame.Data;
18+
end;
19+
20+
function IsTerminated(sender: TRecorder): Boolean;
21+
begin
22+
Result := (not IsProcessRunning(Process)) or (not Target.IsValid());
23+
end;
24+
{$H+}
25+
26+
var
27+
Recorder: TRecorder;
28+
Window: TWindowHandle;
29+
begin
30+
WriteLn('SUBPROCESS');
31+
Process := StrToInt(GetProcessArg('script'));
32+
WriteLn Process;
33+
Window := StrToInt(GetProcessArg('target'));
34+
WriteLn Window;
35+
WriteLn GetProcessArg('plugin');
36+
case GetProcessArg('plugin') of
37+
'remote-input': Target.SetPlugin({$MACRO LOADEDLIB(libremoteinput)}, ToStr(Window.GetPID()));
38+
'wasp-input': Target.SetPlugin({$MACRO LOADEDLIB(waspinput)}, ToStr(Window.GetPID()));
39+
else Target.SetWindow(Window);
40+
end;
41+
42+
Target.GetImage().Save(GetProcessArg('path') + '/img.png');
43+
44+
Recorder := TRecorder.Create(
45+
StrToInt(GetProcessArg('time'), 20), GetProcessArg('path'),
46+
Target.Width, Target.Height,
47+
@GetFrame, @IsTerminated
48+
);
49+
50+
Recorder.SetFFMPEG(SimbaEnv.PluginsPath + 'wasp-plugins' + PATH_SEP + 'librecorder' + PATH_SEP + 'ffmpeg.exe');
51+
52+
try
53+
Recorder.Run(LowerCase(GetProcessArg('debugging')) = 'true');
54+
except
55+
WriteLn GetExceptionMessage();
56+
finally
57+
Recorder.Free();
58+
end;
59+
end;

tools/framerecorder.simba

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ end;
1818
*)
1919

2020
{$DEFINE WL_FRAMERECORDER_INCLUDED}
21-
{$INCLUDE_ONCE WaspLib/utils.simba}
2221

2322
type
2423
(*
@@ -54,7 +53,7 @@ var
5453
selectedDir: String;
5554
imagesDir: String;
5655
begin
57-
if not Target.IsValid then
56+
if not Target.IsValid() then
5857
raise 'No target to screenshot';
5958

6059
Self.FPS := fps;

utils.simba

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
{$IFNDEF WL_WORLDFETCHER_INCLUDED} {$INCLUDE_ONCE WaspLib/utils/worldfetcher.simba}
2929
{$IFNDEF WL_PROFILES_INCLUDED} {$INCLUDE_ONCE utils/profiles.simba}
3030
{$IFNDEF WL_PROFILE_FORM_INCLUDED} {$INCLUDE_ONCE utils/forms/profile_form.simba}
31-
{$IFNDEF WL_RECORDER_INCLUDED} {$INCLUDE_ONCE utils/recorder.simba}
3231
{$IFNDEF WL_SCRIPTFORM_INCLUDED} {$INCLUDE_ONCE utils/forms/scriptform.simba}
3332
{$IFNDEF WL_MODEL_INCLUDED} {$INCLUDE_ONCE utils/math/model.simba}
3433

@@ -37,4 +36,3 @@
3736
{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}
3837
{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}
3938
{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}{$ENDIF}
40-
{$ENDIF}

utils/forms/scriptform.simba

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,6 @@ begin
111111
else
112112
Self.ConfigData.AddInt('goal_level', Self.Goals.Level.Value);
113113
end;
114-
115-
if SimbaRecorder.Enabled then
116-
SimbaRecorder.Start();
117114
end;
118115
{$H+}
119116

0 commit comments

Comments
 (0)