#multiplayer

1 messages · Page 489 of 1

vivid quest
#

does anyone know how specifically character position / movement information is replicated across the network?

#

looking at some comments in UCharacterMovementComponent it seems like this is done with RPC, but in replays i’m not sure that RPC works the same

#

i’m specifically talking about replays

soft relic
#

How would I show a different widget on server connect and a different widget on clients connect?

#

Would I handle this from their PCs?

#

Why is this wrong?

graceful cave
#

theres no need for those to be RPCs since thats only running locally

#

also theyre both calling the same thing

chrome bay
#

When people put strange characters in their name in makes it impossible to tag them.
Character movement is replicated through replicated movement like any other actor.

#

Replaying "Moves" if that's what you're referring to is triggered when a client gets a correction - all moves are played instantly at the start of the tick before processing normal movement for that frame.

thin stratus
#

All Moves that are newer than the correction*

#

And Replays is probably meant to be an actual replay

#

Not the Moves

nocturne berry
#

is there a way to replicate fast to the clients the new location that i set for the pawn on the server? (without waiting for the correction)

chrome bay
#

no

#

it gets there when it gets there

#

That's why you predict changes where possible on the client

soft relic
#

How can I set a pawn and possess it to the logged in PC? What's the process?

#

onpostlogin from GM won't work as it only exists on the server

chrome bay
#

Calls 'Possess' on the Server for the player controller

#

You don't call' Possess' client-side anyway

#

Post Login is probably too early

soft relic
#

So how?

chrome bay
#

The gamemode spawns a pawn for the player anyway and they will possess it automatically

soft relic
#

this will only spawn for the server

chrome bay
#

No it won't

soft relic
#

I wont different pawns based on if its a server or not

chrome bay
#

If you want different pawns you need to override 'Spawn Default Pawn For'

soft relic
#

want*

#

How can I change the pawn on connection though?

chrome bay
#

You can't

#

The Pawn a player controls will always be the same on server and client

soft relic
#

I'm sure I can, I've done it from a tutorial before where it checked what character there as selected and then spawned a pawn for it and possesed the P

#

PC

chrome bay
#

The server is in control of who possesses what

thin stratus
#

'Spawn Default Pawn For' -> IsLocalPlayerController* -> Yes (Server)/No (Client)

chrome bay
#

GetDefaultPawnClassForController is what you want to override

thin stratus
#

One of them yeah

soft relic
#

Well, what if I want to change pawns in game?

chrome bay
#

Then you spawn a new pawn and tell the controller to possess it

soft relic
#

So why won't the picture I sent you above work? What's wrong with it?

chrome bay
#

Because the default pawn will be spawned after that has run

#

And the controller will switch to that instead

soft relic
#

But the server does get that pawn, why?

thin stratus
#

But the server does get that pawn, why?
What does that even mean

#

You are pretty vague in what you want

#

By default, functions like PostLogin call for Server and Client connecting (on the server).
Same for the DefaultPawnClass you can set.

chrome bay
#

Looks like it won't spawn a 'Default' pawn if the controller already has one

#

But still, overriding the default pawn per-controller is better

thin stratus
#

If you need custom logic for who gets what pawn, then you have to set the DefaultPawnClass to NONE and implement the function we mentioned.

soft relic
#

I just want to create a function that would spawn an actor and possess it to the connected controller.

#

Okay\

thin stratus
#

The code you posted above would do that

#

But make sure you set the DefaultPawn to none in the gamemode settings

soft relic
#

Okay it worked, but it needed a delay after onpostlogin

vivid quest
#

@chrome bay it’s weird because i spent a good portion of the day trying to see where this was occurring, i set a breakpoint inside the function which serialises the replicated properties but it doesn’t even get triggered on most frames of the playback so i don’t think that’s what’s happening

#

i also looked at the names of the replicated items and none of them were FRepMovement as you’d expect

thin stratus
#

@soft relic If you need a Delay, you are doing it wrong. Delays are a No-Go in networking

soft relic
#

Fixed it, it's without a delay now

chrome bay
#

What do you mean by replay exactly?

#

I can't tag you because of the Char in your name

#

Are you talking about replay in the networking sense, or are you talking about replaying a full game?

#

Like the paragon/fortnite demo replay system

vivid quest
#

replaying a full game, as in with the demorec / demoplay commands

#

not sure if that’s what it is in fortnite

chrome bay
#

No replication occurs for that

#

There's no server etc.

#

The players movement is stored in a separate struct and saved off somewhere

vivid quest
#

it essentially streams packets from the replay file

chrome bay
#

When you do a replay you download a massive file IIRC

#

and you just scrub through

#

There's no networking involved

vivid quest
#

the massive file is just a list of packets

#

and it serialises it in roughly the same way as any other data from the network

#

there’s definitely replication

#

it’s as if the replay file is the ‘server’

#

but some things are different

#

my use case is that i’m trying to write a replay parser as an external tool

chrome bay
#

PreReplicationForReplay() seems to be what processes replay samples

vivid quest
#

this looks useful

#

thank you

#

not entirely sure how i didn’t find this yet

#

lol

chrome bay
#

I'm not 100% tbh now, I've never used the demo recorder etc.

vivid quest
#

yeah no i think i just realised what i need to do

#

welp

#

i was expecting it to be with the other rep data but it seems like it’s special cased and put somewhere else

high current
#

not that you asked, but iirc demo recorder doesnt work in PIE

thin stratus
#

Does anyone know if you can delay the welcome process of UE4?

#

As in, usually you can deny a player in PreLogin and Login.

#

But if that's tied into an Async Call to the Backend, you can't deny there.

#

I know I could modify the engine to simply not execute the welcoming stuff until I say so, but I wonder if that's already possible without engine changes.

fleet raven
#

I previously tried to do that and found it to be impossible

thin stratus
#

Via Engine Modification?

fleet raven
#

that's what I ended up doing

thin stratus
#

Someone did do that though, at least if you can believe their PlayFab forum post

#

Ah

fleet raven
#

I suppose one way without a modification would be to use the beacon thing

thin stratus
#

It would be an easy engine change though

fleet raven
#

connect a beacon first, handle auth, get the ticket or similar that you can immediately accept, then do a normal connection

#

but that's unreasonably more complicated

thin stratus
#

You just have to give the user the option to call the stuff themselves

#

As in, whereever UE4 calls Welcome (if the ErrorString is empty), you'd just check if the Welcome is delay (boolean).
And then allow them to call the code themselves

#

That would be the easiest way

#

Welp, Engine Mod it is

torpid willow
#

What chat are you using with UE games? We use Photon, it kinda sucks - what other option?

supple musk
#

Hello guys,
I got some problem with Variable replication using a Dedicated Server. I have two actors, owned by two different clients. When I set a variable on the server, only the server and the owner of the actor has the value replicated. Not the other non-owner client.
Is this intended behavior ?

fluid prawn
#

@supple musk If you're the server then your Role is Authority So if you set at variable as the server/owning authority will have that variable changed for owning authority actors the second will be Owner Autonomous proxy will not unless you have a function the Server calls to set the variable for those Autonomous proxies specifically.

#

Think of it as permissions in a file system

#

the other actors are not part of Group Authority

graceful pumice
#

I’m learning multiplayer, and I wanted to make sure my observations seem correct.

  1. When using one time input actions, say swapping weapon, using ReplicatedUsing=OnRep_SomeFunction would suffice since the Both the server and client would only update once, thus this action would only need to be checked once
#

An example of this implementation could be:
UPROPERTY(ReplicatedUsing=OnRep_Variable)
float Variable;

UFUNCTION()
void OnRep_Variable();

fluid prawn
#

@graceful pumice When your variable is replicated from the server then On_RepVariable is called

#

then inside that function you can make it Server side or client

graceful pumice
#

I believe I understand that part.

fluid prawn
#

so in the case of your example with swapping weapons when say the client replicates a bool that says swap weapons then an On_Rep can multicast that the client or w.e swapped a weapon

graceful pumice
#

Multicast meaning it updates both the server and all clients, right?

fluid prawn
#

Server tells everyone

#

hence multicast

graceful pumice
#

Got it

#

Okay so here is what I’m leading up to

fluid prawn
#

so if i multicast a fart

#

everyone connected to the server can smell it

#

it will broadcast it to everyone

graceful pumice
#

Got it

#

So In Rama’s tutorial that I’ve been following

#

He calls his OnRep function inside his server function

fluid prawn
#

That's different

graceful pumice
#

But that’s unnecessary, correct?

fluid prawn
#

When you call an On_Rep that just means you are doing the call back

#

So say you have a situation where you want to On_Rep function to be called when its tied to replicated value and you want to call it when something you did logically happens

#

you get the best of both worlds

#

The On_Rep will be called on replication but also you called it because someone farted

#

or w.e

graceful pumice
#

Why would I call it back though? What’s this other benefit?

fluid prawn
#

flexibility

#

or logic

#

w.e your code requires

#

You have it by default On_Rep for a variable persay

#

but say for some reason when a timer goes to 0 or something else thats not tied to the variable being replicated you want that On_Rep to be called you can just call it yourself

graceful pumice
#

I think I get it.

#

So let me see if I’m following you

#

Using my weapon swap example

fluid prawn
#

sure

graceful pumice
#

I have a bool that replicates using OnRep

fluid prawn
#

Yup

graceful pumice
#

A have a button input that calls an equip function

#

That runs logic locally to determine if the player can equip

#

If the player can equip, I would call me server function, which sets my replicated bool to true

#

Inside that server function, I set my replicated bool and call the on rep function

#

Inside my OnRep function is the logic for actually equipping the weapon

#

Sound correct?

thin stratus
#

That runs logic locally to determine if the player can equip
That's a bit risky

fluid prawn
#

You change that variable on the client to say true.. it gets replicates... then On_Rep is called your logic get executed.. Now for the case of your equip logic I am gonna assume you are validating that bool on the server if it's allowed its replicated then that user can equip w.e item so server says ok. Now for example lets suppose you have the logic coded up and your On_Rep does all that equip logic takes in who its to be equipped to the item etc... Then lets continue on this logic lets say you have a mechanic where if you get a kill streak you get a super weapon or something but its not something the user has access to you can Call On_Rep by the server and pass that super weapon object to the function and the user you specified will get it.

supple musk
#

@fluid prawn i don't quite get what you explained. To me, for a variable to be replicated on every client I just had to set it on the server, regardless of ownership

graceful pumice
#

@thin stratus @fluid prawn So even the check to see if the player can equip should be on the server? If so, then that means I would have my input directly calling my server function. Is that okay?

fluid prawn
#

@twin juniper Sure you can have the variable on server or you can have the variable on Client. Depends on what you want to do but if its on client you have to decide what you want to validate because the client can hack that info

thin stratus
fluid prawn
#

LOl cedric did you just draw that up now XD

thin stratus
#

Once you know how that works it's pretty quick to draw ¯_(ツ)_/¯

graceful pumice
#

Oh wow

#

That makes sense lol

fluid prawn
#

lololol

graceful pumice
#

So I would have the input call a client function

thin stratus
#

Yeah just a function

graceful pumice
#

That checks if it can equip

thin stratus
#

:P

#

Put < > around the link

fluid prawn
#

LET ME SHOW YOU NETCODE

graceful pumice
#

Then the client would send it’s request to the server, which I would do by calling the server function

thin stratus
#

Correct, but only if the Client already switched

graceful pumice
#

If the server says yes, then update the bool

thin stratus
#

it's predicted basically

graceful pumice
#

Then call the OnRep function

#

Which stores all of the equipping logic

fluid prawn
#

ya that function should exist on the server

thin stratus
#

Generally speaking, you'd have some sort of OnRep variable that says what is equipped

#

Like CurrentWeapon

fluid prawn
#

for validation only if you want it to be responsive you can have the client equip it and then ask permission from the server

graceful pumice
#

Right, well I’m not to the actual equipping part yet

#

Basically I’m focusing on the rotation of the character

thin stratus
#

You wanna draw out the whole process though

#

Otherwise you just do it over and over again

fluid prawn
#

That diagram is sound

graceful pumice
#

What I’ll do, then, is write out some pseudo code and send it

fluid prawn
#

Start out small

graceful pumice
#

I’m on mobile, so typing sucks lol

fluid prawn
#

just make a variable replicate it and do a UE_LOG

#

to see if it works

#

like tie it to an input like when you press E

graceful pumice
#

Kk

fluid prawn
#

all that matters is the flow of data you can do the logic after

#

Set a variable to bool say bHasFarted

#

then tie input to E to fart

#

and then UE_Log("Server Smells your fart")

meager spade
#

a lot of games (including fortnite) are NOT predicted equip/pickup

fluid prawn
#

@meager spade I assume that's the case because its well defined what objects are allowed to be equiped

meager spade
#

i think pickups more than equip are not predicted

#

equip might be local, tell server, server disagrees, client rpc back to unequip it

#

else server equips which replicates out

graceful pumice
#

Pseudo Code at its finest lol

#

Does this look correct?

meager spade
#

i dislike calling OnRep from a server function, i prefer the onrep to call a function itself

graceful pumice
#

@meager spade So don’t call the OnRep at all?

meager spade
#

you would have a function

#

that the onrep and server call

#

like void Equip();

#

which you call from server and the OnRep

#

but i do my equip differently

#

i don't use OnRep, i equip it locally, tell the server, server either then equips or client rpc back telling the client to unequip, which returns the player back to the previous weapon

graceful pumice
#

Could you show me a minor example of what you mean?

#

Well let me take a step back here

#

Let me send something real quick

thin stratus
#

@meager spade And what do you do with the simulated clients?

#

We only use OnRep for them

graceful pumice
meager spade
#

Attachment is replicated

graceful pumice
#

Was I close? Lol

meager spade
#

kinda

#

unequip should be a client rpc

graceful pumice
#

Okay let me redo this real quick

meager spade
#

this here uses no OnRep

#

dedicated server, two clients

graceful pumice
#

Does this make more sense?

meager spade
#

only thing i replicated out, is the ActiveItem

#

and thats so simulated know what item they have

#

for animationbp, etc

graceful pumice
#

Sorry that client_equip() in the server function needs to be unequipped

meager spade
#

@graceful pumice nope

graceful pumice
#

Dang it lol

#

So what’s the benefit of doing it this way rather than using an OnRep?

grand kestrel
#

I just thought Kaos was saying he prefers to have the server call the same function OnRep calls in lieu of having the server call OnRep for readability, not to avoid using OnRep

meager spade
#

yeah

grand kestrel
#

I personally prefer to use the OnRep because its always clear where its coming from

meager spade
#

OnRep should just run another function or do very basic things, if server and the onrep need to do the same thing, it should be a function call

grand kestrel
#

One less thing to chase

meager spade
#

but also can cause headache

thin stratus
#
Input()->EquipWeapon(SomeWeapon);

// Generic Equip Function called by Server and owning Client
void EquipWeapon(NewWeapon)
{
    if(CanEquip(NewWeapon))
    {
        // Perform Equip
        SetCurrentWeapon(NewWeapon);
        // Tell Server to do the same
        if(LocallyControlled() && !HasAuthority())
        {
            Server_EquipWeapon(NewWeapon);
        }
    }
    // Server found out we can't equip    
    else if(HasAuthroity())
    {
        Client_ForceUnequip(NewWeapon);
    }
}

// Server RPC
void Server_EquipWeapon(NewWeapon)
{
    EquipWeapon(NewWeapon);
}

// Client RPC
void Client_ForceUnequip(Weapon)
{
    UnequipWeapon(Weapon);    
}

// Handy Setter
void SetCurrentWeapon(NewWeapon)
{
    CurrentWeapon = NewWeapon;

    // Handle Attachment
}

// Simulated Only
void OnRep_CurrentWeapon()
{
    // Handle Attachment
}


void UnequipWeapon(Weapon)
{
    if(Weapon == CurrentWeapon)
    {
        SetCurrentWeapon(NULL);
    }
}
meager spade
#

like ah i need to fix equip, you have no equip function cause you shoved it in an OnRep

grand kestrel
#

What if the client doesn't have the weapon currently equipped that the server rejected 😛

thin stratus
#

That's what nullptr checks are for

#

That's just pseudo code

grand kestrel
#

I was implying you should pass the weapon through the unequip client RPC and check current weapon == that weapon

thin stratus
#

You can do that, correct

meager spade
#

items and weapons in my game share the same 5 slots

thin stratus
#

There

meager spade
#

i originally built it to only be weapons, changing it to be both, with the hud working, was a nightmare

graceful pumice
#

So let me see if I got this right

thin stratus
#

You can do it with bananas if you want

#

The execution is always the same

grand kestrel
#

I do like bananas

thin stratus
#

Check on Client, Do It, Tell Server, Check on Server, Do it, Replicate to Simulated OR Don't do it and correct original client call.

#

May it be equipment or the CharacterMovementComponent

#

It all works the same

#

You could even go as far as saving equipment calls in a list

#

And replaying them in case the client changes fast

#

idk

#

It's really all the same

worthy perch
#

Would it be wrong, in this case, to prefer OnReps instead of RPCs because OnReps will eventually replicate down while RPCs can be dropped?

thin stratus
#

That and you have late joiners or people who are far away and out of relevancy range

worthy perch
#

That is a good point too, yeah.

thin stratus
#

A state change should always be an OnRep

#

But you need to cut stuff in half

#

e.g. you have a door

#

bIsDoorOpen is the state

#

So the OnRep would mark it as open.

#

But the animation isn't relevant for someone who comes in late

#

So the animation of it opening can be an RPC

graceful pumice
#

So RPC are primarily used for checks, and OnRep to run the logic after all the checks are done

#

?

thin stratus
#

RPCs are fire and forget. You fire it, whoever is relevant gets it and then afterwars the story is over

graceful pumice
#

Hmmm

#

I’m going to tinker with this and post what I have later on

#

To make sure my understanding is correct

#

There comes a point to where the best way to learn is to just do it

#

At least for me lol

graceful pumice
#

Alright

#

So this is what I got

#

Now the purpose of this function is to update the character's rotation

#

So not even equipping yet, just changing the rotation.

#

The issue is that OnRep is never called as the character's rotation never changes

#

So am I using OnRep incorrectly?

#

Ah disregard. I just noticed the comment in @thin stratus sample - I am supposed to handle the logic in both the set function and the onrep function

thin stratus
#

Yes, the idea is that the OnRep only calls for Simulated

#

And the Set function for Server and owning client

#

You'd mark the varaible as repnotify with the condition Simulated only or skipowner or what it is

#

Just be aware that if you use C++ it doesn't call on the Server (OnRep) while it does in BPs

graceful pumice
#

Yep that makes sense now. After removing the ReplicatedUsing property tag, the server doesn't replicate to the client...which make sense because the server is the simulated proxy on the client side; and testing with a dedicated server means neither players replicate to each other

#

Okay, OnRep is for simulated proxies...got it

#

And since I am using C++, I don't have to worry about SkipOwner, correct?

#

That doesn't even appear as a property tag in UPROPERTY anyways, so I would assume not

meager spade
#

its in the DOREPLIFETIME

#

DOREPLIFETIME_COND(ASomeActor, SomeProperty, COND_SkipOwner);

graceful pumice
#

Ah, thank you Kaos!

#

And we do skip owner because we don't need to "replicate" it to the owner since we already did that locally

#

correct?

meager spade
#

yes

graceful pumice
#

Learning has occurred! Thank you guys!

spring swift
#

has anyone added steam API to there game before?

meager spade
#

its built into the engine

fluid prawn
#

Question

#

When you Change Variables In the Engine.ini file

#

Does it update on compile in the editor or will i need to Generate Visual Studio files and recompile it?

unique kelp
#

The ini files would at most need an editor restart

#

as far as I know, anyway

fluid prawn
#

ok

#

ya its not taking my changes

#

ill test

fluid prawn
#

Got it working

#

Curious

#

for fast movement games in UE4 is it normal to have larger and 3.0 MAXPOSITIONERRORSQUARED values?

thin stratus
#

We use the default value atm

#

This is the error after which you get corrected

#

If that's bigger, the correction will also be bigger

#

And way more noticable

fluid prawn
#

hmm a question within a question is what should I aim for that realistic error

#

based on the max speed of my movement? or acceleration?

thin stratus
#

I would suggest just playing your game on a simulated high ping

#

And then checking if that feels good

fluid prawn
#

like with clumsy?

limber mortar
#

you can edit your engine config file

#

to simulate lag

fluid prawn
#

I tested with the netpkt lag console setting

limber mortar
#

defaultengine.ini

[PacketSimulationSettings]
PktLag=0
PktLagVariance=0
PktLoss=0
PktOrder=0
PktDup=0

fluid prawn
#

yea

#

I think setting those in the console modifies them at runtime

thin stratus
#

Anyone here setup a Linux DedicatedServer via a Container? I only seem to find "Docker" for this and I'm surprised that Linux has no bare bones free version of this.

fleet raven
#

what do you mean? docker is free and what everyone uses to make containers

young jacinth
#

hey! any1 used Socket.io here for simple multiplayer purposes ?! I want to get some advices before digging it if there's any pitfalls or things to consider ?! Thanks

bitter oriole
#

@young jacinth I guess most people here use the UE4 multiplayer

thin stratus
#

@fleet raven Yeah, I found the community part of it now. Google wasn't my friend.

#

Still no idea how to use it to get a Server Build onto it, but well, youtube tutorials it is

past gate
#

Hi, I'm trying to spawn some Pawns and possess them only locally at OnPostLogin or at a Seamless Travel. I don't want these pawns on any other client. I can't figure out how to do that, since the player controllers all belong to the Server, so "is local player controller" only returns true on the server.

thin stratus
#

How does one disable Steam for a Linux Server build? I have bUsesSteam = false in the Target file.
Do I have to actively change the ini before building?

#

Actually, I should probably fix the reason teh app id file can't be written.

#

Who knows what else can't be written

#

Perfect, nvm. Docker File was setup wrong

winged badger
#

@past gate you can't do it in GameMode

#

BeginPlay of the PC -> if (IsLocalController()) <spawn and possess a local pawn>

#

note that NetRelevancy will cause problems there

#

as in, if you don't touch the settings, nothing over 15k from where PC was spawned will replicate, ever

#

would be much better to server spawn + possess a ReleventOwnerOnly replicated Pawns

chrome bay
#

It'll probably never work properly anyway since a player controllers' pawn and a pawns controller is replicated and it'll alter whatever you've done locally.

grizzled stirrup
#

If you wanted to support multiple subsystems in the future, say for example Steam and EGS (and just for the sake of example, consoles too), would you generally have a giant GameInstance with different sections for different subsystems or instead have a plugin based approach or a separate GI per subsystem?

chrome bay
#

In theory you would just switch out the subsystem and the gamecode would seamlessly interface with it

#

If you're relying on platform-specific features that aren't available through the OSS system, I would either modify the OSS to expose stuff more "generally" or yeah, pre-processors to compile things out depending on platform.

#

I've done the former recently for HLL, since the Steam OSS has a crap implementation for Steam User/Server Stats

#

Just extended the interface so that it needs to provide a new FOnlineUserStatsPtr.

high current
#

When packaging for a specific platform, it might be possible that if you have one giant GI, some stuff might break. Hence why the plugin based approach makes more sense + it would allow you do no package useless information for the platform

grizzled stirrup
#

Thanks! So in theory if you were to keep all subsystems vanilla, you'd have any relevant communication for each in one GameInstance? For example steam lobbies vs whatever lobbies EGS has

#

@high current That makes sense! thanks

chrome bay
#

Apart from a few tiny exceptions, all of our game at least talks to online services via the OSS interface

#

You want to avoid doing things like this regularly because maintenence is just impossible:

#if PLATFORM_XBOXONE
// do something
#else 
//etc...
grizzled stirrup
#

So any calls via the GI would be generic?

#

And you'd branch within the functions there?

chrome bay
#

You wouldn't branch at all, you get the OSS interface and call the functions through that

grizzled stirrup
#

Ah ok so basically it'd be like calling a generic CreateLobby function and depending on the device / subsystem being used you'll run the right code using the #if

chrome bay
#

you avoid the #if's altogether

#

e.g

grizzled stirrup
#

Ah sorry missed the edit

#

I will have to look more into the OSS stuff, thanks!

#

Just trying to plan a bit ahead to not burrow into a corner and have to redo lots of stuff

chrome bay
#
    if (UserStatsIFace.IsValid())
    {
        UserStatsIFace->RefreshUserStats(*PlayerID.Get());
        return true;
    }```
#

The idea is gamecode doesn't care what platform you're on

past gate
#

@winged badger Thanks! I'll settle for ticking Only Relevant to Owner ^^ For now the pawn I wanted only locally is a kind of spectator, but later I might have to add interactions, so I guess there isn't much of a point

winged badger
#

thing is, if its just local

worthy perch
#

Kyle, are you beginning to implement OSS stuff? I'm in the process of doing that now and I am not having a fun time with it. 🙂

winged badger
#

the PC will stay where it was spawned for relevancy calculations

#

the entire game

past gate
#

yeah yeah, i'll untick it later, I was just trying to save memory

chrome bay
#

@worthy perch @grizzled stirrup ShooterGame shows exactly how to do it

worthy perch
#

If you can recall, for ShooterGame, it's pretty much all in their implementation of AGameSession, right?

chrome bay
#

Yeah, the game only makes calls to AGameSession etc, which then passes whatever it needs on to the OSS interface

#

It has a few cases of preprocessor stuff, but it's only for things like this:

        const FText ReturnReason    = NSLOCTEXT( "NetworkFailures", "ServiceUnavailableXbox", "Connection to Xbox LIVE has been lost." );
#elif PLATFORM_PS4
        const FText ReturnReason    = NSLOCTEXT( "NetworkFailures", "ServiceUnavailablePS4", "Connection to \"PSN\" has been lost." );
#else```
#

Which is fair enough really, but hell you could wrap that in the OSS interface if you really wanted to

grizzled stirrup
#

@worthy perch Yeah it's fine for Steam using existing examples but I'm very curious how it links in with more systems later down the road

#

@chrome bay Thank you will dive into ShooterGame again for that!

meager spade
#

@grizzled stirrup

#

you can create GameInstance SubSystems now

#

in 4.22

#

which automatically get loaded in to the subsystem and creates convienient accessors in bp automaticcal

#

automatically

thin stratus
#

yus, got 2 of them in our project by now

#

One handling customizations, the other the backend connection

#

really handy

grizzled stirrup
#

@meager spade Thats amazing thanks for sharing

meager spade
#

i couldnt find a way to make a bp version of it tho

#

cause if you do it loads 2 copies

fleet raven
#

what is the purpose of USceneComponent::AttachChildren being replicated?

#

is AttachParent replicating and components attaching themselves to where they should be not enough?

#

it seems like all OnRep_AttachChildren does is try to fix the mess it just made by replicating it for no reason

#

plus, it makes it cry about objects not supported for networking when you attach non-replicated components on the server

thin stratus
#

@meager spade You could probably override the "ShouldCreateSubsystem" function and mark it to false for the parent.

#

Exact functionname could be different

fleet raven
#

if you make it abstract it won't instantiate it

#

but the problem is with the bps themselves

#

it uses GetDerivedClasses to locate all classes it should instantiate

#

which has two problems:

  • it does not locate currently unloaded blueprints
  • it locates a bunch of editor trash for loaded blueprints
#

things whose name starts with TRASHCLASS_, SKEL_, REINST_

#

it doesn't filter them out and tries to spawn those as subsystems

winged badger
#

@fleet raven also, when it does replicate attachments, it causes any non net addressable attached component on clients to fall off

fleet raven
#

have not seen that happen yet

winged badger
#

I did 😕

fleet raven
#

but I commented out this nonsense and everything still works fine

#

so br_boi

winged badger
#

Not surprised, there is rarely any need to replicate a scene component or its subclass

grizzled stirrup
#

If you have a fairly large struct of floats that define various upgrades that your character has that needs to be replicated to the owner after each seamless travel and potentially other players too, is it fine to have it as a standard OnRep struct? I ask because ~30 floats seems like a lot but they only ever change a few times a minute if even

#

And they'd never all change at once, always one at a time

#

If it makes a difference I could potentially use uint8's instead and convert to float after replication (using some kind of 4:1 conversion as the lowest I ever need is 0.25f)

fleet raven
#

yes it's fine

#

assuming they're individual properties it will only send changed ones

#

it's not changing every tick so 30 floats is like nothing

grizzled stirrup
#

Great thanks!

#

Yeah only changing very rarely when a player levels up or finds a pickup

#

And only ever all being replicated at once at the start of a match after seamless travel

thin stratus
#

Hm, just noticed Linux - DevEditor compiles fine while Linux - DevServer reports:

1>ld.lld.exe : error : undefined symbol: Microsoft::Azure::Gaming::GSDK::logMessage(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)

#

It does call the code to load the library and I don't see any errors.

#

Do DevServers anything different in terms of Build.cs etc?

#

Microsoft::Azure::Gaming::GSDK::logMessage as well as all the other functions of the library report this.

winged badger
#

@grizzled stirrup they always get replicated all at once

#

you can try and force the issue @thin stratus , by adding a project reference to the library from VS manually

#

not sure if there will be any consequences of that tho

thin stratus
#

I kinda have the feeling there is some WITH_SERVER_CODE somewhere that kills something this library needs.

#

At least that's my vague idea

#

by adding a project reference to the library from VS manually
The "LibraryDirectories" in VC++ Directories?

winged badger
#

no right click project, add > reference, browse, and select the library you need

#

(in solution explorer)

thin stratus
#

I can't browse with any of the AddReference

#

Only lists me Solution References to select from

winged badger
#

that is weird, me too

#

i thought that always works 😦

grizzled stirrup
#

@winged badger I thought structs have some clever way of only replicating changed properties within them?

#

Thought I saw that mentioned here recently

winged badger
#

they don't

#

clever, or otherwise

thin stratus
#

We looked into that and afaik they do indeed know what to replicate and what not

#

Same for Arrays

#

It doesn't use NetSerialize but NetDeltaSerialize

winged badger
#

you can custom net serialize them

thin stratus
#

Which sends only the delta to the client

#

At least if you trust the comments

grizzled stirrup
#

So it does in fact only replicate changed values in a struct?

winged badger
#

i don't really

grizzled stirrup
#

It'd make sense especially for larger structs

thin stratus
#

Yeah but not nested

#

So a Struct in a Struct probably will replicate fully

#

As well as an array in a struct or a struct in an array

winged badger
#

that doesn't make sense

#

why would it NetDeltaSerialize itself but not call NetDelta on its members

steady aspen
#

Why does this get ignored? It doesnt get destroyed for anyone and does not stop on breakpoint

winged badger
#

does it print?

steady aspen
#

It even sets the visibility

winged badger
#

do you have anything red in the message log?

steady aspen
#

so yes

#

Yes but nothing to with that

winged badger
#

no accessed bull from node...

#

*null

steady aspen
#

?

winged badger
#

is your LookObjInfo valid?

steady aspen
#

oh. No its not

#

Nvm it is

#

It is sometimes

winged badger
#

its a replicated variable

#

so when a client picks it up

#

how does server know which object to destroy?

#

replication doesn't flow client->Server

steady aspen
#

Because it gets set. Should it not be replicated?

#

Oh right

winged badger
#

so add the reference to it as an input to the RPC

#

along with that boolean

#

and try that

steady aspen
#

This is the blueprints btw

#

I changed it with a new object variable

winged badger
#

add an input of whatever type lookobjinfo is

#

to Pickup RPC

steady aspen
#

What do you mean?

winged badger
#

and then connect destroy to that pin, not a variable

#

same way you added the fuse

#

add an actor reference

steady aspen
#

oh

#

ok

#

It worked!

winged badger
#

no need to put the fuse into RPC, presumably if ActorHasTag on client it does on the server as well, btw

#

so server can do its own tag check

steady aspen
#

Ok. Thank you so much!

#

I still have a lot to learn about replication and stuff, but I've been stuck at this for so long

#

Thanks again

winged badger
#

exi's compendium, if you didn't read it

#

link is on pinned resources on the channel

steady aspen
#

Thanks. I will check it out now

winged badger
#

btw, @steady aspen even if it was server sending an RPC to client and depending on replicated variable

#

it would still break 90% of the time

#

RPCs don't wait for the Actor to get to its scheduled update

#

replicated variables do

steady aspen
#

Ok. I will read the compendium. Thanks @winged badger

#

Would this be a bad way of doing it?

winged badger
#

why is pickup a multicase?

steady aspen
#

Because it didnt work when running on server

winged badger
#

and now it doesn't work when running on clients

steady aspen
#

It did

#

It does*

winged badger
#

multicast from a client is like you just called a normal function

steady aspen
#

Yes, I would like to have it run on server but the clients wont do anything if I do that

steady aspen
#

Finally fixed it! Thank you for all your help @winged badger Now I need to go read the compendium 🙂

grizzled stirrup
#

If sending a player name to spectate from the server via a Client RPC, is it cheaper to send the character reference or a const FString& ?

#

The character reference could be used on the client to get the playerstate and then the name

#

I ask because I recall character pointers to have quite a small footprint since they are essentially an ID

hollow stirrup
#

a pointer is going to be four bytes because it's literally just a 32 bit int

#

It doesn't matter what "type" the pointer is, at it's core it is just a int

grizzled stirrup
#

Great thanks I'll use the pointer then!

grizzled stirrup
#

Is it possible to override a replication condition per actor?

#

For example in my health component, I want players to replicate health to all other players for UI use when spectating, however AI characters using the health component will also be replicating that health value and wasting bandwidth as it'll never be seen or used by the client

jolly siren
#

Your second sentence is hard to understand

gleaming vector
#

replicate it COND_OwnerOnly

#

it'll only replicate to the owning connection

#

AI don't have one, so it wont replicate to anyone

#

oh

jolly siren
#

Right, AI aren't clients. They are driven by the server

gleaming vector
#

you want it to replicate to everyone

#

hmmm

grizzled stirrup
#

Sorry it's late, my explaining isn't great 😄

#

Basically AI and human players share a generic health component

#

In order for human players to spectate other human players they need to know the value of the health float

#

However I don't want to waste bandwidth having potentially 20+ AI also replicating their health

#

As it won't be used anywhere

#

I had it COND_OwnerOnly which works fine for the owning client but as soon as you spectate another human player, you can't get his health

somber glade
#

I've noticed some odd behaviour in a 3D widget I have in a VR game. I have a countdown when the game is about to start. The Gamemode handles the value, but sets it to the game state. The widget in the level goes to the game state and gets that value and displays it as text for the player to see. The widget also goes to the game state to get a variable to see if the text should be visible. It's not visible until countdown starts. In any multiplayer scenario (including PIE with dedicated server checked and only a single client) this text does not turn visible right away for the client. It seems to wait some random arbitrary amount of time before popping up. I've seen it pop up after 2 seconds have passed in the countdown and take as long as 17 seconds (it's a 20 second countdown). After setting that bool, it plays a sound. The client always hears the sound. So the code is definitely running.

#

can there be some kind of delay on the replication of a variable, to the client, even in a PIE situation where there isn't any network lag?

meager spade
#

maybe your net update frequency for gamestate is high

#

it will only replicate stuff as quick as netupdate frequency

somber glade
#

@meager spade I haven't changed it from the default. I don't even know where to change it

winged badger
#

in actor class defaults

#

where the replication settings live

velvet parcel
#

Anyone know the best way to do floating name tags over players heads in multiplayer?

#

I am stumped on this but it seems like it would be pretty easy

chrome bay
#

Create a list of managed widgets locally, one for each player registered in the game state

#

Assign each widget a player

#

Every frame, update the widget position on screen to be above the players head

#

Some people use 3D widgets, personally I prefer doing it in 2D. Cheaper and easier.

velvet parcel
#

I am using a 3d widget right now. So in order for this to work I need to keep a list. Which I am using the game state to do this

chrome bay
#

I do it in the HUD, since it's a convenient place to manage UI elements

velvet parcel
#

Is there a way to get what client you are on the list?

chrome bay
#

Sure

#

just compare the player state the widget is assigned to, to your own player state

#

ez

#

Game State already has a list of Player States, which should contain all the info you need to get information about a player.

#

2D is better IMO. Depending on how many players you have, it's not all that cheap to have a bunch of extra scene components and render targets to move around

thin stratus
#

We are also using widget components in screen space

velvet parcel
#

Yeah hmm so the only challenge is getting the widget to know what player state the player is?

worthy perch
#

You could just use IsLocalPlayerController().

thin stratus
#

Our pawns have healthcomponents which spawnt he widget ones

#

And handle their lifetime

chrome bay
#

Tis easy

#

every frame

#

Do the followiing (psuedo-code)

{
 Widget[Index]->UpdateForPlayer(GameState.PlayerArray[Index];
}```
velvet parcel
#

I am doing this with blueprint

thin stratus
#

Pseudo code is meant to be code that isn't actually code be still explains the idea

#

That can be used in bp or cpp or java etc

#

If you can't read cpp you should at least understand pseudo code:P

velvet parcel
#

Yeah, I just need to know what nodes are to be used

thin stratus
#

A for loop

#

And the widget array

velvet parcel
#

yep seems right

chrome bay
#

In HLL I have an "indicator component", which you can drop onto an actor. It'll register itself in a central list somewhere and the HUD will create the desired indicator widget for it, and update it accordingly.

thin stratus
#

Cpp would be easier, you could just use the OnRep PlayerState in the pawn to create the healthbarwidget and pass the PlayerState

#

-_- why don't they expose it

velvet parcel
#

Cpp isnt easier. You have to learn Cpp

chrome bay
#

Not as scary as it sounds trust me 🙂

thin stratus
#

Creating the solution in cpp is a lot easier

#

Given you can use both

chrome bay
#

The hardest part of CPP is figuring out what all the obscure compiler errors are when you're starting out tbh

velvet parcel
#

but anyway I think I get it, I just need to figure out how to compare the character game state to compare to the game state list

worthy perch
#

? I believe you mean PlayerState.

velvet parcel
#

ANything I try right now just return makes each player see their own name on every other player

#

Yeah player state list

#

sorry

chrome bay
#

Each widget should be assigned one of the player states

velvet parcel
#

Yep got that. hmm

chrome bay
#

And it pulls the info from that player state

velvet parcel
#

that's the issue I am having then. How to assign that player state.

chrome bay
#

Since BP doesn't have any callbacks, the easiest thing to do IMO is on your HUD classes Tick, check the player state array from the game state

velvet parcel
#

ok how

chrome bay
#

Create enough widgets (one for each player state)

velvet parcel
#

what nodes tell me what player state a character has

chrome bay
#

I can't really explain that in anymore detail than I just did.
On each of those HUD ticks, call an 'Update' event in your custom widget and pass in a player state, it's just a big loop.

velvet parcel
#

It makes it so all players have the same name as the player

chrome bay
#

You're calling GetOwningPawn, that will just give you the 'Owner' of the widget which will always be the local player

#

Widgets are created locally, they are owned by the local player

velvet parcel
#

ah! ok ..hmm

chrome bay
#

Hence you use the 'PlayerArray' from the game state, do a big loop through it, and tell each widget to update using a player from that array

velvet parcel
#

Yeah I get that, but you cant iterate through the list if every player is marked as same person to every player

#

I need somethingto define, "This guy is number 3 on the list"

chrome bay
#

But they're not the same person?

#

Each PlayerState in the array is a different player, with a different name

velvet parcel
#

Yep, all I need is a way for me to know what player state each player is. Otherwise a for each loop is pointless because I dont know who is who

#

See what I mean?

#

This would be super easy if know the way to know who is who

chrome bay
#

You can get the pawn from a player state IIRC

#

The alternative is a system I suggested, having a component on each pawn and updating it that way

velvet parcel
#

Player controller I can get the pawn. I think you meant that right?

chrome bay
#

no

#

player controller exists locally only

#

you can't get other player controllers

velvet parcel
#

In MP the pawn may not exist right after the player spawns

chrome bay
#

sure

#

but you have to work around that

somber glade
#

@meager spade My gamestate is set to netupdate 10 min 2 so that shouldn't be the issue

worthy perch
#

There's APawn::GetPlayerState(), btw. Which surprisingly, I've never used.

velvet parcel
#

hmm I think I might know what to do then. hmm

#

Calling owning player pawn to get the owning player state. Compare that variable to the game state list, if I get a match then make that the name that appears.

worthy perch
#

I don't think you would ever get anyone else's name, then.

velvet parcel
#

what about get the player controller?

#

get owning player

#

I feel like the answer is so simple yet I am stuck on this crap....

worthy perch
#

Effectively the same. You would only get your playercontroller. And PlayerC's aren't replicated anyway.

winged badger
#

there is an option to put the WidgetComponent on the PlayerState itself and just attach the PS to Pawn

#

it is an Actor after all

worthy perch
#

That's a pretty interesting approach.

empty axle
#

Where are stored PlayerStates of players that recently left the game?

winged badger
#
    // GameMode.h
    /** PlayerStates of players who have disconnected from the server (saved in case they reconnect) */
    UPROPERTY()
    TArray<class APlayerState*> InactivePlayerArray;
empty axle
#

thanks

twin juniper
#

Is Rcon tool program only for torument servers or does it also work for dedicateds?

somber glade
#

So after a bunch of work, I changed the inventory over to make sure that it's spawned by the server, and that when the code to attach the item to the inventory is run that it is run by the server only, and I'm slightly closer I guess? Again, this still works as the host. But as the client now, when the item is attached, it snaps to the slot, but then immediately falls to the floor. At least it's being located under the map anymore. Why would this attach work for the host but not the client, when this is being run "as server"?

#

This is the call to store it, as you can see, it's running on authority only.

#

I've attached other things as the server and they've always stayed put

grizzled stirrup
#

If you know a replicated property will only have a value in the range of say 0 - 25, and you'd have many similar properties (such as a list of upgrades), would you then try and use uint8 instead of float to represent the current upgrade you are on?

chrome bay
#

Yep

#

You could go a step further and bitpack values too when it makes sense to do so. C++ only ofc

grizzled stirrup
#

Thanks will switch to uint8 from float in that case

#

Is bitpacking like what they do in ShooterGame for bools?

#

So you get 8 bools for the price of 1?

#

Using 8 uint8s?

chrome bay
#

Sort of, UE4 automatically condenses bools to 1-bit anyway IIRC

bitter oriole
#

Not even sure it does tbh

chrome bay
#

Oh for replication I mean

grizzled stirrup
#

Is there a difference between uint8 and int8?

#

Just confused as there is no u in int32

chrome bay
#

there is uint32

#

u = unsigned

grizzled stirrup
#

OH 😄

#

That's amazing

#

So uint8 = 0-255

chrome bay
#

yeah

#

and int8 = -127-127

grizzled stirrup
#

int8 = - 127

#

Ah that explains a lot

#

Thanks

#

And I assumed uint16 is fine to use too?

chrome bay
#

yeah

#

for replication/reflection all the integer types are supported, just they can't all be exposed to BP

worthy perch
#

You can Intellisense to int16 (Platform.h) and all the types are defined there.

grizzled stirrup
#

That's fine I'm doing almost everything in C++ where possible and BPs are data only.

#

Does it mean that you can't even have some types in the defaults window of a BP?

#

And should never be a UPROPERTY(EditDefaultsOnly) for example?

#

Just used internally in code?

chrome bay
#

It won't compile if you try to use a non-BP supported type anyway

grizzled stirrup
#

Great thanks!

#

@worthy perch Many thanks for the platform.h tip, all the bytes specified there too!

#

Learning UE4 C++ first before the fundamentals is proving interesting 😄

#

Missing out on some essentials

#

Am I correct in saying that an int32 / uint32 is equal in size to a standard float ? (4 bytes)

soft relic
#

How would I update a 3D widget's value for all connected players?

#

Instead of only changing to the client calling the function?

#

Should I call it to all PCs using the game mode?

#

Multicast is what I needed

chrome bay
#

@grizzled stirrup yes

grizzled stirrup
#

Thanks!!

velvet parcel
#

Certain objects like the player pawn, player state, player contoller can spawn in nearly random orders and its fairly unpredictable when it happens.

somber glade
#

The client probably wouldn't know that it's missing the actors

tidal onyx
#

Did anyone managed to get Steam overlay in the game without the steam networking?
I want to use the Null subsystem and get the steam overlay.
They say in the documentation that I need to setup the NetDriver class but never say how to do it and to what.

grizzled stirrup
#

@velvet parcel I've also noticed this and with more clients it can be even more random

#

The solution I have found is to just have a pre game countdown before doing anything important

chrome bay
#

All networking spawning is completely random

#

You have pretty much no control over order of actor replication

grizzled stirrup
#

Then all replicated channels will be open

worthy perch
#

Yogev, if you just want the overlay (and other Steam stuff), you can just manually load the Steam .dll's.

grizzled stirrup
#

Yeah just to make sure because so much can work for 5 / 10 clients but not at all for the other 5

#

Waiting fixes all 🙂

#

@chrome bay Sorry for the tag, last question of the day I promise 😄 I saw this quote from you on the forums : It's never been supported. uint8 and int32 are the only numeric types you can expose to Blueprint Does this mean I can't use a uint16 to represent health instead of a float, as the value of health is set in Blueprint defaults / displayed on UI?

chrome bay
#

correcto

#

uint8, int32 and I believe uint64 as of 4.23 are support by Blueprint

#

And that's all yah get

grizzled stirrup
#

Ok thanks I'll stay with floats then since damage is done with floats

#

No need to convert to int32 if there is no bandwidth reduction

chrome bay
#

The trick is to just not code stuff that is time-dependant

#

You have to workaround it, adding delays and the like is a quick way to get into trouble

grizzled stirrup
#

Is there a "MyReplicationChannelsHaveFullyOpened" callback per client?

#

I'd love to not rely on the delay countdown but if I don't it's basically random which clients get initialized correctly

#

Sometimes all

chrome bay
#

Nope, nothing like that

grizzled stirrup
#

Sometimes only the host and 1 client

chrome bay
#

you have zero idea when all objects are received

grizzled stirrup
#

So basically a delay or polling is your friend?

chrome bay
#

Polling or using an event based-system

#

So an actor broadcasting a global delegate in BeginPlay() or something

#

Generally speaking though you shouldn't ever need either

#

generally speaking...

grizzled stirrup
#

The case I ran into it was when spawning and initializing nametags for all other players- without at least a second of delay, a completely random amount of players got their nametags initialized

chrome bay
#

code the game as if objects can be created or destroyed at random and you'll be fine 😄

#

Yeah that's the kind of thing you just have to tick to make life easier

#

Our scoreboard in HLL for example just polls the PlayerArray constantly and adds/removes items as required

grizzled stirrup
#

Thanks! In the initial nametag case would you say a delay isn't the end of the world since they only ever get initialized once and there is no join in progress? Also the countdown will happen anyway pre game

chrome bay
#

It's not the cheapest but it's far from a bottleneck either

#

I also generally prefer UI to poll the game for information rather than driving it via events where possible, as generally you expect the UI to represent what's truly going on in the game, and if it's not it can make it very hard to debug or find problems

grizzled stirrup
#

Got it! I'm trying to do that too, but sometimes the initial bind misses (tries to bind to something in the GS / PS / A spawned actor but they aren't ready yet)

#

I find once the initial binds go off correctly (after the countdown when replication channels are fully open), it's all good

chrome bay
#

Events make sense in a some cases though, particularly if you need to create/remove widgets for things.

grizzled stirrup
#

I really wish there was an option for a listen server host to instead load a local dedicated server and connect via that

#

Similar to how it works in non Single Process PIE

#

then there are no inconsistencies in smoothing and a few other things

soft relic
#

Are multicast functions called to all clients if call the function from server?

worthy perch
#

Yeah.

winged badger
#

all clients and server

soft relic
#

Why is the print string only called from the server then?

winged badger
#

ouch

#

server doesn't need to call ServerRPC

#

it can just call a normal event

#

multicast should also never call another multicast

#

already executes on everyone, what's the point? having the connected logic run twice?

chrome bay
#

also omg why

winged badger
#

it is quite sufficient to just set the health on ClassDefaults, btw

soft relic
#

well actually I want to update the 3d health for everyone

chrome bay
#

Use OnRep

#

not a multicast

#

Ticking the UI is even easier

soft relic
#

Okay, but just to understand, why won't the print string show from the client as well?

#

Server calls the multicast, so is this normal instead of showing to everyone?

worthy perch
#

What class are you doing this in?

soft relic
#

It's a controller

winged badger
#

😄

soft relic
#

Which has an AI controller set up

winged badger
#

controllers do not replicate

#

with exception of PCs, to owner only

soft relic
#

So how would I call a function like that to everyone?

#

What I'm trying to do is to make the server set a health for the AI and then display it in its 3D health bar widget.

#

Could a solution be to connect the AIs with the server PC and call functions from there?

harsh lintel
#

in a dedicated server, is overriding gamemode's PostLogin function the right place to do something to the client controller whenever a new client connects to the server?

winged badger
#

with any server, yes

unreal pine
#

If I have a savegame object with something like "character customization" for like what hat / outfit the player selected. What's a good spot to store that and retrieve it on the server?

#

I was using gameinstance for local multi, but that only exists serverside right?

meager spade
#

gameinstance is local to ALL

#

its created when game exe loads

#

and destroyed when game exe closes

#

it cant be accessed by anything but local

unreal pine
#

So I'd assume I would have to throw the variables into the controller (or some other object) to pass it to the server?

grizzled stirrup
#

@unreal pine The way I do it (could be completely wrong) is each player saves their skin locally in the GI in the main menu and then when they load into the map they load it locally, then do a server RPC to set their skin on the server which also triggers an OnRep event for other clients so they see the correct skin too

hasty adder
#

For customizations how do you get them and are they like steam inventory items etc?

unreal pine
#

They will be, we're doing an alpha this weekend and I'm just gonna unlock 'em all

#

Thanks @grizzled stirrup! Sorry for getting you killed so many times when I was a teenager

harsh lintel
#

this is being called in a client rpc, there's only gonna be one static camera in the game placed in the level, it isn't working tho any idea why?

thin stratus
#

How does one handle a Game Client with Steam and a DedicatedServer without Steam again?

grizzled stirrup
#

@unreal pine I forgive you we got the job done in the end

thin stratus
#

Server is only known by IP

worthy perch
#

You could just ClientTravel to the IP address. If that's what you're asking.

thin stratus
#

Here the thing

#

The Client uses Steam and will 100% use Steam at this point.

#

The Server sits on a CloudServer.

#

Client receives the IP:Port of it.

#

There are two scenarios that both don't work:

If the Server implements the Steam Subsystem, connection via IP doesn't work anymore, cause the Steam NetDriver only works with Steam IDs.
The Server isn't and won't be registered to Steams MasterServer, so I will never get that.

The other scenario is that the Server DOES NOT implement Steam Subsystem, here PreLogin fails cause it checks if the Type of the UniqueNetId is the same.
I could skip that check but I doubt that's a good idea.

#

So I'm a tad lost

worthy perch
#

Well, in short, I think the UWorks plugin can handle connecting directly to a server by IP:port. So you can look how they do that. Which I've been meaning to do too.

thin stratus
#
void AGameModeBase::PreLogin(const FString& Options, const FString& Address, const FUniqueNetIdRepl& UniqueId, FString& ErrorMessage)
{
    // Login unique id must match server expected unique id type OR No unique id could mean game doesn't use them
    const bool bUniqueIdCheckOk = (!UniqueId.IsValid() || (UniqueId.GetType() == UOnlineEngineInterface::Get()->GetDefaultOnlineSubsystemName()));
    if (bUniqueIdCheckOk)
    {
        ErrorMessage = GameSession->ApproveLogin(Options);
    }
    else
    {
        ErrorMessage = TEXT("incompatible_unique_net_id");
    }

    FGameModeEvents::GameModePreLoginEvent.Broadcast(this, UniqueId, ErrorMessage);
}
worthy perch
#

But, the way I've been doing it prior to implementing the OSS stuff, was just by manually loading the Steam dlls. This apparently never did weird NetDriver stuff.

thin stratus
#

This shit is new in 4.21

#

Now I know why that worked a few months back

#

@fleet sluice Correct Vlad for UWorks?

#

Too many Vlads

winged badger
#

that's the Vlad you're looking for

thin stratus
#

Now I wonder, if I remove that line again by overriding PreLogin

#

(it didn'T exist pre 4.21)

#

What does that break?

#

How important is it to have the same type

worthy perch
#

You can search the UWorks Discord for "Ip:port". That seems to be the go method for UWorks people. In fact, the UWorks subsystem was dropped anyway.

thin stratus
#

Yeah I think asking the dev directly helps more in this case

#

But my lucky evening he is probably out enjoying a friday night

#

So apparently that "new" check from 4.21 is to stop behavior that was never intended.
Epic doesn't want you to use two different subsystems at once

#

If you need that, you need to create your own Subsystem that interprets the ids from the various subsystem you are using

#

And I'm def not able to do that in one evening cause I need that running tomorrow

#

Cool

#

Well, it's not a traditional Steam DediServer

#

I won't register any Session with it

#

It just has Steam on it atm cause of this shit UniqueId mismatch

#

Can't I force the SteamNetDriver for now to accept IP connections?

winged badger
#

if im not mistaken

#

they also broken something in 4.20

#

making it pretty difficult to roll your OSS

thin stratus
#

@chrome bay Found that out, yeah @winged badger

#

But if I have to modify the engine, that's also fine

winged badger
#

i did steam connection once, and it was years ago, since then i always found a way to dodge that particular task

thin stratus
#

Using a custom build anyway

#

@woeful anvil Cloud

#

Service returns the client IP:Port

#

But when using Steam it just doesn't connect

#

And if Server doesn't use steam we get back to the Id Mismatch

#

I wouldn't even know how to implement my own Subsystem while still keeping 99% of the Steam features

#

This is basically the diff subsystem issue

#

And the Steam IP connection stuff is sadly generally known

worthy perch
#

He has a unique set up, HighGround.

winged badger
#

why is your dedi without steam again, @thin stratus ?

thin stratus
#

Cause Steam brings the NetDriver that doesn't allow IP connections

#

100% not using SteamSessions

#

This is a cloudhosted Server

#

The service that handles starting and stopping these provides the Ip:port

winged badger
#

so your using IPNetDriver?

thin stratus
#

@winged badger That was the idea first, but that doesn't work anymore since 4.21

winged badger
#

why are your clients using steam OSS then?

thin stratus
#

Cause the game is on Steam

#
  • the Backend Authentication goes through Steam
#
  • we have ListenServer support too
winged badger
#

you could gimmick some lobbies

#

steam lobbies

#

they are quite sufficient to share the IP/Port

#

and connection to a public IP is possible afterwards

thin stratus
#

I read you can get request the steam id of the server via ip:port via Steam

#

But without registering a session I doubt it has an id

winged badger
#

yeah, but lobbies transfer just strings as dara

#

*data

thin stratus
#

Not sure how to add lobbies into the mix

winged badger
#

can send anything through that

thin stratus
#

The Client only knows the IP:Port of the Server

#

And will also only ever know that

#

I have no control over the game server service to send more info

winged badger
#

yeah, but you can get listen servers working via lobbies over IP/Port with IPNetDriver i believe

astral fossil
#

Hey

winged badger
#

not sure how it will handle NAT, UWorks was a bit dodgy on the subject 2-3 years ago

astral fossil
#

I have a small question

winged badger
#

instead of starting a steam session, you create a lobby other clients can find

thin stratus
#

I would rather not change listen servers

astral fossil
#

Is there a way o knowing when all pawn instances of a player controller ( counting the owning client and the others) are spawned?

winged badger
#

you open a normal session, and transfer ip/port to them

#

yeah, your HandleStartingNewPlayer ran as many times as there are players

thin stratus
#

@astral fossil Not really, despite knowing upfront how many it should be an incrementing a value on beginplay of each pawn

#

HandleStartingNewPlayer is Server only though

winged badger
#

i am assuming he was asking server only

#

would be kinda hit&miss to check that on clients 😄

thin stratus
#

Yop

astral fossil
#

I tried notifying each spawn but apparently theres no way of sending message from non-owning clients

winged badger
#

notifying each spawn?

#

cheap&dirty @woeful anvil

astral fossil
#

hmm

#

@woeful anvil Thanks for the shot, will try that 🙂

winged badger
#

the AGameMode::HandleStartingNewPlayer

#

is what actually spawns the Pawns

astral fossil
#

Im spawning on 'SpawnDefaultPawnFor'

#

on blueprint

winged badger
#

and it calls RestartPlayer() by default which does exactly that

#

unless you changed it yourself

#

i have AIs of same class on some levels

#

case where that approach breaks

astral fossil
#

wait, I think I am kinda lost. I actually don't know if Im using the right terms

#

Only the server spawn pawns explicitly, the other clients just replicate that, right?

#

The thing is to know When this replication actually happens, because I don't know how the server would know that

winged badger
#

you really don't want to be checking that on clients

astral fossil
#

right

#

its doing that

winged badger
#

so when it does that the number of times equal to GetNumPlayers

#

all of them are spawned

astral fossil
#

the GetNumPlayer return the number of clients right?

#

clients + listenserver if its the case*

winged badger
#

no

#

PCs

astral fossil
#

yes!

winged badger
#

there is no OnPossessed client side

astral fossil
#

hmm, but my problem is to know when the pawn that doesn't have a owningclient is spawned

winged badger
#

nor anything else you can get to without c++

astral fossil
#

in my case, the problem is that the pawn controlled by the listen server is multicasting something, but the replicate is not spawned yet to receive the multicast

winged badger
#

do not multicast

astral fossil
#

i can solve this with a delay, but its sketchy

winged badger
#

use RepNoitfy instead

astral fossil
#

hmm

winged badger
#

that can't break

astral fossil
#

right

winged badger
#

if the variable is set in the same frame the actor is spawned in

#

it will be set, and its onrep will run before BeginPlay on clients

astral fossil
#

hmm

winged badger
#

and no package loss or latency can interfere with that, as the variable arrives in the same bunch as instructions to spawn the actor in the first place

astral fossil
#

great, im gonna try that, thanks @winged badger =)!

#

and others too!

winged badger
#

always use RepNotify over Multicast if you can help it

#

none i think, as its ~40kB

winged badger
#

what causes the rotation?

#

maybe you can shove it thru the CMC

#

in any case, nothing RPCed on Tick should ever be reliable

#

whats the point? if a RPC doesn't arrive a more up to date one will land before its resent

#

not without having a CMC open in VS, sorry

#

the top pinned link on the channel

#

is a diagram of CMC calls

astral fossil
#

Hey zlo, that thing with rep notify worked great, thanks !

grizzled stirrup
#

By default does a component inherit the NetUpdateFrequency of the actor it is attached to?

#

For example a health component on a character

#

Thanks!

#

Thanks! In this case I definitely want it to inherit

#

For example lower priority enemies should have lower update rates etc

#

So the health component would ideally update at the same rate

meager spade
#

components replicate with the actor

#

components have no custom netupdate

grizzled stirrup
#

Thanks!

meager spade
#

components replicate as subobjects via

#
{
    check(Channel);
    check(Bunch);
    check(RepFlags);

    bool WroteSomething = false;

    for (UActorComponent* ActorComp : ReplicatedComponents)
    {
        if (ActorComp && ActorComp->GetIsReplicated())
        {
            WroteSomething |= ActorComp->ReplicateSubobjects(Channel, Bunch, RepFlags);        // Lets the component add subobjects before replicating its own properties.
            WroteSomething |= Channel->ReplicateSubobject(ActorComp, *Bunch, *RepFlags);    // (this makes those subobjects 'supported', and from here on those objects may have reference replicated)        
        }
    }
    return WroteSomething;
}```
polar wedge
#

Has anyone got any info about the Epic Online Services? I'm having a hard time trying to figure out what exactly they provide.
Reading their website it sounds like right now it's just a ticketing system and a friend list, but doesn't look like it's an actual OnlineSubSystem or anything that could be listing out online sessions.
In general i'm trying to figure out what would be required for a game to be able to "find online sessions", as obviously the null subsystem only finds session on LAN.
Are the only options to use the OnlineSubSystem steam? Is that restricted to a game on steam or can it be on any store?
How are the current EpicGamesStore titles doing it? Do they have some kind of early access to the Epic Online Services?

rose egret
#

Im so confused. why BeginPlay of my PlayerController not get called on clients

#

😦

fossil spoke
#

PlayerControllers only exist for the Server and the Client that owns the PlayerController.

#

It does not exist on other Clients.

#

Therefore it cannot call BeginPlay.

#

Because it doesnt exist.

rose egret
#

I mean the player controller that clients owns himself

thin stratus
#

So the BeginPlay isn't called locally?

#

Is this directly on start or when you SeamlessTravel?

void nest
#

Anyone know why some servers hosted by players playing my game through steam appear twice when fetching the current servers?

trim skiff
#

Am I doing something wrong here? I want to disable input for all players when a match ends. I dispatch the event through C++, and I wanted to implement what I'll do after the match ends here, but the DisableInput is not really doing anything. This is all implemented in the Game Mode blueprint.

meager spade
#

input it Local

#

you need to client RPC it or multicast

#

you are only setting it on the server

trim skiff
#

The game mode itself is only instantiated on the server, though, isn't it?

meager spade
#

yes

#

but you need to call that on the client

#

on all clients to disable the input

#

the disable input function

#

so either have a function on the PlayerController that ClientRPC's to disable input, or multicast it

thin stratus
#

@void nest Maybe because you don't clear the list before fetching servers again?

void nest
#

I do, the container widget is always cleared before it's filled with new servers.

#

it's only a very rare few servers that sometimes appear double

worthy perch
#

How do I get the Session Name from a FOnlineSessionSearchResult? The only way I can think of is to use FOnlineSessionSetting and that seems really bizarre for something so common.

thin stratus
#

Why do you need the Session Name?

#

For like displaying a ServerName?

worthy perch
#

To join a specific session and for displaying the name in a session/lobby browser.

thin stratus
#

Well you join the session by resolving the address via the Session Result

#

And for displaying you should just create a custom setting SERVERNAME

worthy perch
#

Alright, I'll look into resolving the address.
EDIT: Looks like I confused what GameSessionName/PartySessionName macros were for.

thin stratus
#

That's something more internal

#

Usually you always use GameSessionName

worthy perch
#

Yeah, I thought it would be for something like the friendly display name. Anyway, I'll use the custom settings approach. Thanks.

fading river
#

I'm using Load Level Instance (tried both by name and object reference) on the server side, however this doesn't seem to replicate to clients (while LoadStreamLevel doest, but can only be used for one static instance). Anyone has an idea how to fix this or work around it?

slender yarrow
#

does anyone know if Find Sessions will find a dedicated server? if not, is there anyway to connect to a dedicated server other having a hard IP address that the client connects to when the game opens.

meager spade
#

dedicated server ips are normally hidden

#

and handled via master server

#

which connects the clients to a chosen server

slender yarrow
#

so theres no way to run something that just searches the internet for IP's that are running a server for the respective game?

fierce haven
#

sorry for the silly question, i'm handling killing pawns on the server and after a player dies I'm trying to create a widget to append to my HUD widget

#

the death is being handled on the server in the gamestate, from gamestate i'm calling an rpc in the pawn that is set to multicast but the hud is only being updated from whoever killed the player, other players huds aren't being updated.. 🤔

#

well i got it working, not sure if it was the best way but inside my ServerKillPlayer function on the gamestate i'm calling a custom event that is a multi cast which loops through game state's player array and inside the loop gets each players hud and calls the update killfeed function

foggy idol
#

Yo people

glacial sable
#

?

thorny saddle
#

hey guys i have an AI

#

and i want change variable from thirdpersonbp

#

to my ai character bp

#

if i be server

#

its ok

#

but if i change my player to client

#

its cant be done

#

why?

#

its work now

soft relic
#

how can I replicate a fps character's mesh2p? its child weapon does replicate but the hands mesh wont replicate

soft relic
#

Why won't the hands replicate?

meager spade
#

you dont normally replicate the first person mesh to other players

#

your normally have a TP mesh holding a fake gun

#

which acts like the fp gun

foggy idol
#

Please does anyone know how i can do the ik and ads for a first person shooter. With a third person mesh
Cus I want to make a first person multiplayer shooter but not replicate the change in bone location so every else sees you as normal

#

I mesh you see and the mesh others see are the same just that one has ik replicated and one does not

winged badger
#

that works out of the box

#

as UAnimInstance is not replicated

#

nor are bone locations

#

you just need to run IK only on Pawn that IsLocallyControlled

#

probably by deriving from a UAnimInstance you run for other players, and extending it with IK, then just changing the UAnimInstance class on say BeginPlay if Pawn IsLocallyControlled

cosmic star
#

@thin stratus @worthy perch Taking this out of #cpp. I was wondering as well how I can get the SessionName from a SessionSearchResult, since many other methods in the OSS SessionInterface need the SessionName . For example JoinSession needs a player net id, a session name an a OnlineSessionSearchResult. Or one of the GetResolvedConnectString overloads needs a session name.
Or do I get purpose of SessionName completely wrong?

thin stratus
#

You usually know what you are joining

#

This is really just GameSession or PartySession

#

If you are just playing you use GameSession.

#

If you use beacons and shit for parties, you use party sessions (steam only allows one at a time)

#

See it like this: Your player wants to host a game -> GameSession.
Your Player invites another player to a Party -> PartySession

Your Player gets a list of Servers -> GameSession
Your Player clicks on a Server result -> GameSession

#

The only point where I would double check what exactly you are joining is if a Player gets an Invite through e..g the Steam Friends Interface

#

Then you'd need to know if it's a Party or game invite.

cosmic star
#

Ah, so SessionName is more like a "SessionType", which describes the type of the session with either being "open" (in the sense of not created beforehand, e.g. like Battlefield's game join) or "closed" (in the sense of created beforehand, e.g. like R6S)

thin stratus
#

It's just Party vs Game