legman111 Posted December 24, 2014 Share Posted December 24, 2014 Hello, I'm the creator of the mod "Extended Indicators". The mod currently works fine for the host of the server however it fails to work properly for the client. I have done a lot of research into this issue and have found out various things relating to the issue. Please note that I am experienced with programming however I am new to the scene when it comes to creating mods for Don't Starve or Don't Starve Together. Link to steam workshop page for the mod: http://steamcommunity.com/sharedfiles/filedetails/?id=358749986Currently there is a maximum distance that the client computer can travel apart from other users before the server stops sending that client the information. I believe this by looking at the widget "player_common.lua" where between lines 430 and 438 it says the following. [codesyntax]-- "playerexited" is available on both server and client.-- - On clients, this is pushed whenever a player entity is removed-- locally because it has gone out of range of your network view.-- - On servers, this message is identical to "ms_playerleft", since-- players are always in network view range until they disconnect.TheWorld:PushEvent("playerexited", inst)if TheWorld.ismastersim then TheWorld:PushEvent("ms_playerleft", inst)end[/codesyntax] The comment that was provided with the code shows me that this is called for clients when leaving the "network view" however servers have an infinite "network view" which explains why it works perfectly fine on the server.There is also similar code for the player entering the "network view" between lines 262 and 275 of the "player_common.lua". The component "playertargetindicator.lua" makes use of this and between lines 15 to 37 where it makes multiple calls to "playerexited" in order to remove the target indicators. [codesyntax]local PlayerTargetIndicator = Class(function(self, inst) self.inst = inst self.offScreenPlayers = {} self.onScreenPlayersLastTick = {} -- self.recentTargetRemoved = {} self.onplayerexited = function(world, player) OnPlayerExited(self, player) end inst:ListenForEvent("playerexited", self.onplayerexited, TheWorld) inst:StartUpdatingComponent(self)end) function PlayerTargetIndicator:OnRemoveFromEntity() if self.offScreenPlayers ~= nil then self.inst:RemoveEventCallback("playerexited", self.onplayerexited, TheWorld) for i, v in ipairs(self.offScreenPlayers) do self.inst.HUD:RemoveTargetIndicator(v) end self.offScreenPlayers = nil endend[/codesyntax] Simply removing this code would not do anything as I believe the server no longer sends the X and Y positions for the players when outside the "network view" meaning even if the icon stays on screen it wouldn't be at all functional. I'm sure there are some workarounds for this issue even if it's not ideal or entirely efficient. Since the server is always aware of other player information and their positions. I thought it may be possible to make use of "TheWorld.ismastersim" or "TheNet:GetIsServer()" to detect whether the user is the host and then use a function such as "PushEvent()" in order to send the X and Y positions to the client. This may then need me to rewrite how the indicators work in order to accept information from this source. (I discovered these methods from http://forums.kleientertainment.com/topic/47353-guide-getting-started-with-modding-dst-and-some-general-tips-for-ds-as-well as well as reading through various lua scripts.) The seemingly easiest method would be to expand the "network view" of the client so that the client would never exit it and the indicators would never stop functioning. This of course would solve the issue however other issues may occur as a result. I imagine that while inside the network view the client is presented with a lot of information and if expanded to the entire world it would become highly inefficient for them. However even if this wasn't the case i'm not even sure the "network view" can be expanded as I cannot find any relating code in order to do so. I have also thought perhaps the player X and Y values can be excluded from the "network view" and would constantly be pushed to the clients emulating being inside the "network view" but only for these particular variables. It may end up being very similar to the first method that I thought about. I am not sure if it is of any additional help but I was interested in the component "playerprox.lua". This would return player positions and names depending on their position in the world. Lines 9 - 122 are particularly interesting and have been included for reference below. [codesyntax]--[[ PlayerProx component can run in four possible ways - Any player within distance, all players outside distance (PlayerProx.AnyPlayer) - a specific player within and outside distance (PlayerProx.SpecificPlayer) - as soon as a player comes within range, start tracking that one for going out of distance and then relinquish tracking (PlayerProx.LockOnPlayer) - as soon as a player comes within range, start tracking that player and keep tracking that player (PlayerProx.LockAndKeepPlayer)]] local function AnyPlayer(inst) local playerprox = inst.components.playerprox if playerprox then if not playerprox.isclose then local x,y,z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x,y,z, playerprox.near, {"player"}, {"notarget"}) if #ents > 0 then playerprox.isclose = true if playerprox.onnear then playerprox.onnear(inst, ents[1]) end end else local x,y,z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x,y,z, playerprox.far, {"player"}, {"notarget"}) if #ents == 0 then playerprox.isclose = false if playerprox.onfar then playerprox.onfar(inst) end end end endend --simply returns all near playerslocal function AllPlayers(inst) local playerprox = inst.components.playerprox if playerprox then local x,y,z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities( x,y,z, playerprox.near, {"player"}, {"notarget"} ) if #ents > 0 then if playerprox.onnear then playerprox.onnear(inst, ents) end else if playerprox.onfar then playerprox.onfar(inst, ents) end end endend local function SpecificPlayer(inst) local playerprox = inst.components.playerprox if playerprox then if not playerprox.isclose then local player = playerprox.target local distsq = player:GetDistanceSqToInst(inst) if distsq < playerprox.near * playerprox.near then playerprox.isclose = true if playerprox.onnear then playerprox.onnear(inst, player) end end else local player = playerprox.target local distsq = player:GetDistanceSqToInst(inst) if distsq > playerprox.far * playerprox.far then playerprox.isclose = false if playerprox.onfar then playerprox.onfar(inst) end end end endend local function LockOnPlayer(inst) local playerprox = inst.components.playerprox if playerprox then if not playerprox.isclose then local x,y,z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x,y,z, playerprox.near, {"player"}, {"notarget"}) if #ents > 0 then playerprox.isclose = true if playerprox.onnear then playerprox.onnear(inst, ents[1]) end playerprox:SetTarget(ents[1]) end else local player = playerprox.target local distsq = player:GetDistanceSqToInst(inst) if distsq > playerprox.far * playerprox.far then playerprox.isclose = false playerprox:SetTarget(nil) if playerprox.onfar then playerprox.onfar(inst) end end end endend local function LockAndKeepPlayer(inst) local playerprox = inst.components.playerprox if playerprox then if not playerprox.isclose then local x,y,z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x,y,z, playerprox.near, {"player"}, {"notarget"}) if #ents > 0 then playerprox.isclose = true if playerprox.onnear then playerprox.onnear(inst, ents[1]) end playerprox:SetTargetMode(SpecificPlayer, ents[1], true) end else -- we should never get here assert(false) end endend[/codesyntax] Functions such as these could potentially be used as an easier way to get the client position information and dump it to the clients. (A quick description about each function is include at the top of the code in comment form.) It would be great if someone can help me solve the problem of getting it working on the client. If you have any additional information that you could provide that would help me or other people come up with solutions or improve existing ones that too would be very much appreciated. Link to comment Share on other sites More sharing options...
rezecib Posted December 24, 2014 Share Posted December 24, 2014 (edited) i'm not even sure the "network view" can be expanded as I cannot find any relating code in order to do so.I don't believe you can, since it should be handled by the RakNet library in the C++ code. I was actually thinking of making this mod myself, but I wanted to wait for Peter's custom game mode to get an idea of custom networking. I'll come back to this, but I think the way to do it would be to have the host periodically update the clients on the absolute location of each player (it could be piggybacked onto player_classified with an AddClassPostConstruct, I believe), and pass that to playertargetindicator. Edit: Also one feature that might be nice in this mod is to only show the playertargetindicators while the scoreboard is up. That way they're not blocking UI when you're trying to do stuff, but you can bring them up on command. Not sure if you have something like this already, I haven't gone in to test it yet. Edited December 24, 2014 by rezecib Link to comment Share on other sites More sharing options...
rezecib Posted December 31, 2014 Share Posted December 31, 2014 @legman111, At least with my tests between my two computers, I've managed to get it working for clients. I kinda ripped out all the code you were using so far, so I'll have to work on adding the config options back in, but I sent you a request on Steam so we can collaborate a little more easily on it. One thing I want to look into adding tomorrow is support for campfires/firepits also showing up globally, so you can have smoke signals. Link to comment Share on other sites More sharing options...
legman111 Posted December 31, 2014 Author Share Posted December 31, 2014 rezecibThank you so much for the help, I think I was on my way to fixing it but I was finding it quite difficult to fully understand all the networking code. Now I can work on some of the features on my "To Do" list. Thanks Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now