Magic_Pro Posted March 15, 2019 Share Posted March 15, 2019 (edited) Hello there, I converted a DS mod to DST mod. It worked well with Single Play and World without Caves. But in World with Caves, something go wrong when I display my data. Sometimes, it crashes with 'nil'. Sometimes, it shows only 0 level & 0 exp. The actually data is very different when I used my commands to test. local G = GLOBAL local function GetPlayer() if IsDST() then return GLOBAL.ThePlayer else return GLOBAL.GetPlayer() end end local INFO_KEY = GetModConfigData("Show Info") --Show player level info local function GetInfo() if not G.IsPaused() then if IsDST() then GetPlayer().components.talker:Say( string.format( "Level: %d\nXP: %d/%d\nSpeed bonus: +%.4f%%", GetPlayer().components.leveluplan.levelLan, math.floor(GetPlayer().components.leveluplan.expLan), GetPlayer().components.leveluplan:XPneed(), ((2.2 - 1.003 ^ -GetPlayer().components.leveluplan.levelLan) / 1.2 - 1) * 100 ) ) else GetPlayer().components.talker:Say( string.format( "Level: %d\nXP: %d/%d\n%.4f speed", GetPlayer().components.leveluplan.levelLan, math.floor(GetPlayer().components.leveluplan.expLan), GetPlayer().components.leveluplan:XPneed(), GetPlayer().components.leveluplan.speedupLan ) ) end end end G.TheInput:AddKeyDownHandler(INFO_KEY, GetInfo) Edited March 15, 2019 by Magic_Pro Make more clear Link to comment Share on other sites More sharing options...
YakumoYukari Posted March 15, 2019 Share Posted March 15, 2019 (edited) In DST, clients and servers are separated. Clients don't have most data calculated by the server because they don't need it. So most components like leveluplan, class variables are just not existed. The only exception is when you're the host of the server hosted through the game(not dedicated) without a cave. In this case, the server and the client are the same. That is - you have to change the code from the basics. If this code is not the whole features of the mod, you need to work on re-coding about those. Read Differences chapter more carefully. At least if you want to understand this issue, it is required to understand what replica, RPC, netvars is. Please read the thread before you read below. Let's look at the code from the perspective of problem-solving. As I mentioned above, the client doesn't have information about those GetPlayer().components.leveluplan.levelLan, math.floor(GetPlayer().components.leveluplan.expLan), GetPlayer().components.leveluplan:XPneed(), ((2.2 - 1.003 ^ -GetPlayer().components.leveluplan.levelLan) / 1.2 - 1) * 100 because component leveluplan may not exist in the client. But what can we do? Adding the component in the client too? No. We just need to run it in the server. Because the server has the info. And you can do it by using RPC. Let's make a code sending RPC to the server. The server receives the RPC, and execute the function that let the sender(the player prefab) say the info. The first thing to do is to change AddKeyDownHandler(). A client raises KeyDown Event. So the client will send RPC. G.TheInput:AddKeyDownHandler(INFO_KEY, function() if G.TheFrontEnd:GetActiveScreen() ~= nil and G.TheFrontEnd:GetActiveScreen().name == "HUD" then G.SendModRPCToServer(MOD_RPC["modprettyname"]["getinfo"], ThePlayer) end end) You can freely change MOD_RPC's key. Just ensure "modprettyname" part distinguishable compared to other mods. So if you press the key, the client says to the server: "Execute function in MODRPC.modprettyname.getinfo" And... I won't use GetPlayer() because it will only call in DST code part. Oh and IsPaused() is not used in DST. Instead, if G.TheFrontEnd:GetActiveScreen()~ part will prevent further sequences when any screen is activated. Next is to add an RPC handler. If the server receives an RPC, it will execute the function in matching key(modprettyname.getinfo in this case) in MOD_RPC. Adding the function to MOD_RPC is this. AddModRPCHandler("modprettyname", "getinfo", GetInfo) You will notice that the key should be corresponding. Rename it correctly. After the server received the RPC, it will call GetInfo() in server-side. The server does have the information.However, the server doesn't know who GetPlayer(ThePlayer) is. So don't use it in GetInfo(). Instead, use a parameter passed by the RPC which is the sender's player entity. ..."modprettyname"]["getinfo"], ThePlayer) That parameter is actually ThePlayer, the argument of SendModRPCToServer. Since this ThePlayer was sent by the client, the server can distinguish which player is to start function. local function GetInfo(inst) inst.components.talker:Say( string.format( "Level: %d\nXP: %d/%d\n%.4f speed", inst.components.leveluplan.levelLan, math.floor(inst.components.leveluplan.expLan), inst.components.leveluplan:XPneed(), inst.components.leveluplan.speedupLan ) ) end That will do it. Recode it as you want. Take a look at my character mod's code as well. I've already made the feature similar to yours. Edited March 24, 2019 by YakumoYukari Link to comment Share on other sites More sharing options...
Magic_Pro Posted March 16, 2019 Author Share Posted March 16, 2019 Thank you, it works like a charm 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