Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
32cee58
[skip ci] update(gen/docs): Remove li's
skuzzis Dec 8, 2025
bd5fcea
update(config/toml): Property Names
skuzzis Dec 8, 2025
29b8ef0
fix(@aim): Check entity is valid
skuzzis Dec 8, 2025
b133a3f
fix - hotReload state on startup (#168)
PlaneJelly Dec 9, 2025
639e872
[skip ci] chore: Fix and update docs generator (#167)
ELDment Dec 9, 2025
897698e
fix(PluginManager): Reload on Linux
skuzzis Dec 9, 2025
205685a
fix(player): GetUnauthorizedSteamID
skuzzis Dec 9, 2025
c3547af
feat(internal): CServerSideClient
skuzzis Dec 10, 2025
db5dd37
fix(menus): No options
skuzzis Dec 10, 2025
6759c1d
fix(player/language): Retrieve in OnClientPutInServer
skuzzis Dec 10, 2025
4e60541
feat(managed): Add schema class fixed array
samyycX Dec 11, 2025
48bc002
feat: Write minidump file and JSON technical report on crash (#162)
ELDment Dec 11, 2025
d5f9776
chore: restore
samyycX Dec 11, 2025
6248ada
fix: Dictionary, List merged the default values and wrongly used the …
K4ryuu Dec 12, 2025
8c4ff10
fix(player): IsFakeClient check
skuzzis Dec 13, 2025
1f0e7e4
update(config/toml): IgnoreMissingProperties
skuzzis Dec 13, 2025
97e2212
feat(tracer): Add managed tracer
samyycX Dec 13, 2025
733660a
fix(player): Client Authorize on map change
skuzzis Dec 13, 2025
c3aa663
fix(fix(player)): move again authorized
skuzzis Dec 13, 2025
8834179
fix(config): Add overwrite parameter to File.Copy in InitializeWithTe…
BenGorrr Dec 13, 2025
9b3efe9
add(CBaseModelEntity): SetScaleAsync
skuzzis Dec 13, 2025
5c91bc8
fix(managed): Fix exception handler output
samyycX Dec 14, 2025
71f0113
fix(managed): Make menu callbacks safer
samyycX Dec 14, 2025
ca257a1
fix(managed): Fix TraceShape and do some cleanup
samyycX Dec 14, 2025
bf180ec
fix(crashhandler): Try fix linux backtrace
samyycX Dec 14, 2025
4866c52
Merge branch 'feat/crash_handling' into beta
samyycX Dec 14, 2025
6c58820
refactor: Redesign database configuration logic (#174)
ELDment Dec 14, 2025
cfc10d6
feat(menus): Hide title item count
skuzzis Dec 14, 2025
5d6b480
feat(managed): Make function call safer
samyycX Dec 14, 2025
a405da1
fix(managed): Fix order
samyycX Dec 14, 2025
dbc6a6e
fix(managed): Show all warnings
samyycX Dec 14, 2025
2623428
feat(managed): Update tracer
samyycX Dec 14, 2025
a972f8e
fix(database): change stoi
skuzzis Dec 14, 2025
47cf1d8
fix(database): Make port optional
skuzzis Dec 14, 2025
fd4dfae
fix: Correct regular expression (#175)
ELDment Dec 14, 2025
1cde27d
fix(managed): Remove SQLitePCL
skuzzis Dec 14, 2025
1d4d6c1
feat: Add `OptionHovered` and `OptionSelected` events (#177)
ELDment Dec 15, 2025
c3f6d02
feat(core.jsonc): EnableProfiler
skuzzis Dec 16, 2025
8a57524
Merge branch 'beta' of https://github.com/swiftly-solution/swiftlys2 …
skuzzis Dec 16, 2025
4b9235c
update(commands): Execute after message in chat
skuzzis Dec 16, 2025
d604700
revert(ClientConnect): Authorized Double call
skuzzis Dec 16, 2025
b0f9540
fix(concommand): No more commands after dispatch
skuzzis Dec 16, 2025
3dcd3ed
update(schema): Resolving some types
skuzzis Dec 17, 2025
60f90e2
feat(ConVar): Name
skuzzis Dec 17, 2025
89ece49
feat: Add more methods to control plugin auto reload. (#180)
chenbuyi2019 Dec 17, 2025
4d604fe
feat: Add CBaseEntity:TakeDamage (#182) (#183)
samyycX Dec 19, 2025
e0d3994
More player getters (#187)
samyycX Dec 19, 2025
7745ef7
feat: Add `Clear` method to clear all fields of a protobuf message (#…
ELDment Dec 20, 2025
9a6c7bd
chore: Ensure generated code conforms to unified coding standards and…
ELDment Dec 20, 2025
bdd9962
feat(convars): Help Text
skuzzis Dec 20, 2025
d343629
feat: Add `Clear` method to `IProtobufRepeatedFieldSubMessageType` (#…
ELDment Dec 20, 2025
f0f893a
Entity Output Rework (#192)
samyycX Dec 20, 2025
71abb1f
fix(core): Fix OnTick compatibility
samyycX Dec 20, 2025
9259657
fix(managed): Clean code
samyycX Dec 20, 2025
15f493b
feat(core): Remove prefix on SendConsole and fuck c#
samyycX Dec 20, 2025
2ef851a
[skip ci] update(LICENSE): Copyright Year
skuzzis Dec 20, 2025
4b8d0d2
[skip ci] update(LICENSE): fuck you spacebar
skuzzis Dec 20, 2025
569a091
feat: Resupport `UnhookEntityOutput` and implement `HookEntityInput` …
ELDment Dec 21, 2025
4cc2240
fix(managed): Fix TraceShape
samyycX Dec 21, 2025
a885f8c
fix(managed): Fix variant type
samyycX Dec 22, 2025
6c245f5
refactor(managed): Refactor timer to fix the accuracy (#198)
samyycX Dec 23, 2025
34898eb
Fix - Menu option "No options" not deleting (#197)
PlaneJelly Dec 23, 2025
64d1610
chore(managed): Improve thread check
samyycX Dec 23, 2025
a6021b6
feat(managed): Improve player teleport
samyycX Dec 23, 2025
f67dc39
Fix: mid-hook dispose (#199)
chenbuyi2019 Dec 24, 2025
d197f7e
Feat: Add `Equals`,`GetHashCode`, `ToString` For `CEntityInstanceImpl…
chenbuyi2019 Dec 24, 2025
ea992f1
fix(managed): Implement interface
samyycX Dec 24, 2025
9e01abe
feat: Add equality operators and `Invalid` shortcut constructor for C…
ELDment Dec 24, 2025
cf9e434
fix(entitysystem): Enhance safety when accessing entity system
samyycX Dec 25, 2025
672dbee
fix: `CVariant` parameterless construction (#202)
ELDment Dec 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
26 changes: 24 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
- name: Install dependencies
run: |
apt-get update
apt install libreadline-dev
apt install -y libreadline-dev
- name: Checkout repository and submodules
uses: actions/checkout@v4
with:
Expand All @@ -88,6 +88,11 @@ jobs:
with:
name: swiftlys2_linux
path: build/package/addons
- name: Upload tracer as artifact
uses: actions/upload-artifact@v4
with:
name: swiftlys2_linux_tracer
path: tracer/libsw2tracer.so

windows_core:
needs: versioning
Expand Down Expand Up @@ -118,6 +123,11 @@ jobs:
with:
name: swiftlys2_windows_pdb
path: build/windows/x64/release/swiftlys2.pdb
- name: Upload tracer as artifact
uses: actions/upload-artifact@v4
with:
name: swiftlys2_windows_tracer
path: tracer/sw2tracer.dll

linux_loader:
needs: versioning
Expand Down Expand Up @@ -221,7 +231,16 @@ jobs:
with:
name: swiftlys2_loader_windows_pdb
path: ./server.pdb

- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: swiftlys2_linux_tracer
path: ./libsw2tracer.so
- name: Download artifacts
uses: actions/download-artifact@v4
with:
name: swiftlys2_windows_tracer
path: ./sw2tracer.dll
- name: Download artifacts
uses: actions/download-artifact@v4
with:
Expand Down Expand Up @@ -253,6 +272,9 @@ jobs:
cp -r ./swiftlys2.pdb/swiftlys2.pdb ${{ env.WINDOWS_FOLDER }}/swiftlys2/bin/win64/
cp -r ./server.pdb/server.pdb ${{ env.WINDOWS_FOLDER }}/swiftlys2/bin/win64/

cp -r ./libsw2tracer.so/libsw2tracer.so ${{ env.LINUX_FOLDER }}/swiftlys2/bin/linuxsteamrt64/libsw2tracer.so
cp -r ./sw2tracer.dll/sw2tracer.dll ${{ env.WINDOWS_FOLDER }}/swiftlys2/bin/win64/sw2tracer.dll

mkdir -p ${{ env.LINUX_FOLDER }}/swiftlys2/plugins/
mkdir -p ${{ env.LINUX_FOLDER }}/swiftlys2/plugins/disabled
mkdir -p ${{ env.WINDOWS_FOLDER }}/swiftlys2/plugins/
Expand Down
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@
path = vendor/s2sdk
url = https://github.com/swiftly-solution/s2sdk
branch = cs2
[submodule "vendor/breakpad"]
path = vendor/breakpad
url = https://github.com/google/breakpad
[submodule "vendor/third_party/lss"]
path = vendor/third_party/lss
url = https://chromium.googlesource.com/linux-syscall-support
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,7 @@ state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

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

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

SwiftlyS2 Copyright (C) 2025 Swiftly Solution SRL via Sava Andrei-Sebastian
SwiftlyS2 Copyright (C) 2023-2026 Swiftly Solution SRL via Sava Andrei-Sebastian
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
Expand Down
13 changes: 12 additions & 1 deletion LICENSE.MIT
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
SwiftlyS2 is licensed under the GNU General Public License, version 3.

As a special exception to the GNU General Public License 3.0, the license
holder permits licensing of DERIVATIVE WORKS ONLY (that is, SwiftlyS2
plugins, or any software built referencing published .NET packages)
under the MIT license.

The licensed is reproduced below.

----------------------------------------------------------------------------------------------

MIT License

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

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
160 changes: 131 additions & 29 deletions generator/docs_generator/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,108 @@ def escape_generics(text):


def fix_html_for_jsx(text):
"""Fix HTML attributes for JSX compatibility."""
"""Convert HTML to Markdown for MDX compatibility."""
if not text:
return text
# Replace class= with className=
return text.replace('class=', 'className=')

# Convert pre/code blocks to markdown code fences first
def convert_code_block(match):
lang = ''
lang_match = re.search(r'class(?:Name)?="lang-(\w+)"', match.group(0))
if lang_match:
lang = lang_match.group(1)
code_match = re.search(r'<code[^>]*>(.*?)</code>', match.group(0), re.DOTALL)
if code_match:
content = code_match.group(1)
content = content.replace('&gt;', '>').replace('&lt;', '<').replace('&amp;', '&')
return f'\n\n```{lang}\n{content}\n```\n\n'
return match.group(0)
text = re.sub(r'<pre><code[^>]*>.*?</code></pre>', convert_code_block, text, flags=re.DOTALL)

# Convert inline code tags to backticks
text = re.sub(r'<code>(.*?)</code>', r'`\1`', text)

# Remove XML doc tags like <param>, <returns>, <typeparam>, etc.
text = re.sub(r'<param\s+name="([^"]+)">(.*?)</param>', r'- `\1`: \2', text)
text = re.sub(r'<typeparam\s+name="([^"]+)">(.*?)</typeparam>', r'- `\1`: \2', text)
text = re.sub(r'<returns>(.*?)</returns>', r'Returns: \1', text)
text = re.sub(r'<see\s+cref="([^"]+)"\s*/>', r'`\1`', text)
text = re.sub(r'<seealso\s+cref="([^"]+)"\s*/>', r'`\1`', text)

# Fix HTML entities
text = text.replace('&gt;', '>').replace('&lt;', '<').replace('&amp;', '&')

# Convert HTML lists to Markdown lists
if '<ul>' in text or '<li>' in text:
# Process nested lists
def convert_list(html):
result = []
depth = 0
parts = re.split(r'(</?(?:ul|li)>)', html)
current = ''
for part in parts:
if part == '<ul>':
depth += 1
elif part == '</ul>':
depth = max(0, depth - 1)
elif part == '<li>':
current = ''
elif part == '</li>':
if current.strip():
indent = ' ' * max(0, depth - 1)
result.append(f'{indent}- {current.strip()}')
current = ''
else:
current += part
return '\n'.join(result)
text = convert_list(text)

# Convert p tags to paragraphs
def convert_p(match):
content = match.group(1)
# Don't collapse if contains code block
if '```' in content:
return f'{content.strip()}\n\n'
# Collapse whitespace for regular text
content = ' '.join(content.split())
return f'{content}\n\n'
text = re.sub(r'<p>\s*(.*?)\s*</p>', convert_p, text, flags=re.DOTALL)

# Clean up extra newlines
text = re.sub(r'\n{3,}', '\n\n', text)

return text.strip()


def convert_xref_tags(text):
"""Convert DocFX <xref> tags to plain text or links."""
if not text:
return text

import urllib.parse

def replace_xref(match):
href = match.group(1)
# Parse the href to extract type and text
if '?' in href:
type_name, query = href.split('?', 1)
params = urllib.parse.parse_qs(query)
display_text = params.get('text', [type_name])[0]
display_text = urllib.parse.unquote_plus(display_text)
else:
type_name = href
display_text = type_name

# Create link for System types to Microsoft docs
if type_name.startswith('System.'):
url = f"https://learn.microsoft.com/dotnet/api/{type_name.lower()}"
return f"[{display_text}]({url})"

return display_text

# Match <xref href="..." ...></xref> or <xref href="..." ... />
pattern = r'<xref\s+href="([^"]+)"[^>]*(?:></xref>|/>)'
return re.sub(pattern, replace_xref, text)


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

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

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

if 'h4' in item:
h4_text = item['h4']
if h4_text in ['Parameters', 'Returns', 'Field Value', 'Property Value']:
if h4_text in ['Parameters', 'Returns', 'Field Value', 'Property Value', 'Type Parameters', 'Exceptions', 'Remarks', 'Event Type']:
md += f"<ApiLabel>{h4_text}</ApiLabel>\n\n"
else:
md += f"#### {h4_text}\n\n"
Expand Down Expand Up @@ -229,7 +326,8 @@ def generate_markdown(yaml_data):
if 'api3' in item:
src = item.get('src', '')
api3_title = str(item.get('api3', ''))
api3_title = re.sub(r'<[^>]+>', '', api3_title)
# Escape generics for markdown heading (use backslash)
api3_title = api3_title.replace('<', '\\<').replace('>', '\\>')
api3_title = re.sub(r'\[[^\]]+\]', '', api3_title)
md += f"### {api3_title}\n\n"
if src != '':
Expand Down Expand Up @@ -272,31 +370,35 @@ def convert_yaml_file(src_path, dest_path):
os.makedirs(folder_path, exist_ok=True)

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

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


for root, dirs, files in os.walk(SOURCE_DIR):
for file in files:
if file.endswith(".yml") or file.endswith(".yaml"):
raw_base = os.path.splitext(file)[0]
for prefix in ["SwiftlyS2.Core.", "SwiftlyS2.Shared.", "SwiftlyS2."]:
if raw_base.startswith(prefix):
raw_base = raw_base[len(prefix):]
break
new_base = transform_filename(raw_base)
dest_file = os.path.join(DEST_DIR, "/".join(new_base.split(".")).lower() + ".mdx")
convert_yaml_file(os.path.join(root, file), dest_file)

script_dir = os.path.dirname(os.path.abspath(__file__))
index_source = os.path.join(script_dir, "index.mdx")
index_dest = os.path.join(DEST_DIR, "index.mdx")

if os.path.exists(index_source):
shutil.copy2(index_source, index_dest)
print(f"Copied index.mdx to {index_dest}")
else:
print(f"Warning: index.mdx not found at {index_source}")

print("MDX generation complete!")
if __name__ == "__main__":
for root, dirs, files in os.walk(SOURCE_DIR):
for file in files:
if file.endswith(".yml") or file.endswith(".yaml"):
raw_base = os.path.splitext(file)[0]
for prefix in ["SwiftlyS2.Core.", "SwiftlyS2.Shared.", "SwiftlyS2."]:
if raw_base.startswith(prefix):
raw_base = raw_base[len(prefix):]
break
new_base = transform_filename(raw_base)
dest_file = os.path.join(DEST_DIR, "/".join(new_base.split(".")).lower() + ".mdx")
convert_yaml_file(os.path.join(root, file), dest_file)

script_dir = os.path.dirname(os.path.abspath(__file__))
index_source = os.path.join(script_dir, "index.mdx")
index_dest = os.path.join(DEST_DIR, "index.mdx")

if os.path.exists(index_source):
shutil.copy2(index_source, index_dest)
print(f"Copied index.mdx to {index_dest}")
else:
print(f"Warning: index.mdx not found at {index_source}")

print("MDX generation complete!")
3 changes: 1 addition & 2 deletions generator/native_generator/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ def parse_native(lines: list[str]):
writer.add_line()

def write_class_content():
writer.add_line("private static int _MainThreadID;")

for raw_line in native_lines:
if raw_line.strip() == "":
Expand Down Expand Up @@ -156,7 +155,7 @@ def write_class_content():

def write_method_content():
if is_marked_sync:
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.");'))
writer.add_block("if (!NativeBinding.IsMainThread)", lambda: writer.add_line('throw new InvalidOperationException("This method can only be called from the main thread.");'))

string_params = []
bytes_params = []
Expand Down
Loading
Loading