modding Posted October 17, 2016 Share Posted October 17, 2016 (edited) Hi. The goal: make the Finder mod fully client-side. The method: find a way to retrieve contents of visible containers, then cache the results in a tree or table structure for better performance and reducing network traffic. The question: how to get contents of containers on client side in any meaningful way. So the first thing to check is prefab.replica.container.classified of course which uses netvars to sync data. When a container is closed, classified prefab is removed and the field is set to nil, when the container is opened, a new classified prefab springs into existence and is attached to the container replica. Tracing it back on the client side leads to global ReplicateEntity function in mainfunctions.lua, which appears to be never called (from accessible lua code): modding$ grep -nwr ReplicateEntity entityscript.lua:501:-- EntityScript:ReplicateEntity() entityreplica.lua:73:function EntityScript:ReplicateEntity() mainfunctions.lua:441:function ReplicateEntity(guid) mainfunctions.lua:442: Ents[guid]:ReplicateEntity() Ok, the next option are netvars themselves. This is how they are used in container_classified.lua (corresponding event listeners are in RegisterNetListeners): table.insert(inst._itemspool, net_entity(inst.GUID, "container._items["..tostring(i).."]", "items["..tostring(i).."]dirty")) The code is pretty simple, it's not difficult to create a custom entity but for this to work one needs a way to make the server to do the similar steps and this brings us back to the classified object which exists when the container is open. I'd be opening and immediately closing containers from the code just to get the contents and cache them but then I looked for existing RPC handlers in networkclientrpc.lua. There are methods to work with already opened containers but no handler to actually open them except general ones like LeftClick handler. P. S. may be the rummage action will do if it works at distance and the data can be accessed between :Open and :OnUpdate runs P. P. S. no, it will not, doesn't work at distance Am I missing something? Edited October 17, 2016 by modding Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/ Share on other sites More sharing options...
modding Posted October 18, 2016 Author Share Posted October 18, 2016 Hey modding, I doubt that it is possible. I suggest you to make a server-side portion of code and a fallback mode for hosts without the mod installed. Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/#findComment-826465 Share on other sites More sharing options...
Serpens Posted October 22, 2016 Share Posted October 22, 2016 bump, @DarkXero do you know a way to make it work as client_only ?` Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/#findComment-828073 Share on other sites More sharing options...
DarkXero Posted October 22, 2016 Share Posted October 22, 2016 @Serpens, there is no way to make it work as a client_only_mod. Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/#findComment-828082 Share on other sites More sharing options...
Serpens Posted October 23, 2016 Share Posted October 23, 2016 (edited) @IvanX Hey, can you tell me why is it not possible to hack into your Foodcrafting widget? I made this Finder mod "all_clients_require" and added support for your craft pot mod (so hovering over eg the ingredient meat will highlight all containers with meat ) I use FoodIngredientUI OnGainFocus and OnLooseFocus for that. But if you move mouse too fast, it seems OnLooseFocus is not called. That's why I want to remove highlighting when the craft pot UI is closed. But I'm not able to hack into FoodCrafting widget... my code is: -- ### Compatible to Craft Pot Mod, to find food with the searched tags local function testCraftPot() local FoodIngredientUI = _G.require 'widgets/foodingredientui' end if GLOBAL.pcall(testCraftPot) then local cooking = _G.require("cooking") local ing = cooking.ingredients local FoodIngredientUI = _G.require 'widgets/foodingredientui' local __FoodIngredientUI_OnGainFocus = FoodIngredientUI.OnGainFocus function FoodIngredientUI:OnGainFocus(...) local searchtag = self.prefab -- tag or name local isname = self.is_name local owner = self.owner local prefabs = {} -- find all the prefabs with that cooking tag if not isname then for prefab,xyz in pairs(ing) do for tag,number in pairs(xyz.tags) do if tag==searchtag then table.insert(prefabs,prefab) end end end elseif isname and GLOBAL.PREFABDEFINITIONS[searchtag] then table.insert(prefabs,GLOBAL.PREFABDEFINITIONS[searchtag].name) end onactiveitem(owner) -- to unhighlight for k,prefab in pairs(prefabs) do -- send one prefab after the other, cause sedning an array via rpc does not work.. if prefab and owner then local rpc = GetModRPC("FinderMod", "CheckContainersItem") SendModRPCToServer(rpc,prefab) end end if __FoodIngredientUI_OnGainFocus then return __FoodIngredientUI_OnGainFocus(self,...) end end local __FoodIngredientUI_OnLoseFocus = FoodIngredientUI.OnLoseFocus function FoodIngredientUI:OnLoseFocus(...) local owner = self.owner onactiveitem(owner) -- to unhighlight if __FoodIngredientUI_OnLoseFocus then return __FoodIngredientUI_OnLoseFocus(self,...) end end -- following code does not work ?! local FoodCrafting = _G.require 'widgets/foodcrafting' local __FoodCrafting_Close = FoodCrafting.Close -- sometimes OnLoseFocus is not called if moving mouse too fast function FoodCrafting:Close(...) print("HERE finder test close") -- this is never printed and also it is not unhighligted... local owner = self.owner onactiveitem(owner) -- to unhighlight if __FoodCrafting_Close then return __FoodCrafting_Close(self,...) end end end I wonder why it is possible to hack into FoodIngredientUI, but not into FoodCrafting.... Edited October 23, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/#findComment-828379 Share on other sites More sharing options...
Serpens Posted October 23, 2016 Share Posted October 23, 2016 Just for anyone interested: Ivanx toldme to better use "AddClassPostConstruct" to "hack" into those classes and it does work Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/#findComment-828598 Share on other sites More sharing options...
Serpens Posted October 23, 2016 Share Posted October 23, 2016 (edited) Uploaded my "all_clients_require" version of the mod now. So this will work also for clients (original mod does not yet) and supports Craft Pot mod Edited October 23, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/#findComment-828659 Share on other sites More sharing options...
modding Posted October 23, 2016 Author Share Posted October 23, 2016 (edited) 18 hours ago, Serpens said: I wonder why it is possible to hack into FoodIngredientUI, but not into FoodCrafting.... Because when "Close" method is called: player.HUD.controls.foodcrafting:Close(inst.inst) It is called on the instance of MouseFoodCrafting: self.foodcrafting = self.containerroot:AddChild(MouseFoodCrafting()) Which has reference to the original method due to the way how inheritance is simulated in class.lua: elseif type(base) == 'table' then -- our new class is a shallow copy of the base class! for i,v in pairs(base) do c[i] = v end c._base = base end The hack just must be into the proper class: local FoodCrafting = _G.require 'widgets/mousefoodcrafting' Given the other code is correct, it will work (I checked it). Of course your code must be executed after Craft Pot's directory was added to package.path For anyone interested, AddClassPostConstruct uses the same wrapper approach but does entirely different thing. It wraps constructor function and __call metamethod of a class which means that your code will be executed for every instance as opposed to modification of the class itself which will serve as a shared metatable for all instances. I don't like the idea of tailoring code like this for a specific mod though. Quote sometimes OnLoseFocus is not called if moving mouse too fast Sometimes it is also called in reverse order (Gain, Lose instead of Lose, Gain). This is why I don't use it. On 10/22/2016 at 6:45 AM, DarkXero said: there is no way to make it work as a client_only_mod. Challenge accepted By the way, the game interprets "client_only_mod = true" in a manner that allows code execution for mastersim. Yes probably it will end up with server-side portion but still useful without it and not required for all clients (I avoid introducing new netvars). Edited October 23, 2016 by modding Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/#findComment-828663 Share on other sites More sharing options...
Serpens Posted October 23, 2016 Share Posted October 23, 2016 (edited) ah hi modding It sounds like you know more than me about mods, great Quote sometimes OnLoseFocus is not called if moving mouse too fast I found out this was not true. The problem was, that the RPC server calls took ~ 0.05 seconds, so the "unhighlight" command is sent before the highliting is done, when moving mouse to fast. So if craft pot is closed, the highlight is removed now, if it was highlighted by craftpot previously. Same happens for the CraftMenu, but there it is not possible to apply such a workaround, cause it is closed too fast. So if I get you right, you continue working on a "only_client_require" mod? If it works, it will be of course the best solution... but if it does not, I guess the code of my uploaded version is okay. Maybe you can take a look at it The only thing that has to be done by server, is to check the content of containers... like you arelady described in your first post, the client only knows content of opened containers... =/ edit: in case you find a solutio for client_only, please still add the support for Craft Pot Mod Because finding foods in several iceboxes is still too complicated Edited October 23, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/#findComment-828667 Share on other sites More sharing options...
modding Posted October 23, 2016 Author Share Posted October 23, 2016 (edited) 30 minutes ago, Serpens said: I found out this was not true. The problem was, that the RPC server calls took ~ 0.05 seconds, so the "unhighlight" command is sent before the highliting is done, when moving mouse to fast. If I recall correctly, both problems were present in single player version when I was testing it: reverse order of events and missing losefocus. 30 minutes ago, Serpens said: So if I get you right, you continue to working on a "only_client_require" mod? If it works, it will be of course the best solution... but if it does not, I guess the code of my uploaded version is okay. Maybe you can take a look at it Unless some pitfalls appear, I hope to make it not required for all clients at least. I'll take a look. Edited October 23, 2016 by modding Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/#findComment-828674 Share on other sites More sharing options...
Serpens Posted October 27, 2016 Share Posted October 27, 2016 (edited) @modding My all_clients_require" version had some bugs, but I think I fixed them now (also already uploaded here at klei) I also uploaded it to steam, but for now only visible for friends, so I can use it with them. But am I allowed to make it also visible to public? Edited October 27, 2016 by Serpens Link to comment https://forums.kleientertainment.com/forums/topic/70927-finder-mod-client-side/#findComment-829862 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