Jump to content

PushScreen on Client


Recommended Posts

I wanted to port just one Mod from DS to DST. As expected I found a lot of difficulties, but except for this one I could luckily manage to solve them all by myself.

 

What is happening in this mod is that a prefab has a component from which (on activation) a screen is opened via TheFrontEnd:PushScreen(...). Naturally though this pushes the screen to the server instead of the appropriate player (the activator).

I was searching through the code and could not find an instance where anything else than PushScreen was used, neither did I find any indication of "switching" to the appropriate player before pushing screens.

I also checked the screen codes themselves to see if my screen might be missing anything that could relate. Everything to no avail unfortunately.

 

Can anyone point me in the right direction?

I don't want any fleshed out code (unless necessary), just clues, maybe other mods that do something similar, etc.

 

 

If I could manage pushing the screen there I woul "just" need to send whatever happens within the screen to the server, but I have a much better idea of how to do that.

 

Link to comment
Share on other sites

Because the game doesn't switch.

Depending on the context, TheFrontEnd gets executed client side and yields the client FrontEnd.

 

A server side component will yield the FrontEnd of the host/server.

 

You don't push the screen through the net. You use something like net_event. Or replicas.

Link to comment
Share on other sites

@DarkXero, to be honest, that is still a bit to vague for me. Do you know where I could see something similar in action? I just started looking into DST modding on thursday last week, so I am not really familiar with replicas. But if that is a safe way to do it I will need to learn it I guess.

Link to comment
Share on other sites

@Malacath, example:

local function doFunc()	print("Hello!")end--clients only have their own player_classified--thus, we restrict the event to each player--if two clients have a netvar, the change will propagate to both clientsAddPrefabPostInit("player_classified", function(inst)	--both server and client need the variable	inst.pushmyscreen = GLOBAL.net_event(inst.GUID, "player.pushmyscreen")	--client needs to act on the server trigger	if not GLOBAL.TheWorld.ismastersim then		inst:ListenForEvent("player.pushmyscreen", doFunc)	endend)AddPrefabPostInit("spear", function(inst)	--server side is where the calculations are done	if GLOBAL.TheWorld.ismastersim then		inst.components.weapon.onattack = function(weapon, attacker, target)			--if the host is playing, we do the func, clients won't see the effects of it			--else, we push the event			--because only clients listen to the event, the host won't get the effects of the client trigger			if attacker == GLOBAL.ThePlayer then				doFunc()			else				attacker.player_classified.pushmyscreen:push()			end		end	endend)
Link to comment
Share on other sites

@DarkXero, cool, first and foremost thank you a lot!

I feel like my beginnings in DS modding though, so if you don't mind I will try to be more specific and ask some more question.

 

Essentially what your code does is call the function doFunc for the respective player when attacking with a spear. Good so far?

inst.pushmyscreen = GLOBAL.net_event(inst.GUID, "player.pushmyscreen")

This registeres a network event on the player classified. Using the player classified here because it is designed for this I guess?

if not GLOBAL.TheWorld.ismastersim then    inst:ListenForEvent("player.pushmyscreen", doFunc)end

This here just because we can handle the serverside call of doFunv explicitly, like you mention later.

attacker.player_classified.pushmyscreen:push()

This is "essentially" resulting in a call of attacker:PushEvent("player.pushmyscreen") on the clientside? But can I easily pass data as one would expect?

data = {target = target}attacker.player_classified.pushmyscreen:push(data)

Resulting in something like attacker:PushEvent("player.pushmyscreen", data)?

 

Then I can PushScreen in doFunc, needing to pay attention with that screen in may case because it accesses players components and what not. I guess I will need to tinker a lot here, but essentially I can just attach some more net_vars to player_classified and use those to communicate between server and client of what I need to properly represent the screen. Or is it a bad idea to clutter player_classified with more net_vers? Maybe there is some more appropriate way to do this?

Link to comment
Share on other sites

This registers a network event on the player classified. Using the player classified here because it is designed for this I guess?

 

No, that creates a class that is a wrapper of net_bool, a netvar. You can see that in netvars.lua.

net_bool is a variable that can hold 0 or 1.

Net variables are setup in both server and client to communicate.

You use netvar:set(x) to set its value and trigger the event that was defined with it.

 

Player_classified is a prefab that in the server everybody has, but in the client only ThePlayer has it.

It holds a lot of netvars, like your health and your recipes.

 

If I did AddPlayerPostInit, all player prefabs in your screen would have it.

And each would listen to the event. Unless you put another if to limit the listen to only ThePlayer instance.

 

This here just because we can handle the serverside call of doFunv explicitly, like you mention later.

 

Yes, we have to.

 

This is "essentially" resulting in a call of attacker:PushEvent("player.pushmyscreen")

 

That is "essentially" attacker.player_classified:PushEvent("player.pushmyscreen"). Not attacker.

You can reference the parent entity from player_classified though.

Still, use ThePlayer.

 

But can I easily pass data as one would expect?

 

No, you can't stamp a data in there. You will have to use another netvars to setup and pass the values you want the client to read.

 

Resulting in something like attacker:PushEvent("player.pushmyscreen", data)

 

 

No, push doesn't accept extra arguments, see netvars.lua.

 

Then I can PushScreen in doFunc, needing to pay attention with that screen in may case because it accesses players components and what not. I guess I will need to tinker a lot here, but essentially I can just attach some more net_vars to player_classified and use those to communicate between server and client of what I need

 

In doFunc you will use ThePlayer as you used for your current PushScreen, and you will put PushScreen there too.

If more information needs to be sent, then yes, more netvars.

Unless you tell what information are you taking from player components, maybe there is the info client side already.

 

Netvars are server to client information.

SendModRPC are client to server information.

No AND there.

A client can edit netvars but it will be only detrimental to him, because the server won't change its server value.

Link to comment
Share on other sites

@DarkXero, lots of "No"'s  :D

That's why it's important for me to ask. Thank you immensely for explaining me all of this! And sorry for making you explain all of this!

When I was searching I couldn't really find some of the information you gave me in such a clear language, so it really helps a lot.

 

And yes, since I am essentially recreating a crafting menu-of-sorts I am positive that I can reuse quite some existing code.

 

And to summarize in short, more for myself:

-Use the technique given up there to PushScreen on Client

-Use Netvars to properly handle all screen elements and Client interaction

-Use SendModRPC to tell the server the results of the Client interaction

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...