Skip to content

Commit 95d88dc

Browse files
skuzzisPlaneJellyELDmentsamyycXK4ryuu
authored
Release v1.1.0 +semver: minor (#201)
Co-authored-by: PlaneJelly <116096829+PlaneJelly@users.noreply.github.com> Co-authored-by: 菠蘿包 <79680886+ELDment@users.noreply.github.com> Co-authored-by: samyyc <s1myyc@outlook.com> Co-authored-by: samyyc <60744529+samyycX@users.noreply.github.com> Co-authored-by: K4ryuu <104531589+K4ryuu@users.noreply.github.com> Co-authored-by: Bennie <68955649+BenGorrr@users.noreply.github.com> Co-authored-by: Chen Buyi <chenbuyi2019@outlook.com> Co-authored-by: chenbuyi2019 <chenbuyi2019@users.noreply.github.com> Co-authored-by: samyyc <samyyc@member.fsf.org>
1 parent 7dec68a commit 95d88dc

5,256 files changed

Lines changed: 142255 additions & 171202 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/build.yml

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ jobs:
6464
- name: Install dependencies
6565
run: |
6666
apt-get update
67-
apt install libreadline-dev
67+
apt install -y libreadline-dev
6868
- name: Checkout repository and submodules
6969
uses: actions/checkout@v4
7070
with:
@@ -88,6 +88,11 @@ jobs:
8888
with:
8989
name: swiftlys2_linux
9090
path: build/package/addons
91+
- name: Upload tracer as artifact
92+
uses: actions/upload-artifact@v4
93+
with:
94+
name: swiftlys2_linux_tracer
95+
path: tracer/libsw2tracer.so
9196

9297
windows_core:
9398
needs: versioning
@@ -118,6 +123,11 @@ jobs:
118123
with:
119124
name: swiftlys2_windows_pdb
120125
path: build/windows/x64/release/swiftlys2.pdb
126+
- name: Upload tracer as artifact
127+
uses: actions/upload-artifact@v4
128+
with:
129+
name: swiftlys2_windows_tracer
130+
path: tracer/sw2tracer.dll
121131

122132
linux_loader:
123133
needs: versioning
@@ -221,7 +231,16 @@ jobs:
221231
with:
222232
name: swiftlys2_loader_windows_pdb
223233
path: ./server.pdb
224-
234+
- name: Download artifacts
235+
uses: actions/download-artifact@v4
236+
with:
237+
name: swiftlys2_linux_tracer
238+
path: ./libsw2tracer.so
239+
- name: Download artifacts
240+
uses: actions/download-artifact@v4
241+
with:
242+
name: swiftlys2_windows_tracer
243+
path: ./sw2tracer.dll
225244
- name: Download artifacts
226245
uses: actions/download-artifact@v4
227246
with:
@@ -253,6 +272,9 @@ jobs:
253272
cp -r ./swiftlys2.pdb/swiftlys2.pdb ${{ env.WINDOWS_FOLDER }}/swiftlys2/bin/win64/
254273
cp -r ./server.pdb/server.pdb ${{ env.WINDOWS_FOLDER }}/swiftlys2/bin/win64/
255274
275+
cp -r ./libsw2tracer.so/libsw2tracer.so ${{ env.LINUX_FOLDER }}/swiftlys2/bin/linuxsteamrt64/libsw2tracer.so
276+
cp -r ./sw2tracer.dll/sw2tracer.dll ${{ env.WINDOWS_FOLDER }}/swiftlys2/bin/win64/sw2tracer.dll
277+
256278
mkdir -p ${{ env.LINUX_FOLDER }}/swiftlys2/plugins/
257279
mkdir -p ${{ env.LINUX_FOLDER }}/swiftlys2/plugins/disabled
258280
mkdir -p ${{ env.WINDOWS_FOLDER }}/swiftlys2/plugins/

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@
55
path = vendor/s2sdk
66
url = https://github.com/swiftly-solution/s2sdk
77
branch = cs2
8+
[submodule "vendor/breakpad"]
9+
path = vendor/breakpad
10+
url = https://github.com/google/breakpad
11+
[submodule "vendor/third_party/lss"]
12+
path = vendor/third_party/lss
13+
url = https://chromium.googlesource.com/linux-syscall-support

LICENSE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,7 @@ state the exclusion of warranty; and each file should have at least
643643
the "copyright" line and a pointer to where the full notice is found.
644644

645645
SwiftlyS2 is a scripting framework for Source2-based games.
646-
Copyright (C) 2025 Swiftly Solution SRL via Sava Andrei-Sebastian and it's contributors
646+
Copyright (C) 2023-2026 Swiftly Solution SRL via Sava Andrei-Sebastian and it's contributors
647647

648648
This program is free software: you can redistribute it and/or modify
649649
it under the terms of the GNU General Public License as published by
@@ -663,7 +663,7 @@ Also add information on how to contact you by electronic and paper mail.
663663
If the program does terminal interaction, make it output a short
664664
notice like this when it starts in an interactive mode:
665665

666-
SwiftlyS2 Copyright (C) 2025 Swiftly Solution SRL via Sava Andrei-Sebastian
666+
SwiftlyS2 Copyright (C) 2023-2026 Swiftly Solution SRL via Sava Andrei-Sebastian
667667
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
668668
This is free software, and you are welcome to redistribute it
669669
under certain conditions; type `show c' for details.

LICENSE.MIT

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
1+
SwiftlyS2 is licensed under the GNU General Public License, version 3.
2+
3+
As a special exception to the GNU General Public License 3.0, the license
4+
holder permits licensing of DERIVATIVE WORKS ONLY (that is, SwiftlyS2
5+
plugins, or any software built referencing published .NET packages)
6+
under the MIT license.
7+
8+
The licensed is reproduced below.
9+
10+
----------------------------------------------------------------------------------------------
11+
112
MIT License
213

3-
Copyright (c) 2025 Swiftly Solution SRL via Sava Andrei-Sebastian and it's contributors
14+
Copyright (c) 2023-2026 Swiftly Solution SRL via Sava Andrei-Sebastian and it's contributors
415

516
Permission is hereby granted, free of charge, to any person obtaining a copy
617
of this software and associated documentation files (the "Software"), to deal

generator/docs_generator/generator.py

Lines changed: 131 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,108 @@ def escape_generics(text):
1919

2020

2121
def fix_html_for_jsx(text):
22-
"""Fix HTML attributes for JSX compatibility."""
22+
"""Convert HTML to Markdown for MDX compatibility."""
2323
if not text:
2424
return text
25-
# Replace class= with className=
26-
return text.replace('class=', 'className=')
25+
26+
# Convert pre/code blocks to markdown code fences first
27+
def convert_code_block(match):
28+
lang = ''
29+
lang_match = re.search(r'class(?:Name)?="lang-(\w+)"', match.group(0))
30+
if lang_match:
31+
lang = lang_match.group(1)
32+
code_match = re.search(r'<code[^>]*>(.*?)</code>', match.group(0), re.DOTALL)
33+
if code_match:
34+
content = code_match.group(1)
35+
content = content.replace('&gt;', '>').replace('&lt;', '<').replace('&amp;', '&')
36+
return f'\n\n```{lang}\n{content}\n```\n\n'
37+
return match.group(0)
38+
text = re.sub(r'<pre><code[^>]*>.*?</code></pre>', convert_code_block, text, flags=re.DOTALL)
39+
40+
# Convert inline code tags to backticks
41+
text = re.sub(r'<code>(.*?)</code>', r'`\1`', text)
42+
43+
# Remove XML doc tags like <param>, <returns>, <typeparam>, etc.
44+
text = re.sub(r'<param\s+name="([^"]+)">(.*?)</param>', r'- `\1`: \2', text)
45+
text = re.sub(r'<typeparam\s+name="([^"]+)">(.*?)</typeparam>', r'- `\1`: \2', text)
46+
text = re.sub(r'<returns>(.*?)</returns>', r'Returns: \1', text)
47+
text = re.sub(r'<see\s+cref="([^"]+)"\s*/>', r'`\1`', text)
48+
text = re.sub(r'<seealso\s+cref="([^"]+)"\s*/>', r'`\1`', text)
49+
50+
# Fix HTML entities
51+
text = text.replace('&gt;', '>').replace('&lt;', '<').replace('&amp;', '&')
52+
53+
# Convert HTML lists to Markdown lists
54+
if '<ul>' in text or '<li>' in text:
55+
# Process nested lists
56+
def convert_list(html):
57+
result = []
58+
depth = 0
59+
parts = re.split(r'(</?(?:ul|li)>)', html)
60+
current = ''
61+
for part in parts:
62+
if part == '<ul>':
63+
depth += 1
64+
elif part == '</ul>':
65+
depth = max(0, depth - 1)
66+
elif part == '<li>':
67+
current = ''
68+
elif part == '</li>':
69+
if current.strip():
70+
indent = ' ' * max(0, depth - 1)
71+
result.append(f'{indent}- {current.strip()}')
72+
current = ''
73+
else:
74+
current += part
75+
return '\n'.join(result)
76+
text = convert_list(text)
77+
78+
# Convert p tags to paragraphs
79+
def convert_p(match):
80+
content = match.group(1)
81+
# Don't collapse if contains code block
82+
if '```' in content:
83+
return f'{content.strip()}\n\n'
84+
# Collapse whitespace for regular text
85+
content = ' '.join(content.split())
86+
return f'{content}\n\n'
87+
text = re.sub(r'<p>\s*(.*?)\s*</p>', convert_p, text, flags=re.DOTALL)
88+
89+
# Clean up extra newlines
90+
text = re.sub(r'\n{3,}', '\n\n', text)
91+
92+
return text.strip()
93+
94+
95+
def convert_xref_tags(text):
96+
"""Convert DocFX <xref> tags to plain text or links."""
97+
if not text:
98+
return text
99+
100+
import urllib.parse
101+
102+
def replace_xref(match):
103+
href = match.group(1)
104+
# Parse the href to extract type and text
105+
if '?' in href:
106+
type_name, query = href.split('?', 1)
107+
params = urllib.parse.parse_qs(query)
108+
display_text = params.get('text', [type_name])[0]
109+
display_text = urllib.parse.unquote_plus(display_text)
110+
else:
111+
type_name = href
112+
display_text = type_name
113+
114+
# Create link for System types to Microsoft docs
115+
if type_name.startswith('System.'):
116+
url = f"https://learn.microsoft.com/dotnet/api/{type_name.lower()}"
117+
return f"[{display_text}]({url})"
118+
119+
return display_text
120+
121+
# Match <xref href="..." ...></xref> or <xref href="..." ... />
122+
pattern = r'<xref\s+href="([^"]+)"[^>]*(?:></xref>|/>)'
123+
return re.sub(pattern, replace_xref, text)
27124

28125

29126
def escape_generics_in_link_text(text):
@@ -155,14 +252,14 @@ def generate_markdown(yaml_data):
155252
md += f"**{fact_name}**: {fact_value}\n\n"
156253

157254
if 'markdown' in item:
158-
md += f"{item['markdown']}\n\n"
255+
md += f"{fix_html_for_jsx(item['markdown'])}\n\n"
159256

160257
if 'h2' in item:
161258
md += f"## {item['h2']}\n\n"
162259

163260
if 'h4' in item:
164261
h4_text = item['h4']
165-
if h4_text in ['Parameters', 'Returns', 'Field Value', 'Property Value']:
262+
if h4_text in ['Parameters', 'Returns', 'Field Value', 'Property Value', 'Type Parameters', 'Exceptions', 'Remarks', 'Event Type']:
166263
md += f"<ApiLabel>{h4_text}</ApiLabel>\n\n"
167264
else:
168265
md += f"#### {h4_text}\n\n"
@@ -229,7 +326,8 @@ def generate_markdown(yaml_data):
229326
if 'api3' in item:
230327
src = item.get('src', '')
231328
api3_title = str(item.get('api3', ''))
232-
api3_title = re.sub(r'<[^>]+>', '', api3_title)
329+
# Escape generics for markdown heading (use backslash)
330+
api3_title = api3_title.replace('<', '\\<').replace('>', '\\>')
233331
api3_title = re.sub(r'\[[^\]]+\]', '', api3_title)
234332
md += f"### {api3_title}\n\n"
235333
if src != '':
@@ -272,31 +370,35 @@ def convert_yaml_file(src_path, dest_path):
272370
os.makedirs(folder_path, exist_ok=True)
273371

274372
md_content = md_content.replace('/api/shared', '/api').replace('/api/core', '/api')
373+
md_content = convert_xref_tags(md_content)
374+
# Escape < followed by numbers (like <1000) which MDX interprets as JSX tags
375+
md_content = re.sub(r'<(\d)', r'\\<\1', md_content)
275376

276377
with open(final_path, 'w', encoding='utf-8') as f:
277378
f.write(md_content)
278379

279380

280-
for root, dirs, files in os.walk(SOURCE_DIR):
281-
for file in files:
282-
if file.endswith(".yml") or file.endswith(".yaml"):
283-
raw_base = os.path.splitext(file)[0]
284-
for prefix in ["SwiftlyS2.Core.", "SwiftlyS2.Shared.", "SwiftlyS2."]:
285-
if raw_base.startswith(prefix):
286-
raw_base = raw_base[len(prefix):]
287-
break
288-
new_base = transform_filename(raw_base)
289-
dest_file = os.path.join(DEST_DIR, "/".join(new_base.split(".")).lower() + ".mdx")
290-
convert_yaml_file(os.path.join(root, file), dest_file)
291-
292-
script_dir = os.path.dirname(os.path.abspath(__file__))
293-
index_source = os.path.join(script_dir, "index.mdx")
294-
index_dest = os.path.join(DEST_DIR, "index.mdx")
295-
296-
if os.path.exists(index_source):
297-
shutil.copy2(index_source, index_dest)
298-
print(f"Copied index.mdx to {index_dest}")
299-
else:
300-
print(f"Warning: index.mdx not found at {index_source}")
301-
302-
print("MDX generation complete!")
381+
if __name__ == "__main__":
382+
for root, dirs, files in os.walk(SOURCE_DIR):
383+
for file in files:
384+
if file.endswith(".yml") or file.endswith(".yaml"):
385+
raw_base = os.path.splitext(file)[0]
386+
for prefix in ["SwiftlyS2.Core.", "SwiftlyS2.Shared.", "SwiftlyS2."]:
387+
if raw_base.startswith(prefix):
388+
raw_base = raw_base[len(prefix):]
389+
break
390+
new_base = transform_filename(raw_base)
391+
dest_file = os.path.join(DEST_DIR, "/".join(new_base.split(".")).lower() + ".mdx")
392+
convert_yaml_file(os.path.join(root, file), dest_file)
393+
394+
script_dir = os.path.dirname(os.path.abspath(__file__))
395+
index_source = os.path.join(script_dir, "index.mdx")
396+
index_dest = os.path.join(DEST_DIR, "index.mdx")
397+
398+
if os.path.exists(index_source):
399+
shutil.copy2(index_source, index_dest)
400+
print(f"Copied index.mdx to {index_dest}")
401+
else:
402+
print(f"Warning: index.mdx not found at {index_source}")
403+
404+
print("MDX generation complete!")

generator/native_generator/main.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ def parse_native(lines: list[str]):
103103
writer.add_line()
104104

105105
def write_class_content():
106-
writer.add_line("private static int _MainThreadID;")
107106

108107
for raw_line in native_lines:
109108
if raw_line.strip() == "":
@@ -156,7 +155,7 @@ def write_class_content():
156155

157156
def write_method_content():
158157
if is_marked_sync:
159-
writer.add_block("if (Thread.CurrentThread.ManagedThreadId != _MainThreadID)", lambda: writer.add_line('throw new InvalidOperationException("This method can only be called from the main thread.");'))
158+
writer.add_block("if (!NativeBinding.IsMainThread)", lambda: writer.add_line('throw new InvalidOperationException("This method can only be called from the main thread.");'))
160159

161160
string_params = []
162161
bytes_params = []

0 commit comments

Comments
 (0)