BrokenValkyrie

  • Content Count

    9
  • Joined

  • Last visited

Community Reputation

5 Neutral

About BrokenValkyrie

  • Rank
    Junior Member
...

Badges

  1. @Deblat My mistake, I thought this was a character creation. I think you can still pass the mob data to client. Since you are creating custom net variable you as well set the data from component instead of replica, from the host side. From the above code change this line self.net_current:set(self.numberofarray)To this self.net_current:set( math.floor( darkclone.components.health.current + 0.5 ) )This should make self.current(which should be name as self.currenthealth for better context) receive update from the host of the current health of the mob. From the client side self.current can be used. The component should exist otherwise replace darkclone.component.health.current with darkclone.replica.health.currenthealth(or darkclone.replica.health.current if you get a nil) You can do something similar with maxhealth. Can I ask why you need the current health and max health passed to the client?
  2. @DarkXero I want to steer you into the right direction, your last line has me worried. You do not need to create a replica, it more complicated and the variable REPLICATABLE_COMPONENTS from entityreplica which contains a table of component allowed to be replicated is not accessible(at least not easily). You can write a functional network supported component without using a replica class. You need to learn how to use net variable are used, pay close attention to how a net variable is used, especially when the net variable is given a value using the :set(value) function. function OnExampleDirty(inst) inst.components.examplesubcomponent.example = inst.components.examplecomponent.net_example:value() end self.example = 0 self.net_example = net_ushortint(self.inst.GUID, "example", "exampledirty" ) self.net_example:set(some numeric value)Have a look at the similar variable where it is prefixed with net_ in Peter A the huntmod. In the above code it is self.example. The most simplest variable to follow in Peter A example is self.hunt_kills and self.net_hunt_kills. self.hunt_kills is accessible from the client and the host is responsible for modifying self.net_hunt_kills. Once you have grasped the concept of net variable I want to give you some advice on working with net variable to avoid some potential headache. The largest net variable is net_ushort int, it only allows storage of whole number between 0 and 65535. You will need to convert decimal value into integer. You can use this code math.floor(decimalvalue + 0.5)You need to check for the range of value before being entered into net variable using :set(value) I use this which is taken from the classified file. function SomeComponent:SetValue(name, value) assert(value >= 0 and value <= 65535, "Player "..tostring(name).." out of range: "..tostring(value)) self[name]:set(math.ceil(value))endMake good use of this code that is underlined. if TheWorld.ismastersim then --host function only self.localhealth = ThePlayer.component.health.currenthealthelse --client function onlyendSome variable and function can only be accessed by host but not client, for example player current health in decimals. You do not want the client attempting to access host only data, otherwise it will cause a crash. ThePlayer.component.health.currenthealth is an example of a value that can only be accessed by host, if attempted to be access on the client side the program will crash. From client perspective ThePlayer.component.health does not exist and it will return a nil value. and finally in mod.info make sure this flag is set to true. all_clients_require_mod = trueall client must have a copy of the net variable and the local variable which is called from the OnDirty() function. I've done test where the client do not have copy of the net variable while it was not needed it messes up the game. At best you get broken UI and a messy screen, otherwise the game crashes. I am sorry if this confuses you further, attached is a component of my code which uses the net variable code that may give you some idea how it works. Unfortunately it may be as confusing as Peter A The Hunt mod. How ever it contains method handling negative value and a work around to storing small(between 2 and -2) decimal value. If you get confused just keep asking question, don't give up. regeneration_arrowcomponent.lua
  3. If you plan to make custom net var data make sure to use this in component if TheWorld.ismastersim then --serversidefunctionendto differentiate between client and server/host. I can give you a head start code to give you an idea of how it can work. I only give you an example for hunger component since you seem to be running multiple component for your mod. local function OnHungerMaxDirty(inst) inst.components.hunger.max = inst.component.hunger.net_max:value()endlocal function OnHungerCurrentDirty(inst) inst.components.hunger.current = inst.components.hunger.net_current:value()endlocal Hunger = Class(function(self, inst) self.max = 0.0 self.net_max = net_ushortint(self.inst.GUID, "max", "maxdirty" ) self.current = 0.0 self.net_sanityrate = net_ushortint(self.inst.GUID, "current", "sanityratedirty" ) if TheWorld.ismastersim then --Host data only self.numberofarray self.numberofprhase else--Client side only, listen for these data changes. self.inst:ListenForEvent("maxdirty", OnHungerMaxDirty) self.inst:ListenForEvent("currentdirty", OnHungerCurrentDirty) end self.inst:StartUpdatingComponent(self)end)function Hunger:OnUpdate(dt) --If server do if TheWorld.ismastersim then --Do some calculation self.net_max:set(self.numberofphrase) self.net_current:set(self.numberofarray) endendWhat this does is declare two net variable, self.net_max and self.net_current. For client you are creating listener which listen when the netvariable calls :set(wholeinteger) which will update the OnDirty function. For example when self.net_max:set(value) is detected by self.inst:ListenForEvent("maxdirty",OnHungerMaxDirty), OnHungerMaxDirty will be called and the local variable self.max is updated from the net_max variable. This means that self.max is usable for the client, as it is updated from the server. So there is no need to make further calls to retrieve self.max, just use it. One important note, net_ushortint only support 2 byte, meaning only whole number from 0 - 65535. You will need to use math.floor(value + 0.5) to round number before entering into net variable. You will also need range check, I do not not know the consequence if you try enter bad value, but best to take precaution. And if you use custom net variable this flag on mod info must be set true or it will cause issue all_clients_require_mod = trueOther wise if you are just planning to access the character data normally from host as client you can use these code. darkclone.replica.hunger.classified.currenthunger:value()darkclone.replica.hunger.classified:Max()darkclone.replica.health.classified.currenthealth:value()darkclone.replica.health.classified:Max()I'll attach a component of my mod which deals with net variable if you are interested. regeneration_arrowcomponent.lua
  4. I would like to thank you for putting this out, as a modder it really has helped for figuring the network side of don't starve together as I read through the code. "Edit: Known issue: Mod configuration data isn't getting sent to the clients." Is it actually possible for client to get mod configuration from host? I've been digging through the code and can't find any instance of host mod configuration getting passed to client. A function to retrieve mod configuration option from host would be very useful
  5. I'll explain the function of point 1 and the purpose of common and player classified with codes. I'm no expert on code behind don't starve together so correct me if I am wrong. 1. The purpose of on dirty function is to update client data from host, here an example of my code. local function OnHealthRateDirty(inst) inst.components.regeneration_arrowcomponent.healthrate = inst.components.regeneration_arrowcomponent.net_healthrate:value()endlocal Regeneration_ArrowComponent = Class(function(self, inst) self.healthrate = 0.0 self.net_healthrate = net_ushortint(self.inst.GUID, "healthrate", "healthratedirty" ) if TheWorld.ismastersim then --not host, do nothing for this example else --This is the client, add a listener self.inst:ListenForEvent("healthratedirty", OnHealthRateDirty) endendThe event listener, listen for this command self.net_healthrate:set( --Numeric value here )When a listener hears this command it will execute OnHealthRateDirty(inst), which will update the self.healthrate variable 2. Player common is the handling of player on the host side, while player_classified is the network handling of Player common data. As @Sarcen has said. The host can access certain aspect of player data while client can only receive from replica component and classified data. For example this code is accessible to the host but not the client. For the client the health component does not exist. ThePlayer.components.health.currenthealthHow ever both client and host have access to player classified through the replica component. The difference is player classified variable are limited in size, the below code will only give whole number while the code above give it in decimal. The largest net variable I know of is 2 byte(aka short integer. 0 - 65535) ThePlayer.replica.health.classified.currenthealth:value()If you want to get a better idea of the interaction of dirty function, I suggest checking out Peter A The Hunt mod.
  6. Sorry for the double post, I can not find a way to edit post. I'm here to report some problem using this method, it really messes up the user hud if they don't have replica and classified component enabled. It will work fine as long as the client and host have these component in sync. If you're wandering about the UI, the game giving lots of false positive, player on fire, starving, freezing, dead and ghost is present, when none of these condition are present. I can't locate the cause but it appears it is setting off all the is flag in player_classified define health variables. If you change the network variable from inst.decimalhealth = GLOBAL.net_ushortint(inst.GUID,"health.decimalhealth")to this inst.decimalhealth = GLOBAL.net_ushortint(inst.GUID,"decimalhealth")The entire screen goes purple and UI freaks out, all avaliable recipe is avaliable and not avaliable . Overall don't use this method, unless you want to see the game freak out. Anyway Peter A hunt mod avaliable and it has proper handling of the network code. That mod will be a much better reference.
  7. Thank you rezecib for taking your time to answer my problem, your code helped me to develop the final solution. I couldn't get the solution you have given me to work, but it helped me developed a solution that does not require replacing health_replica or any of its component. I like your solution to storing decimal places, I modified the solution to allow storage of more than 2 decimal places which I needed. Here is the final solution, while it doesn't properly define server or client side function it works. Mod Main: AddClassPostConstruct("components/health_replica", function(self) self.GetCurrentDecimal = function(self) if self.inst.components.health ~= nil then return self.inst.components.health.currenthealth elseif self.classified ~= nil then return self.classified.currenthealth:value() + (self.classified.currenthealthdecimal:value()/10000) else return 0 end end self.SetCurrentDecimal = function(self, health) if self.classified ~= nil then self.classified:SetValue("currenthealthdecimal", 10000 * (health - math.floor(health)) ) end endend)AddPrefabPostInit("player_classified", function(inst) inst.currenthealthdecimal = GLOBAL.net_ushortint(inst.GUID, "health.currenthealthdecimal")end)To make this work I needed to update currenthealthdecimal with every game update. So I used my regeneration component on update to do it. local Regeneration = Class(function(self, inst) self.inst = inst self.health = self.inst.components.healthend)function Regeneration:OnUpdate(dt) self.inst.replica.health:SetCurrentDecimal(self.health.currenthealth)endWhile this is not the best solution it is able to retrieve cient health accurate to 4 decimal places from the host and not replace any function of the vanilla scripts. So I call this one a success.
  8. Hi, I am new to LUA language. I am currently developing a health arrow widget, similar to the insanity badge widget, it show when health is regenerating. I'm attempting to get this widget working for multiplayer. Unfortunately my working solution requires replacing the health_replica component and I'm looking for tips for a solution that does not require replacing health_replica to reduce mod conflict. The goal is to obtain the client current health within 2 decimal values from the host. Here are the new lines I inserted into health_replica.lua local Health = Class(function(self, inst) --original code self._decimalhealth = net_ushortint(inst.GUID, "health._decimalhealth") --original codeend)function Health:SetCurrent(current) if self.classified ~= nil then --Store 100 times the value, make sure its not out of bound as only short integer supported. assert(current >= 0 and current <= 65535, "Player ".."_decimalhealth".." out of range: "..tostring(current)) self._decimalhealth:set(math.floor(current * 100)) self.classified:SetValue("currenthealth", current) endend--New method to return health value at 2 decimal place.function Health:GetDecimalCurrent() if self.inst.components.health ~= nil then return self.inst.components.health.currenthealth elseif self.classified ~= nil then return self._decimalhealth:value()/100 else return 0 endendWith this I am able to call GetDecimalCurrent from health arrow widget --Most of the code is absent for simplicity sake.local HealthArrow = Class(Widget, function(self,owner) -- owner parameter is not used here --Get the player self.owner = ThePlayer self.currentHealth = 0.0end)function HealthArrow:OnUpdate(dt) --Without this it will crash, replica.health is not instanced before this is called. if self.owner.replica.health then -- This access the new data created from health_replica component self.currentHealth = self.owner.replica.health:GetDecimalCurrent() endendThe reason for this solution is so I can access the client current health that is accurate within 2 decimal places. This line can get health of the client from the host but it only gives current health in whole numbers which I can't work off. self.owner.replica.health.classified.currenthealth:value()
  9. I had similar issue with my mod not appearing to the public, it was posted on December 21st. It is visible to public now and I am just confirming that the issue appears to be resolved.