diff --git a/Template/Metahook.Plugin/Exportfuncs.cs b/Template/Metahook.Plugin/Exportfuncs.cs
new file mode 100644
index 0000000..d6764b3
--- /dev/null
+++ b/Template/Metahook.Plugin/Exportfuncs.cs
@@ -0,0 +1,51 @@
+using GoldSrc.HLSDK.Native;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using static Plugin.Global;
+using static System.Runtime.InteropServices.JavaScript.JSType;
+
+namespace Plugin;
+public unsafe static class Exportfuncs
+{
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
+ public static int Initialize(cl_enginefunc_t *pEnginefuncs, int iVersion)
+ {
+ var s = sizeof(cl_enginefunc_t);
+
+ gEngfuncs = *pEnginefuncs;
+ return gExportfuncs.Initialize(pEnginefuncs, iVersion);
+ }
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
+ public static void HUD_Init()
+ {
+ gExportfuncs.HUD_Init();
+ }
+ static int count = 0;
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
+ public static int HUD_Redraw(float time, int intermission)
+ {
+ if (count < 10)
+ {
+ using var str = $"Hello World!!!!!(hit:{count + 1})\n".GetNativeString();
+ gEngfuncs.Con_Printf(str);
+ count++;
+ }
+ return gExportfuncs.HUD_Redraw(time, intermission);
+ }
+}
+
+
+public static class StringHelper
+{
+ public unsafe static NativeString GetNativeString(this string s) => new NativeString() { c_str = (sbyte*)Marshal.StringToHGlobalAnsi(s) };
+
+}
+
+public unsafe struct NativeString : IDisposable
+{
+ internal sbyte* c_str;
+ public void Dispose() => Marshal.FreeHGlobal((nint)c_str);
+ public static implicit operator sbyte*(NativeString d) => d.c_str;
+ public static implicit operator byte*(NativeString d) => (byte*)d.c_str;
+ public static implicit operator nint(NativeString d) => (nint)d.c_str;
+}
\ No newline at end of file
diff --git a/Template/Metahook.Plugin/Global.cs b/Template/Metahook.Plugin/Global.cs
new file mode 100644
index 0000000..8918f36
--- /dev/null
+++ b/Template/Metahook.Plugin/Global.cs
@@ -0,0 +1,13 @@
+using GoldSrc.HLSDK.Native;
+using GoldSrc.Metahook.Native;
+
+namespace Plugin;
+
+public unsafe static class Global
+{
+ public static cl_exportfuncs_t gExportfuncs;
+ public static mh_interface_t* g_pInterface;
+ public static metahook_api_t* g_pMetaHookAPI;
+ public static mh_enginesave_t* g_pMetaSave;
+ public static cl_enginefunc_t gEngfuncs;
+}
diff --git a/Template/Metahook.Plugin/Metahook.Plugin.Template.nuspec b/Template/Metahook.Plugin/Metahook.Plugin.Template.nuspec
new file mode 100644
index 0000000..bfb4753
--- /dev/null
+++ b/Template/Metahook.Plugin/Metahook.Plugin.Template.nuspec
@@ -0,0 +1,15 @@
+
+
+
+ Metahook.Plugin.Template
+ 1.0.0-alpha
+ Metahook Plugin
+ CeSun
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Template/Metahook.Plugin/PluginReplaceName.csproj b/Template/Metahook.Plugin/PluginReplaceName.csproj
new file mode 100644
index 0000000..e404687
--- /dev/null
+++ b/Template/Metahook.Plugin/PluginReplaceName.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net9.0
+ enable
+ enable
+ true
+ true
+ Plugin
+
+
+
+
+
+
+
+
diff --git a/Template/Metahook.Plugin/PluginV1.cs b/Template/Metahook.Plugin/PluginV1.cs
new file mode 100644
index 0000000..92f4483
--- /dev/null
+++ b/Template/Metahook.Plugin/PluginV1.cs
@@ -0,0 +1,26 @@
+using GoldSrc.HLSDK.Native;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Plugin;
+
+public class PluginV1
+{
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvThiscall)])]
+ public static unsafe void Init(nint self, cl_exportfuncs_t* pSave)
+ {
+
+ }
+
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvThiscall)])]
+ public static unsafe void Shutdown(nint self, int restart)
+ {
+
+ }
+
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvThiscall)])]
+ public static unsafe void Destructor(nint self)
+ {
+
+ }
+}
diff --git a/Template/Metahook.Plugin/PluginV2.cs b/Template/Metahook.Plugin/PluginV2.cs
new file mode 100644
index 0000000..b4c3d21
--- /dev/null
+++ b/Template/Metahook.Plugin/PluginV2.cs
@@ -0,0 +1,55 @@
+using GoldSrc.HLSDK.Native;
+using GoldSrc.Metahook.Native;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using static Plugin.Global;
+
+namespace Plugin;
+
+public unsafe static class PluginV2
+{
+
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvThiscall)])]
+ public static unsafe void Init(nint self, metahook_api_t* pAPI, mh_interface_t* pInterface, mh_enginesave_t* pSave)
+ {
+ g_pInterface = pInterface;
+ g_pMetaHookAPI = pAPI;
+ g_pMetaSave = pSave;
+ }
+
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvThiscall)])]
+ public static unsafe void LoadClient(nint self, cl_exportfuncs_t* pExportFunc)
+ {
+ gExportfuncs = *pExportFunc;
+
+ pExportFunc->Initialize = &Exportfuncs.Initialize;
+ pExportFunc->HUD_Init = &Exportfuncs.HUD_Init;
+ pExportFunc->HUD_Redraw = &Exportfuncs.HUD_Redraw;
+ }
+
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvThiscall)])]
+ public static unsafe void LoadEngine(nint self)
+ {
+
+ }
+
+
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvThiscall)])]
+ public static unsafe void ExitGame(nint self, int iResult)
+ {
+
+ }
+
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvThiscall)])]
+ public static unsafe void Shutdown(nint self)
+ {
+
+ }
+
+
+ [UnmanagedCallersOnly(CallConvs = [typeof(CallConvThiscall)])]
+ public static unsafe void Destructor(nint self)
+ {
+
+ }
+}
diff --git a/Template/Metahook.Plugin/Register.cs b/Template/Metahook.Plugin/Register.cs
new file mode 100644
index 0000000..5776ccf
--- /dev/null
+++ b/Template/Metahook.Plugin/Register.cs
@@ -0,0 +1,75 @@
+using GoldSrc.Metahook.Native;
+using GoldSrc.Metahook;
+using GoldSrc.HLSDK.Native;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace Plugin;
+
+public static class Register
+{
+
+ [UnmanagedCallersOnly(EntryPoint = "CreateInterface", CallConvs = [typeof(CallConvCdecl)])]
+ public static unsafe nint CreateInterface(nint ptr, int* num)
+ {
+ string? frameworkVersion = Marshal.PtrToStringAnsi(ptr);
+ if (frameworkVersion == null)
+ return IntPtr.Zero;
+ nint pPlugin = IntPtr.Zero;
+ int result = 1;
+ switch (frameworkVersion)
+ {
+ case PluginConst.METAHOOK_PLUGIN_API_VERSION_V2:
+ (pPlugin, result) = GetV2PluginInstance(frameworkVersion);
+ break;
+ case PluginConst.METAHOOK_PLUGIN_API_VERSION_V1:
+ (pPlugin, result) = GetV1PluginInstance(frameworkVersion);
+ break;
+ }
+ return pPlugin;
+ }
+
+
+ public static unsafe (nint, int) GetV1PluginInstance(string version)
+ {
+ var ptr = Marshal.AllocHGlobal(sizeof(PluginValueType));
+ ref var plugin = ref Unsafe.AsRef((void*)ptr);
+ var functionTable = Marshal.AllocHGlobal(sizeof(nint) * 3);
+ Span functions = new Span((void*)functionTable, 3);
+ functions[0] = (nint)(delegate* unmanaged[Thiscall])&PluginV1.Destructor;
+ functions[1] = (nint)(delegate* unmanaged[Thiscall])&PluginV1.Init;
+ functions[2] = (nint)(delegate* unmanaged[Thiscall])&PluginV1.Shutdown;
+ plugin = new PluginValueType
+ {
+ VirtualFunctionTable = functionTable
+ };
+ return (ptr, 0);
+ }
+
+
+ public static unsafe (nint, int) GetV2PluginInstance(string version)
+ {
+ var ptr = Marshal.AllocHGlobal(sizeof(PluginValueType));
+ ref var plugin = ref Unsafe.AsRef((void*)ptr);
+ var functionTable = Marshal.AllocHGlobal(sizeof(nint) * 6);
+ Span functions = new Span((void*)functionTable, 6);
+ functions[0] = (nint)(delegate* unmanaged[Thiscall])&PluginV2.Destructor;
+ functions[1] = (nint)(delegate* unmanaged[Thiscall])&PluginV2.Init;
+ functions[2] = (nint)(delegate* unmanaged[Thiscall])&PluginV2.Shutdown;
+ functions[3] = (nint)(delegate* unmanaged[Thiscall])&PluginV2.LoadEngine;
+ functions[4] = (nint)(delegate* unmanaged[Thiscall])&PluginV2.LoadClient;
+ functions[5] = (nint)(delegate* unmanaged[Thiscall])&PluginV2.ExitGame;
+ plugin = new PluginValueType
+ {
+ VirtualFunctionTable = functionTable
+ };
+ return (ptr, 0);
+ }
+
+ struct PluginValueType
+ {
+ public nint VirtualFunctionTable;
+ }
+}
+
+