Jump to content

Host: server only vs client only

Recommended Posts

I am going to host a world, not a dedicated server.


I know:

Server onlyall_clients_require_mod = falseclient_only_mod = falseClient onlyall_clients_require_mod = falseclient_only_mod = trueServer/Clientall_clients_require_mod = trueclient_only_mod = false

Now, what happens with modmain in the first two cases? Because if I am a host, then being server only makes me load the mod, but because I am also a player, the client only makes me load the mod.


However, despite executing the same mod, I can run into problems.


My example is example.zip, from:



If I have client only, then I crash because the component action isn't properly linked.

If I have server only, then it works.

Link to comment
Share on other sites

@DarkXero, this particular function: AddComponentAction must be ran on both client and server in order to properly execute and you need to be looking for tags not components when determining whether the action can be executed.



Link to comment
Share on other sites

@Kzisor, I understand that.


But I repeat, I'm a host. As in I activate the mod, then go click in Host Game and play.


No matter the type of mod, server side or client side, both have to be loaded in this case.

Server side to trigger changes on the game, altering the world and the server.

The client side of the server side (?) to trigger changes in say, my HUD.


What bothers me is the example.zip I posted.

It works fine when I change it to server side only, and it crashes when set to client only.


I attach another example.

It's simple, it's a specified client side mod that gives the spear 9001 damage.


If I'm the host and I load this mod, the change propagates to the server, and so the spear gets 9001 damage.

Because I'm that host/client mix. My world is the real sim.


Now, why does AddComponentAction crash then, if I'm the host AND the client?

Making it client only should still mean that I get the client side change and that also the change propagates to the server, like with the AddPrefabPostInit in example2, so it should work.


Also, I checked for health replica in my example, not the component.


Edited by DarkXero
Link to comment
Share on other sites

Client only mods are load in a different manner than Server only mods, as stated before the reason it's crash when set to client only is AddComponentActions requires to be loaded on both server and client.


The reason the second example works is because it's simply modifying code already being ran on the server. If you were to try to add a new component to the server, it would not work.

Link to comment
Share on other sites

@DarkXero, okay so basically I don't know how exactly the client only mods are loaded differently than the server only mods, but I do know they are loaded differently and the proof is with AddComponentActions function.

function AddComponentAction(actiontype, component, fn, modname)    --ensure this mod is setup in the tables    if MOD_COMPONENT_ACTIONS[modname] == nil then		MOD_COMPONENT_ACTIONS[modname] = {}		MOD_ACTION_COMPONENT_NAMES[modname] = {}		MOD_ACTION_COMPONENT_IDS[modname] = {}    end        if MOD_COMPONENT_ACTIONS[modname][actiontype] == nil then		MOD_COMPONENT_ACTIONS[modname][actiontype] = {}    end        MOD_COMPONENT_ACTIONS[modname][actiontype][component] = fn    table.insert(MOD_ACTION_COMPONENT_NAMES[modname], component)    MOD_ACTION_COMPONENT_IDS[modname][component] = #MOD_ACTION_COMPONENT_NAMES[modname]endfunction EntityScript:RegisterComponentActions(name)    local id = ACTION_COMPONENT_IDS[name]    if id ~= nil then        table.insert(self.actioncomponents, id)        if self.actionreplica ~= nil then            self.actionreplica.actioncomponents:set(self.actioncomponents)        end    end    	for modname,modtable in pairs(MOD_ACTION_COMPONENT_IDS) do		id = modtable[name]		if id ~= nil then			--found this component in this mod's table			if self.modactioncomponents == nil then				self.modactioncomponents = {}				--print("on ", self, " adding self.modactioncomponents")			end				    			if self.modactioncomponents[modname] == nil then				self.modactioncomponents[modname] = {}				--print("on ", self, " adding self.modactioncomponents[",modname,"]")			end			--print("Adding to self.modactioncomponents[",modname,"] ",id)			table.insert( self.modactioncomponents[modname], id )			if self.actionreplica ~= nil then				self.actionreplica.modactioncomponents[modname]:set(self.modactioncomponents[modname])			end		end	endend

This is the code which is being called with AddComponentAction as you can see it simply adds it to a lookup table which is then being Registered. However, this line is giving a nil error:


That is because it cannot find the modactioncomponent on the server, because you set the mod to client only. This means that even though you were the server and client, that it only loaded the code at the client and not the server. My conclusion is from the following error which points to line 861 after trying to add the action to the component which it could not find on the server:

[string "scripts/componentactions.lua"]:861: attempt to index field '?' (a nil value)LUA ERROR stack traceback:        scripts/componentactions.lua(861,1) in function 'RegisterComponentActions'        scripts/entityscript.lua(522,1) in function 'AddComponent'        ../mods/example3/modmain.lua(2,1)        =(tail call) ?        =[C] in function 'xpcall'        scripts/mods.lua(144,1) in function 'mod'        scripts/mainfunctions.lua(155,1)        =[C] in function 'SpawnPrefab'        scripts/mainfunctions.lua(182,1) in function 'SpawnPrefab'        scripts/mainfunctions.lua(189,1) in function 'SpawnSaveRecord'        scripts/gamelogic.lua(411,1) in function 'PopulateWorld'	...        =[C] in function 'GetPersistentString'        scripts/saveindex.lua(68,1) in function 'Load'        scripts/gamelogic.lua(950,1) in function 'callback'        scripts/playerprofile.lua(564,1) in function 'Set'        scripts/playerprofile.lua(447,1)        =[C] in function 'GetPersistentString'        scripts/playerprofile.lua(445,1) in function 'Load'        scripts/gamelogic.lua(949,1) in main chunk        =[C] in function 'require'        scripts/mainfunctions.lua(690,1)	[00:01:12]: Disabling example3 (Example 3) because it had an error.

This is all backed up by simply commenting out the AddComponentActions code and it will work, just not as intended.

Link to comment
Share on other sites

@Kzisor, I found the reason.


It's this in AddNetwork:

    for _,modname in pairs(ModManager:GetServerModsNames()) do    	inst.actionreplica.modactioncomponents[modname] = net_smallbytearray(guid, "modactioncomponents"..modname, "modactioncomponentsdirty"..modname)    end

since the mod is client only, then it won't be in GetServerModsNames.

Therefore, no netvar, therefore ? indexing, therefore crash.


It makes sense though, why would a client want to generate netvars client side only?

Better to check for the server netvars generated by mods before making them ourselves.


For the sake of examples still, I attach another one.

Server/Client side working AddComponentAction for a testprefab.


Link to comment
Share on other sites

@Kzisor, it does work.

Dedicated server loads the mod properly bypassing the server mod requirement.

Client loads the mod properly as it is client side.


What this causes is a modded server that nobody sees as modded.

So it any poor soul enters the server without the proper mods activated, then the game will run out of memory and crash.

Link to comment
Share on other sites

I just tested it on a random server-only mod and hosted my own game, I changed client_only_mod to true (all_clients_require_mod = false, no change), and the game behaved like the mod was still server-only.


This means two things: (1) if you are the host of a hosted server, your client-only mod is loaded the same way as a server-only mod; (2) hosted simulator and the hosting player's client simulator are actually the same simulator.

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

  • Create New...