#multiplayer

1 messages Β· Page 93 of 1

nova kelp
#

I have something I can't figure out:

  1. I created 2 Character one AI one Player
  2. Associate different AnimInst in the BPdetails Panel: AI -> ABP_ACS_AiCommon and Player -> ABP_ACS_PlayerCommon
  3. in the AnimInstance of the Player I print the TryGetPawnOwner and what I don't understand is that it showing well at init ABP_ACS_PlayerCommon_C_0 -> BP_ACS_Liva_C_0

Note: They both use the same skeleton

But suddenly it's returning the Spawned AI ABP_ACS_AiCommon_C_0 -> BP_ACS_SkeletonEnemy_C_0

#

Do I need somewhere to setup the AnimInstance Pawn Owner on Server or something ?

sinful tree
#

What is it you're trying to do / how would your gate be using that reference? Just asking as this sounds a bit strange of a requirement.

elder lynx
#

While doing network emulation in ue 5 editor if we set emulation target to everyone, then will it add the latency and packet loss twice on both server and clients end? Because when I am testing this there is a lot of jitter observed during the player movement and the ping that is observer is double the ping that was set while enabling network emulation.

hollow eagle
#

yes, it is adding the given settings on both ends.

thin stratus
#

@elder lynx @hollow eagle only if you are playing ListenServer though. DedicatedServer doesn't use that feature.

#

And twice as high can be if you use In and Out. Cause what you see on the PlayerState ping is RTT iirc.

#

+- they factor frames into this

#

So the value can be misleading if you have low frames

hollow eagle
#

an in-process dedicated server in PIE definitely does use that feature

#

I have no clue about out-of-process. But playing as a client in PIE with an in-process dedicated server definitely applies network simulation to the server side if you ask it to.

thin stratus
#

I looked this up a couple of days ago

#

I can check again later when I'm at my pc

#

But I'm relatively sure it checks for DedicatedServer and falls back to using server

#

Or client

#

Whatever, not both at least

hollow eagle
#

I mean... yes? The dedicated server will use server settings, which means that if you have emulation enabled for "everybody" you're effectively doubling everything since both the server and client will be running network emulation.

thin stratus
#

Na I probably mixed that up. I'll send you the parts where they basically ignore the everyone setting.

#

Just has to wait a bit cause I just stood up and gotta get to the office first haha

hollow eagle
#

Seems that the option goes through FLevelEditorPlayNetworkEmulationSettings::IsEmulationEnabledForTarget which returns true if the selected setting is "Any" (everybody).
The server passing in server would still have emulation settings enabled.

#

also wtf that's a UENUM without an E prefix

#

did they make an exception in UHT for that...?

thin stratus
#

I could swear there are multiple lines of code that pass the enum on as Client or so specifically if it's a dedicated server.

hollow eagle
#

it wouldn't matter

#

if the settings are set to "Any" it doesn't care what gets passed in

#

but now I want to know how tf they made a UENUM without a prefix

#

and why lol

thin stratus
#

I'm also pretty sure I have no difference in ping when using everyone vs client on an PIE dedicated server

hollow eagle
#

I definitely do, tested a few minutes ago.

#

so unless it was broken pre-5.2 idk

thin stratus
#

What I looked at was 5.0. cooould be broken. But I don't think they touched that

#

Will double check later. I was very sure what I wrote is correct since I even tested and checked the engine code for it.

#

Designer on clients team also said he never noticed a difference in those settings.

hollow eagle
#

the logic behind this checks does seem to be wrong - dedicated server doesn't seem to be handled, just listen server. But it would still get affected by "Any" being enabled - just not "Server".

#

which is probably a bug lol

thin stratus
#

Any is an option? Isn't that called Everyone?

hollow eagle
#

it's everyone in the display name

thin stratus
#

Ah right

hollow eagle
#
UENUM()
enum class NetworkEmulationTarget
{
    Server UMETA(DisplayName = "Server Only"),
    Client UMETA(DisplayName = "Clients Only"),
    Any UMETA(DisplayName = "Everyone"),
};
thin stratus
#

Ok sure

hollow eagle
#

wait not only is that a non-prefixed UENUM, it also isn't a uint8. wtf is happening in this code

thin stratus
#

I mean the prefix is optional or not? The missing uint8 is weird though

hollow eagle
#

The prefix shouldn't be optional... now I need to test this

#

Huh, it does indeed work even as a BlueprintType... wat. I've definitely seen errors complaining about a lack of uint8

thin stratus
#

Even exposed it doesn't want the uint8?

#

Eh...

hollow eagle
#

I wonder if this was a change in 5.2

thin stratus
#

What if you actually try to expose it as member or function param?

hollow eagle
#

I did, as a UPROPERTY(EditAnywhere, BlueprintReadWrite)

#

I'm very confused

thin stratus
#

Magic

#

Maybe the macro fixes it up

#

Does it work to do byte math on it in BPs?

hollow eagle
#

either UHT is very bad at catching this stuff or it became more lenient in 5.2. Maybe as part of the UHT rewrite they did...

#

good question

#

yeah it still has byte functions in BP.

#

Looking at the new UHT C# codebase it does seem like UHT now keeps track of what the underlying type of the enum is. So... they secretly expanded enum support I guess.

elder lynx
grand kestrel
#

I tested on 5.2 just now, and have same result. Wasn't aware before, so now at least I can compress it manually πŸ™‚

woeful ferry
#

Do you know where this map is? πŸ˜„

grand kestrel
#

This is the rounding on rotation tho. -115.312502 -> -115.312500, only the location was 1 decimal place

queen escarp
#

how would i get info from each players PLayerState from the Gamestate ?

#

i wanna check for a value in each playerstate wich one is highest in the gamestate

grand kestrel
#

Can you be more specific, what isn't it doing that you need

queen escarp
#

@grand kestrel i mean in this case its not working its not getting the right one

grand kestrel
#

@queen escarp also you're using a delay from event tick, which means every single tick, it's going to be doing that 1 second after the tick starts. Instead you should remove the delay and if you want to make sure the world has been alive for at least 1 second, then you should do Get Game Time Seconds >= 1.0

queen escarp
#

@grand kestrelyeah just saw that so i reversed it and now it kinda works ;P

#

aye about the delay, i just dont want it to update each frame thats why, so the get game time >= 1.0 would make it run every 1 sec instead or ?=

grand kestrel
#

FYI, there is no guarantee that everything is setup simply because 1 second has passed

#

But for prototype development, sure, you can do that

queen escarp
#

@grand kestrel oh so call it from beging play and do a loop instead is better ?

grand kestrel
queen escarp
#

oh okey ill have to investigate that after im done with this thing

thin stratus
#

@hollow eagle Yep, I misread the code. I saw the part where it checks for IsListenServer and assigns Server vs Client, but that was just to check and the check returns true for the Any setting either way.
My bad, thanks for pointing that out.

thin stratus
#

I think it's the PackageMapClient

woeful ferry
thin stratus
#

In stuff like ::ReplicatActor and ::ProcessBunch

#
        AActor* NewChannelActor = NULL;
        bSpawnedNewActor = Connection->PackageMap->SerializeNewActor(Bunch, this, NewChannelActor);```
#

It's rather complex, so I can't help much beyond this. Last time I dealt with this was on The Ascent where we had an Engine bug with Id mismatch where the Client was unable to find the Class to spawn the Actor and was also not refreshing the Map.

queen escarp
#

ok so im trying to loop from the "gameste" thru the "playerstates" to get the score value and compare wichone is highest ,2nd higest ,3rd highest and set the m in the text, im kinda clueless on how to get the logic for that

#

this is what i have now anyone have time to help me :_/ ?

thin stratus
#

And THAT calls the same on the FNetGUIDCache class

#

Which then tries to find the object matching the net id

#

Which is what failed on The Ascent in some cases iirc. But that's 4.26/4.27 stuff.

#

LogNetPackageMap might be a good thing to enable logging verbose on

#

@woeful ferry ^

woeful ferry
#

Thank you so much! I'll look into this, hopefully we'll not have to deal with it (not done with the system that would utilize it) πŸ˜„

thin stratus
#

No worries. It's such a rare thing getting to even talk about that stuff

#

Was sure a fun thing to figure out when QA comes at you with "Sometimes the AI in that level just doesn't spawn on Clients."

chrome bay
#

There is an async path, though if a client doesn't actually have the class I'm not sure how it's going to serialize it safely.

#

You'd have to force it to serialize as a string everytime presumably

#

And "wait" for it to exist before trying to spawn the actor.

thin stratus
#

I can't recall what the issue exactly was, but it boiled down to the GUIDCache being shit on the Client

chrome bay
#

The danger though is you might be waiting such a long time, the buffer may overflow

woeful ferry
#

We have a very unique scenario πŸ˜„ So yea, maybe we'll encounter that rare thing

#

Time will tell

chrome bay
#

Never got to the bottom of it. Not my problem anymore πŸ˜„

thin stratus
#

But I think that's 2 differnet things or? When a Class isn't loaded in the Client yet, it will async load it when this stuff comes in (or even sync load, not sure).
That was not the problem though.

#

The problem was that the GUID was pointing to something wrong or so

chrome bay
#

Yeah I've never dealt with an issue where the class itself doesn't exist client-side. That's going to be messy to handle.

thin stratus
#

So the client thought it had everything but it didn't and it just ended somewhere in an early return with a warning

woeful ferry
thin stratus
#

There was a Console Command to force recreating the Map on Client Side every idk what time.
And that fixed it. Reported it on UDN back in the day. They probably fixed it in newer versions.

chrome bay
thin stratus
#

I think the thread is privat though, so as usual, no one will ever know

chrome bay
#

Without that, it doesn't know how to serialize or deserialize

woeful ferry
#

I'll probably be done with the system later today, I'll report back on the results πŸ˜„

thin stratus
#

High chance that you can't inject it the way you want outside the traditional "load pak file runtime" stuff

#

But curious to learn about it working hehe

woeful ferry
#

Me too πŸ˜„

#

Otherwise I gotta deep dive

queen escarp
#

anyone got time to help me πŸ™‚ been stuck for a while on this, and tutorials dosent seem to help me πŸ˜›

chrome bay
#

Put the Player States into an array and "sort" if by their score value, then read the top three entries

#

Not sure how you do Sorting in BP with arrays, never done it

#

Presumably there is some way

queen escarp
#

hmm aye i suppose thats what i need help with then since i dont know how either xsd

chrome bay
#

Incredibly, there is no sort method.

queen escarp
#

xD

chrome bay
dark parcel
#

or make your own sort function?

#

would be a good learning practice

chrome bay
#

How does anybody make a game in Blueprint honestly.

dark parcel
queen escarp
#

lawlz xD

chrome bay
#

As in, what a ballache it is

queen escarp
#

well

#

im doing it so

#

idnno if u can call it a "game" tho

chrome bay
#

I'm just baffled there's no Sort() function in the engine by default.

#

Even if it is horribly inefficient

queen escarp
#

oh wait this wont work at all

dark parcel
#

When I learn C++ at school, one of the first thing we had to do was to sort Arrays

chrome bay
#

Just create a copy of the array and sort that

dark parcel
#

efficient way/inefficient way etc

chrome bay
#

No point individually adding elements

queen escarp
#

since the playerstates gets enabled after joining right ?

chrome bay
#

Player States can be added at any time

queen escarp
#

oh ok

chrome bay
#

via players joining/leaving

dark parcel
#

I dont get that make array part

#

why are u pulling that node

queen escarp
#

yeah removed it

#

this is for preformance really

#

i mean if i cast on tic cost way more then creating the ref at begin play and using the reff right ?

dark parcel
#

What performance?

queen escarp
#

or have i understand it wrong

dark parcel
#

I won't recommend using cast on tick

#

set your references where it make sense

queen escarp
#

exactly so if i set the reff at beging play instead and use that in the tic instead

dark parcel
#

eg. when ur player stats is updated or at event begin play depending on your game

queen escarp
#

"costs" less ?

#

yeah so thats what im trying to do

dark parcel
#

Not sure what you want to do but set your references instead of casting

#

Make variable of the type, then set the reference. Then on your tick you can just get your variable

queen escarp
#

yeah but since im doing a for each loop to cast for each one, how would i make a reff to that specific player

dark parcel
#

What do you want to do?

fathom aspen
dark parcel
#

what's the whole node are suppose to do

queen escarp
#

like in this case

#

im casting to each players own player state right

dark parcel
#

No

#

You probably need whole array if you want to contain the player states but you have to take into account that player array might get updated (Eg player join or leaves)

fathom aspen
queen escarp
#

@dark parcelexactly so this is the part where im having problems with i guess dont quite understand how to do taht

dark parcel
#

You probably want to have a cointainer (array of player states) that is updated whenever a player join/leaves

queen escarp
#

so this dosent do that automaticly ?

#

the player array comes from the game state by default

#

i suppose i should scratch this and go by a simple tutorial first tbh

#

since im not quite getting it

dark parcel
#

I just touched multiplayer last week, maybe other people know the answer

queen escarp
#

aye ty anyways πŸ™‚

dark parcel
#

when you setting array however, you are just grabbing the copy of it.

queen escarp
#

yeah

dark parcel
#

So unless u update the array it will not update. If the game state already update the player array accordingly, then you can just access it?

queen escarp
#

yeah true'

dark parcel
#

I mean, if you don't get the answer here you can probably tested it

queen escarp
#

yeah i will

dark parcel
#

try to print string the value

#

have another comp join/leave

#

Guys, I have question, how often would you use Skip_Owner for replication condition? Seems like any value that requires instant change in the local system should implement this condition?

chrome bay
#

SkipOwner means it'll never replicate to the owner

#

So usually a value that is irrelevant for those objects

#

APawn::RemoteViewPitch is a good example. The local player computes the aim pitch and sends it to the server, so they don't need it to be replicated back to them.

dark parcel
calm prawn
#

Hi there. Can someone help me understand what I'm doing wrong here?

void ACPPCharacter::ProcessSpeed()
{

Fly = UKismetMathLibrary::FInterpTo(Fly, TargetSpeed, GetWorld()->GetDeltaSeconds(), InterpSpeed);
FVector FlyForward = FVector(Fly, 0.0f, 0.0f);
AddActorLocalOffset(FlyForward);

SR_ProcessSpeed(FlyForward);

}

void ACPPCharacter::SR_ProcessSpeed_Implementation(FVector FlyingOffset)
{
if(GetLocalRole() == ROLE_Authority)
{
AddActorLocalOffset(FlyingOffset, true);
}
}

ProcessSpeed() is inside the tick event. The problem is something like this.

  1. In my client view the flying is jittery
  2. In other client's view the flying is smooth.
  3. If I play with the server and the client it's jittery only in the client's view.
chrome bay
thin stratus
#

And renable it when that ended

#

For that ammo property

dark parcel
#

πŸ₯Ή ok, I will try that

thin stratus
#

Just an idea, not that I ever used that advice myself

#

.>

woeful ferry
#

So I don't have to dive deep down into source woho!

fossil spoke
#

@thin stratus @chrome bay Wanted to butt in on your previous conversation about Classes not being loaded for replication serialization etc just to add that we had this issue.

#

Our Weapons were async loaded only when needed.

#

Ages ago QA was complaining that sometimes Clients would not have their Weapons

#

It was really hard to track down what was going on cause the Server would always have the Weapons available.

#

And it was intermittent and only on some Clients

queen escarp
#

Why is this not working :/ i mean logically it would or am i dumb

thin stratus
woeful ferry
#

Well aslong as the classes are created it seems to work. We compile and create the classes in runtime locally and then tell the server that I just created this class, now replicate the actor that has that class

ruby parrot
#

Hiho, how would I trigger a syncronization of a thing I interact with already?
e.g. a chest ->Player 1 opens the chest and there are 2 items in the chest
player 2 opens it now and puts a 3rd item in there.
how do i "tell" player 1 that he has to update that specific chestInventory?

woeful ferry
#

Then just call an OnInventoryUpdated in your OnRep

#

Or if you're using FFastArraySerializer you use it's update functions, but that's another topic.

ruby parrot
#

ye, i understand the OnRep stuff, ill test that πŸ™‚ thanks

obtuse field
#

Can I replicate struct member via class replication?

#

E.g. to use

DOREPLIFETIME(UMyClass, MyStruct.MyMember)

If so, is this safe?

fossil spoke
#

You can control which members are serialized

obtuse field
fossil spoke
#

UPROPERTY(NotReplicated)

#

On struct members you dont want serialized

obtuse field
#

I know

#

What I want to. I have FastArray, and I have one several members that I would prefer to keep inside this struct

#

But as you know, they won't replicate, as they are inside FastArray struct, so only array is being replicated

fossil spoke
#

Huh?

#

The array elements will be replicated

#

If those elements are a struct

obtuse field
#

I know, but nothing else

fossil spoke
#

The struct will be replicated because they are part of the array

obtuse field
#

but I'm not talking about array member. I have something like this:

#
struct FItemList : public FFastArraySerializer
{
    GENERATED_BODY()

    FItemList() {};
    
    FItemList(AActor* NewOwner);

    const TArray<FEquipmentSlotWrapper>& GetItems();

    UPROPERTY()
    AActor* Owner; //Not replicated, but I want it replicated
    
private:

    UPROPERTY()
    TArray<FEquipmentSlotWrapper> Items;

    bool NetDeltaSerialize(FNetDeltaSerializeInfo & DeltaParms)
    {
        return FastArrayDeltaSerialize<FEquipmentSlotWrapper, FItemList>(Items, DeltaParms, *this);
    }
};
fossil spoke
#

Yeah thats not going to work

obtuse field
#

Even with this as in my actor class?

DOREPLIFETIME(AMyActor, MyStruct.Owner)
fossil spoke
#

How would you expect that to work. That member is not a member of AMyActor its a member of FItemList

#

Take a look at the GAS plugin and how they use FastArrays

#

They have good examples of achieving what you need if i remember correctly

obtuse field
fossil spoke
#

No

#

GAS itself is a plugin with the engine

#

Go and read its code

obtuse field
#

ok

#

In which category is it? 2D, AI, Animation etc.?

#

Can't find it

bitter robin
#

It stands for Gameplay Ability System

kindred widget
rocky kestrel
#

Okay Thanks I do that

toxic pawn
#

I'm making a ready up system for my game, and the way I plan to do it is to have a replicated bIsReady field in my playerstate, which the client can tell the server to update with an RPC. But I realize that this may come with a potential problem of cheating. Since player states are replicated to all clients, what if a cheating client calls that RPC on other player states, outside of its own? I'm not even sure this is possible as I never tried to call server RPCs from anywhere but the owning client, and honestly I think it would make sense for the server to simply drop all RPCs that are not called from the owning client. Can someone confirm if this is the case? And if it's not, what measures should I take to prevent this from happening? I though of storing the ready state on the player controller, since that only exists on the owning client and the server, but unfortunately that's not suitable for me since I need the ready state of any player to be visible to everyone else.

chrome bay
#

A client can't call an RPC on an actor it doesn't own, and clients do not own other player states

#

They only own their own

#

If a client machine tries to call an RPC on an object it doesn't own, the server will ignore it

#

So even if you can spoof the RPC it's "secure" in that sense

toxic pawn
#

Thanks, that's what I was expecting to be the default behavior also.

#

And turns out, I'm really dumb, I read right past that in @thin stratus 's multiplayer compendium

queen escarp
#

how do i play something to all affected players ?

#

i mean in this case

#

i wanna play it on all players in game'

#

should i just use it in a multicast/ `?

toxic pawn
#

Not realy sure how you do that with blueprints, but I think you need to create a function that is called on the server, and then from the server another multicast function that just calls add loading screen

toxic pawn
queen escarp
#

yeah

#

gotcha

toxic pawn
queen escarp
#

yeah

thin stratus
toxic pawn
ruby parrot
# woeful ferry Then just call an OnInventoryUpdated in your OnRep

Ive tried for quite a while now but this part is where i am stuck πŸ˜„
The OnRep function is in an ActorComponent (Inventory) on the chest.

the WidgetBlueprint is WB_LootContainer wich is part of the players UI.

How does the OnRep function know that Player1 is interacting with it?

woeful ferry
#

that is like OnInventoryUpdated

#

and it'll update for everyone that is in the chest

#

when they get the new inventory info

ruby parrot
#

brb googling what delegate is πŸ˜„

woeful ferry
#

event dispatcher in BP

#

Ignore the description for Event Dispatchers

#

Allows a Blueprint Class to report on its state to the Level Blueprint.

#

@ruby parrot

ruby parrot
#

ye, im reading πŸ˜„

#

its so nice that unreal actually shows proper examples and how they work in their documentation /irony off

toxic pawn
#

Going back to my question earlier about the ready system, currently I store how many players are needed at a minimum to start the game in the game mode itself. But I realized now that it may be useful for that info to be displayed also on the player's screens. How would I go about that, since game modes don't exist on the clients?

woeful ferry
dark edge
#

Game mode is kind of weird. I wonder why they did not just have game state with guarded functions

toxic pawn
toxic pawn
#

I mean, I know roughly what subsystems are but I don't see how it connects to what I asked

woeful ferry
#

Only available in c++, but there are plugins which enables BP to make them too

toxic pawn
woeful ferry
#

With subsystems you don't have to clutter everything in game state

#

and easily work with modules to separate your code

#

It's basically unreals way to make singletons for your game

#

But they don't support replication, but instead you route it from the subsystem to a subsystem actor that replicates what you want πŸ˜„

toxic pawn
#

So you suggest that instead of just adding that field that describes how many players the game needs to start on the game state, I should add it on a subsystem actor?

woeful ferry
#

Depends what you need πŸ˜›

#

For just a simple check like that it's probably best for game state

toxic pawn
woeful ferry
#

But if you want a game manager that is not a game state,

#

subsystems are the way to go

#

Less cluttered game state πŸ˜„

quasi tide
#

Just put the amount that is ready'd up in your game state and move on with your life.

#

Going the subsystem/aactor route has its own drawbacks/costs.

toxic pawn
kindred widget
#

IMO people abstract to subsystems too much. They're nice. But I've seen a lot of implementations that would be a ton easier as a simple component on the game state.

#

You get abstraction, code clarity, replication, all in the same class.

woeful ferry
#

Aslong as its readable πŸ˜„

#

idc which route you go

ivory bear
#

Does this mean that it fires just like an event that you have marked Replicatin: Run on Server?

quasi tide
kindred widget
quasi tide
#

Doesn't help that the component tools in Unreal are trash compared to other things. Admittingly, I'm mostly talking about how to reference a specific component. FComponentReference is silly. Typing in the name is so archaic.

latent heart
#

UseComponentPicker meta tag?

quasi tide
#

Doesn't work for BP editor though

toxic pawn
# quasi tide Doesn't work for BP editor though

As a side note, idk why epic does this, but there's also that EditWidget meta tag, or whatever it's called, that's supposed to be useful when editing vectors. But again, it only shows up on actor instances in the level, not on blueprints, where I would say they are actually more useful.

ruby parrot
#

thanks for now though ❀️

rotund onyx
#

Does an event need to be a "Run on Server" event if I know it will only ever be called by the server itself? I'm trying to reduce the amount of RPCs I'm calling because I have a lot and they all need to be "reliable" so I need to look into ways to keep that reliability without massively bogging down the network. At the moment I have even reliable RPC events that will just fail to work, even server side, so I'm just trying to make things function at all.

viscid heart
#

Is it guaranteed that APlayerController::BeginPlay is called before APlayerController::AcknowledgePossession(APawn* P) when playing as client in multiplayer?

wanton bear
#

i have an actor im moving around, it seems it's replicated but the movement isnt eye_think

#

ill try checking replicate movement

#

well that makes things jump around weirdly

#

ohhh i only need to replicate the start position

viscid heart
#

AHPlayerController::AcknowledgePossession(APawn* P) my GameState is sometimes null here on clients 😭 where is a place where Pawn is possessed, GameState is valid and BeginPlay has been called? Everything I try fails when simulating lag enough times

rotund onyx
#

Sort is same vein as my last question.
Right now I run pretty much any action a client takes through their PC, which then triggers a "Run on Server" RPC that does the rest. So far this has been necessary to get the UI to send events properly (Eg. Click Button>PC Event>Server Event). If I know a client owns an actor, can I simply call an event directly in that actor instead of running it through the PC, or is that bad?

wanton bear
#

trying to think through this

spawn actor on server and set position -> replicate -> make random variables on server -> replicate to client -> move actor using random variables -> loop 0.033 second until in new position -> back to make random variables on server, ensure actor is in new final position?

ivory bear
# quasi tide No.

Hmmm. Interesting. My pic above in green, shows a non replicated function being called by IsServer, yet my client player has an empty anim instance so the things called seem to break for the client. This means that the blendpace is missing when the client sees others change held items...the upperbody blend fails.

quasi tide
keen axle
#

is it possible to have client spawned ai controller controll server spawned pawn? I need this for my open world racing game

quasi tide
keen axle
#

I need it because the physics are almost like beamng. It would absolutely break the immersion if everything was done on server 😦

keen axle
quasi tide
#

You'd have to do something entirely custom

#

Networked physics is a PITA

#

You'd pretty much have to have your own possession system and not use UE's built-in one

keen axle
#

FUCK πŸ˜„

#

3 years of work in shit

quasi tide
#

Possession only happens on the server

#

I mean...you might be able to fandangle ownership though πŸ€”

#

Overall - it's going to be a headache

ivory bear
quasi tide
#

And I wasn't responding to you originally. I didn't even pay attention to your problem.

#

Run On Server is only for client -> server communication. If you're running a function on the server already, and it was the server that called that function, you don't need it to be Run On Server

ivory bear
#

It seems my server call (or anim instance) is hosed. Here is my client viewing the server player chaning weapons.

rotund onyx
quasi tide
#

I don't recall honestly. It could very well be treated as just a regular function call, but it could also be a reliable RPC with 0 latency so it is near instant.

rotund onyx
#

Hmm

#

I have some reliable stuff that works fine in editor but in a compiled game becomes quite unreliable

#

So I'm basically debugging that

#

I'm just assuming I'm calling too much stuff at once

#

Because my game is turn based, so I am potentially looping through a lot of actors to update them at end of turn

keen axle
#

spawn the car on server, set ownership to client after that

quasi tide
kindred widget
#

Not sure whether to ask this here or in OSS room. But I wonder if anyone would happen to know a generic way I could disable voice chat temporarily? It's causing issues during seamless travels. PlayerController seems to have functions related to toggling it, but I am under the impression that these could be turned on again with a PTT key.

dark parcel
#

@kindred widget Never touched it or know what Im talking about but is the command ToggleSpeaking 1/0?

kindred widget
#

That is what is in the player controller. A few other calls and such led me to believe this was PTT functions. Which isn't good because I don't want them to be able to enable it from PTT if I disable it.

#

I dunno, this may work. I don't think we use any PTT stuff.

dark parcel
#

I think push to talk have to be enabled in the config?

#

for PTT to happend

#

not sure

kindred widget
#

Platform specific OSS stuff

winged badger
#

IVoiceChatUser?

kindred widget
#

That sounds semi right, lemme look.

#

IOnlineVoice children

winged badger
#

It should have functions to join/leave from a channel

#

As the OSS typically support multiple voice channels

#

I only worked with EOS one though

nocturne quail
#

Why server is spawning the item in the center of the level and not at the location of the character actor?

FTransform SpawnLocation = FTransform(FRotator(0), FVector(MyCharacterRef->GetActorLocation()), FVector(1));
MyItem->FinishSpawning(SpawnLocation);
kindred widget
#

Hmm. I think the ToggleSpeaking might work. GenericPlayerInitialization uses it to set a client's voice on/off based on game session requiring PTT.

winged badger
#

That or not using PC for anything except forwarding PTT input

#

OSS is there and working during seamless

zinc acorn
#

so i have something set up where when the player aims down sight it snaps the weapon to the camera for specifically the player like its supposed to be client side but on the host player it seems to replicate it to others, i have is local player as a check but it seems to not work for the host

kindred widget
zinc acorn
#

prolly a bit scuffed to send this way but i think it will be of use πŸ˜‚

kindred widget
#

And this only breaks for the listenserver host player?

winged badger
#

As in dorsnt work for host or just replicates when it shouldnt?

#

Big difference

zinc acorn
#

it replicates when it shouldnt basically

#

causing the hosts weapon to be floating behind them πŸ˜‚

kindred widget
#

Probably the attachment stuff. Attachment is replicated.

zinc acorn
#

here is what is happening

kindred widget
#

Also don't use SetVisibility for local visibility. Use SetHiddenInGame. Visibility is replicated, HiddenInGame is not.

zinc acorn
#

that part seems to work fine but i will take note of that

kindred widget
#

It's just because that component isn't replicated. If it were it would cause an issue, just a nice habit.

winged badger
#

Not visible and no collisions will also turn relevancy off

zinc acorn
#

is there any way i can not replicate the attachment?

#

but still have the weapon be replicated because i think i still need it to be replicated

winged badger
#

Replicated actor will replicate attachments

#

In c++ you could hack the onrep not to exec

#

Im on mobile so cant really check BP code you pasted

zinc acorn
#

im thining it is probably attachment so ill probably have to delve into C++ for it which will be put on my list of 2 things i will probably need to do so for (this and if possible toggling self shadows on weapon when ads so there isnt floaty shadow haha)

wanton bear
#

how would i wait for two variables to replicate, repnotify with both and logic to check if both are done?

#

i guess i could make a map but

kindred widget
wanton bear
#

if i have a custom event running on the server to set one variable and then the next variable with a repnotify on the last one to be set would that work

#

or could the first finish replicating after the second

quasi tide
#

No guarantees

#

If you are building time dependencies in your networking code, you're just inviting trouble.

wanton bear
#

thats what i figured

kindred widget
#

"Generally" most required stuff on an actor will replicate at the same time. But there is no promises. Bundling them in a struct is the only general way to deal with that if you don't want multiple onreps waiting for specific state from multiple properties.

viscid heart
#
void AElfCharacter::OnRep_PlayerState()
{
    Super::OnRep_PlayerState();
    auto* ElfWidget = CastChecked<UElfWidget>(WidgetComponent->GetWidget());
}

That works on clients, but the following cast always fails on singleplayer or listen server for the local player

void AElfCharacter::PossessedBy(AController* NewController)
{
    Super::PossessedBy(NewController);
    auto* ElfWidget = CastChecked<UElfWidget>(WidgetComponent->GetWidget());
}

WidgetComponent->GetWidget() always returns null 😭 why

broken shale
#

Curious what y’all’s thoughts are on changing teams in multiplayer games… should it only be permitted between matches or at any time?

sudden plinth
#

Between matches

thin stratus
#

I mean, that really depends on your game.

#

Enough games allow switching at any time if the balance is kept.

broken shale
#

It’s a goal based game. I can see the advantage of letting people switch in game if a new player joins or players leave. But I can also see the frustration of someone abusing the option to grief

quasi tide
#

Still entirely your decision. No one else can make the choice for you.

latent heart
#

Changing from the losing to the winning side should always really be blocked

kindred widget
#

IMO these are balance changes you would discuss with testers or existing playerbase.

quasi tide
nocturne quail
#

the character drop item logic should be handled in AMyController or AMyCharacter?

#

currently I am doing this in AMyController, and when the first client drop an item, it is working fine, but if second client drop an item, the item goes to location of first client

graceful flame
#

How can you show steam avatar without using Advanced Steam Sessions plugin? I can't seem to compile with that plugin in 5.2 anymore.

twilit plume
#

does unreal eos support mobile now ?

queen escarp
#

hey guys how would i cast to player character to get each player ?

sinful tree
queen escarp
#

ah nice

sinful tree
wanton bear
#

how can i simulate ping times?

#

i'd like to be able to test how someone with 200-500 ping would see the game

cursive steeple
wanton bear
#

oh awesome they built it in

#

thanks

nocturne quail
# sinful tree It sort of doesn't matter, but whichever you use, you have to make sure you're u...

yes I am doing the exact mistake.

AMyController.cpp calling by server reliable

AMyCharacterBase* MyCharacterRef = Cast<AMyCharacterBase>(UGameplayStatics::GetPlayerCharacter(this, 0));

if (!MyCharacterRef)
{
    printerror("MyCharacterRef is not valid", 30.0f, FColor::Green);
    return;
}
FActorSpawnParameters SpawnParams;
SpawnParams.bDeferConstruction = true;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
FTransform SpawnLocation = FTransform(FRotator(0), FVector(MyCharacterRef->GetActorLocation()), FVector(1));
APickupWeapon* NewWeaponPickup = GetWorld()->SpawnActor<APickupWeapon>(WeaponPickupStaticClass, SpawnLocation, SpawnParams);
if (IsValid(NewWeaponPickup))
{
    NewWeaponPickup->Mesh = WeaponMeshPath;
    NewWeaponPickup->Quantity = 1;
    NewWeaponPickup->FinishSpawning(SpawnLocation);
    NewCreatedItem = NewWeaponPickup;
}
nocturne quail
nocturne quail
#

but the same result

#

the same issue

#

maybe there is function to GetCurrentlyPocessed and get its location

sinful tree
#

That's what GetPawn() is supposed to be.

nocturne quail
#

for me GetPawn is getting the location of the first client

sinful tree
#

There is nothing specifically in your function that looks wrong that I can see. You're getting a reference to the pawn that this controller would be possessing and attempting to spawn something at that pawn's location. There is no reason why GetPawn() would return anything other than the pawn that the current instance of the player controller is controlling. I think the issue is starting prior to your calling of this particular bit of code, like the event is being called on the wrong Player Controller if you're using the GameplayStatics anywhere else before this.

nocturne quail
nimble snow
#

Hey anyone knows the proper way to make replicated attach actor to actor?

sinful tree
nocturne quail
#

I think this has nothing to do what I am doing in PC

sinful tree
# nocturne quail I think this has nothing to do what I am doing in PC

Probably not, but GameMode only ever exists on the server, so if you're doing a GetPlayerCharacter on the server, then you'd only get a valid reference if you're running a listen server, and it'd always be the Host's character. Nevermind about the valid reference part... It'd get the first valid character but that's still likely not what you want.

nocturne quail
#

running as two clients in new window

nimble snow
sinful tree
nocturne quail
#

any idea, calling the logic using character class is not working?

nimble snow
sinful tree
twilit plume
nimble snow
#

the actor gets spawned but not attached

sinful tree
# nocturne quail any idea, calling the logic using character class is not working?

It all has to do with how you're getting your references and how you may be calling into the different classes based on those references.

Something to note:
Controller has a reference to Pawn (GetPawn()) and PlayerState (Variable)
PlayerState has reference to Pawn (Through variable Pawn Private) and Controller (through GetOwner() function which you can cast to your custom controller)
Pawn has reference to controller (GetController()) and PlayerState (Variable).

This means regardless of which of these classes you're using, you can get access to the main actors that relate to a specific player that you would be able to RPC through and would primarily be used for replicating data about a player. If you use any of the GameplayStatics functions for trying to retrieve the pawn, the controller or their playerstate, you can't reliably get a specific reference you may be looking for, especially so when running on the server, so it's best to avoid using them in multiplayer entirely.

hushed rain
#

If my listen-server-developed game works while in "Play as Client" network mode does that mean it will work on a dedicated server?

sinful tree
nimble snow
sinful tree
#

This is what I've got and it works just fine (this is executing in my Character class)

#

The +200 just moves the actor so it's above my actor's head πŸ˜›

nimble snow
#

sorry for pinging if that disturbs you

sinful tree
#

S'all good

boreal bison
#

In my game, players have an inventory widget that lists words in their inventory (which is a variable in their playerstate). Players will also be able to mouse over each others names to pull up a list widget that has their inventory. In the game, Players can steal individual letters from words in other players inventories. Basically, I need to give players the ability to see everyone's inventory in real time, and have the UI update any time letters are successfully stolen (the stealing logic is already written).

My main question is how to structure the replication. Do I have the gamestate call a multicast to update everyone's UI to reflect the state of players' inventories when changes are made? I have logic set up for players claiming words and right now it only updates for the player doing the claiming, so they also cant see when their letters get stolen until the next time they claim words

sinful tree
# boreal bison In my game, players have an inventory widget that lists words in their inventory...

Stateful things should be done in replicated variables. The OnRep of those variables can then be used to trigger things you want to happen when the new value is received by a client.
So if you're "stealing" from one person's inventory, you'd remove what you're stealing from that inventory and put it in to the inventory that is receiving it. Both of these inventories would have their own onreps which can be used to trigger any UI to update. If you have it on the playerstate already, that's a fine place - and that means whatever UI you're using to display the values needs to be looking at the playerstate that is associated to the inventory you're trying to view and it needs to know when it was updated - which you can do similar to the event dispatcher and bindings we were doing with the turn changes, except this time you're binding to an event dispatcher on the playerstate and it's being called on the OnRep of the inventory variable.

boreal bison
fossil spoke
#

TMaps are not replicated

#

It is likely better to just store an ID on the Item to indicate its position in the inventory

#

TMaps and TSets are not replicated

thin stratus
#

@twin juniper If you are using CPP, you might want to use FastArraySerializer for your Inventory anyway

ruby rock
#

Quick question.

In MP, 2 clients running in the editor.
I have a light that I have attached to my actors mesh. The actor is marked as replicates, as is the light (component replicates). For ease of understanding call the actor BP_MyActor.

If I set the light to green on the server (BP_MyActor) that should replicate to each client (and even late joining clients) shouldn't it?

winged badger
#

is that c++ or BP @ruby rock ?

ruby rock
#

Either πŸ˜‰ But happy to talk C++

winged badger
#

so it will replicate to late joiners if the engine replicates the light color in c++ by default

#

which is not something i would just assume without checking

ruby rock
#

because the component (the point light) is replicating right? as a new client arrives it'll get a copy of what the server's truth is

winged badger
#

the component replicates yes, so clients will receive its replicated properties

#

but the question is - is the Color here a replicated property

#

generally if there are both pros and cons to replicating a property in the engine by default, engine will not replicate it by default

#

because its much easier to add replication when you need it then undo default one in engine

#

in your case - if all you are replicating is light color or just a few light params, its more performant to replicate the property through the Actor then adjust the component from OnRep

ruby rock
#

Color here a replicated property
Sorry - no it's not. There is value "Faction" that is driving the color. So if Faction = Good, Color of the light -> Green, etc

winged badger
#

as then component doesn't need to be replicated or evaluated for replication

#

so, replicate faction, and from OnRep_Faction wire logic that will adjust the LightComponents visuals

#

and turn off replication on LightCOmponent completely

#

btw, you can enable dropping late joiners in PIE and test it too

#

there is an experimental feature in editor preferences, just search for "join", then you'll get a button to join extra client during PIE sessions next to play

ruby rock
#

ah - actually now you say that, I think what I've been doing is this. And then intercepting OnFactionChanged_Client in BP to set the light. That might be the issue

winged badger
#

that should work fine

#

only c++ OnRep will not trigger for listen server host

#

so you need to call FactionChanged from SetFaction as well

ruby rock
#

Like so ?

{
    Faction = faction;
    OnFactionChanged_Client();
}```
winged badger
#

whats the declaration look like?

#

as the _Implementation part seems a little odd

ruby rock
#
    void SetFaction(EFaction faction);
    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    EFaction Faction;
    UFUNCTION()
    void OnRep_Faction();
    UFUNCTION(BlueprintImplementableEvent)
    void OnFactionChanged_Client();```
winged badger
#

ah, server RPC, do they get to choose faction while in play?

#

but yes, that should work, you just need to rename OnFactionChanged_Client() as its no longer client exclusive callback

ruby rock
#

Yeah lobby - they choose their faction

#

Needing to also deal with non-player's having faction (like friendly units, etc)

winged badger
#

there is an ITeamAgentInterface in the engine

ruby rock
#

ITeamAgentInterface
Well - the more you know!

#

Oh - just looked, I wrote my own version of all of that

#

Thanks for your help - I'll play around a little and see what I find.

twin juniper
#

After the last client (tho only server and 1 client in this case) joins the session, I client travel and then call Server Travel on server RPC. But server doesn't seem to travel?
I had already previosuly called ServerTravel once for Lobby. I can call it again, right?

Also server is working weirdly in standalone. When I run the game in UE Editor in Level editor, the server instance works correctly by creating server, going to lobby and coming back to Main Menu, hitting all the correct breakpoints. But in standalone using batch file, the server goes to lobby and then at the end shows the gameplay message engine with Tie?

blissful atlas
#

I have tried all of that but it didn’t work. Is there any other solution or do I need to get a dedicated server from Steam?

woven bramble
#

Guys, What is the best spawn system for multiplayer? EventBeginPlay RunOnServer > Multicast > SpawnActor in GameMode or RepNotify method?

thin stratus
#

RunOnServer -> Multicast on BeginPlay of the GameMode?

#

Any more random, totally wrong and redundant things to chain? xD

#

Posting that all I can suggest you is to go back to the basics

twin juniper
#

There is error of ServerTravelFailure in PIE. How can I debug then?

thin stratus
twin juniper
thin stratus
#

Did you enable the experimental support for it in PIE?

#

Otherwise you can't do that in PIE

#

Seamless ServerTravel is by default unsupported in PIE

twin juniper
twin juniper
woven bramble
thin stratus
woven bramble
thin stratus
#

Hence the "Go back and read the basics."

#

Like, you posted not a single option that is correct :D

twin juniper
#

ServerStartGame is server RPC for servertravel

thin stratus
#

Are you connected to the Server or just in the Session?

#

And why would it need a ServerRPC, shouldn't the Server know all of this?

twin juniper
twin juniper
#

I'll share code

thin stratus
#

But if you are already connected, what is the ClientTravel for?

#

You only travel as Client once after the Session is joined. After that you only perform ServerTravels. And where even do you call that code?

twin juniper
woven bramble
# thin stratus Like, you posted not a single option that is correct :D

I always read the documentation from the beginning, there is no consistent information required. Everything is piecemeal.
Can you summarize how to spawn Enemy please, let me do a deep research according to what you summarized.
I wan to start with the parts you said to at least learn the basics of Multiplayer. Because I always research and read Multiplayer, but some things are always missing.

thin stratus
#

Eh

woven bramble
#

the spawn system is one of them

twin juniper
thin stratus
#

You are writing a lot of random stuff. Can you please fully explain the flow of your connection and session stuff?

#

Because by default, Clients search for a Session, Join the Session. Travel to the Server (connect) and after that the Server Travels with all Clients. Any further Client Travel would cause a disconnect.

thin stratus
#

The question you asked is answered by reading and understanding that document.

#

It's written so me and others don't have to repeat the basics

twin juniper
thin stratus
#

Please go and read it (again if you have already)

thin stratus
twin juniper
thin stratus
#

A player that opens a LISTEN game simply Client Travels to the map it wants, with ?listen as option.

#

If you host as a player, you just OpenLevel(Lobby, "Listen")

#

And then when everyone is connected, you do ServerTravel, on the Server

#

No need for an RPC here either

#

Also

#

You screenshot of teh code

#

Shows ServerRPC in the GameInstance

#

You can basically join the queue from punkfloyed and read the basics..

twin juniper
thin stratus
#

GameInstance is not replicated

#

You can't access the GI of other players in any way

#

And ServerRPCs are totally redundant and not working

twin juniper
thin stratus
#

Your Server should check if everyone is connected n the GameMode

#

There are events to react to players joining (e.g. PostLogin)

#

Count them there, check how many you expect.

#

Start the game from there

#

No need for RPCs

twin juniper
thin stratus
#

Don't think so

glass orchid
twin juniper
glass orchid
#

technically yes

#

but seamless travel doesnt work in PIE

#

not until i believe 5.1

twin juniper
glass orchid
#

unless you use the console command to enable it, and even then it might still crash

thin stratus
glass orchid
nocturne quail
#

running the game as two clients, both clients are clients_0 how to fix it?

drifting stirrup
#

what is state sync
is it sending inputs and correcting every now and then with state
or is it sending both at the same time

twin juniper
nimble snow
#

what happens if I cast my character and set it in a variable on multicast event? will that cause any issues?

nocturne quail
charred patrol
fringe dove
fringe dove
#

oh that's in the area where people receive the event, I thought you meant cast before sending a pointer through multicast rpc

#

that delay loop might go forever if you have an error where your pawn is something else

charred patrol
# nimble snow it looks like this

Like I said if you use multiple Character_Base in your game cast could fail. But if all the Characters is using this Character_Base this should be fine I believe.

nimble snow
fringe dove
#

should be fine, but I'm not sure you need networking for this, could do it in the player controller on begin play with a similar delay loop

nimble snow
#

this event runs on event on possess

charred patrol
fringe dove
#

a nasty surprise is that reliable multicast isn't reliable in unreal engine

fringe dove
#

there is a timeout that abandon's retries that is shorter than the disconnection timeout

nimble snow
charred patrol
fringe dove
#

yeah, it makes no sense, I've only run into it when paused for debugging but it could happen and get you into some invalid states if networking went out for a few seconds

#

so now I only use reliable unicast and just manually send to all

charred patrol
fringe dove
#

I think so, maybe it has been fixed though it has been a few years

#

if a reliable multicast rpc times out for a client, it should really just disconnect them at that point

keen hound
#

How would I make a simple team system?
I just want the player to spawn on one side of the map or the other as a different pawn on each side

twin juniper
keen hound
#

I know how to do a random system already, I just haven't been able to figure out possesion

nocturne quail
nocturne quail
twin juniper
#

Probably what looks like is you are getting the controller and then it's pawn and then it's name, or something along those lines, right?

thin stratus
#

Just post the code, no need for guess work

nocturne quail
thin stratus
#

Keep in mind those DisplayNames are debug only

#

They aren't meant to be used for anything else, in case you want this to be different to identify them

nocturne quail
#
void AMyPlayerControllerBase::FindCurrentlyPocessedPawn()
{
    AMyCharacterBase* MyCharacterRef = Cast<AMyCharacterBase>(GetPawn());
    PrintLogScreen("Pawn Name: %s", 30.0f, FColor::Green, *GetNameSafe(GetPawn()));
}

void AMyCharacterBase::PressedOneKeyEvent()
{
    AMyPlayerControllerBase* MyPlayerControllerRef = Cast<AMyPlayerControllerBase>(UGameplayStatics::GetPlayerController(GetWorld(), 0));
    MyPlayerControllerRef->FindCurrentlyPocessedPawn();
}
twin juniper
#

And also you'd need to make sure player controllers are replicated, I am not sure if it is by default or not

nocturne quail
green latch
#

Hi! I'm currently making a multiplayer game using the OnlineSubsystemSteam, and I'm having trouble making a Character Selection. I've stored the character type in a custom Game Instance, and spawned an actor in the lobby according to the custom Game Instance. The trouble is, that whatever character the client selects is overwritten by the character selected by the server. Any help?

twin juniper
nocturne quail
#

this print the correct pawn

void AMyPlayerControllerBase::PressedOneKeyEvent()
{
   FindCurrentlyPocessedPawn();
}
nocturne quail
twin juniper
twin juniper
twin juniper
#

Lemme think

#

Then the only problem that can be is you are calling it on wrong player controller

#

Given whatever you said uptil now is correct

#

Because if replication had problem then it wouldn't work from Playercontroller also

#

But because you are saying it is working correctly, then it means that it is being called on wrong player controller

#

Else the result should be identical

nocturne quail
twin juniper
#

Yes, seems so

nocturne quail
#

I can see the pc index is 0

twin juniper
#

If you wanna do it, then keep it in PC only

#

Why do you even need it in Character?

#

I mean why one more level of indirection?

nocturne quail
#

I will use it to drop the weapon using pc

twin juniper
#

If you wanna be sure you can actually debug and compare the PC's that's being used in each case🀷

#

Character is on the client right?

nocturne quail
#

yeah I can try now to change that index to 1 , lets see what I will get

nocturne quail
twin juniper
#

During runtime

nocturne quail
twin juniper
nocturne quail
# twin juniper Okay. Keep it up 😊

this is the actual problem

AMyPlayerControllerBase* MyPlayerControllerRef = Cast<AMyPlayerControllerBase>(UGameplayStatics::GetPlayerController(GetWorld(), 0));

changing the index to 1 now the client two is the pawn owner

twin juniper
#

Why need Character and even if you need it can't character get it from PC?

nocturne quail
#

I need to avoid using UGameplayStatics but don't know how to get the ref to PC

nocturne quail
twin juniper
#

In the case it's working fine, how do you decide which PC calls this func?

#

You know how to check CallStack in VS?

#

I meam you wrote the code but still

nocturne quail
#

maybe I need to store all the pc indexes in an array and process it

#

switch may help

twin juniper
#

You know about architecture and design?

#

This is not the right way of thinking

nocturne quail
#

OFC

twin juniper
nocturne quail
#

first I need it to work , later will find a better solution

twin juniper
#

Can you tell me how do you decide which PCs call this function?

twin juniper
#

But you are missing the point

#

You don't need to do something you don't need to

twin juniper
nocturne quail
nocturne quail
twin juniper
#

The case in which it is working correctly?

nocturne quail
#

yes

#

pc got direct ref to current pawn

#

but If I want to get that current pawn from pc using character class, this is not working

twin juniper
#

And it is replicated by default

#

What you can do is get all actors of class PC on server

#

And do whatever you are trying to do there?

#

Does that work for you?

#

If it gets called on every client's PC then you don't need to select any PC in particular

nocturne quail
#

the problem is this line
AMyPlayerControllerBase* MyPlayerControllerRef = Cast<AMyPlayerControllerBase>(UGameplayStatics::GetPlayerController(GetWorld(), 0));

if the index is 0, any client will drop item for the pawn related to this index

#

ex: if I print location of the current pawn from Client two, it will print the location of the first client

twin juniper
#

Take a minute to think

nocturne quail
#

so if I drop anything in the level using second client, it will go to the location of first client stored at index 0

nocturne quail
#

I will try to work on it

twin juniper
#

Like getting their names

#

Server and all the clients

nocturne quail
#

I just spawned an item from the client two to the location of client two.
but the item spawned on the location of client one.

twin juniper
#

You need to pass the PC reference to server

nocturne quail
#

if I set this index to 1
AMyPlayerControllerBase* MyPlayerControllerRef = Cast<AMyPlayerControllerBase>(UGameplayStatics::GetPlayerController(GetWorld(), 1));

the client two spawn item to its own location and client one will spawn to the location of client 2

twin juniper
#

Atleast that's how I solved this problem

#

I just pass the PC reference as parameter in RPC call

#

I thought you were trying to print name of all the PCs in the game

nocturne quail
#

the issue is the index

twin juniper
#

For dropping items tho I will just call the spawn item function with spawn location

twin juniper
nocturne quail
#

but it was just for testing

twin juniper
#

See rather than PCRef->MyFunc(), you can also do MyFunc(PCRef)

nocturne quail
twin juniper
nocturne quail
latent heart
#

This all sounds terrible.

nocturne quail
twin juniper
nocturne quail
#

now to trying to implement it

nocturne quail
#

but I am not sure it will work

#

I can give it a try

twin juniper
#

I thought that using index 0 with Getworld to get PC gave the PC of current character

#

Never ran into problem with this though

#

You can try and let me know

nocturne quail
#

Ok

latent heart
twin juniper
latent heart
#

Client to server?

twin juniper
latent heart
#

Every client to server RPC must already happen on a client-owned actor.

#

So why do you need to also send the client's PC?

#

Since no other PC will be available on a client.

#

It must be that their own one.

#

I just don't see why it's necessary...

twin juniper
#

Once the RPC is executed how do you get a reference to calling client?

latent heart
#

It will be the object it is execute on on the server.

#

E.g. you have basically 3 options - A client's PC, PS or Pawn.

twin juniper
#

Yes, i agree

latent heart
#

All 3 of them uniquely identify the client.

#

And can be used to get the other.

twin juniper
#

Okay so you get the character's PC directly?

latent heart
#

In what situation?

#

If client 3 run's a server RPC on his character, it will be triggered on that character on the server. That character then just needs to do GetController() and they have the correct player controller.

twin juniper
latent heart
#

It's stored on the character...

#

Character <-> player controller <-> player state

twin juniper
#

Oh, Okay. I'll check once again. Maybe I didn't consider that at that time.

#

TY for correcting me.😊

boreal bison
latent heart
#

OnReps don't work client to server.

#

If a user interacts with their inventory, it should send a server rpc to the server to tell the server what it's doing. And possibly for it to say "no".

#

Or to even ask the server if it is allowed before doing it.

sinful tree
boreal bison
#

Yeah, I have a ton of validation that happens all server-side before any claiming or stealing is done, although right now the stealing and moving items around the inventories is a bit buggy - only works some times and I'm not sure why

#

so I'm taking a break to try to represent it visually in the hopes that it'll help me track down the issue if I can see things more clearly

#

that said, I think I do have the adding of words to the inventory as a server to client rpc after all the validation

#

should I just keep it all on the server?

woven bramble
#

Guys why no one using "HandleStartingNewPlayer" to spawning character?? less tutorial, less information

nocturne quail
#

so PlayerState is the replicated extension of PlayerController and PlayerController is not replicated to other clients other then local machine?

nocturne quail
#

this ref is casted in character class, so now I get the correct possessed pawn

sinful tree
# boreal bison should I just keep it all on the server?

It should all be handled on the server. There is no need to send a client RPC if you're using OnRep variables as when you change the values on the server, the OnRep will be called on clients which can perform any necessary visual updates based on the newly received value.

boreal bison
#

Holy, I think correcting my code by handling it on the server just fixed a really annoying bug I was having where elements of an array were not all being passed to the client

#

by not passing it to the client anymore, I stopped dropping array elements

#

yippeeeeeeee

sinful tree
#

noice

boreal bison
#

okay so the main thing now is the inventory widget only shows up for the listen server and then I still need to implement this onrep stuff

#

so the inventory variable is on the playerstate, and when I call the UpdateInventoryUI event dispatcher onrep, nothing happens

#

but when I call it just in the logic it works

#

i.e.

#

this is on the gamestate and correctly calls the player who owns the inventory's UI to update

#

but doing this on the playerstate doesn't seem to do anything

#

and the I have the added issue of the widget itself not updating at all on remote clients

#

the inventory ui widget is created like this

nocturne quail
# twin juniper This doesn't say anything

Working solution is:

void AMyPlayerControllerBase::FindCurrentlyPocessedPawn()
{
    AMyCharacterBase* MyCharacterRef = Cast<AMyCharacterBase>(GetPawn());
    PrintLogScreen("Name: %s", 30.0f, FColor::Green, *GetNameSafe(GetPawn()));
    PrintLogScreen("Location: %s", 30.0f, FColor::Green, *GetPawn()->GetActorLocation().ToString());
}

void AMyCharacterBase::PressedOneKeyEvent()
{
    AMyPlayerControllerBase * MyPlayerControllerRef = Cast<AMyPlayerControllerBase>(GetController());
    MyPlayerControllerRef->FindCurrentlyPocessedPawn();
}

Now it prints the correct name and location of the currently pocessed pawn πŸ₯³

sinful tree
boreal bison
sinful tree
#

And the BP_Tile are replicated actors, yea?

boreal bison
#

correct

sinful tree
#

Ok, so then the problem is likely your UI is not bound to the correct playerstate.

boreal bison
#

How would I check/fix that?

sinful tree
#

How are you finding the playerstate to begin with? Are you just going through the Player Array? Are you getting a reference to the specific player when displaying their UI?

boreal bison
#

So I'm actually getting the playerstate initially from the UI, they submit an answer through an OnTextCommit

#

it calls OnSubmitAnswer on the playercontroller

#

which goes to the gamestate

#

the playerstate reference has worked for other UI related things like visually updating the score of the player

sinful tree
#

Ok, we're two players in a game.
You submit your answer, how does my UI know your playerstate?

boreal bison
#

It doesn't?

sinful tree
#

So if my UI doesn't know your playerstate, how can I see what your inventory looks like?

boreal bison
#

Do you mean for the stealing? Or for mousing over and pulling up inventories

sinful tree
#

Either.

#

If at any point, I need to know your playerstate to look up your inventory.

boreal bison
#

The stealing is handled on the server, I store each tile with its corresponding owner with a BP_Tile : Playerstate map whenever a tile is claimed or stolen

#

so one of the validation checks is if the tile is on the board, if it's not, then the logic checks the map to see who owns it, then steals it from the player by reassigning the owner

#

i.e. readds the BP_Tile key with the new playerstate as the value

#

for mousing over and pulling up inventories visually, I have no idea how to do that πŸ˜…

#

that's something I want to add

#

I was hoping that a UI element could hold a reference to a specific player that you could access when you mouse over it

sinful tree
#

Just a moment ago, you said:
"and the I have the added issue of the widget itself not updating at all on remote clients"

The widget is local to a client. How are your remote clients seeing the data at all if they do not have a reference to the playerstate where the data is stored?

boreal bison
#

As of now they can only see their own inventory

#

well, the listen server can see their own inventory

#

when I successfully claim a word, it gets added to the ListView

#

as Player 0

#

but as the other players that doesn't happen

#

players cant currently see into other players inventories yet

#

so stealing is based on just remembering who claimed which tiles

#

basically the next feature is to visually represent all the things that are functioning correctly on the backend

woven bramble
#

Guys what do you think about that? This system works, but I wonder if I will have problems in the future? (The Respawn is SpawnActor > Posses etc)

sinful tree
#

Playerstate is instanced per player, so each player has their own PlayerState actor running. That means each player has their own Inventory variable, each their own OnRep for the Inventory variable, and each their own Event Dispatcher.

Your UI, which again each player would have their own local instance of, would need to bind to the event dispatcher of the specific player you're wanting to view in order to properly display data for other players. So when you say "Your UI is not updating at all on remote clients" how do you know you are binding to the appropriate playerstate where the data is being changed? You still haven't clarified this as your UI is showing you have a reference to a playerstate, but you haven't shown which playerstate your UI is using.

Perhaps it is also me misunderstanding. What I am interpreting what you meant by your issue is you're having your clients attempting to all look at one particular playerstate to see the change, but if they aren't looking at that particular playerstate, then they won't see it. Either way, if you put a print string on the OnRep Inventory immediately after your Call On Inventory Update, then you should see it print after you've changed the inventory of any player and it should print multiple times based on the number of players in the game. That'll indicate that the OnRep is indeed working, but it has to do with how your UI is binding to the dispatcher on the correct PlayerState. @boreal bison

sinful tree
woven bramble
boreal bison
# sinful tree Playerstate is instanced per player, so each player has their own PlayerState ac...

Thank you for this, I'll see what the print statement yields. I think it's also partly me crossing streams with what I'm trying to explain. In the game, my intention is to visually show the player's inventory to themselves in the top left at all times. It should update whenever they claim a word, and whenever someone steals letters from them. In addition, I want players to be able optionally scout out other inventories for letters they might want to steal.

Right now, the issue is just that the logic for submitting an answer and seeing the word pop up in the player's inventory only works for the Player 0, the listen server. The listen server submits a word, and if its valid you immediately see it populate the inventory. When a remote client submits a word, the same does not happen. All my playerstate references in the UI I'm getting from Get Owning Player:

#

that's the whole Main UI blueprint

#

and the part of the controller related to the UI:

sinful tree
#

And the "Handle Answer Submission" event on the GameState eventually calls the "Claim Tiles" function?

boreal bison
#

correct, after many validations to make sure the word is a playable word

#

So when stealing happens, the onrep is correctly being called on the two players

#

when hooked up to the event dispatcher it's just seemingly not running the logic it would when it's being called from the gamestate

sinful tree
#

You don't want the gamestate to call the event dispatcher as it's only running on the server. You want the event dispatcher being called when the OnRep happens.

boreal bison
#

yeah, I hooked it up to the onrep

#

and then threw a print statement here

#

which is not getting called

woven bramble
#

Guys, why is there a need to make RunOnServer in GameMode? GameMode not already running on Server? So the client cannot access it.

#

that's right?

quasi tide
#

There isn't a need.

sinful tree
# boreal bison and then threw a print statement here

Which can go back to what I was just saying - the widget is binding to a specific playerstate's event dispatcher. If you're seeing the OnRep fire twice (via the Print String you put on the OnRep) then you'll probably only ever see one "Updating Inventory" in the bound widget. If it's not firing in the widget, that means it's not the PlayerState you're expecting.

woven bramble
#

Meanwhile, what is the order of priority when starting the server? So does GameMode start first or PlayerController? etc.

boreal bison
#

Maybe I'm confused about this widget binding to specific playerstate's event dispatcher stuff

sinful tree
#

It could also be because you're creating your widget too soon. The client creates a local playercontroller and playerstate before the replicated versions come in and the PlayerState that you bound to may no longer be valid. To test this, put like a 2 second delay in the OnConstruct in the widget before doing anything.

boreal bison
#

but it didn't work on the listen server this time lol

woven bramble
woven bramble
# sinful tree

I need some things in the PlayerController (which I saved earlier) to start some things in GameMode. So on every startup I access the PlayerController.
Wouldn't this be a problem if Game Mode starts before PlayerController?

sinful tree
# woven bramble I need some things in the PlayerController (which I saved earlier) to start some...

GameMode must exist before PlayerController as the Game Mode defines which PlayerController to use. When a client is joining, they have a local playercontroller and playerstate that are overwritten by replicated copies.
GameMode also has it's own sequence of things it does when a player joins the game.

The main ones in relating to players are (in no particular order):
PreLogin (Called when a player first attempts to join)
GetDefaultPawnClassForController (Reads the default GameMode pawn class, otherwise you can override this function to provide a different pawn class programmatically)
ChoosePlayerStart (Attempts to find a playerstart based on some saved StartActor, otherwise uses FindPlayerStart)
FindPlayerStart (Attempts to find the first appropriate playerstart, otherwise you can override this function to find an appropriate one yourself)
HandleStartingNewPlayer (This is usually where the player controller's pawn is spawned, but it is not necessarily available for RPCs)
OnPostLogin (This is supposed to be the first point at which an RPC can occur)

So, if you don't want the GameMode to handle spawning, you probably want to override HandleStartingNewPlayer, and you can use OnPostLogin, but in doing so, you're having to also handle the spawning location yourself too.

Regardless of the method, using a delay in any of these processes is a bad idea as these events are not instanced, so each subsequent call will override the previous call as I mentioned before. You have to let it flow. You can prevent things from happening by overriding events and then call your own events when you need to so long as you're handling what these functions would be doing, but a delay will break how it all works in this case.

woven bramble
boreal bison
fluid summit
#

Hi everybody! one question about level streaming, it seems like I have a misconception about how it works.

Is it possible with level streaming (or possible at all) to have a multiplayer session where players switch between levels, but still keep the same session?

Use case: Table top game with a world map, but players can "enter" each tile and that creates a level like maps of path of exile.

Currently i'm just using the same level for everything and creating/destroying things when needed and placing the maps on different and distant places of the world, but having separated levels for each map would be great

thin stratus
# fluid summit Hi everybody! one question about level streaming, it seems like I have a misconc...

Kinda but also not. LevelStreaming is mainly for loading and unloading parts of your level on demand while having a persistent level that never changes.
UE multiplayer, by default, does not support clients on different maps. You could load and unload the dungeons though to save resources and you can also spawn a level instance multiple times, but that would need to be in a different locations cause they would otherwise visually overlap.

You can control who sees what for replicated actors via IsNetRelevantFor, but you would ultimately run into situations where the server still handles collision between players that are supposedly in two different instances of the same dungeon.
UE networking doesn't reallllly support the idea of Diablo/PoE I think.

#

At least I haven't seen it being done yet I think. And I think there would be a lot of problems to fight

fluid summit
dark edge
#

Town/Base is in the sky, level is on the ground

#

There only can ever be one level/dungeon loaded up at a time, so players in the party can be back at base or on the ground, but never in 2 level/dungeons at once.

sinful tree
# boreal bison So the delay has the update inventory working for the remote clients, but not th...

The appropriate implmentation would be to override OnRep_PlayerState in something like your controller in C++ and have it execute a function or have it call a dispatcher of its own so that you know that your PlayerState has been appropriately replicated before attempting to bind to it.

As far as the event dispatcher not working on the listen server, I'm not sure what to say. If you are binding to the appropriate player state's event dispatcher, then it should work, delay or not.

boreal bison
#

What I found is that player 2 this works

#

player 1 (playerstate 0) the cast fails

#

any idea why?

#

btw this event is being called onrep

dark edge
#

What are you trying to do here, is the owning client special or do you want all machines to update something when the data changes?

boreal bison
#

I forgot to set it to not replicated. Basically I’m trying to update a UI element that references a replicated variable on each player state (their inventory). It works correctly for the remote client but for some reason not the hosting player

dark edge
#

Show your code as it is now with the RPC removed

boreal bison
twin juniper
nocturne quail
# twin juniper What? PlayerState holds data about specific player. It is replicated by default....

ShadowRiver Says
PlayerState is extension of PlayerController, main diffrence is that PlayerState is replicated, PlayerController is not. PlayerController is not replicated for security reasons, if PlayerControllers information would be contained in client memory there risk it could be manipulated, it a open window for cheat software, best example is GTA:SA multiplayer mod which fully synchronizes clients without any safety measures (since GTA:SA is not really made for multiplayer), typical single player hacks are normally replicated to other clients there. Thats why PlayerControllers are only on server side and they control pawns on server which later are replicated to clients. PlayerState is where you place information from PlayerController that you want to be replicated to all clients, but server should not relay on that information, so you just copy information that clients need to know.

Same thing with GameMode and GameState

twin juniper
#

If I understand it correctly, he means that without security concerns you would rather have them in a single structure and have them replicated to client.

latent heart
nocturne quail
#

he is saying we should use Player state not pc to store client rep data

twin juniper
#

They are complementary

twin juniper
#

Tho

#

If it is spawned on server

latent heart
#

The fact that the PC is repliacted only to the owning client is true. And that PS is replicated to everyone.

#

But just about everything else is wrong :/

twin juniper
latent heart
#

State vs controller is about function, not security

#

If you want stuff to not replicate to other clients, you can still put it ont eh PS.

#

You just tag it as teh owning client only.

twin juniper
sinful tree
#

No. PC is. PS replicates to all.

twin juniper
twin juniper
latent heart
#

But you can't do taht.

#

Because you don't have a reference to the PC of any other charaters.

#

You could pass another player's PS or Pawn.

twin juniper
#

On server?

latent heart
#

On server, sure, they all exist, but you wouldn't be calling an RPC on a server.

#

And if you were, it would fail because not all teh clients would have the PC you were sending.

twin juniper
#

I need to check again. I am all burnt out.

boreal bison
#

it's called onrep in the playerstate

#

the inventory variable gets altered in the gamestate where words are added here:

sinful tree
#

It's going to fail because when it's being called, it's on a specific playerstate, and player controllers do not replicate, so you can't get the controller of the playerstate.

boreal bison
#

or subtracted here:

boreal bison
sinful tree
boreal bison
#

the cast I mean

#

and it updates the UI element

sinful tree
#

That means it'll only ever change for that particular player, and no one else when you're changing the value on that particular playerstate.

nocturne quail
#

how to get rid of UGameplayStatics I mean how to cast to character without using UGameplayStatics in the usual actor class?
I don't want to get player by index.

void APickupBase::OnOverlapBegin(class UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
    ACharacter* PlayerCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
    if (AMyCharacterBase* MyCharacterRef = Cast<AMyCharacterBase>(PlayerCharacter))
    {
        if (OtherActor == MyCharacterRef)
        {
            On_BeginOverlap.Broadcast(this);
            EnableOutline(true);
        }
    }
}
boreal bison
twin juniper
latent heart
#

Honestly if it works, it works.

#

If it's just client->server->client communication, passing the client's PC isn't going to fail. It's just not needed.

twin juniper
sinful tree
latent heart
twin juniper
boreal bison
latent heart
boreal bison
#

It’s succeeding on the remote client

twin juniper
boreal bison
#

so the code after the cast runs and updates the client’s UI but it doesn’t run for the host so the host’s UI doesn’t update

latent heart
#

Are you somehow changing your player state manually?

quasi tide
#

Honestly if it works, it works.
Daekesh

Ah. I would definitely not hire you if you did that πŸ˜›
Also Daekesh

🀣

boreal bison
latent heart
#

Lesson learned, learn other things!

twin juniper
sinful tree
#

Technically, it should work just fine on clients so long as it is their playerstate.

latent heart
#

UI will only exist on the client.

boreal bison
whole pine
#

i have an issue where playfab is sending to a get field node, the account info the user thats logged in and setting a variable so i can bind it to text in my player inventory but it dissappears randomly and periodically, do you think thats playfab being inconsistant or my code being trash. if i cant figure it out im gonna try to get the entered text from when they type in the username box on login and convert that to a variable maybe? then replicate it so other people can see it?

sinful tree
boreal bison
#

yeah I have no clue what is different about my setup. there are situations where only one inventory should be updating rather than two players’, so in those cases I don’t know why the cast would fail

#

because changes to the inventory don’t always involve stealing from another player’s inventory

dark edge
#

I haven't considered doing Unreal as a job as it'd probably be a pay cut from what I've heard about entry level gamedev stuff but I'd entertain offers.

boreal bison
#

on the remoteclient it's printing Player Controller 0 which you would expect as its run locally

#

on the host it prints out nothing

#

so get player controller on the host is returning nothing

#

Player 2:

#

Player 1:

sinful tree
#

You're misinterpreting what is happening.
When you see Client1: that means it's the client running the code. The cast can fail on a client as they don't have access to all player controllers.

#

It may be the host's player state, but it's the client's copy of the host's playerstate, and you're trying to get the player controller of that playerstate which you cannot as the client wouldn't have access to the host's playercontroller (hence why it fails).

#

A bit more for additional clarification:

You as host, have a PlayerState. I as a client have a PlayerState. These are both replicated. Therefore we would both have 2 playerstates on either of our machines. One is mine, one is yours, but in total there are 4 that exist - your 2 copies and my 2 copies, but one for each player in the game.

You as host, have a PlayerController. I as a client have a PlayerController. PlayerControllers are only replicated to the owning client. As host, you must see mine as you're the one in control of the game, so you have 2 PlayerControllers, one for me, one for you. I as a client however, only receive my PlayerController, and if I try to reference yours, I don't have a reference to it as it's not replicated to me. In total there will be 3 copies of the PlayerController, 2 that exist on your computer, one for me and one for you, and I have only 1 on my computer which is my PlayerController.

So if I receive instructions to run "Update Inventory" on your PlayerState, which would happen if your OnRep triggers because the inventory value on your PlayerState changed and you call the "UpdateInventory" event in your OnRep, when I attempt to get your PlayerController from your PlayerState, I have nothing available about your PlayerController, so casting nothing to BP_PlayerController = failed cast.

You as host however, also receive instructions to run "Update Inventory" the same way, but in your case, since you are in control of the game and you have a copy of my PlayerController, when you do GetPlayerController on my playerstate, you can still get a reference to my PlayerController as it exists on your end.

drifting stirrup
drifting stirrup
obtuse field
#

Is there something like PostReplicatedRemove for FastArraySerializerItem? I need an event that would be called after the item is removed

dark edge
#

That's my day job

#

@boreal bison

#

as a client, you only have your own playercontrller

fossil spoke
drifting stirrup
#

sounds like a shitty career in general but you'll have the skills to make what you really want if theres something in mind

obtuse field
pure elm
#

Quick question, if I made a multiplayer game in blueprints using create advanced session/join advanced session (advanced session plugin) would it work when I package it? Like if one person creates a session and another person from another city launches it, would he be able to join the session?

#

If not, how would I go around creating something that will do that?

wheat niche
#

hello how can i check if steam is running?

woven bramble
#

Guys, how can I add a delay inside the RepNotify func?

kindred widget
kindred widget
kindred widget
kindred widget
drifting stirrup
#

well i commonly hear about it

#

arent there no unions for game devs

woven bramble
pure elm
#

I mean, what node do I use?

kindred widget
kindred widget
#

If memory serves, the plugin has a readme or something that should go over basic testing setup.

pure elm
#

Ok thanks πŸ‘

woven bramble
wheat niche
runic plover
#
--Weapon.h--
UPROPERTY(EditAnywhere, ReplicatedUsing = OnRep_Ammo)
int32 Ammo;

UFUNCTION()
void OnRep_Ammo();

void AWeapon::AddAmmo(int32 Amount)
{
    Ammo = FMath::Clamp(Ammo + Amount, 0 , MagCapacity);
}



--CombatComponent.cpp--

void UCombatComponent::Reload()
{
    if (CombatState != ECombatState::ECS_Reloading)
    {
        ServerReload();
    }
}

void UCombatComponent::ServerReload_Implementation()
{
    Weapon->AddAmmo(1);
    
}

bool UCombatComponent::CanFire()
{
if(Weapon->Ammo <= 0) return false;
return true;
}
``` i have these functionalities, where when i press the R Key i call the Reload() Function and try to increase the Ammo Value, on the server it works, if im the client it says that it got replicated but if i call CanFire() it returns false, i tried printing the Ammo Value, if i print it on server after Reload() it says "1", if im the Client it prints "0"
latent heart
#

Does OnRep_Ammo ever fire?

#

Also your CanFire method could just be return Weapon->Ammo > 0;

#

Though I would do return Weapon && Weapon->Ammo > 0;

keen axle
#

Hey there, just managed to spawn ai cars that are simulated on client. Now I would like to destroy them when the client disconnects. Is there any way to do this?

#

Normally the ai cars turn their ownership back to the server, which btw does not call the SetOwner event....

runic plover
# latent heart Does OnRep_Ammo ever fire?

i put a UE_LOG inside OnRep_Ammo to test, it does print the Log and the correct value of "1", so i guess it does fire OnRep_Ammo, but afterwards the Value returns to 0

latent heart
#

Find in your code where Ammo is being set. Add a breakpoint and/or log to that place and have it trigger only on the client (GetWorld()->GetNetMode() == NM_Client) and see if anything else is setting it.

pure elm
kindred widget
pure elm
#

It does not seem to fail, however, no sessions are found which is strange

#

This is my code for hosting the server

#

And this is for joining