Jump to content

[SOLVED] Writing a component that interacts with both the client and server


Recommended Posts

I wrote a mod, tested it and it worked. Then I realized I forgot to test it on a remote server (so I was acting as host rather than a remote client). Queue remote server testing via a world with caves and lots of things broke. After a lot of delving into networkclientrpc.lua and trying to rip off blinkstaff.lua + staff.lua to no avail, I figured I'd save myself the headache and come ask just what I'm missing which should be obvious.

Quote

Night Battle Idiot
-Deals and receives 50% more damage at night. Deals 25% less damage during the day.
-Moves 50% faster at night.
-Damage and speed buffs are halved for dusk.

Ninja
-Evasion chance of 10%.
-Double tap to teleport a short distance.

Nocturnal
-Sanity regen at night. Sanity drain per action during the day.
-Cannot sleep at night. Can sleep during the day. Siestas are still available only during the day.
-Nightvision. Looks like a full moon every night (can't die to Charlie).
-Sanity regen is halved at dusk.

This is the planning sheet for how the character is supposed to work. Right now, I have the Night Battle Idiot part more-or-less working as intended. Ninja's dash/teleport is broken on the server side (it rubberbands you back to your original location but you teleport on the client side). Sleeping in the day works as intended. Nightvision doesn't work on either side even though I think the client is also running the inst.components.playervision:ForceNightVision stuff.

As for stuff I've tried, mostly in regards to the dash:

  • Running an RPC in the modmain.lua file that used a ListenForEvent in AddPostPrefabInit to start it off via a PushEvent("dashed"). As far as I could tell, the server was getting the command but it wasn't doing anything. The command in the RPC was caster.Physics:Teleport(pt:Get()), with both passed via the event.
  • Moving the AddComponent("dasher") stuff around through the different initialization function (ie. common_postinit and master_postinit). I thought about separating the visual parts from the working parts and splitting those between the client and server but I'm not getting an error on either side so I don't think that's the issue.
  • Adding TheWorld.ismastersim checks around the place. Mostly pointless but I had to try.

The functionality is in a component mostly to make it easily to "drag, drop and go" for other modders. I hope that making the mod functionalities into components will inspire people to use my components in their own mods to make some cool things (which would also hopefully be of the same genre so I can play more KanColle characters). If possible, I'd like to maintain it as a component but it's fine if that's impossible.

scripts.zip

Edited by Yabumi
Link to comment
Share on other sites

The problem is that I can't figure out how to get the server to also update the player's location.

In the components/dasher.lua file, I have a function Dasher:Dash. This function with the OnDashed function should teleport the player a short distance in the direction of movement. As it is right now, the code applies client-side so you appear to warp but any further movement rubberbands back to the original location. That is to say, you end up where you started performing the dash.

As for how I've tried it, I added these lines to my modmain.lua file originally:

local function RPCTeleport(pt, caster)
  caster.Physics:Teleport(pt:Get())
end
AddModRPCHandler(modname, "RPCTeleport", RPCTeleport)

local function OnDashed(data)
  SendModRPCToServer(MOD_RPC[modname]["RPCTeleport"], data.pt, data.caster)
end

AddPrefabPostInit(function(inst)
  if not TheWorld.ismastersim then
    inst:ListenForEvent("dashed", OnDashed)
  end
end)

This was supposed to be triggered by the line in components/dasher.lua:

self.inst:PushEvent("dashed", { pt = pt, caster = caster })

 

Edited by Yabumi
Link to comment
Share on other sites

8 minutes ago, Lumina said:

Maybe you could take a look at webber frog for the "teleport" part ? It's a leap in the mod but i guess it could help to see how to travel server side ?

I'll check that out right now.

EDIT: It looks like it's all done via the stategraph. I originally skipped over that option because I don't have an action that utilizes any of the 5 (ie. SCENE, USEITEM, POINT, EQUIPPED or INVENTORY), so I don't think I can add to the actions table.

Edited by Yabumi
Link to comment
Share on other sites

The RPC takes a "hidden" first argument which is the "player" sending the request.

Try

local function RPCTeleport(player, pt, caster)
  caster.Physics:Teleport(pt:Get())
end
AddModRPCHandler(modname, "RPCTeleport", RPCTeleport)

local function OnDashed(data)
  SendModRPCToServer(MOD_RPC[modname]["RPCTeleport"], data.pt, data.caster)
end

AddPrefabPostInit(function(inst)
  if not TheWorld.ismastersim then
    inst:ListenForEvent("dashed", OnDashed)
  end
end)

You should try to put print function when debuging RPC to check that the arguments are where and what you expect them to be.

 

EDIT: About the actions, you can add custom actions if you want

Edited by ZupaleX
Link to comment
Share on other sites

 

5 hours ago, ZupaleX said:

You should try to put print function when debuging RPC to check that the arguments are where and what you expect them to be.

I did do this before I posted the thread. The problem was that I was getting nothing printed in the server logs that even indicated that the RPC had been run at all.

Here is in-game: http://prntscr.com/fwksw8

Here is the server log after disconnecting:

[00:00:21]: New incoming connection 127.0.0.1|56980 <13598583758756611349>
[00:00:21]: Client connected from [LAN] 127.0.0.1|56980 <13598583758756611349>
[00:00:21]: ValidateGameSessionToken pgs-usc^KU_2DNgIYVr^DontStarveTogether^pKP3figVY24xDabhgZExC8/GO4nwxeQugbq5WjWAlSA= for <13598583758756611349>
[00:00:21]: Client authenticated: (KU_2DNgIYVr) 保登 心愛
[00:00:21]: [Steam] Authenticated host '76561198057306696'
[00:00:22]: [Shard] Read save location file for (KU_2DNgIYVr)
[00:00:33]: Resuming user: session/6DA1AAC62AB5194B/A7G8QNL4K9VL/0000000027
[00:00:33]: Spawning player at: [Load] (83.00, 0.00, -73.51)	
[00:00:33]: Sim unpaused
[00:01:15]: [Steam] SendUserDisconnect for '76561198057306696'
[00:01:15]: [Shard] (KU_2DNgIYVr) disconnected from [SHDMASTER](1)
[00:01:15]: [IPC] Received shutdown signal.
[00:01:15]: Serializing user: session/6DA1AAC62AB5194B/A7G8QNL4K9VL/0000000028
[00:01:15]: Serializing world: session/6DA1AAC62AB5194B/0000000028
[00:01:15]: Truncating to snapshot #28...
[00:01:15]:  - session/6DA1AAC62AB5194B/0000000022
[00:01:15]:  - session/6DA1AAC62AB5194B/A7G8QNL4K9VL/0000000022
[00:01:15]:    2 file(s) removed
[00:01:15]: unloading prefabs for mod MOD_workshop-375850593	
[00:01:15]: unloading prefabs for mod MOD_workshop-709198071	
[00:01:15]: unloading prefabs for mod MOD_workshop-347079953	
[00:01:15]: unloading prefabs for mod MOD_workshop-666155465	
[00:01:15]: unloading prefabs for mod MOD_sendai	
[00:01:15]: unloading prefabs for mod MOD_workshop-356930882	
[00:01:15]: unloading prefabs for mod MOD_workshop-898070061	
[00:01:15]: unloading prefabs for mod MOD_workshop-378160973	
[00:01:16]: [Shard] Stopping shard mode
[00:01:16]: Collecting garbage...
[00:01:16]: lua_gc took 0.21 seconds
[00:01:16]: ~ShardLuaProxy()
[00:01:16]: ~ItemServerLuaProxy()
[00:01:16]: ~InventoryLuaProxy()
[00:01:16]: ~NetworkLuaProxy()
[00:01:16]: ~SimLuaProxy()
[00:01:17]: lua_close took 0.47 seconds
[00:01:17]:  Manager - ORPHANED UNKNOWN RESOURCES:
[00:01:17]: shaders/ui_yuv.ksh - 1
[00:01:17]: CurlRequestManager::ClientThread::Main() complete
[00:01:17]: HttpClient2 discarded 0 callbacks.
[00:01:17]: Shutting down

I only included from the connection to the end.

Here are the lines I have in the files atm:

local function RPCTeleport(player, pt, caster)
  print("SERVER RECEIVED THE RPC WITH VALUES:")
  print(player)
  print(pt)
  print(caster)
  caster.Physics:Teleport(pt:Get())
  print("SERVER EXECUTED THE TELEPORT")
end
AddModRPCHandler(modname, "RPCTeleport", RPCTeleport)

local function OnDashed(inst, data)
  print("SENDING RPC TO SERVER WITH DATA:")
  print(inst)
  print(data.pt)
  print(data.caster)
  SendModRPCToServer(MOD_RPC[modname]["RPCTeleport"], data.pt, data.caster)
  print("RPC SENT TO SERVER")
end

EDIT: I popped open the client_log.txt file after expecting it to look the same and instead found a line that's different. I can't find the error anywhere in the networkclientrpc.lua file though (or in any other file for that case).

[00:00:50]: SENDING RPC TO SERVER WITH DATA:	
[00:00:50]: 100035 - sendai	
[00:00:50]: (80.24, 0.00, -66.70)	
[00:00:50]: 100035 - sendai	
[00:00:50]: Invalid RPC data type <--- This right here
[00:00:50]: RPC SENT TO SERVER	

 

Edited by Yabumi
Link to comment
Share on other sites

I got the dash working. It had a few weird issues that I didn't notice when I first wrote this thread...and I apparently was really close to having it done correctly at that point. For the record, this is how I did it in the end:

-- In modmain.lua
local function RPCTeleport(player, x, y, z)
  player.Physics:Teleport(x, y, z)
end
AddModRPCHandler(modname, "RPCTeleport", RPCTeleport)

local function OnDashed(inst, data)
  local x, y, z = data.pt:Get()
  SendModRPCToServer(MOD_RPC[modname]["RPCTeleport"], x, y, z)
end

AddPlayerPostInit(function(inst)
  if not TheWorld.ismastersim then
    inst:ListenForEvent("dashed", OnDashed)
  end
end)

-- In dasher.lua
self.inst:PushEvent("dashed", { ["pt"] = pt })

It's not said directly, but it would appear that RPCs silently fail (with regards to the in-game console) if you send them a custom data type (Vector3 in this case).

A big thank you to ZupaleX for all your help. Now I just have to figure out how to make it work for nightvision.

Edited by Yabumi
Link to comment
Share on other sites

RPC don't accept any type of data. It would print in the client "Invalid RPC data type" if it doesn't like it. Table cannot be passed for instance.

It can take basic variable types like number, book, strings, and a few userdata from Klei. I don't have the exact list.

Glad you solved your issue.

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...