├── .gitignore ├── LICENSE ├── README.md ├── pawn.json ├── pawno └── include │ └── DeepL.inc └── plugins ├── DeepL.def ├── DeepL.filters ├── DeepL.sln ├── DeepL.vcxproj ├── DeepL.vcxproj.filters ├── lib ├── json │ ├── json11.cpp │ └── json11.hpp └── sdk │ ├── amx │ ├── amx.h │ ├── getch.h │ └── sclinux.h │ ├── amxplugin.cpp │ ├── plugin.h │ └── plugincommon.h ├── makefile └── src ├── cache.cpp ├── cache.h ├── deepl.cpp ├── deepl.h ├── main.cpp ├── main.h ├── natives.cpp └── natives.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Linux stuff 2 | *.so 3 | *.o 4 | 5 | ## Ignore Visual Studio temporary files, build results, and 6 | ## files generated by popular Visual Studio add-ons. 7 | 8 | # User-specific files 9 | *.suo 10 | *.user 11 | *.sln.docstates 12 | *.db 13 | *.opendb 14 | *.amx 15 | rus.txt 16 | 17 | # Build results 18 | [Dd]ebug/ 19 | [Dd]ebugPublic/ 20 | [Rr]elease/ 21 | x64/ 22 | build/ 23 | bld/ 24 | [Bb]in/ 25 | [Oo]bj/ 26 | 27 | # MSTest test Results 28 | [Tt]est[Rr]esult*/ 29 | [Bb]uild[Ll]og.* 30 | 31 | #NUNIT 32 | *.VisualState.xml 33 | TestResult.xml 34 | 35 | # Build Results of an ATL Project 36 | [Dd]ebugPS/ 37 | [Rr]eleasePS/ 38 | dlldata.c 39 | 40 | *_i.c 41 | *_p.c 42 | *_i.h 43 | *.ilk 44 | *.meta 45 | *.obj 46 | *.pch 47 | *.pdb 48 | *.pgc 49 | *.pgd 50 | *.rsp 51 | *.sbr 52 | *.tlb 53 | *.tli 54 | *.tlh 55 | *.tmp 56 | *.tmp_proj 57 | *.log 58 | *.vspscc 59 | *.vssscc 60 | .builds 61 | *.pidb 62 | *.svclog 63 | *.scc 64 | 65 | # Chutzpah Test files 66 | _Chutzpah* 67 | 68 | # Visual C++ cache files 69 | ipch/ 70 | *.aps 71 | *.ncb 72 | *.opensdf 73 | *.sdf 74 | *.cachefile 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | *.vspx 80 | 81 | # TFS 2012 Local Workspace 82 | $tf/ 83 | 84 | # Guidance Automation Toolkit 85 | *.gpState 86 | 87 | # ReSharper is a .NET coding add-in 88 | _ReSharper*/ 89 | *.[Rr]e[Ss]harper 90 | *.DotSettings.user 91 | 92 | # JustCode is a .NET coding addin-in 93 | .JustCode 94 | 95 | # TeamCity is a build add-in 96 | _TeamCity* 97 | 98 | # DotCover is a Code Coverage Tool 99 | *.dotCover 100 | 101 | # NCrunch 102 | *.ncrunch* 103 | _NCrunch_* 104 | .*crunch*.local.xml 105 | 106 | # MightyMoose 107 | *.mm.* 108 | AutoTest.Net/ 109 | 110 | # Web workbench (sass) 111 | .sass-cache/ 112 | 113 | # Installshield output folder 114 | [Ee]xpress/ 115 | 116 | # DocProject is a documentation generator add-in 117 | DocProject/buildhelp/ 118 | DocProject/Help/*.HxT 119 | DocProject/Help/*.HxC 120 | DocProject/Help/*.hhc 121 | DocProject/Help/*.hhk 122 | DocProject/Help/*.hhp 123 | DocProject/Help/Html2 124 | DocProject/Help/html 125 | 126 | # Click-Once directory 127 | publish/ 128 | 129 | # Publish Web Output 130 | *.[Pp]ublish.xml 131 | *.azurePubxml 132 | 133 | # NuGet Packages Directory 134 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 135 | #packages/* 136 | ## TODO: If the tool you use requires repositories.config, also uncomment the next line 137 | #!packages/repositories.config 138 | 139 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets 140 | # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) 141 | !packages/build/ 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | 163 | # RIA/Silverlight projects 164 | Generated_Code/ 165 | 166 | # Backup & report files from converting an old project file to a newer 167 | # Visual Studio version. Backup files are not needed, because we have git ;-) 168 | _UpgradeReport_Files/ 169 | Backup*/ 170 | UpgradeLog*.XML 171 | UpgradeLog*.htm 172 | 173 | # SQL Server files 174 | *.mdf 175 | *.ldf 176 | 177 | # Business Intelligence projects 178 | *.rdl.data 179 | *.bim.layout 180 | *.bim_*.settings 181 | 182 | # Microsoft Fakes 183 | FakesAssemblies/ 184 | 185 | # ========================= 186 | # Windows detritus 187 | # ========================= 188 | 189 | # Windows image file caches 190 | Thumbs.db 191 | ehthumbs.db 192 | 193 | # Folder config file 194 | Desktop.ini 195 | 196 | # Recycle Bin used on file shares 197 | $RECYCLE.BIN/ 198 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 IS4 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DeepL Plugin v1.3 2 | ========== 3 | 4 | This plugin adds integration for the [DeepL Translate API](https://developers.deepl.com/docs/api-reference/translate). To use the plugin, you have to provide your [DeepL authentication key](https://developers.deepl.com/docs/getting-started/auth#authentication). 5 | 6 | *There are no warranties nor support for the quality of the translation, which is handled purely by DeepL and system-defined locale conversions.* 7 | 8 | ## Usage 9 | 10 | Before requesting translation, call `DeepL_SetAuthKey` to set your authentication key: 11 | ```pawn 12 | DeepL_SetAuthKey("cbae67e8-63cd-4f7f-a0c9-a2a32905679d:fx"); // example key 13 | ``` 14 | 15 | To request translation via the API, call `DeepL_Translate`: 16 | ```pawn 17 | native DeepL_Translate( 18 | const text[], // the text to translate 19 | const from[], // the source language and encoding 20 | const to[], // the target language and encoding 21 | const callback[] = #DeepL_OnTranslationDone, // the callback to invoke when translation is ready 22 | cookie = 0, // the cookie to pass to callback 23 | bool:preserve_formatting = true, // see the DeepL API for description of these parameters 24 | const tag_handling[] = "", 25 | const formality[] = "", 26 | const split_sentences[] = "" 27 | ); 28 | ``` 29 | 30 | The function returns `0` on success. 31 | 32 | The callback function is in this form: 33 | ```pawn 34 | forward bool:DeepL_OnTranslationDone( 35 | bool:success, // whether translation was produced or not 36 | result[], // if success, the translated text, otherwise the error message 37 | from[], // the detected source language 38 | cookie // cookie passed to DeepL_Translate 39 | ); 40 | ``` 41 | 42 | If the returned value is `true` and the text was successfully translated, the result is cached. 43 | 44 | ### Specifying language 45 | 46 | The value of `from` and `to` is in the form *language*:*locales*, where *locales* is a `|`-separated list of locale names (see [`std::locale`](https://en.cppreference.com/w/cpp/locale/locale/locale) for more description). If the first locale name is not found, it tries the second one, and so forth. 47 | 48 | On POSIX systems, you may use `locale -a` to list the existing locale names. On Unix, it is possible to define a custom locale using the [`localedef` command](https://man7.org/linux/man-pages/man1/localedef.1.html). For example, to define the locale `en_US.CP1250`, you could use `localedef -i en_US -f CP1250 'en_US.CP1250'` which you can then use as the argument in the form `"en:en_US.CP1250|.1250"`. On Windows, .*codepage* can be used directly for a locale based on a particular codepage. 49 | 50 | The locales may be omitted altogether, in which case UTF-8 will be used for `text`/`result`. 51 | 52 | ### Caching 53 | 54 | Successful responses from DeepL are cached in the file `scriptfiles/deepl_cache.txt`. This file is composed of alternating key-value lines, where the key is formed from the API parameters, and value is the encoded JSON response. 55 | 56 | The cache file is written after every translation, when `true` is returned from the callback. It may also be modified freely to change the particular translations. If the file is modified on-the-fly while the server is running, call `DeepL_LoadCache` to reload it. 57 | 58 | ## Installation 59 | Download the latest [release](//github.com/IS4Code/Pawn-DeepL/releases/latest) for your platform to the "plugins" directory and add "DeepL" (or "DeepL.so" on Linux) to the `plugins` line in server.cfg. 60 | 61 | Include [DeepL.inc](pawno/include/DeepL.inc) in your Pawn program and you are done. 62 | 63 | ## Building 64 | Use Visual Studio to build the project on Windows, or `make` or `make static` on Linux. Requires GCC >= 4.9 and [cURL](https://curl.se/docs/install.html) to be installed. 65 | -------------------------------------------------------------------------------- /pawn.json: -------------------------------------------------------------------------------- 1 | { 2 | "user": "IS4Code", 3 | "repo": "DeepL", 4 | "dependencies": ["sampctl/pawn-stdlib"], 5 | "resources": [ 6 | { 7 | "name": "DeepL.dll", 8 | "platform": "windows", 9 | "archive": false 10 | }, 11 | { 12 | "name": "DeepL.so", 13 | "platform": "linux", 14 | "archive": false 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /pawno/include/DeepL.inc: -------------------------------------------------------------------------------- 1 | /** DeepL v1.3 by IS4 **/ 2 | //github.com/IS4Code/Pawn-DeepL 3 | 4 | #if defined _inc_DeepL 5 | #undef _inc_DeepL 6 | #endif 7 | #if defined _DeepL_included 8 | #endinput 9 | #endif 10 | #define _DeepL_included 11 | 12 | forward bool:DeepL_OnTranslationDone(bool:success, result[], from[], cookie); 13 | 14 | native DeepL_SetAuthKey(const key[]); 15 | native DeepL_SetEndpoint(const endpoint_url[]); 16 | native DeepL_Translate(const text[], const from[], const to[], const callback[] = #DeepL_OnTranslationDone, cookie = 0, bool:preserve_formatting = true, const tag_handling[] = "", const formality[] = "", const split_sentences[] = ""); 17 | native DeepL_LoadCache(); 18 | -------------------------------------------------------------------------------- /plugins/DeepL.def: -------------------------------------------------------------------------------- 1 | LIBRARY "DeepL" 2 | 3 | EXPORTS 4 | Supports 5 | Load 6 | Unload 7 | AmxLoad 8 | AmxUnload 9 | ProcessTick -------------------------------------------------------------------------------- /plugins/DeepL.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | lib\subhook 6 | 7 | 8 | lib\sdk 9 | 10 | 11 | src 12 | 13 | 14 | src 15 | 16 | 17 | src 18 | 19 | 20 | src 21 | 22 | 23 | src 24 | 25 | 26 | src 27 | 28 | 29 | src\amx 30 | 31 | 32 | src\lua 33 | 34 | 35 | src\lua 36 | 37 | 38 | src\lua\interop 39 | 40 | 41 | src\lua\interop 42 | 43 | 44 | src\lua\interop 45 | 46 | 47 | src\lua\interop 48 | 49 | 50 | src\lua\interop 51 | 52 | 53 | src\lua\interop 54 | 55 | 56 | src\lua 57 | 58 | 59 | lib\lua 60 | 61 | 62 | lib\lua 63 | 64 | 65 | lib\lua 66 | 67 | 68 | lib\lua 69 | 70 | 71 | lib\lua 72 | 73 | 74 | lib\lua 75 | 76 | 77 | lib\lua 78 | 79 | 80 | lib\lua 81 | 82 | 83 | lib\lua 84 | 85 | 86 | lib\lua 87 | 88 | 89 | lib\lua 90 | 91 | 92 | lib\lua 93 | 94 | 95 | lib\lua 96 | 97 | 98 | lib\lua 99 | 100 | 101 | lib\lua 102 | 103 | 104 | lib\lua 105 | 106 | 107 | lib\lua 108 | 109 | 110 | lib\lua 111 | 112 | 113 | lib\lua 114 | 115 | 116 | lib\lua 117 | 118 | 119 | lib\lua 120 | 121 | 122 | lib\lua 123 | 124 | 125 | lib\lua 126 | 127 | 128 | lib\lua 129 | 130 | 131 | lib\lua 132 | 133 | 134 | lib\lua 135 | 136 | 137 | lib\lua 138 | 139 | 140 | lib\lua 141 | 142 | 143 | lib\lua 144 | 145 | 146 | lib\lua 147 | 148 | 149 | lib\lua 150 | 151 | 152 | lib\lua 153 | 154 | 155 | lib\lua 156 | 157 | 158 | src\lua\interop 159 | 160 | 161 | src\lua\interop 162 | 163 | 164 | src 165 | 166 | 167 | 168 | 169 | lib\subhook 170 | 171 | 172 | lib\subhook 173 | 174 | 175 | lib\subhook 176 | 177 | 178 | lib\subhook 179 | 180 | 181 | lib\subhook 182 | 183 | 184 | lib\subhook 185 | 186 | 187 | lib\sdk 188 | 189 | 190 | lib\sdk 191 | 192 | 193 | lib\sdk\amx 194 | 195 | 196 | lib\sdk\amx 197 | 198 | 199 | lib\sdk\amx 200 | 201 | 202 | src\fixes 203 | 204 | 205 | src 206 | 207 | 208 | src 209 | 210 | 211 | src 212 | 213 | 214 | src\utils 215 | 216 | 217 | src\utils 218 | 219 | 220 | src\utils 221 | 222 | 223 | src\utils 224 | 225 | 226 | src 227 | 228 | 229 | src 230 | 231 | 232 | src 233 | 234 | 235 | src\amx 236 | 237 | 238 | src\lua 239 | 240 | 241 | src\lua 242 | 243 | 244 | src\lua\interop 245 | 246 | 247 | src\lua\interop 248 | 249 | 250 | src\lua\interop 251 | 252 | 253 | src\lua\interop 254 | 255 | 256 | src\lua\interop 257 | 258 | 259 | src\lua\interop 260 | 261 | 262 | src\lua 263 | 264 | 265 | lib\lua 266 | 267 | 268 | lib\lua 269 | 270 | 271 | lib\lua 272 | 273 | 274 | lib\lua 275 | 276 | 277 | lib\lua 278 | 279 | 280 | lib\lua 281 | 282 | 283 | lib\lua 284 | 285 | 286 | lib\lua 287 | 288 | 289 | lib\lua 290 | 291 | 292 | lib\lua 293 | 294 | 295 | lib\lua 296 | 297 | 298 | lib\lua 299 | 300 | 301 | lib\lua 302 | 303 | 304 | lib\lua 305 | 306 | 307 | lib\lua 308 | 309 | 310 | lib\lua 311 | 312 | 313 | lib\lua 314 | 315 | 316 | lib\lua 317 | 318 | 319 | lib\lua 320 | 321 | 322 | lib\lua 323 | 324 | 325 | lib\lua 326 | 327 | 328 | lib\lua 329 | 330 | 331 | lib\lua 332 | 333 | 334 | lib\lua 335 | 336 | 337 | lib\lua 338 | 339 | 340 | lib\lua 341 | 342 | 343 | src\lua 344 | 345 | 346 | src\lua\interop 347 | 348 | 349 | src\lua\interop 350 | 351 | 352 | src 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | {3d6a091a-259f-4fe8-8bba-120286323d40} 361 | 362 | 363 | {ea02da0c-7d5b-4184-a17e-c9362a2a0219} 364 | 365 | 366 | {d04663e9-3029-49cf-853e-feae3cd594d5} 367 | 368 | 369 | {7516e3ab-581e-47dc-b112-f524e53b8c77} 370 | 371 | 372 | {1013b1a8-51b7-4b2c-aa29-cc2e6607954b} 373 | 374 | 375 | {973f41a2-0716-4217-b2b2-ec5673be5f47} 376 | 377 | 378 | {470fb0f2-8ac6-4cf8-b645-a8820627a0a7} 379 | 380 | 381 | {abd01d7f-1955-4c11-b3f6-2d6a36909315} 382 | 383 | 384 | {d682c4ee-957c-49aa-ae1c-6d01519b1479} 385 | 386 | 387 | {e9e9cdfb-0e46-453d-8029-7abc274bb4a8} 388 | 389 | 390 | {fac941d1-b141-4cde-befa-8bb2283defbe} 391 | 392 | 393 | -------------------------------------------------------------------------------- /plugins/DeepL.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio 15 3 | VisualStudioVersion = 15.0.27004.2002 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeepL", "DeepL.vcxproj", "{2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Debug|Win32 = Debug|Win32 11 | Release|Any CPU = Release|Any CPU 12 | Release|Win32 = Release|Win32 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Debug|Any CPU.ActiveCfg = Debug|Win32 16 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Debug|Win32.Build.0 = Debug|Win32 18 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Release|Any CPU.ActiveCfg = Release|Win32 19 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Release|Win32.ActiveCfg = Release|Win32 20 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5}.Release|Win32.Build.0 = Release|Win32 21 | EndGlobalSection 22 | GlobalSection(SolutionProperties) = preSolution 23 | HideSolutionNode = FALSE 24 | EndGlobalSection 25 | GlobalSection(ExtensibilityGlobals) = postSolution 26 | SolutionGuid = {F3B8C0C8-8838-42EF-9075-40A3BC4DF3E6} 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /plugins/DeepL.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Release 6 | Win32 7 | 8 | 9 | Debug 10 | Win32 11 | 12 | 13 | 14 | {2F8D97ED-64C2-4F78-A343-3F23C64D1AD5} 15 | Win32Proj 16 | DeepL 17 | DeepL 18 | 10.0.16299.0 19 | 20 | 21 | 22 | DynamicLibrary 23 | false 24 | MultiByte 25 | v141 26 | true 27 | 28 | 29 | DynamicLibrary 30 | true 31 | MultiByte 32 | v141 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | false 46 | bin\win32\Release\ 47 | obj\win32\Release\ 48 | DeepL 49 | .dll 50 | AllRules.ruleset 51 | 52 | 53 | C:\curl\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\include\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 54 | C:\curl\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\lib\;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86 55 | 56 | 57 | true 58 | D:\Program Files\Rockstar Games\GTA San Andreas\Samp server\0.3.7\plugins\ 59 | obj\win32\Debug\ 60 | DeepL 61 | .dll 62 | AllRules.ruleset 63 | 64 | 65 | C:\curl\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\include\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 66 | C:\curl\builds\libcurl-vc-x86-release-static-ipv6-sspi-schannel\lib\;$(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86 67 | 68 | 69 | 70 | NotUsing 71 | Level3 72 | false 73 | HAVE_STDINT_H;_CRT_SECURE_NO_WARNINGS;NDEBUG;SAMPGDK_AMALGAMATION;SUBHOOK_IMPLEMENTATION;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) 74 | include;lib;src;%(AdditionalIncludeDirectories) 75 | MaxSpeed 76 | true 77 | true 78 | false 79 | Speed 80 | true 81 | true 82 | true 83 | AnySuitable 84 | true 85 | 1Byte 86 | true 87 | stdcpp14 88 | 89 | 90 | BOOST_ALL_NO_LIB;BOOST_CHRONO_HEADER_ONLY;_CRT_SECURE_NO_WARNINGS;NDEBUG;SAMPGDK_AMALGAMATION;%(PreprocessorDefinitions) 91 | include;lib;%(AdditionalIncludeDirectories) 92 | 93 | 94 | Windows 95 | false 96 | true 97 | true 98 | bin\win32\Release\DeepL.lib 99 | DeepL.def 100 | $(ProjectDir)bin\win32\Release\DeepL.dll 101 | libcurl_a.lib;Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;psapi.lib;winmm.lib;Ws2_32.lib;%(AdditionalDependencies) 102 | false 103 | false 104 | true 105 | 106 | 107 | 108 | 109 | NotUsing 110 | Level3 111 | false 112 | HAVE_STDINT_H;_CRT_SECURE_NO_WARNINGS;SAMPGDK_AMALGAMATION;SUBHOOK_IMPLEMENTATION;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) 113 | include;lib;src;%(AdditionalIncludeDirectories) 114 | OldStyle 115 | $(OutDir)DeepL.pdb 116 | Disabled 117 | 1Byte 118 | stdcpp14 119 | 120 | 121 | 122 | 123 | BOOST_ALL_NO_LIB;BOOST_CHRONO_HEADER_ONLY;_CRT_SECURE_NO_WARNINGS;SAMPGDK_AMALGAMATION;%(PreprocessorDefinitions) 124 | include;lib;%(AdditionalIncludeDirectories) 125 | 126 | 127 | Windows 128 | true 129 | bin\win32\Debug\DeepL.lib 130 | DeepL.def 131 | true 132 | D:\Program Files\Rockstar Games\GTA San Andreas\Samp server\0.3.7\plugins\DeepL.dll 133 | libcurl_a.lib;Ws2_32.lib;Crypt32.lib;Wldap32.lib;Normaliz.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;Ws2_32.lib;%(AdditionalDependencies) 134 | 135 | 136 | msvcrt 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /plugins/DeepL.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | lib\sdk 6 | 7 | 8 | src 9 | 10 | 11 | src 12 | 13 | 14 | src 15 | 16 | 17 | lib\json 18 | 19 | 20 | src 21 | 22 | 23 | 24 | 25 | lib\sdk 26 | 27 | 28 | lib\sdk 29 | 30 | 31 | lib\sdk\amx 32 | 33 | 34 | lib\sdk\amx 35 | 36 | 37 | lib\sdk\amx 38 | 39 | 40 | src 41 | 42 | 43 | src 44 | 45 | 46 | src 47 | 48 | 49 | lib\json 50 | 51 | 52 | src 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | {a4fd26cf-a2b4-4803-8d67-b7b0d036eb21} 61 | 62 | 63 | {e2d507f8-555b-42b7-adcf-ecafaa28b415} 64 | 65 | 66 | {072cd0b9-a015-41e5-bd5a-94e3e77f6ba3} 67 | 68 | 69 | {14346158-17c8-4f00-97a4-366965acac73} 70 | 71 | 72 | {fa08e708-8ba5-465e-ae6b-b4dc64697417} 73 | 74 | 75 | -------------------------------------------------------------------------------- /plugins/lib/json/json11.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013 Dropbox, Inc. 2 | * 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy 4 | * of this software and associated documentation files (the "Software"), to deal 5 | * in the Software without restriction, including without limitation the rights 6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | * copies of the Software, and to permit persons to whom the Software is 8 | * furnished to do so, subject to the following conditions: 9 | * 10 | * The above copyright notice and this permission notice shall be included in 11 | * all copies or substantial portions of the Software. 12 | * 13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | * THE SOFTWARE. 20 | */ 21 | 22 | #include "json11.hpp" 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | namespace json11 { 30 | 31 | static const int max_depth = 200; 32 | 33 | using std::string; 34 | using std::vector; 35 | using std::map; 36 | using std::make_shared; 37 | using std::initializer_list; 38 | using std::move; 39 | 40 | /* Helper for representing null - just a do-nothing struct, plus comparison 41 | * operators so the helpers in JsonValue work. We can't use nullptr_t because 42 | * it may not be orderable. 43 | */ 44 | struct NullStruct { 45 | bool operator==(NullStruct) const { return true; } 46 | bool operator<(NullStruct) const { return false; } 47 | }; 48 | 49 | /* * * * * * * * * * * * * * * * * * * * 50 | * Serialization 51 | */ 52 | 53 | static void dump(NullStruct, string &out) { 54 | out += "null"; 55 | } 56 | 57 | static void dump(double value, string &out) { 58 | if (std::isfinite(value)) { 59 | char buf[32]; 60 | snprintf(buf, sizeof buf, "%.17g", value); 61 | out += buf; 62 | } else { 63 | out += "null"; 64 | } 65 | } 66 | 67 | static void dump(int value, string &out) { 68 | char buf[32]; 69 | snprintf(buf, sizeof buf, "%d", value); 70 | out += buf; 71 | } 72 | 73 | static void dump(bool value, string &out) { 74 | out += value ? "true" : "false"; 75 | } 76 | 77 | static void dump(const string &value, string &out) { 78 | out += '"'; 79 | for (size_t i = 0; i < value.length(); i++) { 80 | const char ch = value[i]; 81 | if (ch == '\\') { 82 | out += "\\\\"; 83 | } else if (ch == '"') { 84 | out += "\\\""; 85 | } else if (ch == '\b') { 86 | out += "\\b"; 87 | } else if (ch == '\f') { 88 | out += "\\f"; 89 | } else if (ch == '\n') { 90 | out += "\\n"; 91 | } else if (ch == '\r') { 92 | out += "\\r"; 93 | } else if (ch == '\t') { 94 | out += "\\t"; 95 | } else if (static_cast(ch) <= 0x1f) { 96 | char buf[8]; 97 | snprintf(buf, sizeof buf, "\\u%04x", ch); 98 | out += buf; 99 | } else if (static_cast(ch) == 0xe2 && static_cast(value[i+1]) == 0x80 100 | && static_cast(value[i+2]) == 0xa8) { 101 | out += "\\u2028"; 102 | i += 2; 103 | } else if (static_cast(ch) == 0xe2 && static_cast(value[i+1]) == 0x80 104 | && static_cast(value[i+2]) == 0xa9) { 105 | out += "\\u2029"; 106 | i += 2; 107 | } else { 108 | out += ch; 109 | } 110 | } 111 | out += '"'; 112 | } 113 | 114 | static void dump(const Json::array &values, string &out) { 115 | bool first = true; 116 | out += "["; 117 | for (const auto &value : values) { 118 | if (!first) 119 | out += ", "; 120 | value.dump(out); 121 | first = false; 122 | } 123 | out += "]"; 124 | } 125 | 126 | static void dump(const Json::object &values, string &out) { 127 | bool first = true; 128 | out += "{"; 129 | for (const auto &kv : values) { 130 | if (!first) 131 | out += ", "; 132 | dump(kv.first, out); 133 | out += ": "; 134 | kv.second.dump(out); 135 | first = false; 136 | } 137 | out += "}"; 138 | } 139 | 140 | void Json::dump(string &out) const { 141 | m_ptr->dump(out); 142 | } 143 | 144 | /* * * * * * * * * * * * * * * * * * * * 145 | * Value wrappers 146 | */ 147 | 148 | template 149 | class Value : public JsonValue { 150 | protected: 151 | 152 | // Constructors 153 | explicit Value(const T &value) : m_value(value) {} 154 | explicit Value(T &&value) : m_value(move(value)) {} 155 | 156 | // Get type tag 157 | Json::Type type() const override { 158 | return tag; 159 | } 160 | 161 | // Comparisons 162 | bool equals(const JsonValue * other) const override { 163 | return m_value == static_cast *>(other)->m_value; 164 | } 165 | bool less(const JsonValue * other) const override { 166 | return m_value < static_cast *>(other)->m_value; 167 | } 168 | 169 | const T m_value; 170 | void dump(string &out) const override { json11::dump(m_value, out); } 171 | }; 172 | 173 | class JsonDouble final : public Value { 174 | double number_value() const override { return m_value; } 175 | int int_value() const override { return static_cast(m_value); } 176 | bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } 177 | bool less(const JsonValue * other) const override { return m_value < other->number_value(); } 178 | public: 179 | explicit JsonDouble(double value) : Value(value) {} 180 | }; 181 | 182 | class JsonInt final : public Value { 183 | double number_value() const override { return m_value; } 184 | int int_value() const override { return m_value; } 185 | bool equals(const JsonValue * other) const override { return m_value == other->number_value(); } 186 | bool less(const JsonValue * other) const override { return m_value < other->number_value(); } 187 | public: 188 | explicit JsonInt(int value) : Value(value) {} 189 | }; 190 | 191 | class JsonBoolean final : public Value { 192 | bool bool_value() const override { return m_value; } 193 | public: 194 | explicit JsonBoolean(bool value) : Value(value) {} 195 | }; 196 | 197 | class JsonString final : public Value { 198 | const string &string_value() const override { return m_value; } 199 | public: 200 | explicit JsonString(const string &value) : Value(value) {} 201 | explicit JsonString(string &&value) : Value(move(value)) {} 202 | }; 203 | 204 | class JsonArray final : public Value { 205 | const Json::array &array_items() const override { return m_value; } 206 | const Json & operator[](size_t i) const override; 207 | public: 208 | explicit JsonArray(const Json::array &value) : Value(value) {} 209 | explicit JsonArray(Json::array &&value) : Value(move(value)) {} 210 | }; 211 | 212 | class JsonObject final : public Value { 213 | const Json::object &object_items() const override { return m_value; } 214 | const Json & operator[](const string &key) const override; 215 | public: 216 | explicit JsonObject(const Json::object &value) : Value(value) {} 217 | explicit JsonObject(Json::object &&value) : Value(move(value)) {} 218 | }; 219 | 220 | class JsonNull final : public Value { 221 | public: 222 | JsonNull() : Value({}) {} 223 | }; 224 | 225 | /* * * * * * * * * * * * * * * * * * * * 226 | * Static globals - static-init-safe 227 | */ 228 | struct Statics { 229 | const std::shared_ptr null = make_shared(); 230 | const std::shared_ptr t = make_shared(true); 231 | const std::shared_ptr f = make_shared(false); 232 | const string empty_string; 233 | const vector empty_vector; 234 | const map empty_map; 235 | Statics() {} 236 | }; 237 | 238 | static const Statics & statics() { 239 | static const Statics s {}; 240 | return s; 241 | } 242 | 243 | static const Json & static_null() { 244 | // This has to be separate, not in Statics, because Json() accesses statics().null. 245 | static const Json json_null; 246 | return json_null; 247 | } 248 | 249 | /* * * * * * * * * * * * * * * * * * * * 250 | * Constructors 251 | */ 252 | 253 | Json::Json() noexcept : m_ptr(statics().null) {} 254 | Json::Json(std::nullptr_t) noexcept : m_ptr(statics().null) {} 255 | Json::Json(double value) : m_ptr(make_shared(value)) {} 256 | Json::Json(int value) : m_ptr(make_shared(value)) {} 257 | Json::Json(bool value) : m_ptr(value ? statics().t : statics().f) {} 258 | Json::Json(const string &value) : m_ptr(make_shared(value)) {} 259 | Json::Json(string &&value) : m_ptr(make_shared(move(value))) {} 260 | Json::Json(const char * value) : m_ptr(make_shared(value)) {} 261 | Json::Json(const Json::array &values) : m_ptr(make_shared(values)) {} 262 | Json::Json(Json::array &&values) : m_ptr(make_shared(move(values))) {} 263 | Json::Json(const Json::object &values) : m_ptr(make_shared(values)) {} 264 | Json::Json(Json::object &&values) : m_ptr(make_shared(move(values))) {} 265 | 266 | /* * * * * * * * * * * * * * * * * * * * 267 | * Accessors 268 | */ 269 | 270 | Json::Type Json::type() const { return m_ptr->type(); } 271 | double Json::number_value() const { return m_ptr->number_value(); } 272 | int Json::int_value() const { return m_ptr->int_value(); } 273 | bool Json::bool_value() const { return m_ptr->bool_value(); } 274 | const string & Json::string_value() const { return m_ptr->string_value(); } 275 | const vector & Json::array_items() const { return m_ptr->array_items(); } 276 | const map & Json::object_items() const { return m_ptr->object_items(); } 277 | const Json & Json::operator[] (size_t i) const { return (*m_ptr)[i]; } 278 | const Json & Json::operator[] (const string &key) const { return (*m_ptr)[key]; } 279 | 280 | double JsonValue::number_value() const { return 0; } 281 | int JsonValue::int_value() const { return 0; } 282 | bool JsonValue::bool_value() const { return false; } 283 | const string & JsonValue::string_value() const { return statics().empty_string; } 284 | const vector & JsonValue::array_items() const { return statics().empty_vector; } 285 | const map & JsonValue::object_items() const { return statics().empty_map; } 286 | const Json & JsonValue::operator[] (size_t) const { return static_null(); } 287 | const Json & JsonValue::operator[] (const string &) const { return static_null(); } 288 | 289 | const Json & JsonObject::operator[] (const string &key) const { 290 | auto iter = m_value.find(key); 291 | return (iter == m_value.end()) ? static_null() : iter->second; 292 | } 293 | const Json & JsonArray::operator[] (size_t i) const { 294 | if (i >= m_value.size()) return static_null(); 295 | else return m_value[i]; 296 | } 297 | 298 | /* * * * * * * * * * * * * * * * * * * * 299 | * Comparison 300 | */ 301 | 302 | bool Json::operator== (const Json &other) const { 303 | if (m_ptr == other.m_ptr) 304 | return true; 305 | if (m_ptr->type() != other.m_ptr->type()) 306 | return false; 307 | 308 | return m_ptr->equals(other.m_ptr.get()); 309 | } 310 | 311 | bool Json::operator< (const Json &other) const { 312 | if (m_ptr == other.m_ptr) 313 | return false; 314 | if (m_ptr->type() != other.m_ptr->type()) 315 | return m_ptr->type() < other.m_ptr->type(); 316 | 317 | return m_ptr->less(other.m_ptr.get()); 318 | } 319 | 320 | /* * * * * * * * * * * * * * * * * * * * 321 | * Parsing 322 | */ 323 | 324 | /* esc(c) 325 | * 326 | * Format char c suitable for printing in an error message. 327 | */ 328 | static inline string esc(char c) { 329 | char buf[12]; 330 | if (static_cast(c) >= 0x20 && static_cast(c) <= 0x7f) { 331 | snprintf(buf, sizeof buf, "'%c' (%d)", c, c); 332 | } else { 333 | snprintf(buf, sizeof buf, "(%d)", c); 334 | } 335 | return string(buf); 336 | } 337 | 338 | static inline bool in_range(long x, long lower, long upper) { 339 | return (x >= lower && x <= upper); 340 | } 341 | 342 | namespace { 343 | /* JsonParser 344 | * 345 | * Object that tracks all state of an in-progress parse. 346 | */ 347 | struct JsonParser final { 348 | 349 | /* State 350 | */ 351 | const string &str; 352 | size_t i; 353 | string &err; 354 | bool failed; 355 | const JsonParse strategy; 356 | 357 | /* fail(msg, err_ret = Json()) 358 | * 359 | * Mark this parse as failed. 360 | */ 361 | Json fail(string &&msg) { 362 | return fail(move(msg), Json()); 363 | } 364 | 365 | template 366 | T fail(string &&msg, const T err_ret) { 367 | if (!failed) 368 | err = std::move(msg); 369 | failed = true; 370 | return err_ret; 371 | } 372 | 373 | /* consume_whitespace() 374 | * 375 | * Advance until the current character is non-whitespace. 376 | */ 377 | void consume_whitespace() { 378 | while (str[i] == ' ' || str[i] == '\r' || str[i] == '\n' || str[i] == '\t') 379 | i++; 380 | } 381 | 382 | /* consume_comment() 383 | * 384 | * Advance comments (c-style inline and multiline). 385 | */ 386 | bool consume_comment() { 387 | bool comment_found = false; 388 | if (str[i] == '/') { 389 | i++; 390 | if (i == str.size()) 391 | return fail("unexpected end of input after start of comment", false); 392 | if (str[i] == '/') { // inline comment 393 | i++; 394 | // advance until next line, or end of input 395 | while (i < str.size() && str[i] != '\n') { 396 | i++; 397 | } 398 | comment_found = true; 399 | } 400 | else if (str[i] == '*') { // multiline comment 401 | i++; 402 | if (i > str.size()-2) 403 | return fail("unexpected end of input inside multi-line comment", false); 404 | // advance until closing tokens 405 | while (!(str[i] == '*' && str[i+1] == '/')) { 406 | i++; 407 | if (i > str.size()-2) 408 | return fail( 409 | "unexpected end of input inside multi-line comment", false); 410 | } 411 | i += 2; 412 | comment_found = true; 413 | } 414 | else 415 | return fail("malformed comment", false); 416 | } 417 | return comment_found; 418 | } 419 | 420 | /* consume_garbage() 421 | * 422 | * Advance until the current character is non-whitespace and non-comment. 423 | */ 424 | void consume_garbage() { 425 | consume_whitespace(); 426 | if(strategy == JsonParse::COMMENTS) { 427 | bool comment_found = false; 428 | do { 429 | comment_found = consume_comment(); 430 | if (failed) return; 431 | consume_whitespace(); 432 | } 433 | while(comment_found); 434 | } 435 | } 436 | 437 | /* get_next_token() 438 | * 439 | * Return the next non-whitespace character. If the end of the input is reached, 440 | * flag an error and return 0. 441 | */ 442 | char get_next_token() { 443 | consume_garbage(); 444 | if (failed) return static_cast(0); 445 | if (i == str.size()) 446 | return fail("unexpected end of input", static_cast(0)); 447 | 448 | return str[i++]; 449 | } 450 | 451 | /* encode_utf8(pt, out) 452 | * 453 | * Encode pt as UTF-8 and add it to out. 454 | */ 455 | void encode_utf8(long pt, string & out) { 456 | if (pt < 0) 457 | return; 458 | 459 | if (pt < 0x80) { 460 | out += static_cast(pt); 461 | } else if (pt < 0x800) { 462 | out += static_cast((pt >> 6) | 0xC0); 463 | out += static_cast((pt & 0x3F) | 0x80); 464 | } else if (pt < 0x10000) { 465 | out += static_cast((pt >> 12) | 0xE0); 466 | out += static_cast(((pt >> 6) & 0x3F) | 0x80); 467 | out += static_cast((pt & 0x3F) | 0x80); 468 | } else { 469 | out += static_cast((pt >> 18) | 0xF0); 470 | out += static_cast(((pt >> 12) & 0x3F) | 0x80); 471 | out += static_cast(((pt >> 6) & 0x3F) | 0x80); 472 | out += static_cast((pt & 0x3F) | 0x80); 473 | } 474 | } 475 | 476 | /* parse_string() 477 | * 478 | * Parse a string, starting at the current position. 479 | */ 480 | string parse_string() { 481 | string out; 482 | long last_escaped_codepoint = -1; 483 | while (true) { 484 | if (i == str.size()) 485 | return fail("unexpected end of input in string", ""); 486 | 487 | char ch = str[i++]; 488 | 489 | if (ch == '"') { 490 | encode_utf8(last_escaped_codepoint, out); 491 | return out; 492 | } 493 | 494 | if (in_range(ch, 0, 0x1f)) 495 | return fail("unescaped " + esc(ch) + " in string", ""); 496 | 497 | // The usual case: non-escaped characters 498 | if (ch != '\\') { 499 | encode_utf8(last_escaped_codepoint, out); 500 | last_escaped_codepoint = -1; 501 | out += ch; 502 | continue; 503 | } 504 | 505 | // Handle escapes 506 | if (i == str.size()) 507 | return fail("unexpected end of input in string", ""); 508 | 509 | ch = str[i++]; 510 | 511 | if (ch == 'u') { 512 | // Extract 4-byte escape sequence 513 | string esc = str.substr(i, 4); 514 | // Explicitly check length of the substring. The following loop 515 | // relies on std::string returning the terminating NUL when 516 | // accessing str[length]. Checking here reduces brittleness. 517 | if (esc.length() < 4) { 518 | return fail("bad \\u escape: " + esc, ""); 519 | } 520 | for (size_t j = 0; j < 4; j++) { 521 | if (!in_range(esc[j], 'a', 'f') && !in_range(esc[j], 'A', 'F') 522 | && !in_range(esc[j], '0', '9')) 523 | return fail("bad \\u escape: " + esc, ""); 524 | } 525 | 526 | long codepoint = strtol(esc.data(), nullptr, 16); 527 | 528 | // JSON specifies that characters outside the BMP shall be encoded as a pair 529 | // of 4-hex-digit \u escapes encoding their surrogate pair components. Check 530 | // whether we're in the middle of such a beast: the previous codepoint was an 531 | // escaped lead (high) surrogate, and this is a trail (low) surrogate. 532 | if (in_range(last_escaped_codepoint, 0xD800, 0xDBFF) 533 | && in_range(codepoint, 0xDC00, 0xDFFF)) { 534 | // Reassemble the two surrogate pairs into one astral-plane character, per 535 | // the UTF-16 algorithm. 536 | encode_utf8((((last_escaped_codepoint - 0xD800) << 10) 537 | | (codepoint - 0xDC00)) + 0x10000, out); 538 | last_escaped_codepoint = -1; 539 | } else { 540 | encode_utf8(last_escaped_codepoint, out); 541 | last_escaped_codepoint = codepoint; 542 | } 543 | 544 | i += 4; 545 | continue; 546 | } 547 | 548 | encode_utf8(last_escaped_codepoint, out); 549 | last_escaped_codepoint = -1; 550 | 551 | if (ch == 'b') { 552 | out += '\b'; 553 | } else if (ch == 'f') { 554 | out += '\f'; 555 | } else if (ch == 'n') { 556 | out += '\n'; 557 | } else if (ch == 'r') { 558 | out += '\r'; 559 | } else if (ch == 't') { 560 | out += '\t'; 561 | } else if (ch == '"' || ch == '\\' || ch == '/') { 562 | out += ch; 563 | } else { 564 | return fail("invalid escape character " + esc(ch), ""); 565 | } 566 | } 567 | } 568 | 569 | /* parse_number() 570 | * 571 | * Parse a double. 572 | */ 573 | Json parse_number() { 574 | size_t start_pos = i; 575 | 576 | if (str[i] == '-') 577 | i++; 578 | 579 | // Integer part 580 | if (str[i] == '0') { 581 | i++; 582 | if (in_range(str[i], '0', '9')) 583 | return fail("leading 0s not permitted in numbers"); 584 | } else if (in_range(str[i], '1', '9')) { 585 | i++; 586 | while (in_range(str[i], '0', '9')) 587 | i++; 588 | } else { 589 | return fail("invalid " + esc(str[i]) + " in number"); 590 | } 591 | 592 | if (str[i] != '.' && str[i] != 'e' && str[i] != 'E' 593 | && (i - start_pos) <= static_cast(std::numeric_limits::digits10)) { 594 | return std::atoi(str.c_str() + start_pos); 595 | } 596 | 597 | // Decimal part 598 | if (str[i] == '.') { 599 | i++; 600 | if (!in_range(str[i], '0', '9')) 601 | return fail("at least one digit required in fractional part"); 602 | 603 | while (in_range(str[i], '0', '9')) 604 | i++; 605 | } 606 | 607 | // Exponent part 608 | if (str[i] == 'e' || str[i] == 'E') { 609 | i++; 610 | 611 | if (str[i] == '+' || str[i] == '-') 612 | i++; 613 | 614 | if (!in_range(str[i], '0', '9')) 615 | return fail("at least one digit required in exponent"); 616 | 617 | while (in_range(str[i], '0', '9')) 618 | i++; 619 | } 620 | 621 | return std::strtod(str.c_str() + start_pos, nullptr); 622 | } 623 | 624 | /* expect(str, res) 625 | * 626 | * Expect that 'str' starts at the character that was just read. If it does, advance 627 | * the input and return res. If not, flag an error. 628 | */ 629 | Json expect(const string &expected, Json res) { 630 | assert(i != 0); 631 | i--; 632 | if (str.compare(i, expected.length(), expected) == 0) { 633 | i += expected.length(); 634 | return res; 635 | } else { 636 | return fail("parse error: expected " + expected + ", got " + str.substr(i, expected.length())); 637 | } 638 | } 639 | 640 | /* parse_json() 641 | * 642 | * Parse a JSON object. 643 | */ 644 | Json parse_json(int depth) { 645 | if (depth > max_depth) { 646 | return fail("exceeded maximum nesting depth"); 647 | } 648 | 649 | char ch = get_next_token(); 650 | if (failed) 651 | return Json(); 652 | 653 | if (ch == '-' || (ch >= '0' && ch <= '9')) { 654 | i--; 655 | return parse_number(); 656 | } 657 | 658 | if (ch == 't') 659 | return expect("true", true); 660 | 661 | if (ch == 'f') 662 | return expect("false", false); 663 | 664 | if (ch == 'n') 665 | return expect("null", Json()); 666 | 667 | if (ch == '"') 668 | return parse_string(); 669 | 670 | if (ch == '{') { 671 | map data; 672 | ch = get_next_token(); 673 | if (ch == '}') 674 | return data; 675 | 676 | while (1) { 677 | if (ch != '"') 678 | return fail("expected '\"' in object, got " + esc(ch)); 679 | 680 | string key = parse_string(); 681 | if (failed) 682 | return Json(); 683 | 684 | ch = get_next_token(); 685 | if (ch != ':') 686 | return fail("expected ':' in object, got " + esc(ch)); 687 | 688 | data[std::move(key)] = parse_json(depth + 1); 689 | if (failed) 690 | return Json(); 691 | 692 | ch = get_next_token(); 693 | if (ch == '}') 694 | break; 695 | if (ch != ',') 696 | return fail("expected ',' in object, got " + esc(ch)); 697 | 698 | ch = get_next_token(); 699 | } 700 | return data; 701 | } 702 | 703 | if (ch == '[') { 704 | vector data; 705 | ch = get_next_token(); 706 | if (ch == ']') 707 | return data; 708 | 709 | while (1) { 710 | i--; 711 | data.push_back(parse_json(depth + 1)); 712 | if (failed) 713 | return Json(); 714 | 715 | ch = get_next_token(); 716 | if (ch == ']') 717 | break; 718 | if (ch != ',') 719 | return fail("expected ',' in list, got " + esc(ch)); 720 | 721 | ch = get_next_token(); 722 | (void)ch; 723 | } 724 | return data; 725 | } 726 | 727 | return fail("expected value, got " + esc(ch)); 728 | } 729 | }; 730 | }//namespace { 731 | 732 | Json Json::parse(const string &in, string &err, JsonParse strategy) { 733 | JsonParser parser { in, 0, err, false, strategy }; 734 | Json result = parser.parse_json(0); 735 | 736 | // Check for any trailing garbage 737 | parser.consume_garbage(); 738 | if (parser.failed) 739 | return Json(); 740 | if (parser.i != in.size()) 741 | return parser.fail("unexpected trailing " + esc(in[parser.i])); 742 | 743 | return result; 744 | } 745 | 746 | // Documented in json11.hpp 747 | vector Json::parse_multi(const string &in, 748 | std::string::size_type &parser_stop_pos, 749 | string &err, 750 | JsonParse strategy) { 751 | JsonParser parser { in, 0, err, false, strategy }; 752 | parser_stop_pos = 0; 753 | vector json_vec; 754 | while (parser.i != in.size() && !parser.failed) { 755 | json_vec.push_back(parser.parse_json(0)); 756 | if (parser.failed) 757 | break; 758 | 759 | // Check for another object 760 | parser.consume_garbage(); 761 | if (parser.failed) 762 | break; 763 | parser_stop_pos = parser.i; 764 | } 765 | return json_vec; 766 | } 767 | 768 | /* * * * * * * * * * * * * * * * * * * * 769 | * Shape-checking 770 | */ 771 | 772 | bool Json::has_shape(const shape & types, string & err) const { 773 | if (!is_object()) { 774 | err = "expected JSON object, got " + dump(); 775 | return false; 776 | } 777 | 778 | const auto& obj_items = object_items(); 779 | for (auto & item : types) { 780 | const auto it = obj_items.find(item.first); 781 | if (it == obj_items.cend() || it->second.type() != item.second) { 782 | err = "bad type for " + item.first + " in " + dump(); 783 | return false; 784 | } 785 | } 786 | 787 | return true; 788 | } 789 | 790 | } // namespace json11 791 | -------------------------------------------------------------------------------- /plugins/lib/json/json11.hpp: -------------------------------------------------------------------------------- 1 | /* json11 2 | * 3 | * json11 is a tiny JSON library for C++11, providing JSON parsing and serialization. 4 | * 5 | * The core object provided by the library is json11::Json. A Json object represents any JSON 6 | * value: null, bool, number (int or double), string (std::string), array (std::vector), or 7 | * object (std::map). 8 | * 9 | * Json objects act like values: they can be assigned, copied, moved, compared for equality or 10 | * order, etc. There are also helper methods Json::dump, to serialize a Json to a string, and 11 | * Json::parse (static) to parse a std::string as a Json object. 12 | * 13 | * Internally, the various types of Json object are represented by the JsonValue class 14 | * hierarchy. 15 | * 16 | * A note on numbers - JSON specifies the syntax of number formatting but not its semantics, 17 | * so some JSON implementations distinguish between integers and floating-point numbers, while 18 | * some don't. In json11, we choose the latter. Because some JSON implementations (namely 19 | * Javascript itself) treat all numbers as the same type, distinguishing the two leads 20 | * to JSON that will be *silently* changed by a round-trip through those implementations. 21 | * Dangerous! To avoid that risk, json11 stores all numbers as double internally, but also 22 | * provides integer helpers. 23 | * 24 | * Fortunately, double-precision IEEE754 ('double') can precisely store any integer in the 25 | * range +/-2^53, which includes every 'int' on most systems. (Timestamps often use int64 26 | * or long long to avoid the Y2038K problem; a double storing microseconds since some epoch 27 | * will be exact for +/- 275 years.) 28 | */ 29 | 30 | /* Copyright (c) 2013 Dropbox, Inc. 31 | * 32 | * Permission is hereby granted, free of charge, to any person obtaining a copy 33 | * of this software and associated documentation files (the "Software"), to deal 34 | * in the Software without restriction, including without limitation the rights 35 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 36 | * copies of the Software, and to permit persons to whom the Software is 37 | * furnished to do so, subject to the following conditions: 38 | * 39 | * The above copyright notice and this permission notice shall be included in 40 | * all copies or substantial portions of the Software. 41 | * 42 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 43 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 44 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 45 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 46 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 47 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 48 | * THE SOFTWARE. 49 | */ 50 | 51 | #pragma once 52 | 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | 59 | #ifdef _MSC_VER 60 | #if _MSC_VER <= 1800 // VS 2013 61 | #ifndef noexcept 62 | #define noexcept throw() 63 | #endif 64 | 65 | #ifndef snprintf 66 | #define snprintf _snprintf_s 67 | #endif 68 | #endif 69 | #endif 70 | 71 | namespace json11 { 72 | 73 | enum JsonParse { 74 | STANDARD, COMMENTS 75 | }; 76 | 77 | class JsonValue; 78 | 79 | class Json final { 80 | public: 81 | // Types 82 | enum Type { 83 | NUL, NUMBER, BOOL, STRING, ARRAY, OBJECT 84 | }; 85 | 86 | // Array and object typedefs 87 | typedef std::vector array; 88 | typedef std::map object; 89 | 90 | // Constructors for the various types of JSON value. 91 | Json() noexcept; // NUL 92 | Json(std::nullptr_t) noexcept; // NUL 93 | Json(double value); // NUMBER 94 | Json(int value); // NUMBER 95 | Json(bool value); // BOOL 96 | Json(const std::string &value); // STRING 97 | Json(std::string &&value); // STRING 98 | Json(const char * value); // STRING 99 | Json(const array &values); // ARRAY 100 | Json(array &&values); // ARRAY 101 | Json(const object &values); // OBJECT 102 | Json(object &&values); // OBJECT 103 | 104 | // Implicit constructor: anything with a to_json() function. 105 | template 106 | Json(const T & t) : Json(t.to_json()) {} 107 | 108 | // Implicit constructor: map-like objects (std::map, std::unordered_map, etc) 109 | template ().begin()->first)>::value 111 | && std::is_constructible().begin()->second)>::value, 112 | int>::type = 0> 113 | Json(const M & m) : Json(object(m.begin(), m.end())) {} 114 | 115 | // Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc) 116 | template ().begin())>::value, 118 | int>::type = 0> 119 | Json(const V & v) : Json(array(v.begin(), v.end())) {} 120 | 121 | // This prevents Json(some_pointer) from accidentally producing a bool. Use 122 | // Json(bool(some_pointer)) if that behavior is desired. 123 | Json(void *) = delete; 124 | 125 | // Accessors 126 | Type type() const; 127 | 128 | bool is_null() const { return type() == NUL; } 129 | bool is_number() const { return type() == NUMBER; } 130 | bool is_bool() const { return type() == BOOL; } 131 | bool is_string() const { return type() == STRING; } 132 | bool is_array() const { return type() == ARRAY; } 133 | bool is_object() const { return type() == OBJECT; } 134 | 135 | // Return the enclosed value if this is a number, 0 otherwise. Note that json11 does not 136 | // distinguish between integer and non-integer numbers - number_value() and int_value() 137 | // can both be applied to a NUMBER-typed object. 138 | double number_value() const; 139 | int int_value() const; 140 | 141 | // Return the enclosed value if this is a boolean, false otherwise. 142 | bool bool_value() const; 143 | // Return the enclosed string if this is a string, "" otherwise. 144 | const std::string &string_value() const; 145 | // Return the enclosed std::vector if this is an array, or an empty vector otherwise. 146 | const array &array_items() const; 147 | // Return the enclosed std::map if this is an object, or an empty map otherwise. 148 | const object &object_items() const; 149 | 150 | // Return a reference to arr[i] if this is an array, Json() otherwise. 151 | const Json & operator[](size_t i) const; 152 | // Return a reference to obj[key] if this is an object, Json() otherwise. 153 | const Json & operator[](const std::string &key) const; 154 | 155 | // Serialize. 156 | void dump(std::string &out) const; 157 | std::string dump() const { 158 | std::string out; 159 | dump(out); 160 | return out; 161 | } 162 | 163 | // Parse. If parse fails, return Json() and assign an error message to err. 164 | static Json parse(const std::string & in, 165 | std::string & err, 166 | JsonParse strategy = JsonParse::STANDARD); 167 | static Json parse(const char * in, 168 | std::string & err, 169 | JsonParse strategy = JsonParse::STANDARD) { 170 | if (in) { 171 | return parse(std::string(in), err, strategy); 172 | } else { 173 | err = "null input"; 174 | return nullptr; 175 | } 176 | } 177 | // Parse multiple objects, concatenated or separated by whitespace 178 | static std::vector parse_multi( 179 | const std::string & in, 180 | std::string::size_type & parser_stop_pos, 181 | std::string & err, 182 | JsonParse strategy = JsonParse::STANDARD); 183 | 184 | static inline std::vector parse_multi( 185 | const std::string & in, 186 | std::string & err, 187 | JsonParse strategy = JsonParse::STANDARD) { 188 | std::string::size_type parser_stop_pos; 189 | return parse_multi(in, parser_stop_pos, err, strategy); 190 | } 191 | 192 | bool operator== (const Json &rhs) const; 193 | bool operator< (const Json &rhs) const; 194 | bool operator!= (const Json &rhs) const { return !(*this == rhs); } 195 | bool operator<= (const Json &rhs) const { return !(rhs < *this); } 196 | bool operator> (const Json &rhs) const { return (rhs < *this); } 197 | bool operator>= (const Json &rhs) const { return !(*this < rhs); } 198 | 199 | /* has_shape(types, err) 200 | * 201 | * Return true if this is a JSON object and, for each item in types, has a field of 202 | * the given type. If not, return false and set err to a descriptive message. 203 | */ 204 | typedef std::initializer_list> shape; 205 | bool has_shape(const shape & types, std::string & err) const; 206 | 207 | private: 208 | std::shared_ptr m_ptr; 209 | }; 210 | 211 | // Internal class hierarchy - JsonValue objects are not exposed to users of this API. 212 | class JsonValue { 213 | protected: 214 | friend class Json; 215 | friend class JsonInt; 216 | friend class JsonDouble; 217 | virtual Json::Type type() const = 0; 218 | virtual bool equals(const JsonValue * other) const = 0; 219 | virtual bool less(const JsonValue * other) const = 0; 220 | virtual void dump(std::string &out) const = 0; 221 | virtual double number_value() const; 222 | virtual int int_value() const; 223 | virtual bool bool_value() const; 224 | virtual const std::string &string_value() const; 225 | virtual const Json::array &array_items() const; 226 | virtual const Json &operator[](size_t i) const; 227 | virtual const Json::object &object_items() const; 228 | virtual const Json &operator[](const std::string &key) const; 229 | virtual ~JsonValue() {} 230 | }; 231 | 232 | } // namespace json11 233 | -------------------------------------------------------------------------------- /plugins/lib/sdk/amx/amx.h: -------------------------------------------------------------------------------- 1 | /* Pawn Abstract Machine (for the Pawn language) 2 | * 3 | * Copyright (c) ITB CompuPhase, 1997-2005 4 | * 5 | * This software is provided "as-is", without any express or implied warranty. 6 | * In no event will the authors be held liable for any damages arising from 7 | * the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any purpose, 10 | * including commercial applications, and to alter it and redistribute it 11 | * freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you must not 14 | * claim that you wrote the original software. If you use this software in 15 | * a product, an acknowledgment in the product documentation would be 16 | * appreciated but is not required. 17 | * 2. Altered source versions must be plainly marked as such, and must not be 18 | * misrepresented as being the original software. 19 | * 3. This notice may not be removed or altered from any source distribution. 20 | * 21 | * Version: $Id: amx.h,v 1.5 2006/03/26 16:56:15 spookie Exp $ 22 | */ 23 | 24 | #if defined __linux__ || defined __FreeBSD__ || defined __OpenBSD__ 25 | #include "sclinux.h" 26 | #endif 27 | 28 | #ifndef AMX_H_INCLUDED 29 | #define AMX_H_INCLUDED 30 | 31 | #if defined HAVE_STDINT_H 32 | #include 33 | #else 34 | #if defined __LCC__ || defined __DMC__ || defined __linux__ 35 | #if defined HAVE_INTTYPES_H 36 | #include 37 | #else 38 | #include 39 | #endif 40 | #elif !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L 41 | /* The ISO C99 defines the int16_t and int_32t types. If the compiler got 42 | * here, these types are probably undefined. 43 | */ 44 | #if defined __MACH__ 45 | #include 46 | typedef unsigned short int uint16_t; 47 | typedef unsigned long int uint32_t; 48 | #elif defined __FreeBSD__ 49 | #include 50 | #else 51 | typedef short int int16_t; 52 | typedef unsigned short int uint16_t; 53 | #if defined SN_TARGET_PS2 54 | typedef int int32_t; 55 | typedef unsigned int uint32_t; 56 | #else 57 | typedef long int int32_t; 58 | typedef unsigned long int uint32_t; 59 | #endif 60 | #if defined _WIN32 61 | typedef __int64 int64_t; 62 | typedef unsigned __int64 uint64_t; 63 | #define HAVE_I64 64 | #elif defined __GNUC__ 65 | typedef long long int64_t; 66 | typedef unsigned long long uint64_t; 67 | #define HAVE_I64 68 | #endif 69 | #endif 70 | #endif 71 | #define HAVE_STDINT_H 72 | #endif 73 | #if defined _LP64 || defined _WIN64 74 | #if !defined __64BIT__ 75 | #define __64BIT__ 76 | #endif 77 | #endif 78 | 79 | #if HAVE_ALLOCA_H 80 | #include 81 | #endif 82 | #if defined _WIN32 83 | #if !defined alloca 84 | //#define alloca(n) _alloca(n) 85 | #endif 86 | #endif 87 | 88 | #if !defined arraysize 89 | #define arraysize(array) (sizeof(array) / sizeof((array)[0])) 90 | #endif 91 | 92 | #ifdef __cplusplus 93 | extern "C" { 94 | #endif 95 | 96 | #if defined PAWN_DLL 97 | #if !defined AMX_NATIVE_CALL 98 | #define AMX_NATIVE_CALL __stdcall 99 | #endif 100 | #if !defined AMXAPI 101 | #define AMXAPI __stdcall 102 | #endif 103 | #endif 104 | 105 | /* calling convention for native functions */ 106 | #if !defined AMX_NATIVE_CALL 107 | #define AMX_NATIVE_CALL 108 | #endif 109 | /* calling convention for all interface functions and callback functions */ 110 | #if !defined AMXAPI 111 | #if defined STDECL 112 | #define AMXAPI __stdcall 113 | #elif defined CDECL 114 | #define AMXAPI __cdecl 115 | #elif defined GCC_HASCLASSVISIBILITY 116 | #define AMXAPI __attribute__ ((visibility("default"))) 117 | #else 118 | #define AMXAPI 119 | #endif 120 | #endif 121 | #if !defined AMXEXPORT 122 | #define AMXEXPORT 123 | #endif 124 | 125 | /* File format version Required AMX version 126 | * 0 (original version) 0 127 | * 1 (opcodes JUMP.pri, SWITCH and CASETBL) 1 128 | * 2 (compressed files) 2 129 | * 3 (public variables) 2 130 | * 4 (opcodes SWAP.pri/alt and PUSHADDR) 4 131 | * 5 (tagnames table) 4 132 | * 6 (reformatted header) 6 133 | * 7 (name table, opcodes SYMTAG & SYSREQ.D) 7 134 | * 8 (opcode STMT, renewed debug interface) 8 135 | */ 136 | #define CUR_FILE_VERSION 8 /* current file version; also the current AMX version */ 137 | #define MIN_FILE_VERSION 6 /* lowest supported file format version for the current AMX version */ 138 | #define MIN_AMX_VERSION 8 /* minimum AMX version needed to support the current file format */ 139 | 140 | #if !defined PAWN_CELL_SIZE 141 | #define PAWN_CELL_SIZE 32 /* by default, use 32-bit cells */ 142 | #endif 143 | #if PAWN_CELL_SIZE==16 144 | typedef uint16_t ucell; 145 | typedef int16_t cell; 146 | #elif PAWN_CELL_SIZE==32 147 | typedef uint32_t ucell; 148 | typedef int32_t cell; 149 | #elif PAWN_CELL_SIZE==64 150 | typedef uint64_t ucell; 151 | typedef int64_t cell; 152 | #else 153 | #error Unsupported cell size (PAWN_CELL_SIZE) 154 | #endif 155 | 156 | #define UNPACKEDMAX ((1L << (sizeof(cell)-1)*8) - 1) 157 | #define UNLIMITED (~1u >> 1) 158 | 159 | struct tagAMX; 160 | typedef cell (AMX_NATIVE_CALL *AMX_NATIVE)(struct tagAMX *amx, cell *params); 161 | typedef int (AMXAPI *AMX_CALLBACK)(struct tagAMX *amx, cell index, 162 | cell *result, cell *params); 163 | typedef int (AMXAPI *AMX_DEBUG)(struct tagAMX *amx); 164 | #if !defined _FAR 165 | #define _FAR 166 | #endif 167 | 168 | #if defined _MSC_VER 169 | #pragma warning(disable:4103) /* disable warning message 4103 that complains 170 | * about pragma pack in a header file */ 171 | #pragma warning(disable:4100) /* "'%$S' : unreferenced formal parameter" */ 172 | #endif 173 | 174 | /* Some compilers do not support the #pragma align, which should be fine. Some 175 | * compilers give a warning on unknown #pragmas, which is not so fine... 176 | */ 177 | #if (defined SN_TARGET_PS2 || defined __GNUC__) && !defined AMX_NO_ALIGN 178 | #define AMX_NO_ALIGN 179 | #endif 180 | 181 | #if defined __GNUC__ 182 | #define PACKED __attribute__((packed)) 183 | #else 184 | #define PACKED 185 | #endif 186 | 187 | #if !defined AMX_NO_ALIGN 188 | #if defined __linux__ || defined __FreeBSD__ 189 | #pragma pack(1) /* structures must be packed (byte-aligned) */ 190 | #elif defined MACOS && defined __MWERKS__ 191 | #pragma options align=mac68k 192 | #else 193 | #pragma pack(push) 194 | #pragma pack(1) /* structures must be packed (byte-aligned) */ 195 | #if defined __TURBOC__ 196 | #pragma option -a- /* "pack" pragma for older Borland compilers */ 197 | #endif 198 | #endif 199 | #endif 200 | 201 | typedef struct tagAMX_NATIVE_INFO { 202 | const char _FAR *name PACKED; 203 | AMX_NATIVE func PACKED; 204 | } PACKED AMX_NATIVE_INFO; 205 | 206 | #define AMX_USERNUM 4 207 | #define sEXPMAX 19 /* maximum name length for file version <= 6 */ 208 | #define sNAMEMAX 31 /* maximum name length of symbol name */ 209 | 210 | typedef struct tagAMX_FUNCSTUB { 211 | ucell address PACKED; 212 | char name[sEXPMAX+1]; 213 | } PACKED AMX_FUNCSTUB; 214 | 215 | typedef struct tagFUNCSTUBNT { 216 | ucell address PACKED; 217 | uint32_t nameofs PACKED; 218 | } PACKED AMX_FUNCSTUBNT; 219 | 220 | /* The AMX structure is the internal structure for many functions. Not all 221 | * fields are valid at all times; many fields are cached in local variables. 222 | */ 223 | typedef struct tagAMX { 224 | unsigned char _FAR *base PACKED; /* points to the AMX header plus the code, optionally also the data */ 225 | unsigned char _FAR *data PACKED; /* points to separate data+stack+heap, may be NULL */ 226 | AMX_CALLBACK callback PACKED; 227 | AMX_DEBUG debug PACKED; /* debug callback */ 228 | /* for external functions a few registers must be accessible from the outside */ 229 | cell cip PACKED; /* instruction pointer: relative to base + amxhdr->cod */ 230 | cell frm PACKED; /* stack frame base: relative to base + amxhdr->dat */ 231 | cell hea PACKED; /* top of the heap: relative to base + amxhdr->dat */ 232 | cell hlw PACKED; /* bottom of the heap: relative to base + amxhdr->dat */ 233 | cell stk PACKED; /* stack pointer: relative to base + amxhdr->dat */ 234 | cell stp PACKED; /* top of the stack: relative to base + amxhdr->dat */ 235 | int flags PACKED; /* current status, see amx_Flags() */ 236 | /* user data */ 237 | long usertags[AMX_USERNUM] PACKED; 238 | void _FAR *userdata[AMX_USERNUM] PACKED; 239 | /* native functions can raise an error */ 240 | int error PACKED; 241 | /* passing parameters requires a "count" field */ 242 | int paramcount; 243 | /* the sleep opcode needs to store the full AMX status */ 244 | cell pri PACKED; 245 | cell alt PACKED; 246 | cell reset_stk PACKED; 247 | cell reset_hea PACKED; 248 | cell sysreq_d PACKED; /* relocated address/value for the SYSREQ.D opcode */ 249 | #if defined JIT 250 | /* support variables for the JIT */ 251 | int reloc_size PACKED; /* required temporary buffer for relocations */ 252 | long code_size PACKED; /* estimated memory footprint of the native code */ 253 | #endif 254 | } PACKED AMX; 255 | 256 | /* The AMX_HEADER structure is both the memory format as the file format. The 257 | * structure is used internaly. 258 | */ 259 | typedef struct tagAMX_HEADER { 260 | int32_t size PACKED; /* size of the "file" */ 261 | uint16_t magic PACKED; /* signature */ 262 | char file_version; /* file format version */ 263 | char amx_version; /* required version of the AMX */ 264 | int16_t flags PACKED; 265 | int16_t defsize PACKED; /* size of a definition record */ 266 | int32_t cod PACKED; /* initial value of COD - code block */ 267 | int32_t dat PACKED; /* initial value of DAT - data block */ 268 | int32_t hea PACKED; /* initial value of HEA - start of the heap */ 269 | int32_t stp PACKED; /* initial value of STP - stack top */ 270 | int32_t cip PACKED; /* initial value of CIP - the instruction pointer */ 271 | int32_t publics PACKED; /* offset to the "public functions" table */ 272 | int32_t natives PACKED; /* offset to the "native functions" table */ 273 | int32_t libraries PACKED; /* offset to the table of libraries */ 274 | int32_t pubvars PACKED; /* the "public variables" table */ 275 | int32_t tags PACKED; /* the "public tagnames" table */ 276 | int32_t nametable PACKED; /* name table */ 277 | } PACKED AMX_HEADER; 278 | 279 | #if PAWN_CELL_SIZE==16 280 | #define AMX_MAGIC 0xf1e2 281 | #elif PAWN_CELL_SIZE==32 282 | #define AMX_MAGIC 0xf1e0 283 | #elif PAWN_CELL_SIZE==64 284 | #define AMX_MAGIC 0xf1e1 285 | #endif 286 | 287 | enum { 288 | AMX_ERR_NONE, 289 | /* reserve the first 15 error codes for exit codes of the abstract machine */ 290 | AMX_ERR_EXIT, /* forced exit */ 291 | AMX_ERR_ASSERT, /* assertion failed */ 292 | AMX_ERR_STACKERR, /* stack/heap collision */ 293 | AMX_ERR_BOUNDS, /* index out of bounds */ 294 | AMX_ERR_MEMACCESS, /* invalid memory access */ 295 | AMX_ERR_INVINSTR, /* invalid instruction */ 296 | AMX_ERR_STACKLOW, /* stack underflow */ 297 | AMX_ERR_HEAPLOW, /* heap underflow */ 298 | AMX_ERR_CALLBACK, /* no callback, or invalid callback */ 299 | AMX_ERR_NATIVE, /* native function failed */ 300 | AMX_ERR_DIVIDE, /* divide by zero */ 301 | AMX_ERR_SLEEP, /* go into sleepmode - code can be restarted */ 302 | AMX_ERR_INVSTATE, /* invalid state for this access */ 303 | 304 | AMX_ERR_MEMORY = 16, /* out of memory */ 305 | AMX_ERR_FORMAT, /* invalid file format */ 306 | AMX_ERR_VERSION, /* file is for a newer version of the AMX */ 307 | AMX_ERR_NOTFOUND, /* function not found */ 308 | AMX_ERR_INDEX, /* invalid index parameter (bad entry point) */ 309 | AMX_ERR_DEBUG, /* debugger cannot run */ 310 | AMX_ERR_INIT, /* AMX not initialized (or doubly initialized) */ 311 | AMX_ERR_USERDATA, /* unable to set user data field (table full) */ 312 | AMX_ERR_INIT_JIT, /* cannot initialize the JIT */ 313 | AMX_ERR_PARAMS, /* parameter error */ 314 | AMX_ERR_DOMAIN, /* domain error, expression result does not fit in range */ 315 | AMX_ERR_GENERAL, /* general error (unknown or unspecific error) */ 316 | }; 317 | 318 | /* AMX_FLAG_CHAR16 0x01 no longer used */ 319 | #define AMX_FLAG_DEBUG 0x02 /* symbolic info. available */ 320 | #define AMX_FLAG_COMPACT 0x04 /* compact encoding */ 321 | #define AMX_FLAG_BYTEOPC 0x08 /* opcode is a byte (not a cell) */ 322 | #define AMX_FLAG_NOCHECKS 0x10 /* no array bounds checking; no STMT opcode */ 323 | #define AMX_FLAG_NTVREG 0x1000 /* all native functions are registered */ 324 | #define AMX_FLAG_JITC 0x2000 /* abstract machine is JIT compiled */ 325 | #define AMX_FLAG_BROWSE 0x4000 /* busy browsing */ 326 | #define AMX_FLAG_RELOC 0x8000 /* jump/call addresses relocated */ 327 | 328 | #define AMX_EXEC_MAIN -1 /* start at program entry point */ 329 | #define AMX_EXEC_CONT -2 /* continue from last address */ 330 | 331 | #define AMX_USERTAG(a,b,c,d) ((a) | ((b)<<8) | ((long)(c)<<16) | ((long)(d)<<24)) 332 | 333 | #if !defined AMX_COMPACTMARGIN 334 | #define AMX_COMPACTMARGIN 64 335 | #endif 336 | 337 | /* for native functions that use floating point parameters, the following 338 | * two macros are convenient for casting a "cell" into a "float" type _without_ 339 | * changing the bit pattern 340 | */ 341 | #if PAWN_CELL_SIZE==32 342 | #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */ 343 | #define amx_ctof(c) ( * ((float*)&c) ) /* cell to float */ 344 | #elif PAWN_CELL_SIZE==64 345 | #define amx_ftoc(f) ( * ((cell*)&f) ) /* float to cell */ 346 | #define amx_ctof(c) ( * ((double*)&c) ) /* cell to float */ 347 | #else 348 | #error Unsupported cell size 349 | #endif 350 | 351 | #define amx_StrParam(amx,param,result) \ 352 | do { \ 353 | cell *amx_cstr_; int amx_length_; \ 354 | amx_GetAddr((amx), (param), &amx_cstr_); \ 355 | amx_StrLen(amx_cstr_, &amx_length_); \ 356 | if (amx_length_ > 0 && \ 357 | ((result) = (char*)alloca((amx_length_ + 1) * sizeof(*(result)))) != NULL) \ 358 | amx_GetString((char*)(result), amx_cstr_, sizeof(*(result))>1, amx_length_ + 1); \ 359 | else (result) = NULL; \ 360 | } while (0) 361 | 362 | uint16_t * AMXAPI amx_Align16(uint16_t *v); 363 | uint32_t * AMXAPI amx_Align32(uint32_t *v); 364 | #if defined _I64_MAX || defined HAVE_I64 365 | uint64_t * AMXAPI amx_Align64(uint64_t *v); 366 | #endif 367 | int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr); 368 | int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params); 369 | int AMXAPI amx_Cleanup(AMX *amx); 370 | int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data); 371 | int AMXAPI amx_Exec(AMX *amx, cell *retval, int index); 372 | int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index); 373 | int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index); 374 | int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr); 375 | int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname); 376 | int AMXAPI amx_Flags(AMX *amx,uint16_t *flags); 377 | int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr); 378 | int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname); 379 | int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname); 380 | int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr); 381 | int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar, size_t size); 382 | int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id); 383 | int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr); 384 | int AMXAPI amx_Init(AMX *amx, void *program); 385 | int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code); 386 | int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap); 387 | int AMXAPI amx_NameLength(AMX *amx, int *length); 388 | AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func); 389 | int AMXAPI amx_NumNatives(AMX *amx, int *number); 390 | int AMXAPI amx_NumPublics(AMX *amx, int *number); 391 | int AMXAPI amx_NumPubVars(AMX *amx, int *number); 392 | int AMXAPI amx_NumTags(AMX *amx, int *number); 393 | int AMXAPI amx_Push(AMX *amx, cell value); 394 | int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells); 395 | int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar); 396 | int AMXAPI amx_RaiseError(AMX *amx, int error); 397 | int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number); 398 | int AMXAPI amx_Release(AMX *amx, cell amx_addr); 399 | int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback); 400 | int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug); 401 | int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar, size_t size); 402 | int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr); 403 | int AMXAPI amx_StrLen(const cell *cstring, int *length); 404 | int AMXAPI amx_UTF8Check(const char *string, int *length); 405 | int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value); 406 | int AMXAPI amx_UTF8Len(const cell *cstr, int *length); 407 | int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value); 408 | 409 | #if PAWN_CELL_SIZE==16 410 | #define amx_AlignCell(v) amx_Align16(v) 411 | #elif PAWN_CELL_SIZE==32 412 | #define amx_AlignCell(v) amx_Align32(v) 413 | #elif PAWN_CELL_SIZE==64 && (defined _I64_MAX || defined HAVE_I64) 414 | #define amx_AlignCell(v) amx_Align64(v) 415 | #else 416 | #error Unsupported cell size 417 | #endif 418 | 419 | #define amx_RegisterFunc(amx, name, func) \ 420 | amx_Register((amx), amx_NativeInfo((name),(func)), 1); 421 | 422 | #if !defined AMX_NO_ALIGN 423 | #if defined __linux__ || defined __FreeBSD__ 424 | #pragma pack() /* reset default packing */ 425 | #elif defined MACOS && defined __MWERKS__ 426 | #pragma options align=reset 427 | #else 428 | #pragma pack(pop) /* reset previous packing */ 429 | #endif 430 | #endif 431 | 432 | #ifdef __cplusplus 433 | } 434 | #endif 435 | 436 | #endif /* AMX_H_INCLUDED */ 437 | -------------------------------------------------------------------------------- /plugins/lib/sdk/amx/getch.h: -------------------------------------------------------------------------------- 1 | /* Extremely inefficient but portable POSIX getch(), see getch.c */ 2 | #ifndef GETCH_H 3 | #define GETCH_H 4 | 5 | #if defined __cplusplus 6 | extern "C" { 7 | #endif 8 | int getch(void); 9 | int kbhit(void); 10 | 11 | #if defined __cplusplus 12 | } 13 | #endif 14 | 15 | #endif /* GETCH_H */ 16 | -------------------------------------------------------------------------------- /plugins/lib/sdk/amx/sclinux.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Things needed to compile under linux. 3 | * 4 | * Should be reworked totally to use GNU's 'configure' 5 | */ 6 | #ifndef SCLINUX_H 7 | #define SCLINUX_H 8 | 9 | /* getchar() is not a 'cool' replacement for MSDOS getch: Linux/unix depends on the features activated or not about the 10 | * controlling terminal's tty. This means that ioctl(2) calls must be performed, for instance to have the controlling 11 | * terminal tty's in 'raw' mode, if we want to be able to fetch a single character. This also means that everything must 12 | * be put back correctly when the function ends. See GETCH.C for an implementation. 13 | * 14 | * For interactive use of SRUN/SDBG if would be much better to use GNU's readline package: the user would be able to 15 | * have a complete emacs/vi like line editing system. 16 | */ 17 | #include "getch.h" 18 | 19 | #define stricmp(a,b) strcasecmp(a,b) 20 | #define strnicmp(a,b,c) strncasecmp(a,b,c) 21 | 22 | /* 23 | * WinWorld wants '\'. Unices do not. 24 | */ 25 | #define DIRECTORY_SEP_CHAR '/' 26 | #define DIRECTORY_SEP_STR "/" 27 | 28 | /* 29 | * SC assumes that a computer is Little Endian unless told otherwise. It uses 30 | * (and defines) the macros BYTE_ORDER and BIG_ENDIAN. 31 | * For Linux, we must overrule these settings with those defined in glibc. 32 | */ 33 | #if !defined __BYTE_ORDER 34 | # include 35 | #endif 36 | 37 | #if defined __OpenBSD__ || defined __FreeBSD__ 38 | # define __BYTE_ORDER BYTE_ORDER 39 | # define __LITTLE_ENDIAN LITTLE_ENDIAN 40 | # define __BIG_ENDIAN BIG_ENDIAN 41 | #endif 42 | 43 | #if !defined __BYTE_ORDER 44 | # error "Can't figure computer byte order (__BYTE_ORDER macro not found)" 45 | #endif 46 | 47 | #endif /* SCLINUX_H */ 48 | -------------------------------------------------------------------------------- /plugins/lib/sdk/amxplugin.cpp: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------- 2 | // 3 | // SA-MP Multiplayer Modification For GTA:SA 4 | // Copyright 2004-2009 SA-MP Team 5 | // 6 | //---------------------------------------------------------- 7 | // 8 | // This provides an interface to call amx library functions 9 | // within samp-server. 10 | // 11 | //---------------------------------------------------------- 12 | 13 | #include "plugin.h" 14 | 15 | //---------------------------------------------------------- 16 | 17 | void *pAMXFunctions; 18 | 19 | //---------------------------------------------------------- 20 | 21 | typedef uint16_t * AMXAPI (*amx_Align16_t)(uint16_t *v); 22 | uint16_t * AMXAPI amx_Align16(uint16_t *v) 23 | { 24 | amx_Align16_t fn = ((amx_Align16_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Align16]; 25 | return fn(v); 26 | } 27 | 28 | typedef uint32_t * AMXAPI (*amx_Align32_t)(uint32_t *v); 29 | uint32_t * AMXAPI amx_Align32(uint32_t *v) 30 | { 31 | amx_Align32_t fn = ((amx_Align32_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Align32]; 32 | return fn(v); 33 | } 34 | 35 | #if defined _I64_MAX || defined HAVE_I64 36 | typedef uint64_t * AMXAPI (*amx_Align64_t)(uint64_t *v); 37 | uint64_t * AMXAPI amx_Align64(uint64_t *v) 38 | { 39 | amx_Align64_t fn = ((amx_Align64_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Align64]; 40 | return fn(v); 41 | } 42 | 43 | #endif 44 | typedef int AMXAPI (*amx_Allot_t)(AMX *amx, int cells, cell *amx_addr, cell **phys_addr); 45 | int AMXAPI amx_Allot(AMX *amx, int cells, cell *amx_addr, cell **phys_addr) 46 | { 47 | amx_Allot_t fn = ((amx_Allot_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Allot]; 48 | return fn(amx, cells, amx_addr, phys_addr); 49 | } 50 | 51 | typedef int AMXAPI (*amx_Callback_t)(AMX *amx, cell index, cell *result, cell *params); 52 | int AMXAPI amx_Callback(AMX *amx, cell index, cell *result, cell *params) 53 | { 54 | amx_Callback_t fn = ((amx_Callback_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Callback]; 55 | return fn(amx, index, result, params); 56 | } 57 | 58 | typedef int AMXAPI (*amx_Cleanup_t)(AMX *amx); 59 | int AMXAPI amx_Cleanup(AMX *amx) 60 | { 61 | amx_Cleanup_t fn = ((amx_Cleanup_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Cleanup]; 62 | return fn(amx); 63 | } 64 | 65 | typedef int AMXAPI (*amx_Clone_t)(AMX *amxClone, AMX *amxSource, void *data); 66 | int AMXAPI amx_Clone(AMX *amxClone, AMX *amxSource, void *data) 67 | { 68 | amx_Clone_t fn = ((amx_Clone_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Clone]; 69 | return fn(amxClone, amxSource, data); 70 | } 71 | 72 | typedef int AMXAPI (*amx_Exec_t)(AMX *amx, cell *retval, int index); 73 | int AMXAPI amx_Exec(AMX *amx, cell *retval, int index) 74 | { 75 | amx_Exec_t fn = ((amx_Exec_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec]; 76 | return fn(amx, retval, index); 77 | } 78 | 79 | typedef int AMXAPI (*amx_FindNative_t)(AMX *amx, const char *name, int *index); 80 | int AMXAPI amx_FindNative(AMX *amx, const char *name, int *index) 81 | { 82 | amx_FindNative_t fn = ((amx_FindNative_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_FindNative]; 83 | return fn(amx, name, index); 84 | } 85 | 86 | typedef int AMXAPI (*amx_FindPublic_t)(AMX *amx, const char *funcname, int *index); 87 | int AMXAPI amx_FindPublic(AMX *amx, const char *funcname, int *index) 88 | { 89 | amx_FindPublic_t fn = ((amx_FindPublic_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_FindPublic]; 90 | return fn(amx, funcname, index); 91 | } 92 | 93 | typedef int AMXAPI (*amx_FindPubVar_t)(AMX *amx, const char *varname, cell *amx_addr); 94 | int AMXAPI amx_FindPubVar(AMX *amx, const char *varname, cell *amx_addr) 95 | { 96 | amx_FindPubVar_t fn = ((amx_FindPubVar_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_FindPubVar]; 97 | return fn(amx, varname, amx_addr); 98 | } 99 | 100 | typedef int AMXAPI (*amx_FindTagId_t)(AMX *amx, cell tag_id, char *tagname); 101 | int AMXAPI amx_FindTagId(AMX *amx, cell tag_id, char *tagname) 102 | { 103 | amx_FindTagId_t fn = ((amx_FindTagId_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_FindTagId]; 104 | return fn(amx, tag_id, tagname); 105 | } 106 | 107 | typedef int AMXAPI (*amx_Flags_t)(AMX *amx,uint16_t *flags); 108 | int AMXAPI amx_Flags(AMX *amx,uint16_t *flags) 109 | { 110 | amx_Flags_t fn = ((amx_Flags_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Flags]; 111 | return fn(amx,flags); 112 | } 113 | 114 | typedef int AMXAPI (*amx_GetAddr_t)(AMX *amx,cell amx_addr,cell **phys_addr); 115 | int AMXAPI amx_GetAddr(AMX *amx,cell amx_addr,cell **phys_addr) 116 | { 117 | amx_GetAddr_t fn = ((amx_GetAddr_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetAddr]; 118 | return fn(amx,amx_addr,phys_addr); 119 | } 120 | 121 | typedef int AMXAPI (*amx_GetNative_t)(AMX *amx, int index, char *funcname); 122 | int AMXAPI amx_GetNative(AMX *amx, int index, char *funcname) 123 | { 124 | amx_GetNative_t fn = ((amx_GetNative_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetNative]; 125 | return fn(amx, index, funcname); 126 | } 127 | 128 | typedef int AMXAPI (*amx_GetPublic_t)(AMX *amx, int index, char *funcname); 129 | int AMXAPI amx_GetPublic(AMX *amx, int index, char *funcname) 130 | { 131 | amx_GetPublic_t fn = ((amx_GetPublic_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetPublic]; 132 | return fn(amx, index, funcname); 133 | } 134 | 135 | typedef int AMXAPI (*amx_GetPubVar_t)(AMX *amx, int index, char *varname, cell *amx_addr); 136 | int AMXAPI amx_GetPubVar(AMX *amx, int index, char *varname, cell *amx_addr) 137 | { 138 | amx_GetPubVar_t fn = ((amx_GetPubVar_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetPubVar]; 139 | return fn(amx, index, varname, amx_addr); 140 | } 141 | 142 | typedef int AMXAPI (*amx_GetString_t)(char *dest,const cell *source, int use_wchar, size_t size); 143 | int AMXAPI amx_GetString(char *dest,const cell *source, int use_wchar, size_t size) 144 | { 145 | amx_GetString_t fn = ((amx_GetString_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetString]; 146 | return fn(dest,source, use_wchar, size); 147 | } 148 | 149 | typedef int AMXAPI (*amx_GetTag_t)(AMX *amx, int index, char *tagname, cell *tag_id); 150 | int AMXAPI amx_GetTag(AMX *amx, int index, char *tagname, cell *tag_id) 151 | { 152 | amx_GetTag_t fn = ((amx_GetTag_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetTag]; 153 | return fn(amx, index, tagname, tag_id); 154 | } 155 | 156 | typedef int AMXAPI (*amx_GetUserData_t)(AMX *amx, long tag, void **ptr); 157 | int AMXAPI amx_GetUserData(AMX *amx, long tag, void **ptr) 158 | { 159 | amx_GetUserData_t fn = ((amx_GetUserData_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetUserData]; 160 | return fn(amx, tag, ptr); 161 | } 162 | 163 | typedef int AMXAPI (*amx_Init_t)(AMX *amx, void *program); 164 | int AMXAPI amx_Init(AMX *amx, void *program) 165 | { 166 | amx_Init_t fn = ((amx_Init_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Init]; 167 | return fn(amx, program); 168 | } 169 | 170 | typedef int AMXAPI (*amx_InitJIT_t)(AMX *amx, void *reloc_table, void *native_code); 171 | int AMXAPI amx_InitJIT(AMX *amx, void *reloc_table, void *native_code) 172 | { 173 | amx_InitJIT_t fn = ((amx_InitJIT_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_InitJIT]; 174 | return fn(amx, reloc_table, native_code); 175 | } 176 | 177 | typedef int AMXAPI (*amx_MemInfo_t)(AMX *amx, long *codesize, long *datasize, long *stackheap); 178 | int AMXAPI amx_MemInfo(AMX *amx, long *codesize, long *datasize, long *stackheap) 179 | { 180 | amx_MemInfo_t fn = ((amx_MemInfo_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_MemInfo]; 181 | return fn(amx, codesize, datasize, stackheap); 182 | } 183 | 184 | typedef int AMXAPI (*amx_NameLength_t)(AMX *amx, int *length); 185 | int AMXAPI amx_NameLength(AMX *amx, int *length) 186 | { 187 | amx_NameLength_t fn = ((amx_NameLength_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_NameLength]; 188 | return fn(amx, length); 189 | } 190 | 191 | typedef AMX_NATIVE_INFO * AMXAPI (*amx_NativeInfo_t)(const char *name, AMX_NATIVE func); 192 | AMX_NATIVE_INFO * AMXAPI amx_NativeInfo(const char *name, AMX_NATIVE func) 193 | { 194 | amx_NativeInfo_t fn = ((amx_NativeInfo_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_NativeInfo]; 195 | return fn(name, func); 196 | } 197 | 198 | typedef int AMXAPI (*amx_NumNatives_t)(AMX *amx, int *number); 199 | int AMXAPI amx_NumNatives(AMX *amx, int *number) 200 | { 201 | amx_NumNatives_t fn = ((amx_NumNatives_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_NumNatives]; 202 | return fn(amx, number); 203 | } 204 | 205 | typedef int AMXAPI (*amx_NumPublics_t)(AMX *amx, int *number); 206 | int AMXAPI amx_NumPublics(AMX *amx, int *number) 207 | { 208 | amx_NumPublics_t fn = ((amx_NumPublics_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_NumPublics]; 209 | return fn(amx, number); 210 | } 211 | 212 | typedef int AMXAPI (*amx_NumPubVars_t)(AMX *amx, int *number); 213 | int AMXAPI amx_NumPubVars(AMX *amx, int *number) 214 | { 215 | amx_NumPubVars_t fn = ((amx_NumPubVars_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_NumPubVars]; 216 | return fn(amx, number); 217 | } 218 | 219 | typedef int AMXAPI (*amx_NumTags_t)(AMX *amx, int *number); 220 | int AMXAPI amx_NumTags(AMX *amx, int *number) 221 | { 222 | amx_NumTags_t fn = ((amx_NumTags_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_NumTags]; 223 | return fn(amx, number); 224 | } 225 | 226 | typedef int AMXAPI (*amx_Push_t)(AMX *amx, cell value); 227 | int AMXAPI amx_Push(AMX *amx, cell value) 228 | { 229 | amx_Push_t fn = ((amx_Push_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Push]; 230 | return fn(amx, value); 231 | } 232 | 233 | typedef int AMXAPI (*amx_PushArray_t)(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells); 234 | int AMXAPI amx_PushArray(AMX *amx, cell *amx_addr, cell **phys_addr, const cell array[], int numcells) 235 | { 236 | amx_PushArray_t fn = ((amx_PushArray_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_PushArray]; 237 | return fn(amx, amx_addr, phys_addr, array, numcells); 238 | } 239 | 240 | typedef int AMXAPI (*amx_PushString_t)(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar); 241 | int AMXAPI amx_PushString(AMX *amx, cell *amx_addr, cell **phys_addr, const char *string, int pack, int use_wchar) 242 | { 243 | amx_PushString_t fn = ((amx_PushString_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_PushString]; 244 | return fn(amx, amx_addr, phys_addr, string, pack, use_wchar); 245 | } 246 | 247 | typedef int AMXAPI (*amx_RaiseError_t)(AMX *amx, int error); 248 | int AMXAPI amx_RaiseError(AMX *amx, int error) 249 | { 250 | amx_RaiseError_t fn = ((amx_RaiseError_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_RaiseError]; 251 | return fn(amx, error); 252 | } 253 | 254 | typedef int AMXAPI (*amx_Register_t)(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number); 255 | int AMXAPI amx_Register(AMX *amx, const AMX_NATIVE_INFO *nativelist, int number) 256 | { 257 | amx_Register_t fn = ((amx_Register_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Register]; 258 | return fn(amx, nativelist, number); 259 | } 260 | 261 | typedef int AMXAPI (*amx_Release_t)(AMX *amx, cell amx_addr); 262 | int AMXAPI amx_Release(AMX *amx, cell amx_addr) 263 | { 264 | amx_Release_t fn = ((amx_Release_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_Release]; 265 | return fn(amx, amx_addr); 266 | } 267 | 268 | typedef int AMXAPI (*amx_SetCallback_t)(AMX *amx, AMX_CALLBACK callback); 269 | int AMXAPI amx_SetCallback(AMX *amx, AMX_CALLBACK callback) 270 | { 271 | amx_SetCallback_t fn = ((amx_SetCallback_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_SetCallback]; 272 | return fn(amx, callback); 273 | } 274 | 275 | typedef int AMXAPI (*amx_SetDebugHook_t)(AMX *amx, AMX_DEBUG debug); 276 | int AMXAPI amx_SetDebugHook(AMX *amx, AMX_DEBUG debug) 277 | { 278 | amx_SetDebugHook_t fn = ((amx_SetDebugHook_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_SetDebugHook]; 279 | return fn(amx, debug); 280 | } 281 | 282 | typedef int AMXAPI (*amx_SetString_t)(cell *dest, const char *source, int pack, int use_wchar, size_t size); 283 | int AMXAPI amx_SetString(cell *dest, const char *source, int pack, int use_wchar, size_t size) 284 | { 285 | amx_SetString_t fn = ((amx_SetString_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_SetString]; 286 | return fn(dest, source, pack, use_wchar, size); 287 | } 288 | 289 | typedef int AMXAPI (*amx_SetUserData_t)(AMX *amx, long tag, void *ptr); 290 | int AMXAPI amx_SetUserData(AMX *amx, long tag, void *ptr) 291 | { 292 | amx_SetUserData_t fn = ((amx_SetUserData_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_SetUserData]; 293 | return fn(amx, tag, ptr); 294 | } 295 | 296 | typedef int AMXAPI (*amx_StrLen_t)(const cell *cstring, int *length); 297 | int AMXAPI amx_StrLen(const cell *cstring, int *length) 298 | { 299 | amx_StrLen_t fn = ((amx_StrLen_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_StrLen]; 300 | return fn(cstring, length); 301 | } 302 | 303 | typedef int AMXAPI (*amx_UTF8Check_t)(const char *string, int *length); 304 | int AMXAPI amx_UTF8Check(const char *string, int *length) 305 | { 306 | amx_UTF8Check_t fn = ((amx_UTF8Check_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_UTF8Check]; 307 | return fn(string, length); 308 | } 309 | 310 | typedef int AMXAPI (*amx_UTF8Get_t)(const char *string, const char **endptr, cell *value); 311 | int AMXAPI amx_UTF8Get(const char *string, const char **endptr, cell *value) 312 | { 313 | amx_UTF8Get_t fn = ((amx_UTF8Get_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_UTF8Get]; 314 | return fn(string, endptr, value); 315 | } 316 | 317 | typedef int AMXAPI (*amx_UTF8Len_t)(const cell *cstr, int *length); 318 | int AMXAPI amx_UTF8Len(const cell *cstr, int *length) 319 | { 320 | amx_UTF8Len_t fn = ((amx_UTF8Len_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_UTF8Len]; 321 | return fn(cstr, length); 322 | } 323 | 324 | typedef int AMXAPI (*amx_UTF8Put_t)(char *string, char **endptr, int maxchars, cell value); 325 | int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value) 326 | { 327 | amx_UTF8Put_t fn = ((amx_UTF8Put_t*)pAMXFunctions)[PLUGIN_AMX_EXPORT_UTF8Put]; 328 | return fn(string, endptr, maxchars, value); 329 | } 330 | 331 | //---------------------------------------------------------- 332 | // EOF 333 | -------------------------------------------------------------------------------- /plugins/lib/sdk/plugin.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------- 2 | // 3 | // SA-MP Multiplayer Modification For GTA:SA 4 | // Copyright 2004-2009 SA-MP Team 5 | // 6 | //---------------------------------------------------------- 7 | 8 | #include "plugincommon.h" 9 | #include "amx/amx.h" 10 | 11 | //---------------------------------------------------------- 12 | // EOF 13 | -------------------------------------------------------------------------------- /plugins/lib/sdk/plugincommon.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------- 2 | // 3 | // SA-MP Multiplayer Modification For GTA:SA 4 | // Copyright 2004-2009 SA-MP Team 5 | // 6 | //---------------------------------------------------------- 7 | 8 | #pragma once 9 | 10 | //---------------------------------------------------------- 11 | 12 | #define SAMP_PLUGIN_VERSION 0x0200 13 | 14 | //---------------------------------------------------------- 15 | 16 | #ifdef __cplusplus 17 | #define PLUGIN_EXTERN_C extern "C" 18 | #else 19 | #define PLUGIN_EXTERN_C 20 | #endif 21 | 22 | #if defined __linux__ || defined __FreeBSD__ || defined __OpenBSD__ 23 | #ifndef __GNUC__ 24 | #pragma message "Warning: Not using a GNU compiler." 25 | #endif 26 | #define PLUGIN_CALL 27 | #ifndef SAMPSVR 28 | // Compile code with -fvisibility=hidden to hide non-exported functions. 29 | #define PLUGIN_EXPORT PLUGIN_EXTERN_C __attribute__((visibility("default"))) 30 | #else 31 | #define PLUGIN_EXPORT PLUGIN_EXTERN_C 32 | #endif 33 | #elif defined _WIN32 34 | #ifndef _MSC_VER 35 | #pragma message "Warning: Not using a VC++ compiler." 36 | #endif 37 | #define PLUGIN_CALL __stdcall 38 | #define PLUGIN_EXPORT PLUGIN_EXTERN_C 39 | #else 40 | #error "Unknown operating system." 41 | #endif 42 | 43 | //---------------------------------------------------------- 44 | 45 | enum SUPPORTS_FLAGS 46 | { 47 | SUPPORTS_VERSION = SAMP_PLUGIN_VERSION, 48 | SUPPORTS_VERSION_MASK = 0xffff, 49 | SUPPORTS_AMX_NATIVES = 0x10000, 50 | SUPPORTS_PROCESS_TICK = 0x20000 51 | }; 52 | 53 | //---------------------------------------------------------- 54 | 55 | enum PLUGIN_DATA_TYPE 56 | { 57 | // For some debugging 58 | PLUGIN_DATA_LOGPRINTF = 0x00, // void (*logprintf)(char* format, ...) 59 | PLUGIN_DATA_NETGAME = 0xE1, // CNetGame* GetNetGame(); 60 | PLUGIN_DATA_RAKSERVER = 0xE2, // RakServerInterface* PluginGetRakServer() 61 | PLUGIN_DATA_LOADFSCRIPT = 0xE3, // bool LoadFilterscriptFromMemory(char* pFileName, char* pFileData) 62 | PLUGIN_DATA_UNLOADFSCRIPT = 0xE5, // bool UnloadFilterScript(char* pFileName) 63 | PLUGIN_DATA_CONSOLE = 0xE4, // CConsole* GetConsole(); 64 | 65 | // AMX 66 | PLUGIN_DATA_AMX_EXPORTS = 0x10, // void* AmxFunctionTable[] (see PLUGIN_AMX_EXPORT) 67 | PLUGIN_DATA_CALLPUBLIC_FS = 0x11, // int (*AmxCallPublicFilterScript)(char *szFunctionName) 68 | PLUGIN_DATA_CALLPUBLIC_GM = 0x12, // int (*AmxCallPublicGameMode)(char *szFunctionName) 69 | 70 | }; 71 | 72 | //---------------------------------------------------------- 73 | 74 | enum PLUGIN_AMX_EXPORT 75 | { 76 | PLUGIN_AMX_EXPORT_Align16 = 0, 77 | PLUGIN_AMX_EXPORT_Align32 = 1, 78 | PLUGIN_AMX_EXPORT_Align64 = 2, 79 | PLUGIN_AMX_EXPORT_Allot = 3, 80 | PLUGIN_AMX_EXPORT_Callback = 4, 81 | PLUGIN_AMX_EXPORT_Cleanup = 5, 82 | PLUGIN_AMX_EXPORT_Clone = 6, 83 | PLUGIN_AMX_EXPORT_Exec = 7, 84 | PLUGIN_AMX_EXPORT_FindNative = 8, 85 | PLUGIN_AMX_EXPORT_FindPublic = 9, 86 | PLUGIN_AMX_EXPORT_FindPubVar = 10, 87 | PLUGIN_AMX_EXPORT_FindTagId = 11, 88 | PLUGIN_AMX_EXPORT_Flags = 12, 89 | PLUGIN_AMX_EXPORT_GetAddr = 13, 90 | PLUGIN_AMX_EXPORT_GetNative = 14, 91 | PLUGIN_AMX_EXPORT_GetPublic = 15, 92 | PLUGIN_AMX_EXPORT_GetPubVar = 16, 93 | PLUGIN_AMX_EXPORT_GetString = 17, 94 | PLUGIN_AMX_EXPORT_GetTag = 18, 95 | PLUGIN_AMX_EXPORT_GetUserData = 19, 96 | PLUGIN_AMX_EXPORT_Init = 20, 97 | PLUGIN_AMX_EXPORT_InitJIT = 21, 98 | PLUGIN_AMX_EXPORT_MemInfo = 22, 99 | PLUGIN_AMX_EXPORT_NameLength = 23, 100 | PLUGIN_AMX_EXPORT_NativeInfo = 24, 101 | PLUGIN_AMX_EXPORT_NumNatives = 25, 102 | PLUGIN_AMX_EXPORT_NumPublics = 26, 103 | PLUGIN_AMX_EXPORT_NumPubVars = 27, 104 | PLUGIN_AMX_EXPORT_NumTags = 28, 105 | PLUGIN_AMX_EXPORT_Push = 29, 106 | PLUGIN_AMX_EXPORT_PushArray = 30, 107 | PLUGIN_AMX_EXPORT_PushString = 31, 108 | PLUGIN_AMX_EXPORT_RaiseError = 32, 109 | PLUGIN_AMX_EXPORT_Register = 33, 110 | PLUGIN_AMX_EXPORT_Release = 34, 111 | PLUGIN_AMX_EXPORT_SetCallback = 35, 112 | PLUGIN_AMX_EXPORT_SetDebugHook = 36, 113 | PLUGIN_AMX_EXPORT_SetString = 37, 114 | PLUGIN_AMX_EXPORT_SetUserData = 38, 115 | PLUGIN_AMX_EXPORT_StrLen = 39, 116 | PLUGIN_AMX_EXPORT_UTF8Check = 40, 117 | PLUGIN_AMX_EXPORT_UTF8Get = 41, 118 | PLUGIN_AMX_EXPORT_UTF8Len = 42, 119 | PLUGIN_AMX_EXPORT_UTF8Put = 43, 120 | }; 121 | 122 | //---------------------------------------------------------- 123 | // EOF 124 | -------------------------------------------------------------------------------- /plugins/makefile: -------------------------------------------------------------------------------- 1 | GPP = g++ -m32 -std=c++11 -Ilib -Isrc -fno-stack-protector 2 | GCC = gcc -m32 -Ilib -Isrc -fno-stack-protector 3 | LINK = $(GPP) -Wl,-z,defs -lstdc++ -lcurl 4 | OUTFILE = "./DeepL.so" 5 | 6 | COMPILE_FLAGS = -c -O3 -fPIC -w -DLINUX -fno-operator-names 7 | 8 | DeepL = -D DeepL $(COMPILE_FLAGS) 9 | 10 | all: DeepL 11 | 12 | clean: 13 | -rm -f *~ *.o *.so 14 | 15 | static: GPP = g++ -m32 -std=c++11 -Ilib -Isrc -fno-stack-protector -static-libgcc -static-libstdc++ 16 | static: GCC = gcc -m32 -Ilib -Isrc -fno-stack-protector -static-libgcc -static-libstdc++ 17 | static: LINK = $(GPP) -static -Wl,-z,defs -lcurl 18 | static: all 19 | 20 | DeepL: clean 21 | $(GPP) $(DeepL) ./lib/sdk/*.cpp 22 | $(GPP) $(DeepL) ./lib/json/*.cpp 23 | $(GPP) $(DeepL) ./src/*.cpp 24 | $(LINK) -shared -o $(OUTFILE) *.o 25 | -------------------------------------------------------------------------------- /plugins/src/cache.cpp: -------------------------------------------------------------------------------- 1 | #include "cache.h" 2 | 3 | #include "main.h" 4 | #include "json/json11.hpp" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | std::unordered_map cache_data; 12 | 13 | void cache::load() 14 | { 15 | std::ifstream in("scriptfiles/deepl_cache.txt"); 16 | cache_data.clear(); 17 | std::string err; 18 | for(std::string key; std::getline(in, key); ) 19 | { 20 | std::string value; 21 | if(!std::getline(in, value)) break; 22 | auto json_val = json11::Json::parse(value, err); 23 | if(json_val == json11::Json()) 24 | { 25 | logprintf("JSON parsing error: %s", err.c_str()); 26 | break; 27 | } 28 | cache_data[std::move(key)] = json_val.string_value(); 29 | } 30 | } 31 | 32 | const std::string &cache::get(const std::string &key) 33 | { 34 | return cache_data[key]; 35 | } 36 | 37 | void cache::set_or_get(const std::string &key, std::string &value) 38 | { 39 | auto &ref = cache_data[key]; 40 | if(!ref.empty()) 41 | { 42 | value = ref; 43 | return; 44 | } 45 | ref = value; 46 | std::ofstream out("scriptfiles/deepl_cache.txt"); 47 | std::string buffer; 48 | for(const auto &pair : cache_data) 49 | { 50 | buffer.clear(); 51 | json11::Json(pair.second).dump(buffer); 52 | out << pair.first << std::endl << buffer << std::endl; 53 | } 54 | out.close(); 55 | } 56 | -------------------------------------------------------------------------------- /plugins/src/cache.h: -------------------------------------------------------------------------------- 1 | #ifndef CACHE_H_INCLUDED 2 | #define CACHE_H_INCLUDED 3 | 4 | #include 5 | 6 | namespace cache 7 | { 8 | void load(); 9 | const std::string &get(const std::string &key); 10 | void set_or_get(const std::string &key, std::string &value); 11 | } 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /plugins/src/deepl.cpp: -------------------------------------------------------------------------------- 1 | #include "deepl.h" 2 | #include "main.h" 3 | #include "cache.h" 4 | 5 | #define CURL_STATICLIB 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | std::string deepl::auth_header; 14 | std::string deepl::endpoint_url = "https://api-free.deepl.com/v2/translate"; 15 | 16 | struct curlm_deleter 17 | { 18 | void operator()(CURLM *curlm) 19 | { 20 | curl_multi_cleanup(curlm); 21 | } 22 | }; 23 | 24 | struct curl_deleter 25 | { 26 | void operator()(CURL *curl) 27 | { 28 | curl_easy_cleanup(curl); 29 | } 30 | }; 31 | 32 | struct curl_slist_deleter 33 | { 34 | void operator()(curl_slist *slist) 35 | { 36 | curl_slist_free_all(slist); 37 | } 38 | }; 39 | 40 | typedef std::unique_ptr curl_handle; 41 | 42 | std::unique_ptr curlm_ptr; 43 | 44 | std::queue curl_pool; 45 | 46 | std::unique_ptr http_headers = []() 47 | { 48 | curl_slist *headers = nullptr; 49 | headers = curl_slist_append(headers, "Accept: application/json"); 50 | return std::unique_ptr(headers); 51 | }(); 52 | 53 | void deepl::load() 54 | { 55 | curlm_ptr = std::unique_ptr(curl_multi_init()); 56 | } 57 | 58 | void deepl::unload() 59 | { 60 | curl_pool.empty(); 61 | curlm_ptr = nullptr; 62 | } 63 | 64 | curl_handle curl_easy_get() 65 | { 66 | curl_handle handle; 67 | if(!curl_pool.empty()) 68 | { 69 | std::swap(handle, curl_pool.front()); 70 | curl_pool.pop(); 71 | }else{ 72 | handle = curl_handle(curl_easy_init()); 73 | } 74 | return handle; 75 | } 76 | 77 | class curl_request 78 | { 79 | curl_handle handle; 80 | std::string fields; 81 | deepl::callback_func callback; 82 | 83 | std::string response; 84 | char error_buffer[CURL_ERROR_SIZE + 1] = {}; 85 | 86 | size_t write(char *ptr, size_t size, size_t nmemb) 87 | { 88 | response.append(ptr, size * nmemb); 89 | return size * nmemb; 90 | } 91 | 92 | public: 93 | curl_request(curl_handle handle, std::string fields, deepl::callback_func callback) : handle(std::move(handle)), fields(std::move(fields)), callback(std::move(callback)) 94 | { 95 | auto curl = this->handle.get(); 96 | 97 | curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, error_buffer); 98 | 99 | curl_slist *headers = nullptr; 100 | headers = curl_slist_append(headers, deepl::auth_header.c_str()); 101 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 102 | 103 | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, this->fields.c_str()); 104 | curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, this->fields.size()); 105 | 106 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, this); 107 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, +[](void *ptr, size_t size, size_t nmemb, void *data) -> size_t 108 | { 109 | return reinterpret_cast(data)->write(reinterpret_cast(ptr), size, nmemb); 110 | }); 111 | } 112 | 113 | curl_handle finish(long status_code) 114 | { 115 | if(response.size() == 0 && error_buffer[0] != '\0') 116 | { 117 | callback(false, error_buffer, status_code); 118 | }else{ 119 | bool should_cache = callback(true, response, status_code); 120 | if(should_cache && status_code == 200) 121 | { 122 | cache::set_or_get(fields, response); 123 | } 124 | } 125 | return std::move(handle); 126 | } 127 | }; 128 | 129 | std::unordered_map> requests; 130 | 131 | class fake_request 132 | { 133 | const std::string &response; 134 | deepl::callback_func callback; 135 | 136 | public: 137 | fake_request(const std::string &response, deepl::callback_func callback) : response(std::move(response)), callback(std::move(callback)) 138 | { 139 | 140 | } 141 | 142 | void process() const 143 | { 144 | callback(true, response, 200); 145 | } 146 | }; 147 | 148 | std::vector fake_requests; 149 | 150 | void deepl::process() 151 | { 152 | auto multi = curlm_ptr.get(); 153 | 154 | int running; 155 | curl_multi_perform(multi, &running); 156 | 157 | if(static_cast(running) < requests.size()) 158 | { 159 | CURLMsg *msg; 160 | 161 | do{ 162 | int msgq = 0; 163 | msg = curl_multi_info_read(multi, &msgq); 164 | if(msg && (msg->msg == CURLMSG_DONE)) 165 | { 166 | CURL *curl = msg->easy_handle; 167 | curl_multi_remove_handle(multi, curl); 168 | 169 | auto it = requests.find(curl); 170 | if(it == requests.end()) 171 | { 172 | curl_easy_cleanup(curl); 173 | }else{ 174 | long http_code = 0; 175 | curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code); 176 | 177 | std::unique_ptr request; 178 | std::swap(request, it->second); 179 | requests.erase(it); 180 | 181 | curl_pool.push(request->finish(http_code)); 182 | } 183 | } 184 | }while(msg); 185 | } 186 | 187 | decltype(fake_requests) copy; 188 | std::swap(copy, fake_requests); 189 | for(const auto &req : copy) 190 | { 191 | req.process(); 192 | } 193 | } 194 | 195 | int deepl::make_request(bool preserve_formatting, const char *tag_handling, const char *formality, const char *split_sentences, const char *source_lang, const char *target_lang, const std::string&text, deepl::callback_func callback) 196 | { 197 | auto curl_handle = curl_easy_get(); 198 | auto curl = curl_handle.get(); 199 | 200 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, http_headers.get()); 201 | 202 | curl_easy_setopt(curl, CURLOPT_URL, endpoint_url.c_str()); 203 | curl_easy_setopt(curl, CURLOPT_POST, 1); 204 | 205 | std::string fields; 206 | 207 | fields += "text="; 208 | char *encoded = curl_easy_escape(curl, text.c_str(), text.size()); 209 | fields += encoded; 210 | curl_free(encoded); 211 | 212 | if(preserve_formatting) 213 | { 214 | fields += "&preserve_formatting=1"; 215 | } 216 | 217 | if(tag_handling) 218 | { 219 | fields += "&tag_handling="; 220 | encoded = curl_easy_escape(curl, tag_handling, 0); 221 | fields += encoded; 222 | curl_free(encoded); 223 | } 224 | 225 | if(formality) 226 | { 227 | fields += "&formality="; 228 | encoded = curl_easy_escape(curl, formality, 0); 229 | fields += encoded; 230 | curl_free(encoded); 231 | } 232 | 233 | if(split_sentences) 234 | { 235 | fields += "&split_sentences="; 236 | encoded = curl_easy_escape(curl, split_sentences, 0); 237 | fields += encoded; 238 | curl_free(encoded); 239 | } 240 | 241 | if(source_lang) 242 | { 243 | fields += "&source_lang="; 244 | encoded = curl_easy_escape(curl, source_lang, 0); 245 | fields += encoded; 246 | curl_free(encoded); 247 | } 248 | 249 | if(target_lang) 250 | { 251 | fields += "&target_lang="; 252 | encoded = curl_easy_escape(curl, target_lang, 0); 253 | fields += encoded; 254 | curl_free(encoded); 255 | } 256 | 257 | const auto &cached = cache::get(fields); 258 | if(!cached.empty()) 259 | { 260 | fake_requests.push_back(fake_request(cached, std::move(callback))); 261 | return 0; 262 | } 263 | 264 | requests[curl] = std::unique_ptr(new curl_request(std::move(curl_handle), std::move(fields), std::move(callback))); 265 | return curl_multi_add_handle(curlm_ptr.get(), curl); 266 | } 267 | 268 | -------------------------------------------------------------------------------- /plugins/src/deepl.h: -------------------------------------------------------------------------------- 1 | #ifndef DEEPL_H_INCLUDED 2 | #define DEEPL_H_INCLUDED 3 | 4 | #include 5 | #include 6 | 7 | namespace deepl 8 | { 9 | typedef std::function callback_func; 10 | 11 | void load(); 12 | void process(); 13 | void unload(); 14 | 15 | int make_request(bool preserve_formatting, const char *tag_handling, const char *formality, const char *split_sentences, const char *source_lang, const char *target_lang, const std::string &text, callback_func callback); 16 | 17 | extern std::string auth_header; 18 | extern std::string endpoint_url; 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /plugins/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include "deepl.h" 3 | #include "cache.h" 4 | #include "natives.h" 5 | 6 | #include "sdk/amx/amx.h" 7 | #include "sdk/plugincommon.h" 8 | 9 | logprintf_t logprintf; 10 | extern void *pAMXFunctions; 11 | 12 | std::unordered_map> amx_map; 13 | 14 | PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() 15 | { 16 | return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES | SUPPORTS_PROCESS_TICK; 17 | } 18 | 19 | PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) 20 | { 21 | pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS]; 22 | logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF]; 23 | 24 | deepl::load(); 25 | cache::load(); 26 | 27 | logprintf(" DeepL API v1.3 loaded"); 28 | logprintf(" Created by IS4"); 29 | return true; 30 | } 31 | 32 | PLUGIN_EXPORT void PLUGIN_CALL Unload() 33 | { 34 | deepl::unload(); 35 | 36 | logprintf(" DeepL API v1.3 unloaded"); 37 | } 38 | 39 | PLUGIN_EXPORT void PLUGIN_CALL ProcessTick() 40 | { 41 | deepl::process(); 42 | } 43 | 44 | PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx) 45 | { 46 | amx_Register(amx, natives, -1); 47 | return AMX_ERR_NONE; 48 | } 49 | 50 | PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx) 51 | { 52 | amx_map.erase(amx); 53 | return AMX_ERR_NONE; 54 | } 55 | 56 | std::weak_ptr get_amx(AMX *amx) 57 | { 58 | auto &ref = amx_map[amx]; 59 | if(ref) return ref; 60 | return ref = std::shared_ptr(std::make_shared(false), amx); 61 | } 62 | -------------------------------------------------------------------------------- /plugins/src/main.h: -------------------------------------------------------------------------------- 1 | #ifndef MAIN_H_INCLUDED 2 | #define MAIN_H_INCLUDED 3 | 4 | #include "sdk/amx/amx.h" 5 | #include 6 | #include 7 | 8 | typedef void(*logprintf_t)(const char* format, ...); 9 | extern logprintf_t logprintf; 10 | 11 | std::weak_ptr get_amx(AMX *amx); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /plugins/src/natives.cpp: -------------------------------------------------------------------------------- 1 | #include "natives.h" 2 | #include "deepl.h" 3 | #include "cache.h" 4 | #include "main.h" 5 | 6 | #include "json/json11.hpp" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | char *split_locale(char *str) 13 | { 14 | auto pos = std::strstr(str, ":"); 15 | if(pos) 16 | { 17 | *pos = '\0'; 18 | ++pos; 19 | } 20 | return pos; 21 | } 22 | 23 | char *split_locale_alt(char *str) 24 | { 25 | auto pos = std::strstr(str, "|"); 26 | if(pos) 27 | { 28 | *pos = '\0'; 29 | ++pos; 30 | } 31 | return pos; 32 | } 33 | 34 | std::locale find_locale(char *&spec) 35 | { 36 | char *nextspec; 37 | while(nextspec = split_locale_alt(spec)) 38 | { 39 | try{ 40 | return std::locale(spec); 41 | }catch(const std::runtime_error &) 42 | { 43 | 44 | } 45 | spec = nextspec; 46 | } 47 | return std::locale(spec); 48 | } 49 | 50 | static std::wstring_convert> utf8; 51 | 52 | namespace Natives 53 | { 54 | cell SetAuthKey(AMX *amx, cell *params) 55 | { 56 | cell *key; 57 | amx_GetAddr(amx, params[1], &key); 58 | int len; 59 | amx_StrLen(key, &len); 60 | 61 | auto &str = deepl::auth_header = "Authorization: DeepL-Auth-Key "; 62 | auto start = str.size(); 63 | str.resize(start + len); 64 | amx_GetString(&str[start], key, false, len + 1); 65 | return 1; 66 | } 67 | 68 | cell SetEndpoint(AMX *amx, cell *params) 69 | { 70 | cell *endpoint; 71 | amx_GetAddr(amx, params[1], &endpoint); 72 | int len; 73 | amx_StrLen(endpoint, &len); 74 | 75 | auto &str = deepl::endpoint_url = std::string(len, '\0'); 76 | amx_GetString(&str[0], endpoint, false, len + 1); 77 | return 1; 78 | } 79 | 80 | cell Translate(AMX *amx, cell *params) 81 | { 82 | cell *addr; 83 | amx_GetAddr(amx, params[1], &addr); 84 | int len; 85 | amx_StrLen(addr, &len); 86 | std::string text(len, '\0'); 87 | amx_GetString(&text[0], addr, false, len + 1); 88 | 89 | char *from, *to; 90 | amx_StrParam(amx, params[2], from); 91 | amx_StrParam(amx, params[3], to); 92 | 93 | cell cookie = params[5]; 94 | 95 | bool preserve_formatting = params[6]; 96 | char *tag_handling, *formality, *split_sentences; 97 | amx_StrParam(amx, params[7], tag_handling); 98 | amx_StrParam(amx, params[8], formality); 99 | amx_StrParam(amx, params[9], split_sentences); 100 | 101 | amx_GetAddr(amx, params[4], &addr); 102 | amx_StrLen(addr, &len); 103 | std::string callback(len, '\0'); 104 | amx_GetString(&callback[0], addr, false, len + 1); 105 | 106 | if(auto from_locale = split_locale(from)) 107 | { 108 | try{ 109 | auto loc = find_locale(from_locale); 110 | std::wstring buffer(text.size(), L'\0'); 111 | std::use_facet>(loc).widen(text.data(), text.data() + text.size(), &buffer[0]); 112 | text = utf8.to_bytes(buffer.data()); 113 | }catch(const std::exception &e) 114 | { 115 | logprintf("[DeepL] Translate error: %s (input locale %s)", e.what(), from_locale); 116 | return -1; 117 | } 118 | } 119 | 120 | std::locale *to_locale_ptr = nullptr; 121 | if(auto to_locale = split_locale(to)) 122 | { 123 | try{ 124 | to_locale_ptr = new std::locale(find_locale(to_locale)); 125 | }catch(const std::exception &e) 126 | { 127 | logprintf("[DeepL] Translate error: %s (output locale %s)", e.what(), to_locale); 128 | return -1; 129 | } 130 | } 131 | 132 | auto amx_handle = get_amx(amx); 133 | return deepl::make_request(preserve_formatting, tag_handling, formality, split_sentences, from, to, text, [callback, amx_handle, cookie, to_locale_ptr](bool success, const std::string &result, long status_code) 134 | { 135 | if(auto handle = amx_handle.lock()) 136 | { 137 | auto amx = handle.get(); 138 | 139 | std::string message; 140 | std::string from; 141 | if(success) 142 | { 143 | success = false; 144 | auto json = json11::Json::parse(result, message); 145 | if(json.is_object()) 146 | { 147 | for(const auto &item : json["translations"].array_items()) 148 | { 149 | if(item.is_object()) 150 | { 151 | message = item["text"].string_value(); 152 | from = item["detected_source_language"].string_value(); 153 | success = true; 154 | break; 155 | } 156 | } 157 | if(!success) 158 | { 159 | const auto &msg = json["message"]; 160 | message = msg.string_value(); 161 | } 162 | } 163 | 164 | if(to_locale_ptr) 165 | { 166 | if(success) 167 | { 168 | try{ 169 | auto buffer = utf8.from_bytes(message); 170 | message.resize(buffer.size(), '\0'); 171 | std::use_facet>(*to_locale_ptr).narrow(buffer.data(), buffer.data() + buffer.size(), '?', &message[0]); 172 | }catch(const std::exception &e) 173 | { 174 | message = e.what(); 175 | success = false; 176 | } 177 | } 178 | delete to_locale_ptr; 179 | } 180 | 181 | if(!success) 182 | { 183 | message += " (input: "; 184 | message += result; 185 | message += ")"; 186 | } 187 | }else{ 188 | message = result; 189 | } 190 | 191 | int index; 192 | if(amx_FindPublic(amx, callback.c_str(), &index) != AMX_ERR_NONE) 193 | { 194 | return false; 195 | } 196 | cell message_addr, *message_ptr; 197 | if(amx_Allot(amx, message.size() + 1, &message_addr, &message_ptr) != AMX_ERR_NONE) 198 | { 199 | return false; 200 | } 201 | amx_SetString(message_ptr, message.c_str(), false, false, message.size() + 1); 202 | 203 | cell from_addr, *from_ptr; 204 | if(amx_Allot(amx, from.size() + 1, &from_addr, &from_ptr) != AMX_ERR_NONE) 205 | { 206 | amx_Release(amx, message_addr); 207 | return false; 208 | } 209 | amx_SetString(from_ptr, from.c_str(), false, false, from.size() + 1); 210 | 211 | amx_Push(amx, cookie); 212 | amx_Push(amx, from_addr); 213 | amx_Push(amx, message_addr); 214 | amx_Push(amx, success); 215 | cell retval; 216 | amx_Exec(amx, &retval, index); 217 | 218 | amx_Release(amx, message_addr); 219 | 220 | return static_cast(retval); 221 | } 222 | return false; 223 | }); 224 | } 225 | 226 | cell LoadCache(AMX *amx, cell *params) 227 | { 228 | cache::load(); 229 | return 1; 230 | } 231 | } 232 | 233 | AMX_NATIVE_INFO natives[] = { 234 | { "DeepL_SetAuthKey", Natives::SetAuthKey }, 235 | { "DeepL_SetEndpoint", Natives::SetEndpoint }, 236 | { "DeepL_Translate", Natives::Translate }, 237 | { "DeepL_LoadCache", Natives::LoadCache }, 238 | { nullptr, nullptr } 239 | }; 240 | -------------------------------------------------------------------------------- /plugins/src/natives.h: -------------------------------------------------------------------------------- 1 | #ifndef NATIVES_H_INCLUDED 2 | #define NATIVES_H_INCLUDED 3 | 4 | #include "sdk/amx/amx.h" 5 | 6 | extern AMX_NATIVE_INFO natives[]; 7 | 8 | #endif 9 | --------------------------------------------------------------------------------