sourcepawn icon indicating copy to clipboard operation
sourcepawn copied to clipboard

VFormat varpos is shifted within methodmap

Open dragokas opened this issue 2 years ago • 4 comments

Help us help you

  • [x] I have checked that my issue doesn't exist yet.
  • [x] I have tried my absolute best to reduce the problem-space and have provided the absolute smallest test-case possible.
  • [x] I can always reproduce the issue with the provided description below.

Environment

  • Operating System version: -
  • Game/AppID (with version if applicable): -
  • Current SourceMod version: 1.11.0.6736
  • Current SourceMod snapshot: 1.11.0.6736
  • Current Metamod: Source snapshot: 1.11.0-dev+1145
  • [x] I have updated SourceMod to the latest version and it still happens.
  • [x] I have updated SourceMod to the latest snapshot and it still happens.
  • [x] I have updated SourceMM to the latest snapshot and it still happens.

Description

I understand, this happens due to pushing "this" in the stack. However, can I count below behaviour won't change in future? In such a case, I prefer it should be directly stated in the VFormat documentation.

Problematic Code (or Steps to Reproduce)

#pragma semicolon 1
#pragma newdecls required

#include <sourcemod>

methodmap Met < Handle
{
	public Met()
	{
		return view_as<Met>(-1);
	}
	
	public void Print_p2(char[] format, any ...)
	{
		char buffer[1024];
		SetGlobalTransTarget(LANG_SERVER);
		VFormat(buffer, sizeof(buffer), format, 2);
		PrintToServer("%s", buffer);
	}
	public void Print_p3(char[] format, any ...)
	{
		char buffer[1024];
		SetGlobalTransTarget(LANG_SERVER);
		VFormat(buffer, sizeof(buffer), format, 3);
		PrintToServer("%s", buffer);
	}
}

public void OnPluginStart()
{
	Met m = new Met();
	
	Local_Print	("[Loc Print, varpos 2] Hello: %s", "World" );
	m.Print_p2	("[Met Print, varpos 2] Hello: %s", "World" );
	m.Print_p3	("[Met Print, varpos 3] Hello: %s", "World" );
}

void Local_Print(char[] format, any ...)
{
	char buffer[1024];
	SetGlobalTransTarget(LANG_SERVER);
	VFormat(buffer, sizeof(buffer), format, 2);
	PrintToServer("%s", buffer);
}

Logs

[Loc Print, varpos 2] Hello: World
[Met Print, varpos 2] Hello: [Met Print, varpos 2] Hello: %s
[Met Print, varpos 3] Hello: World

dragokas avatar Aug 13 '21 17:08 dragokas

This is expected, I believe it is documented already in the context of methodmaps that they have this as an implicit first argument.

asherkin avatar Aug 13 '21 17:08 asherkin

Indeed - working as intended. But the usability of varargs is gross. I'll leave this open to bikeshed new syntax. For example:

  public void Print_p3(char[] format, any args...)
  {
  	char buffer[1024];
  	SetGlobalTransTarget(LANG_SERVER);
  	VFormat(buffer, sizeof(buffer), format, args.position);
  	PrintToServer("%s", buffer);
  }

dvander avatar Aug 13 '21 17:08 dvander

Indeed - working as intended. But the usability of varargs is gross. I'll leave this open to bikeshed new syntax. For example:

  public void Print_p3(char[] format, any args...)
  {
  	char buffer[1024];
  	SetGlobalTransTarget(LANG_SERVER);
  	VFormat(buffer, sizeof(buffer), format, args.position);
  	PrintToServer("%s", buffer);
  }

In your example if args is going to be a pseudo-element that exists as a syntactic shortcut, can we just let args evaluate to it's parameter number & not have to call position on it. Calling a property (.position) on something that doesn't exist feels too spooky unless you have other justification

Headline avatar Aug 13 '21 21:08 Headline

I'm thinking it would be a pseduo-object or pseudo-array, like in C# or Java. There's lots of precedent for things like that.

dvander avatar Aug 13 '21 21:08 dvander