mirror of
https://github.com/tilgep/stripper.git
synced 2025-12-06 18:08:24 +00:00
Merge 3b7f563bd2 into 42f3ed9b31
This commit is contained in:
commit
28f7176c2a
6
.github/dependabot.yml
vendored
Normal file
6
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
89
.github/workflows/ci.yml
vendored
Normal file
89
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
name: CI
|
||||
|
||||
on: [push, pull_request, workflow_dispatch]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: "Build"
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-24.04]
|
||||
include:
|
||||
- os: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Build sourcemod plugin
|
||||
uses: maxime1907/action-sourceknight@v1
|
||||
with:
|
||||
cmd: build
|
||||
|
||||
- name: Create package
|
||||
run: |
|
||||
mkdir -p /tmp/package
|
||||
cp -R .sourceknight/package/* /tmp/package
|
||||
cp -R addons/sourcemod/configs /tmp/package/common/addons/sourcemod/
|
||||
|
||||
- name: Upload build archive for test runners
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ runner.os }}
|
||||
path: /tmp/package
|
||||
|
||||
tag:
|
||||
name: Tag
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main'
|
||||
|
||||
- uses: dev-drprasad/delete-tag-and-release@v0.2.1
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main'
|
||||
with:
|
||||
delete_release: true
|
||||
tag_name: latest
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- uses: rickstaa/action-create-tag@v1
|
||||
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main'
|
||||
with:
|
||||
tag: "latest"
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
release:
|
||||
name: Release
|
||||
if: startsWith(github.ref, 'refs/tags/') || github.ref == 'refs/heads/master' || github.ref == 'refs/heads/main'
|
||||
needs: [build, tag]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: Versioning
|
||||
run: |
|
||||
version="latest"
|
||||
if [[ "${{ github.ref_type }}" == 'tag' ]]; then
|
||||
version=`echo $GITHUB_REF | sed "s/refs\/tags\///"`;
|
||||
fi
|
||||
echo "RELEASE_VERSION=$version" >> $GITHUB_ENV
|
||||
|
||||
- name: Package
|
||||
run: |
|
||||
ls -Rall
|
||||
if [ -d "./Linux/" ]; then
|
||||
cd ./Linux/
|
||||
tar -czf ../${{ github.event.repository.name }}-${{ env.RELEASE_VERSION }}.tar.gz -T <(\ls -1)
|
||||
cd -
|
||||
fi
|
||||
|
||||
- name: Release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: '*.tar.gz'
|
||||
tag: ${{ env.RELEASE_VERSION }}
|
||||
file_glob: true
|
||||
overwrite: true
|
||||
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
build/
|
||||
release/
|
||||
|
||||
.DS_Store
|
||||
.vscode
|
||||
|
||||
*.smx
|
||||
plugins/
|
||||
.sourceknight
|
||||
.venv
|
||||
86
addons/sourcemod/configs/stripper/global_filters.cfg
Normal file
86
addons/sourcemod/configs/stripper/global_filters.cfg
Normal file
@ -0,0 +1,86 @@
|
||||
;; Changes ammo to 8000 on every map-spawned weapon
|
||||
;modify:
|
||||
;{
|
||||
; match:
|
||||
; {
|
||||
; "classname" "/weapon_.*/"
|
||||
; }
|
||||
; replace:
|
||||
; {
|
||||
; "ammo" "8000"
|
||||
; }
|
||||
;}
|
||||
|
||||
;; Remove game_end
|
||||
;filter:
|
||||
;{
|
||||
; "classname" "game_end"
|
||||
;}
|
||||
|
||||
;;Cool Music Entities
|
||||
;add:
|
||||
;{
|
||||
; "origin" "0 0 0"
|
||||
; "targetname" "GlobalAmbientGenericStripper"
|
||||
; "spawnflags" "49"
|
||||
; "radius" "1250"
|
||||
; "pitchstart" "100"
|
||||
; "pitch" "100"
|
||||
; "message" "music/hl1_song10.mp3"
|
||||
; "health" "10"
|
||||
; "classname" "ambient_generic"
|
||||
;}
|
||||
|
||||
;add:
|
||||
;{
|
||||
; "origin" "0 0 0"
|
||||
; "targetname" "GlobalAmbientGenericStripper2"
|
||||
; "spawnflags" "49"
|
||||
; "radius" "1250"
|
||||
; "pitchstart" "100"
|
||||
; "pitch" "100"
|
||||
; "message" "music/hl2_song23_suitsong3.mp3"
|
||||
; "health" "10"
|
||||
; "classname" "ambient_generic"
|
||||
;}
|
||||
|
||||
;add:
|
||||
;{
|
||||
; "origin" "0 0 0"
|
||||
; "targetname" "GlobalAmbientGenericStripper2"
|
||||
; "spawnflags" "49"
|
||||
; "radius" "1250"
|
||||
; "pitchstart" "100"
|
||||
; "pitch" "100"
|
||||
; "message" "music/hl2_song23_suitsong3.mp3"
|
||||
; "health" "10"
|
||||
; "classname" "ambient_generic"
|
||||
;}
|
||||
|
||||
;add:
|
||||
;{
|
||||
; "origin" "0 0 0"
|
||||
; "targetname" "GlobalLogicTimerStripper"
|
||||
; "RefireTime" "0.1"
|
||||
; "spawnflags" "0"
|
||||
; "StartDisabled" "1"
|
||||
; "UseRandomTime" "0"
|
||||
; "classname" "logic_timer"
|
||||
;}
|
||||
|
||||
;add:
|
||||
;{
|
||||
; "origin" "0 0 0"
|
||||
; "targetname" "GlobalGameTextStripper"
|
||||
; "x" "-1"
|
||||
; "y" ".20"
|
||||
; "channel" "4"
|
||||
; "message" "Default Message"
|
||||
; "color" "0 255 255"
|
||||
; "color2" "0 240 240"
|
||||
; "fadein" ".1"
|
||||
; "fadeout" ".1"
|
||||
; "holdtime" "3"
|
||||
; "spawnflags" "1"
|
||||
; "classname" "game_text"
|
||||
;}
|
||||
35
addons/sourcemod/configs/stripper/maps/example_map.cfg
Normal file
35
addons/sourcemod/configs/stripper/maps/example_map.cfg
Normal file
@ -0,0 +1,35 @@
|
||||
;;EXAMPLE - remove all physics props
|
||||
;remove:
|
||||
;{
|
||||
; "classname" "/prop_physics.*/"
|
||||
;}
|
||||
|
||||
;;EXAMPLE - add the hostage to the map
|
||||
;add:
|
||||
;{
|
||||
; "origin" "1376 3168 -112"
|
||||
; "HostageType" "0"
|
||||
; "classname" "hostage_entity"
|
||||
}
|
||||
|
||||
;;EXAMPLE - replace all garbage cans with a hostage
|
||||
;modify:
|
||||
;{
|
||||
; match:
|
||||
; {
|
||||
; "model" "models/props_junk/garbage_metalcan002a.mdl"
|
||||
; "classname" "prop_physics_multiplayer"
|
||||
; }
|
||||
; replace:
|
||||
; {
|
||||
; "classname" "hostage_entity"
|
||||
; }
|
||||
; delete:
|
||||
; {
|
||||
; "model" "models/props_junk/garbage_metalcan002a.mdl"
|
||||
; }
|
||||
; insert:
|
||||
; {
|
||||
; "scale" "0.99"
|
||||
; }
|
||||
;}
|
||||
@ -3,13 +3,14 @@
|
||||
|
||||
#include <sourcemod>
|
||||
#include <regex>
|
||||
#include <Stripper>
|
||||
|
||||
public Plugin myinfo =
|
||||
{
|
||||
name = "Stripper:Source (SP edition)",
|
||||
version = "1.3.1",
|
||||
version = "1.3.3",
|
||||
description = "Stripper:Source functionality in a Sourcemod plugin",
|
||||
author = "tilgep, Stripper:Source by BAILOPAN",
|
||||
author = "Original Author: BAILOPAN. Ported to SM by: tilgep. Edited by: Lerrdy, .Rushaway",
|
||||
url = "https://forums.alliedmods.net/showthread.php?t=339448"
|
||||
}
|
||||
|
||||
@ -71,20 +72,56 @@ enum struct Block
|
||||
}
|
||||
|
||||
char file[PLATFORM_MAX_PATH];
|
||||
char g_sLogPath[PLATFORM_MAX_PATH];
|
||||
bool g_bConfigLoaded = false;
|
||||
bool g_bConfigError = false;
|
||||
Handle g_hFwd_OnErrorLogged = INVALID_HANDLE;
|
||||
ConVar fileLowercase;
|
||||
Block prop; // Global current stripper block
|
||||
int section;
|
||||
|
||||
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
|
||||
{
|
||||
CreateNative("Stripper_LogError", Native_Log);
|
||||
g_hFwd_OnErrorLogged = CreateGlobalForward("Stripper_OnErrorLogged", ET_Ignore, Param_String);
|
||||
|
||||
RegPluginLibrary("Stripper");
|
||||
return APLRes_Success;
|
||||
}
|
||||
|
||||
public void OnPluginStart()
|
||||
{
|
||||
prop.Init();
|
||||
|
||||
RegAdminCmd("stripper_dump", Command_Dump, ADMFLAG_ROOT, "Writes all of the map entity properties to a file in configs/stripper/dumps/");
|
||||
RegAdminCmd("sm_stripper", Command_Stripper, ADMFLAG_GENERIC, "Prints out if the current map has a loaded stripper file");
|
||||
|
||||
fileLowercase = CreateConVar("stripper_file_lowercase", "0", "Whether to load map config filenames as lower case", _, true, 0.0, true, 1.0);
|
||||
AutoExecConfig(true, "stripper");
|
||||
}
|
||||
|
||||
public Action Command_Stripper(int client, int args)
|
||||
{
|
||||
bool bAccess = CheckCommandAccess(client, "sm_stripper", ADMFLAG_ROOT);
|
||||
if (g_bConfigLoaded)
|
||||
{
|
||||
ReplyToCommand(client, "[Strippper] The current map has a loaded stripper config.");
|
||||
if(bAccess) ReplyToCommand(client, "[Strippper] Actual cfg: %s", file);
|
||||
}
|
||||
else if (g_bConfigError)
|
||||
{
|
||||
ReplyToCommand(client, "[Strippper] The current map has a loaded stripper config but it contains error(s)");
|
||||
if(bAccess) ReplyToCommand(client, "[Strippper] Check (%s)", file);
|
||||
}
|
||||
else
|
||||
{
|
||||
ReplyToCommand(client, "[Strippper] The current map did not load a stripper config.");
|
||||
if(bAccess) ReplyToCommand(client, "[Strippper] No file found: (%s)", file);
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action Command_Dump(int client, int args)
|
||||
{
|
||||
char buf1[PLATFORM_MAX_PATH], buf2[PLATFORM_MAX_PATH], path[PLATFORM_MAX_PATH];
|
||||
@ -92,9 +129,9 @@ public Action Command_Dump(int client, int args)
|
||||
|
||||
GetCurrentMap(buf1, PLATFORM_MAX_PATH);
|
||||
|
||||
BuildPath(Path_SM, buf2, PLATFORM_MAX_PATH, "configs/stripper/dumps");
|
||||
BuildPath(Path_SM, buf2, PLATFORM_MAX_PATH, "logs/stripper/dumps");
|
||||
|
||||
if(!DirExists(buf2)) CreateDirectory(buf2, FPERM_O_READ|FPERM_O_EXEC|FPERM_G_READ|FPERM_G_EXEC|FPERM_U_READ|FPERM_U_WRITE|FPERM_U_EXEC);
|
||||
if(!DirExists(buf2)) CreateDirectory(buf2, 0o666);
|
||||
|
||||
do
|
||||
{
|
||||
@ -107,7 +144,7 @@ public Action Command_Dump(int client, int args)
|
||||
File fi = OpenFile(path, "w");
|
||||
if(fi == null)
|
||||
{
|
||||
LogError("Failed to create dump file \"%s\"", path);
|
||||
Stripper_LogError("Failed to create dump file \"%s\"", path);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
@ -138,31 +175,37 @@ public Action Command_Dump(int client, int args)
|
||||
|
||||
public void OnMapInit(const char[] mapName)
|
||||
{
|
||||
// Path used for logging.
|
||||
BuildPath(Path_SM, g_sLogPath, sizeof(g_sLogPath), "logs/stripper/maps/%s.log", mapName);
|
||||
|
||||
g_bConfigLoaded = false;
|
||||
g_bConfigError = false;
|
||||
|
||||
// Parse global filters
|
||||
BuildPath(Path_SM, file, sizeof(file), "configs/stripper/global_filters.cfg");
|
||||
|
||||
ParseFile();
|
||||
ParseFile(false);
|
||||
|
||||
// Now parse map config
|
||||
strcopy(file, sizeof(file), mapName);
|
||||
BuildPath(Path_SM, file, sizeof(file), "configs/stripper/maps/%s.cfg", mapName);
|
||||
|
||||
if(fileLowercase.BoolValue)
|
||||
if(!ParseFile(true) && fileLowercase.BoolValue)
|
||||
{
|
||||
strcopy(file, sizeof(file), mapName);
|
||||
for(int i = 0; file[i]; i++)
|
||||
file[i] = CharToLower(file[i]);
|
||||
|
||||
BuildPath(Path_SM, file, sizeof(file), "configs/stripper/maps/%s.cfg", file);
|
||||
ParseFile(true);
|
||||
}
|
||||
|
||||
BuildPath(Path_SM, file, sizeof(file), "configs/stripper/maps/%s.cfg", file);
|
||||
|
||||
ParseFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a stripper config file
|
||||
*
|
||||
* @param path Path to parse from
|
||||
* @return True if successful, false otherwise
|
||||
*/
|
||||
public void ParseFile()
|
||||
public bool ParseFile(bool mapconfig)
|
||||
{
|
||||
int line, col;
|
||||
section = 0;
|
||||
@ -175,19 +218,31 @@ public void ParseFile()
|
||||
SMCError result = SMC_ParseFile(parser, file, line, col);
|
||||
delete parser;
|
||||
|
||||
if (result == SMCError_Okay)
|
||||
{
|
||||
if (mapconfig)
|
||||
g_bConfigLoaded = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(result != SMCError_Okay && result != SMCError_StreamOpen)
|
||||
{
|
||||
if(result == SMCError_StreamOpen)
|
||||
{
|
||||
g_bConfigLoaded = false;
|
||||
LogMessage("Failed to open stripper config \"%s\"", file);
|
||||
}
|
||||
else
|
||||
{
|
||||
char error[128];
|
||||
g_bConfigError = true;
|
||||
SMC_GetErrorString(result, error, sizeof(error));
|
||||
LogError("%s on line %d, col %d of %s", error, line, col, file);
|
||||
Stripper_LogError("%s on line %d, col %d of %s", error, line, col, file);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public SMCResult Config_NewSection(SMCParser smc, const char[] name, bool opt_quotes)
|
||||
@ -197,7 +252,8 @@ public SMCResult Config_NewSection(SMCParser smc, const char[] name, bool opt_qu
|
||||
{
|
||||
if(prop.mode != Mode_None)
|
||||
{
|
||||
LogError("Found 'filter' block while inside another block at section %d in file '%s'", section, file);
|
||||
g_bConfigError = true;
|
||||
Stripper_LogError("Found 'filter' block while inside another block at section %d in file '%s'", section, file);
|
||||
}
|
||||
|
||||
prop.Clear();
|
||||
@ -207,7 +263,8 @@ public SMCResult Config_NewSection(SMCParser smc, const char[] name, bool opt_qu
|
||||
{
|
||||
if(prop.mode != Mode_None)
|
||||
{
|
||||
LogError("Found 'add' block while inside another block at section %d in file '%s'", section, file);
|
||||
g_bConfigError = true;
|
||||
Stripper_LogError("Found 'add' block while inside another block at section %d in file '%s'", section, file);
|
||||
}
|
||||
|
||||
prop.Clear();
|
||||
@ -217,7 +274,8 @@ public SMCResult Config_NewSection(SMCParser smc, const char[] name, bool opt_qu
|
||||
{
|
||||
if(prop.mode != Mode_None)
|
||||
{
|
||||
LogError("Found 'modify' block while inside another block at section %d in file '%s'", section, file);
|
||||
g_bConfigError = true;
|
||||
Stripper_LogError("Found 'modify' block while inside another block at section %d in file '%s'", section, file);
|
||||
}
|
||||
|
||||
prop.Clear();
|
||||
@ -231,12 +289,14 @@ public SMCResult Config_NewSection(SMCParser smc, const char[] name, bool opt_qu
|
||||
else if(!strcmp(name, "insert:", false)) prop.submode = SubMode_Insert;
|
||||
else
|
||||
{
|
||||
LogError("Found invalid section '%s' in modify block at section %d in file '%s'", name, section, file);
|
||||
g_bConfigError = true;
|
||||
Stripper_LogError("Found invalid section '%s' in modify block at section %d in file '%s'", name, section, file);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("Found invalid section name '%s' at section %d in file '%s'", name, section, file);
|
||||
g_bConfigError = true;
|
||||
Stripper_LogError("Found invalid section name '%s' at section %d in file '%s'", name, section, file);
|
||||
}
|
||||
|
||||
return SMCParse_Continue;
|
||||
@ -256,7 +316,7 @@ public SMCResult Config_KeyValue(SMCParser smc, const char[] key, const char[] v
|
||||
case Mode_Add:
|
||||
{
|
||||
// Adding an entity without a classname will crash the server (shortest classname is "gib")
|
||||
if(StrEqual(key, "classname", false) && strlen(value) > 2) prop.hasClassname = true;
|
||||
if(strcmp(key, "classname", false) == 0 && strlen(value) > 2) prop.hasClassname = true;
|
||||
|
||||
prop.insert.PushArray(kv);
|
||||
}
|
||||
@ -289,8 +349,13 @@ public SMCResult Config_EndSection(SMCParser smc)
|
||||
{
|
||||
if(prop.insert.Length > 0)
|
||||
{
|
||||
if(prop.hasClassname) RunAddFilter();
|
||||
else LogError("Add block with no classname found at section %d in file '%s'", section, file);
|
||||
if(prop.hasClassname)
|
||||
RunAddFilter();
|
||||
else
|
||||
{
|
||||
g_bConfigError = true;
|
||||
Stripper_LogError("Add block with no classname found at section %d in file '%s'", section, file);
|
||||
}
|
||||
}
|
||||
|
||||
prop.mode = Mode_None;
|
||||
@ -493,3 +558,18 @@ stock bool FormatRegex(char[] pattern, int len)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// native Stripper_LogError(const char[] format, any...);
|
||||
public int Native_Log(Handle plugin, int numParams)
|
||||
{
|
||||
char sBuffer[2048];
|
||||
FormatNativeString(0, 1, 2, sizeof(sBuffer), _, sBuffer);
|
||||
LogToFileEx(g_sLogPath, "%s", sBuffer);
|
||||
|
||||
// Start forward call
|
||||
Call_StartForward(g_hFwd_OnErrorLogged);
|
||||
Call_PushString(sBuffer);
|
||||
Call_Finish();
|
||||
|
||||
return 1;
|
||||
}
|
||||
39
addons/sourcemod/scripting/include/Stripper.inc
Normal file
39
addons/sourcemod/scripting/include/Stripper.inc
Normal file
@ -0,0 +1,39 @@
|
||||
#if defined _stripper_included
|
||||
#endinput
|
||||
#endif
|
||||
#define _stripper_included
|
||||
|
||||
/*********************************************************
|
||||
* Log a message into logs/stripper/maps/<mapname>.log
|
||||
*
|
||||
* @param format Message to log
|
||||
* @noreturn
|
||||
*********************************************************/
|
||||
native void Stripper_LogError(const char[] format, any ...);
|
||||
|
||||
/**
|
||||
* Called right after stripper loged a error.
|
||||
*
|
||||
* @param sBuffer Buffer to store the log message in.
|
||||
* @param maxlen Size of the log buffer.
|
||||
* @noreturn
|
||||
*/
|
||||
forward void Stripper_OnErrorLogged(char[] sBuffer, int maxlen);
|
||||
|
||||
public SharedPlugin __pl_stripper =
|
||||
{
|
||||
name = "Stripper",
|
||||
file = "Stripper.smx",
|
||||
#if defined REQUIRE_PLUGIN
|
||||
required = 1
|
||||
#else
|
||||
required = 0
|
||||
#endif
|
||||
};
|
||||
|
||||
#if !defined REQUIRE_PLUGIN
|
||||
public void __pl_stripper_SetNTVOptional()
|
||||
{
|
||||
MarkNativeAsOptional("Stripper_Log");
|
||||
}
|
||||
#endif
|
||||
15
sourceknight.yaml
Normal file
15
sourceknight.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
project:
|
||||
sourceknight: 0.2
|
||||
name: Stripper
|
||||
dependencies:
|
||||
- name: sourcemod
|
||||
type: tar
|
||||
version: 1.11.0-git6934
|
||||
location: https://sm.alliedmods.net/smdrop/1.11/sourcemod-1.11.0-git6934-linux.tar.gz
|
||||
unpack:
|
||||
- source: /addons
|
||||
dest: /addons
|
||||
root: /
|
||||
output: /addons/sourcemod/plugins
|
||||
targets:
|
||||
- Stripper
|
||||
Loading…
Reference in New Issue
Block a user