alliedmodders / sourcepawn Goto Github PK
View Code? Open in Web Editor NEWA small, statically typed scripting language.
License: Other
A small, statically typed scripting language.
License: Other
SourceMod Forums Thread: https://forums.alliedmods.net/showthread.php?p=2529668#post2529668
I am using the latest SourceMod, Linux Server, Half-Life 2: DM. This is driving me absolutely crazy! I am simply trying to create a database, and it does, but for some reason, if I use a timer, and then call StrEqual...it makes a SECOND empty database with whatever name is in the first field of "StrEqual"
Here is an image from FTP showing the two files being made:
http://imgur.com/GFSrYC2l.png
Compile the code below to reproduce it; the databases can be found here
addons/sourcemod/data/sqlite
#include <sourcemod>
new Handle:g_hDB = INVALID_HANDLE;
public OnPluginStart()
{
InitDB();
CreateTimer(3.0, wtf_is_going_on);
}
stock Action:wtf_is_going_on(Handle:timer)
{
if(StrEqual("it_makes_an_empty_database_named_with_whatever_is_here", "")) {}
}
stock InitDB()
{
new String:error[255];
g_hDB = SQLite_UseDatabase("my_database", error, sizeof(error));
}
If you do something like public void OnPluginStart() { char arr[1024 * 64]; }
, then the VM (at least in recent versions) will report "instruction contained invalid parameter" (SP_ERROR_INSTRUCTION_PARAM
) at runtime. This gets triggered by the verifier because an operand used when constructing the array is too large for the stack.
It'd be nice if the compiler errored instead where the size is fixed. Alternatively, SP_ERROR_STACKLOW
at runtime instead.
(If you do something like int x = 64; char[] arr = new char[1024 * 64];
you get a much more helpful "not enough space on the heap" (SP_ERROR_HEAPLOW
).)
Checking if a handle equals to null gives an assignment error.
Handle abc;
if(abc == null)
SourcePawn Compiler 1.9.0.5921
I noticed that you can initalize (array) variables with blank types that wont throw any errors while compiling, even with newdecls required
.
Example plugin: https://forums.alliedmods.net/showthread.php?t=288689
#pragma semicolon 1
#pragma newdecls required
int myInt; //Valid
myInt2; //error 147: new-style declarations are required // Valid when newdecls are optional
myInt3[6]; //Valid?!
sourcepawn/include/smx/smx-v1-opcodes.h
Line 129 in d653700
jless
not jsless
or i wrong?docgen is broken, had to use 4a09669 commit (edit: which crashes at handles.inc
...).
chokes on clients.inc
, most probably at public const int MaxClients;
Assertion failed: sym->isByRef() == type->isReference(), file D:\dev\sourcepawn\exp\compiler\sema\type-resolver.cpp, line 982
Problem:
SaveMe.sp does not compile on SM1.10
Expected:
spcomp exports a .smx (or I guess with 1.8; prints a slew of errors).
str:
Drag and drop a .sp on spcomp.
problem space:
1.8 gives an error message; 1.10 instantly fails.
D:\Git\SourcePawn-Plugins>spcomp2.exe SaveMe.sp
SourcePawn Compiler 1.10.0.6334
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC
D:\Git\SourcePawn-Plugins>spcomp.exe SaveMe.sp
SourcePawn Compiler 1.8.0.6040
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2015 AlliedModders LLC
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(43) : error 001: expected token: "public", but found "const"
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(44) : error 001: expected token: "}", but found "const"
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(45) : error 001: expected token: "=", but found "["
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(46) : error 001: expected token: "=", but found "["
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(47) : error 001: expected token: "=", but found "["
D:\Git\SourcePawn-Plugins\include\sourcemod.inc(48) : error 010: invalid function or declaration
D:\Git\SourcePawn-Plugins\include\core.inc(45) : error 001: expected token: "public", but found "-identifier-"
D:\Git\SourcePawn-Plugins\include\core.inc(49) : error 010: invalid function or declaration
D:\Git\SourcePawn-Plugins\include\core.inc(56) : error 021: symbol already defined: "INVALID_FUNCTION"
D:\Git\SourcePawn-Plugins\include\core.inc(82) : error 096: could not find member "version" in struct "__version"
D:\Git\SourcePawn-Plugins\include\core.inc(122) : error 001: expected token: "public", but found "const"
D:\Git\SourcePawn-Plugins\include\core.inc(123) : error 001: expected token: "}", but found "const"
D:\Git\SourcePawn-Plugins\include\core.inc(126) : error 010: invalid function or declaration
D:\Git\SourcePawn-Plugins\include\core.inc(133) : error 001: expected token: "public", but found "const"
D:\Git\SourcePawn-Plugins\include\core.inc(134) : error 001: expected token: "}", but found "const"
D:\Git\SourcePawn-Plugins\include\core.inc(136) : error 010: invalid function or declaration
D:\Git\SourcePawn-Plugins\include\core.inc(146) : error 096: could not find member "name" in struct "__ext_core"
D:\Git\SourcePawn-Plugins\include\usermessages.inc(165) : warning 237: coercing functions to and from primitives is unsupported and will be removed in the future
D:\Git\SourcePawn-Plugins\include\menus.inc(503) : warning 219: local variable "time" shadows a variable at a preceding level
D:\Git\SourcePawn-Plugins\include\menus.inc(794) : warning 237: coercing functions to and from primitives is unsupported and will be removed in the future
D:\Git\SourcePawn-Plugins\include\halflife.inc(589) : warning 219: local variable "time" shadows a variable at a preceding level
SaveMe.sp(6) : error 096: could not find member "name" in struct "myinfo"
SaveMe.sp(126) : warning 203: symbol is never used: "__unknown__"
SaveMe.sp(124) : warning 203: symbol is never used: "autoload"
SaveMe.sp(47) : warning 203: symbol is never used: "date"
SaveMe.sp(46) : warning 203: symbol is never used: "filevers"
SaveMe.sp(125) : warning 203: symbol is never used: "required"
SaveMe.sp(49) : warning 203: symbol is never used: "time"
18 Errors.
D:\Git\SourcePawn-Plugins>
Original pawn supports this code.
public main()
{
new a[5];
test(a);
new b[10];
test(b);
}
test(a[], size = sizeof(a))
{
printf("arr size %d\n", size);
}
Output
arr size 5
arr size 10
Would be great see this in sourcepawn.
Compiler exits prematurely with no errors or messages.
methodmap B {
public static void TestB() {
A.TestA();
PrintToServer("TestB");
}
}
methodmap A {
public static void TestA() {
PrintToServer("TestA");
}
}
Output from Sublime:
[Finished in 0.9s with exit code 3221225477]
or
[Finished in 0.8s]
Output from spcomp:
What about a implementing define with name __FILE__
which contains current included filename?
This has been a known issue for a long while, but documenting it here. Example below.
Include:
native KeyValues CreateKeyValues(const char[] name, const char[] firstKey="", const char[] firstValue="");
Output:
KeyValues CreateKeyValues(const char[] name, const char[] firstKey, const char[] firstValue)
void foo()
{
bar(baz(1));
}
public main() { }
If you make foo
public
, the compiler doesn't assert. If you make the body of foo
just baz(1)
, it doesn't assert. The 1.8 compiler successfully compiles (as it ignores foo
since it's unused).
I was screwing around with methodmaps as menu handlers and the sp compiler crashed when I moved the declaration of CTestMenu
from line 28 to the bottom of the file. There are a lot of weird errors and warnings in there too, I hope this sample can help you discover more of the inconsistencies I encountered when working with methodmaps. I'll attach the source and the dmp file generated by vs.
Anonymous methodmap instantiation fails because spcomp expects an olddecl int declaration, but it's not.
/*
plugin.sp(14) : warning 219: local variable "ArrayList" shadows a variable at a preceding level
plugin.sp(14) : error 001: expected token: ";", but found "("
plugin.sp(14) : error 029: invalid expression, assumed zero
plugin.sp(14) : error 001: expected token: ")", but found ";"
plugin.sp(14) : fatal error 190: too many error messages on one line
*/
#include <sourcemod>
public void OnPluginStart()
{
new ArrayList();
}
See test in #114.
Correct output:
main.1
inner.1
main.2
Broken output:
main.1
inner.1
inner.2
inner.3
Exception thrown: Stack went below stack boundary
[0] test.sp::inner, line 13
[1] test.sp::main, line 19
[23:57:24] <dvander> asherkin: my guess is it's dumber than that: we never actually return from the interpreter
[23:58:32] <dvander> there doesn't appear to be any code that says "stop trying to run functions and exit"
I'm not sure it is actually that, this dumb patch seems to make everything work as expected, but I haven't tried more complex cases:
diff --git a/vm/interpreter.cpp b/vm/interpreter.cpp
index 578c1f6..b71e199 100644
--- a/vm/interpreter.cpp
+++ b/vm/interpreter.cpp
@@ -65,6 +65,13 @@ Interpreter::run()
while (reader_.more()) {
if (reader_.peekOpcode() == OP_PROC || reader_.peekOpcode() == OP_ENDPROC)
break;
+
+ if (reader_.peekOpcode() == OP_RETN) {
+ if (!reader_.visitNext())
+ return false;
+ break;
+ }
+
if (!reader_.visitNext())
return false;
}
But this looks really silly and I'm not sure how to factor it in properly.
I can't seem to get the compiler to ever emit OP_ENDPROC (or anywhere in the could where it would), what is it used for?
If a while loop uses a counter and has no foreseeable exit condition, I would like a compile warning to be added. This way, the user can correct this error before it crashes their plugin.
void myInfiniteWhileLoop()
{
int index = 20;
while (index >=0)
{
PrintToChatAll("I like apples");
}
}
This example may be better suited for a for-loop. But there are other use cases with multiple conditions.
Just as it says on the tin, I'd like to see support for Pawn's #warning preprocessor directive implemented in a future version of Sourcepawn, as an alternative to the compilation-halting #error directive. This is obviously incredibly niche and would only really find use for a very small selection of those of us creating includes for use in others' plugins.
(I'm also not sure how to tag this as a feature request or enhancement, or if someone else has to do that for me.)
Passing a reference to an array in an enum-struct is broken when the parameter requires a different tag than the array has in the enum-struct.
Tested in SourcePawn Compiler 1.9.0.6115.
Here's how I noticed it - the data written to the file was garbage after converting the plugin to the transitional syntax.
enum Test {
Float:vec3[3],
Float:vec2[2]
};
public void main() {
int test[Test];
File hFile = OpenFile(..);
WriteFile(hFile, test[vec3], 3, 4); // warning: tag mismatch but works
WriteFile(hFile, _:test[vec3], 3, 4); // All fine
WriteFile(hFile, view_as<int>(test[vec3]), 3, 4); // Writes random memory
}
testcase.zip
testcase_shell.zip
The attached testcase is a shorter version without the need of sourcemod natives.
The assembly of Bar
and Bar2
is equivalent:
0xd90: break
0xd94: break
0xd98: push.c 0x2 ; 2
0xda0: load.s.pri 0xc ; test
0xda8: add.c 0xc ; 12
0xdb0: push.pri
0xdb4: push.c 0x2 ; 2
0xdbc: call 0xe50 ; Foo
0xdc4: zero.pri
0xdc8: retn
Bar3
uses view_as<>()
and generates an extra load.i
in between:
0xe10: break
0xe14: break
0xe18: push.c 0x2 ; 2
0xe20: load.s.pri 0xc ; test
0xe28: add.c 0xc ; 12
0xe30: load.i
0xe34: push.pri
0xe38: push.c 0x2 ; 2
0xe40: call 0xe50 ; Foo
0xe48: zero.pri
0xe4c: retn
Seems like the default case on switches aren't seen by the compiler as a definite return, and gives us a warning. See testcase below
int main() {
funct(2);
}
int funct(int input) {
switch (input) {
case 0:
return 1;
case 1:
return 2;
default:
return 3;
}
} // warning 209: function "funct" should return a value
Error output from SourceMod:
L 12/10/2017 - 02:02:55: SourceMod error session started
L 12/10/2017 - 02:02:55: Info (map "de_nuke") (file "errors_20171210.log")
L 12/10/2017 - 02:02:55: [SM] Exception reported: Fatal error creating dynamic native!
L 12/10/2017 - 02:02:55: [SM] Blaming: testcase.smx
L 12/10/2017 - 02:02:55: [SM] Call stack trace:
L 12/10/2017 - 02:02:55: [SM] [0] CreateNative
L 12/10/2017 - 02:02:55: [SM] [1] Line 6, E:\scripting\testcase.sp::AskPluginLoad2
L 12/10/2017 - 02:02:55: [SM] [2] Line 21, E:\scripting\testcase.sp::GetClientButtons
Minimal test case:
#include <sourcemod>
#include <sdkhooks>
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
{
CreateNative("FakeNative_1", Native_Fake1);
}
public int Native_Fake1(Handle handler, int numParams)
{
}
public void OnClientPutInServer(int client)
{
SDKHook(client, SDKHook_PostThinkPost, PostThinkPost);
}
void PostThinkPost(int client)
{
GetClientButtons(client);
}
Changing PostThinkPost
's accessibility to public
gets rid of the error.
However, the stack trace outputted from SourceMod is terribly wrong and doesn't relate to the actual error in the code.
Something like this:
void foo(MyEnum e) { }
enum MyEnum { }
Will produce an error message like this:
error 181: function argument named 'e' differs from prototype
This code:
public void OnPluginStart()
{
PrintFloatArray( { 0.0, 1.0, 2.0, 3.0 }, 4 );
}
void PrintFloatArray( float[] arr, int count )
{
for( int i = 0; i < count; i++ )
{
PrintToServer( "%f\n", arr[i] );
}
}
results in a tag mismatch error.
plugin.sp(3) : warning 213: tag mismatch
The current hack people use to fix this is to just wrap the array in a view_as<float>
like so:
view_as<float>({ 0.0, 1.0, 2.0, 3.0 })
It'd be nice if the compiler was able to figure out the correct tag based on the contents to get the original code to work without warnings.
Currently the following throws a compiler error:
methodmap Foo < StringMap {};
Foo foo = new Foo(); // error 172: methodmap 'Foo' does not have a constructor
Is this by design? It would be great if the compiler called the parent constructor (if there is one) and cast the return type.
having this feature, especially for specific Handle types, would be a nice feature.
I figured it would require 2 kinds []=
for setting and []
for simple getting.
The general gist of it could like
public void operator[]=(type ArrayType, type IndexType, type Valuetype);
public type operator[](type ArrayType, type IndexType);
// for setting
public void operator[]=(StringMap hMap, char []strIndex, any value)
{
...
}
// for getting
public any operator[](StringMap hMap, char []strIndex)
{
any val;
// does this entry exist?
if( !hMap.GetValue(strIndex, val) )
return 0;
return val;
}
StringMap hMyMap = new StringMap();
hMyMap["fvalue"] = 4.0;
hMyMap["ivalue"] = 5;
delete hMyMap;
another example using the dynamic array.
// for setting
public void operator[]=(ArrayList hArray, int Index, any value)
{
hArray.Set(Index, value);
}
public void operator[]=(ArrayList hArray, int Index, char []StrVal)
{
hArray.SetString(Index, StrVal);
}
// for getting
public any operator[](ArrayList hArray, int index)
{
return hArray.Get(index);
}
ArrayList hArray = new ArrayList();
hArray.Push(5);
int i = hArray[0]; // sets 'i' to '5'
delete hArray;
Using #pragma newdecls required
should trigger warnings for using old syntax. Now that there is a new syntax available for enum structs I think the old syntax should also trigger a warning.
int g_a = 0;
methodmap CTest
{
public static void A()
{
g_a++;
if (g_a == 5)
PrintToServer("Done");
else
CTest.A(); // error 105: cannot find method or property CTest.A
}
}
public void OnPluginStart()
{
CTest.A();
}
This is probably good test case
methodmap MM { public static void sFunc(int a = 0) { if (a < 5) MM.sFunc(a + 1); } };
public void main() { MM.sFunc(); }
Test environment: Windows 10, SM 1.9.0.6245 & 1.10.0.6316
Update: the same for non-static
methodmap MM < Handle
{
public void sFunc(int a = 0)
{
if (a < 5)
this.sFunc(a + 1); // error 105: cannot find method or property MM.sFunc
}
}
public void OnPluginStart()
{
view_as<MM>(GetMyHandle()).sFunc();
}
#pragma semicolon 1
#include <sourcemod>
/* native bool:GetTrieString(Handle:map, const String:key[], String:value[], max_size, &size=0) */
public OnPluginStart()
{
PrintToServer("%b", GetTrieString(INVALID_HANDLE, "pickles", "", 0));
}
/*
Your plugin successfully compiled!
Use the link below to download your plugin. It will be valid for ten minutes.
http://www.sourcemod.net/compiler.php?go=dl&id=685667
SourcePawn Compiler 1.7.1
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2014 AlliedModders LLC
Code size: 3044 bytes
Data size: 2240 bytes
Stack/heap size: 16384 bytes
Total requirements: 21668 bytes
*/
Commit bb83d1b seems to sometimes cause the compiler to incorrectly warn that a variable is being shadowed. Here's a test case:
stock unused() {
buffer
}
public void main() {
char buffer[2];
buffer[0] = 2;
}
Compiling this results in warning 219: local variable "buffer" shadows a variable at a preceding level
. Prior to this commit, no warning is emitted.
The unused stock appears to have to have an error of some kind involving an identifier with the code later using the same identifier. For example, stock unused() { char buffer[2]; foo }
does not cause the warning to be emitted.
Add support for lambda
functions. Like this:
void DisplayDBTablesInServerConsole() {
g_hDB.Query( [] (Database hDB, DBResultSet hResults, const char[] szError, any data) -> void {
char szTable[64];
while (hResults.FetchRow()) {
hResults.FetchString(0, szTable, sizeof(szTable));
PrintToServer("Found table in DB: %s", szTable);
}
}, "SHOW TABLES;", 0, DBPrio_Low);
}
Friend catched this case while coding plugin. Here my example for demonstrating it.
crash1.sp
#include "crash2.sp"
public void OnPluginStart()
{
DoIt(); // - Shia LaBeouf
}
crash2.sp
#include "crash3.sp"
methodmap Shia
{
public static Speak()
{
PrintToServer("Do it! - Shia LaBeouf");
}
};
crash3.sp
void DoIt()
{
Shia.Speak();
}
log
crash3.sp(3) : error 017: undefined symbol "Shia"
Compiler crashed while compilation.
If move #include "crash3.sp"
below mathodmap - everything ok.
Test environment: Windows 10, SM 1.8.0.6041 & 1.9.0.6226
Now pre incriment of variable reference give code like this:
public void MyFunc(int &a)
{
++a;
}
push.pri
lref.s.pri 12
inc.pri
sref.s.pri 12
pop.pri
lref.s.pri 12
I think need to improve this.
The following code:
native void Touhou_GetUserBullet(int client, bullet_t bullet);
results in the following error message:
error 135: cannot use enum struct type "Touhou_GetUserBullet" in natives
The native name is being used in the error message rather than the enum struct type name.
Hi,
I know that this code is not meant to be compiled, but I think that it should give a proper error instead of crashing.
My test case:
Broken code:
public void OnPluginStart()
{
int arr[5];
arr["hello"] = 0;
}
spcomp.exe spcrash.sp
SourcePawn Compiler 1.9.0.6245
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2017 AlliedModders LLC
spcrash.sp(4) : error 033:
spcomp.exe spcrash.sp
SourcePawn Compiler 1.10.0.6355
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC
spcomp spcrash.sp
SourcePawn Compiler 1.9.0.6261
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2017 AlliedModders LLC
Segmentation fault
spcomp spcrash.sp
SourcePawn Compiler 1.10.0.6341
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC
Segmentation fault
Test case:
int main()
{
char a = 'a';
}
Warning:
SourcePawn Compiler 1.8.0.6014
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2015 AlliedModders LLC
C:\Users\Micha\Desktop\test2.sp(3) : warning 213: tag mismatch
IRC discussion:
<dvander> you'd have to step through matchtag() to figure out why
<dvander> but asherkin's right
<dvander> char resolves to the deprecated "String" tag, which is a big, big hack
<dvander> that technically only applies to arrays
<dvander> so probably it's just some archaic mess up
<dvander> i think that assignment should be supported though
Add static property support for methodmaps;
Example:
int g_val;
methodmap Test
{
property static int TestVal
{
public get() { return g_val; }
public set(int v) { g_val = v; }
}
}
... //Later in code
Test.TestVal = 1;
thanks to shavit for reporting this one.
Gave it a shot myself, but a solution wasn't obvious to me. Here's how to replicate
int main(){
if(
{
int b = c();
}
}
C:\Users\Micha\Desktop\alliedmodders\sourcemod\sourcepawn\build\compiler\spcomp>spcomp test.sp
SourcePawn Compiler 1.10
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC
Assertion failed: lval1->sym!=NULL, file C:\Users\Micha\Desktop\alliedmodders\sourcemod\sourcepawn\compiler\expressions.cpp, line 1057
'ello m8s, I would like to put an official request for typedefing to extend to variables.
I know that using "enum" with a name can technically do this by implicitly typedefing int to the enum's name but I'd like the option to typedef other names as well as arrays of these types.
EDIT: I've edited the examples to fit the grammar of 'typedef' which is typedef ::= "typedef" symbol "=" full-type-expr term
I'll just code in my examples
#include <sourcemod>
// makes declaring vec3 an array of float.
typedef vec3_t = float[3];
...
// is really 'float origin[3];'
vec3_t origin;
// this would be an error, functions can only return 'type[]'
vec3_t GetOrigin()
{
return origin;
}
void SetOrigin(vec3_t origin)
{
SetEntPropFloat(1, Prop_Send, "m_flOrigin", origin);
}
or another example case with strings
typedef StrNameBuffer_t = char[64];
// "char name[64];"
StrNameBuffer_t name;
strcopy(name, sizeof(name), "example typedef");
more complex example
typedef PlayerFields_t = StringMap;
...
PlayerFields_t fields;
fields = new PlayerFields_t();
methodmap Player {
public Player() {
}
property int iEquipment
{
public get() {
int i; fields.GetValue("iEquipment", i);
return i;
}
public set(const int val) {
fields.SetValue("iEquipment", val);
}
}
};
// player methodmap is defined, we can typedef it now
typedef Enemy_t, Friendly_t = Player;
another, more 'out of the wild' example
typedef color_t = int[4];
color_t color={ 255,255,255,255 };
SetEntityRenderColor(client, color[0], color[1], color[2], color[3]);
Faster method of creating convars!
enum {
...
VersionNum
};
typedef Convars_t = ConVars[VersionNum+1];
Convars_t PluginConvars;
more practical example from an existing plugin called "projectile detector".
Original code.
stock void GetProjPosToScreen ( const int client, const float vecDelta[3], float& xpos, float& ypos )
{
float playerAngles[3]; GetClientEyeAngles(client, playerAngles);
float vecforward[3], right[3], up[3] = { 0.0, 0.0, 1.0 };
GetAngleVectors(playerAngles, vecforward, nullvec, nullvec );
vecforward[2] = 0.0;
NormalizeVector(vecforward, vecforward);
GetVectorCrossProduct(up, vecforward, right);
float front = GetVectorDotProduct(vecDelta, vecforward);
float side = GetVectorDotProduct(vecDelta, right);
xpos = 360.0 * -front;
ypos = 360.0 * -side;
float flRotation = (ArcTangent2(xpos, ypos) + FLOAT_PI) * (57.29577951);
float yawRadians = -flRotation * 0.017453293; //FLOAT_PI / 180.0; // Convert back to radians
// Rotate it around the circle
xpos = ( 500 + (360.0 * Cosine(yawRadians)) ) / 1000.0; // divide by 1000 to make it fit with HudTextParams
ypos = ( 500 - (360.0 * Sine(yawRadians)) ) / 1000.0;
}
code using typedef
typedef vec3_t = float[3];
stock void GetProjPosToScreen ( const int client, const vec3_t vecDelta, float &xpos, float &ypos )
{
vec3_t playerAngles;
GetClientEyeAngles(client, playerAngles);
vec3_t vecforward, right, up = { 0.0, 0.0, 1.0 };
GetAngleVectors(playerAngles, vecforward, NULL_VECTOR, NULL_VECTOR );
vecforward[2] = 0.0;
NormalizeVector(vecforward, vecforward);
GetVectorCrossProduct(up, vecforward, right);
float front = GetVectorDotProduct(vecDelta, vecforward);
float side = GetVectorDotProduct(vecDelta, right);
xpos = 360.0 * -front;
ypos = 360.0 * -side;
float flRotation = (ArcTangent2(xpos, ypos) + FLOAT_PI) * (57.29577951);
float yawRadians = -flRotation * 0.017453293;
// Rotate it around the circle
// divide by 1000 to make it fit with HudTextParams
xpos = ( 500 + (360.0 * Cosine(yawRadians)) ) / 1000.0;
ypos = ( 500 - (360.0 * Sine(yawRadians)) ) / 1000.0;
}
If use "delete" on array that returned by function, you got "Invalid memory access" exception.
Because heap destroyed before zeroing variable.
Plugin example:
Handle g_handle[1];
public OnPluginStart()
{
g_handle[0] = CreateDataPack();
delete (GetHandle())[0];
}
Handle[] GetHandle()
{
return g_handle;
}
Bytecode of delete:
3404: heap 8
3412: push.alt
3416: push.c 0
3424: call 2964
3432: pop.pri
3436: heap -8
3444: push.pri
3448: load.i
3452: push.pri
3456: sysreq.n 2 1
3468: pop.alt
3472: zero.pri
3476: stor.i
Error log:
L 02/07/2018 - 19:28:31: [SM] Exception reported: Invalid memory access
L 02/07/2018 - 19:28:31: [SM] Blaming: hb.smx
L 02/07/2018 - 19:28:31: [SM] Call stack trace:
L 02/07/2018 - 19:28:31: [SM] [1] Line 6, H:\workdir\_Lab\hb.sp::OnPluginStart
P.S. I think no one ever will use statement like this and it doesn't matter, but Mr. asherkin says:
"Kailo, we'd still appreciate the bug report if you have a mo to file it"
This is from the forums (also discussed in IRC)
When compiling
int test = ByteCountToCells(PLATFORM_MAX_PATH)
in the global scope you get this error
plugin.sp(3) : fatal error 195: compiler bug: calling stock "ByteCountToCells" that has no generated code
However, when calling a native instead
int test = GetMaxClients()
you get this
plugin.sp(3) : error 010: invalid function or declaration plugin.sp(3 -- 4) : error 008: must be a constant expression; assumed zero
As Fyren pointed out the error should probably be what the last one error'd with.
I found interesting behavior in the file parser.
If i try parse file with methodmaps with properties with setters/getters (datapack.inc
for example), or without properies (regex.inc
), he works correctly.
kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ ./docparse ~/alliedmodders/sourcemod/plugins/include/datapack.inc 2>&1 > /dev/null
kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ echo $?
0
kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ ./docparse ~/alliedmodders/sourcemod/plugins/include/regex.inc 2>&1 > /dev/null
kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ echo $?
0
But if i try parse file with property without getter/setter (admin.inc
and AdminId.GroupCount
/ GroupId.GroupImmunitiesCount
), i receive segfault...
kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ ./docparse ~/alliedmodders/sourcemod/plugins/include/admin.inc 2>&1 > /dev/null
Segmentation fault (core dumped)
kruzya@UBUNTU:~/alliedmodders/sourcemod/sourcepawn/build/exp/tools/docparse/docparse$ echo $?
139
P.S.: Sorry for my english. I'm from Russia.
Specifically https://github.com/alliedmodders/sourcemod/blob/74512575/plugins/include/topmenus.inc
I've not had luck in narrowing this down further. Output of generate.py is just:
Failed to process ../../../../sourcemod/plugins/include/topmenus.inc:
Traceback (most recent call last):
File "generate.py", line 624, in <module>
main()
File "generate.py", line 601, in main
gen.generate()
File "generate.py", line 189, in generate
self.parse_include(include)
File "generate.py", line 208, in parse_include
raise Exception('failed to parse file')
Exception: failed to parse file
I wrote about this feature in Discord and IRC. And retry here, in issue.
Code like:
public void OnPluginStart() {
sleep;
}
cause the server to crash.
Accelerator: https://crash.limetech.org/uhqigne5rpie
SM Version:
SourceMod Version Information:
SourceMod Version: 1.8.0.6036
SourcePawn Engine: SourcePawn 1.8, jit-x86 (build 1.8.0.6036)
SourcePawn API: v1 = 4, v2 = 11
Compiled on: Nov 3 2017 19:06:38
Built from: https://github.com/alliedmodders/sourcemod/commit/fef5583
Build ID: 6036:fef5583
http://www.sourcemod.net/
Code with this "feature":
Lines 5434 to 5437 in a1c9bfb
Lines 5442 to 5445 in a1c9bfb
another enhancement I think would benefit SP is having closures or at minimum function pointers of some sort.
I first tried to test if SP already had something like this in Asherkin's Spider but sadly the compiler bitched at me.
#include <sourcemod>
#pragma semicolon 1
#pragma newdecls required
public Plugin myinfo = {
name = "",
author="",
description="",
version="0.0.0",
url=""
};
void myfunc()
{
PrintToServer("myfunc called.\n");
}
public void OnPluginStart()
{
Function func = myfunc;
func();
}
I also tried doing this but it failed too.
public void OnPluginStart()
{
function func = myfunc;
func();
}
Example time!
in my VSH2 plugin, specific code from certain methodmaps are run on different players.
each action and event uses a switch construct to decide which methodmap and which method is called.
public void ManageBossHelp(const BaseBoss base)
{
switch ( base.iType ) {
case -1: {}
case Hale: ToCHale(base).Help();
case Vagineer: ToCVagineer(base).Help();
case CBS: ToCChristian(base).Help();
case HHHjr: ToCHHHJr(base).Help();
case Bunny: ToCBunny(base).Help();
case PlagueDoc: ToCPlague(base).Help();
}
}
by having closures (or func pointers, which ever)
the code can be simplified into.
public void ManageBossHelp(const BaseBoss base)
{
// this array wouldn't really be in this function !
// just example
function fnBossHelp[] = {
ToCHale(base).Help,
ToCVagineer(base).Help,
ToCChristian(base).Help,
ToCHHHJr(base).Help,
ToCBunny(base).Help,
ToCPlague(base).Help
};
// get func ptr of methodmap then call like method.
base.fnBossHelp[base.iType]();
}
I haven't narrowed down the difference between which ones display fine and which ones have the issue, but for some typeset parameters of functions, the typeset definition is displayed as the type, instead of the typeset name. Some examples are below.
Include:
typedef SQLTCallback = function void (Handle owner, Handle hndl, const char[] error, any data);
Display:
void SQL_TQuery(Handle database, SQLTCallback callback, const char[] query, any data, DBPriority prio)
Include:
typedef MsgPostHook = function void (UserMsg msg_id, bool sent);
native void HookUserMessage(UserMsg msg_id, MsgHook hook, bool intercept=false, MsgPostHook post=INVALID_FUNCTION);
Display:
void HookUserMessage(UserMsg msg_id, MsgHook hook, bool intercept, function void(UserMsg msg_id, bool sent) post)
Ever since 15d6c93, console output has been weird when plugins error out and compilations are aborted. Here’s what it looks like.
C:\Users\Micha\Desktop\New folder\sourcepawn\build\compiler\spcomp>spcomp test.sp
SourcePawn Compiler 1.10
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2017 AlliedModders LLC
test.sp(2) : fatal error 194: user error: testing 1 2 3
Compilation aborted.Code size: 0 bytes
Data size: 0 bytes
Stack/heap size: 16384 bytes
Total requirements: 16384 bytes
I have a directory layout like this.
│ plugin.sp
└───includes
│ extension.inc
└───extension
file.inc
plugin.sp
includes extension.inc
like this
#include "includes/extension"
extension.inc
includes file.inc
like this
#include "extension/file"
spcomp is in the PATH
and i compile from the directory where plugin.sp
is like this
spcomp plugin.sp
A test case that compiles on linux but fails on windows can be found here: includebug.zip.
The version i used were
Windows: 1.10.0.6336
Linux: 1.10.0.6335
The error i get is this
SourcePawn Compiler 1.10.0.6336
Copyright (c) 1997-2006 ITB CompuPhase
Copyright (c) 2004-2018 AlliedModders LLC
includes/extension.inc(1) : fatal error 183: cannot read from file: "extension/file"
Compilation aborted.
1 Error.
If i change the include inside extension.inc
to
#include "includes/extension/file"
it works.
The problem is that this is inconsistent between windows and linux. If i make the change described here then it works on windows but not on linux.
Ideally one would expect that the include paths are always relative to the file that includes them
like in the attached includebug.zip.
Please let me know if you need more information.
Compiler show no error when you try to compile forward with wrong prototype (without arguments).
public void OnClientPostAdminCheck()
{
}
I tried compile the doc from the sourcepawn repository, and everything was ok, but when i try to execute the generate.py i have a access permission problem. Anyone knows how to fix?
ushakov@thinkpad-x201s:~/Desktop/generate$ sudo python ./generate.py
[sudo] password for ushakov:
Failed to process ./include/sounds.inc:
./include/sounds.inc: 1: ./include/sounds.inc: ./docparse: Permission denied
Traceback (most recent call last):
File "./generate.py", line 621, in <module>
main()
File "./generate.py", line 598, in main
gen.generate()
File "./generate.py", line 189, in generate
self.parse_include(include)
File "./generate.py", line 209, in parse_include
raise Exception('failed to parse file')
Exception: failed to parse file
When i have include and docparse in the same folder of generate.py i have that error
``
Failed to process ./sounds.inc:
Usage: ./docparse [-h] filename
error: Missing value for 'filename'.
Traceback (most recent call last):
File "./generate.py", line 621, in <module>
main()
File "./generate.py", line 598, in main
gen.generate()
File "./generate.py", line 189, in generate
self.parse_include(include)
File "./generate.py", line 209, in parse_include
raise Exception('failed to parse file')
Exception: failed to parse file
I attached a includes and compiled docparse here
https://drive.google.com/file/d/1dni6O3gu-u1Wffvu5wsUb1cZ21CnhWmy/view
What i did wrong?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.