logo
Main

Forums

Downloads

Unreal-Netiquette

Donate for Oldunreal:
Donate

borderline

Links to our wiki:
Wiki

Walkthrough

Links

Tutorials

Unreal Reference

Usermaps

borderline

Contact us:
Submit News
Page Index Toggle Pages: 1 Send TopicPrint
Normal Topic Forwarding non-replicated user-level commands: ActivateInventoryItem, BehindView, GetWeapon (Read 104 times)
Masterkent
Developer Team
Offline



Posts: 1169
Location: Russia
Joined: Apr 5th, 2013
Gender: Male
Forwarding non-replicated user-level commands: ActivateInventoryItem, BehindView, GetWeapon
Nov 27th, 2018 at 10:45am
Print Post  
There are three commands that are not automatically replicated from a client to a server and sometimes cannot function well when executed client-side:

1. ActivateInventoryItem - does not work at all in an online game.

2. GetWeapon - may switch to a weapon that differ from the requested one if there are other weapons that share the same slot number.

3. When joining the game as a spectator, BehindView does not modify server-side bChaseCam which is responsible for remembering the desired view mode (1st person view or 3rd person view).

My suggestion is to allow these commands to be forwarded to the server by means of the Admin command without requiring admin rights:

Code
Select All
// Execute an administrative console command on the server.
exec function Admin( string CommandLine )
{
	local string Result;

	if (StartsWith(CommandLine, "ForwardUserCommand ", true))
		ConsoleCommand(CommandLine);
	else if (Level.Game.GetAccessManager().CanExecuteCheatStr(Self, 'Admin', CommandLine))
	{
		bConsoleCommandMessage = true;
		if ( Level.Game.GameRules!=None )
			Result = Level.Game.GameRules.ExecAdminCmd(Self,CommandLine);
		else Result = ConsoleCommand( CommandLine );
		bConsoleCommandMessage = false;
		if ( Len(Result)>0 )
			ClientMessage( Result );
	}
}

// Hack for forwarding known user-level non-replicated functions from client to server
exec final function ForwardUserCommand(string Command)
{
	local string FuncName, Params;

	if (Level.NetMode == NM_Client)
	{
		Admin("ForwardUserCommand" @ Command);
		return;
	}

	if (!Divide(Command, " ", FuncName, Params))
		FuncName = Command;

	if (FuncName ~= "ActivateInventoryItem" ||
		FuncName ~= "BehindView" ||
		FuncName ~= "GetWeapon")
	{
		ConsoleCommand(Command);
	}
} 


For ActivateInventoryItem such a forwarding can be done unconditionally, because otherwise this command would not have effect at all:

Code
Select All
// Activate specific inventory item
exec function ActivateInventoryItem( class InvItem )
{
	local Inventory Inv;

	if (Level.NetMode == NM_Client)
	{
		ForwardUserCommand("ActivateInventoryItem" @ InvItem);
		return;
	}
	if (!CanInteractWithWorld())
		return;

	Inv = FindInventoryType(InvItem);
	if ( Inv != None )
		Inv.Activate();
} 


The other two commands can be forwarded when flag bForwardUserCommands is set client-side for the given PlayerPawn:

Code
Select All
exec function GetWeapon(class<Weapon> NewWeaponClass )
{
	local Inventory Inv;
	local Weapon NewWeapon;

	if ( Level.NetMode==NM_Client )
	{
		if ( NewWeaponClass!=None )
		{
			if (bForwardUserCommands)
				ForwardUserCommand("GetWeapon" @ NewWeaponClass);
			else
				SwitchWeapon(NewWeaponClass.Default.InventoryGroup); // Stupid workaround for clients...
		}
		return;
	}
	if (!CanInteractWithWorld() ||
		Inventory == None ||
		NewWeaponClass == None ||
		Weapon != None && Weapon.Class == NewWeaponClass)
	{
		return;
	}

	for ( Inv=Inventory; Inv!=None; Inv=Inv.Inventory )
		if ( Inv.Class == NewWeaponClass )
		{
			NewWeapon = Weapon(Inv);
			if (NewWeapon.AmmoType != none && NewWeapon.AmmoType.AmmoAmount <= 0)
			{
				ClientMessage(NewWeapon.ItemName $ NewWeapon.MessageNoAmmo);
				return;
			}

			if (Weapon == none)
			{
				PendingWeapon = NewWeapon;
				ChangedWeapon();
			}
			else if (Weapon.PutDown())
				PendingWeapon = NewWeapon;
			return;
		}
} 


Code
Select All
exec function BehindView( Bool B )
{
	if (Level.NetMode == NM_Client && bForwardUserCommands)
	{
		ForwardUserCommand("BehindView" @ B);
		return;
	}
	if (!bCanChangeBehindView)
		return;
	bBehindView = B;
	bChaseCam = bBehindView;
} 


Since ForwardUserCommand may execute functions only from the predefined set, it should not introduce any security flaws.

Some mods may disallow execution of ForwardUserCommand without admin permissions, but, I presume, there is no better solution anyway.
  
Back to top
 
IP Logged
 
[]KAOS[]Casey
Developer Team
Betatester
Offline


nedm

Posts: 3138
Joined: Aug 7th, 2011
Gender: Male
Re: Forwarding non-replicated user-level commands: ActivateInventoryItem, BehindView, GetWeapon
Reply #1 - Nov 28th, 2018 at 8:24am
Print Post  
Always wondered why getweapon never worked like i thought it was supposed to.. never bothered to look into it though
  
Back to top
 
IP Logged
 
Masterkent
Developer Team
Offline



Posts: 1169
Location: Russia
Joined: Apr 5th, 2013
Gender: Male
Re: Forwarding non-replicated user-level commands: ActivateInventoryItem, BehindView, GetWeapon
Reply #2 - Nov 29th, 2018 at 10:12am
Print Post  
I think, we can also allow forwarding of GetWeapon and BehindView for the standard PlayerPawn subclasses regardless of bForwardUserCommands:

Code
Select All
function bool ShouldForwardUserCommands()
{
	return
		bForwardUserCommands ||
		Class.Outer.Name == 'UnrealI' ||
		Class.Outer.Name == 'UnrealShare' ||
		Class.Outer.Name == 'UPak';
} 


Code
Select All
exec function GetWeapon(class<Weapon> NewWeaponClass )
{
	local Inventory Inv;
	local Weapon NewWeapon;

	if ( Level.NetMode==NM_Client )
	{
		if ( NewWeaponClass!=None )
		{
			if (ShouldForwardUserCommands())
				ForwardUserCommand("GetWeapon" @ NewWeaponClass);
			else
				SwitchWeapon(NewWeaponClass.Default.InventoryGroup); // Stupid workaround for clients...
		}
		return;
	} 


The reason why such conditions should be used is that mods may define custom subclasses of PlayerPawn where function PlayerPawn.Admin can be overridden so that ForwardUserCommand would not work there. Then unconditional forwarding would make GetWeapon and BehindView non-working.

Since we know that the standard player classes use the default definition of Admin, we can conclude that ForwardUserCommand can reliably forward GetWeapon and BehindView via the Admin function for such classes.
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Send TopicPrint
Bookmarks: del.icio.us Digg Facebook Google Google+ Linked in reddit StumbleUpon Twitter Yahoo