Open Ismoh opened 2 years ago
Based on the default player_base.xml I created in the past a client_player_base.xml to see a copy of clients minä. I commented out everything not need by best guess. As @GrandpaGameHacker mentioned, after RE Noita, it might be enough to add a CameraBoundComponent (double check wording) to make the clients minä copy trigger spawning entities on server instance to be synced on all clients. This is needed, because entities on client will be removed by default, otherwise everything would be duplicated and not in sync.
PlatformShooterPlayerComponent controls which entity the camera follows and where it is positioned, and the GameGetCameraPos, GameSetCameraPos, GameSetCameraFree allow for the camera to be moved with lua, but I don't think they will be useful for what we need to do.
I assume there can only be one entity with a PlatformShooterPlayerComponent in the world, as the camera can't be centred on two entities.
How about adding the component and setting center_camera_on_this_entity and move_camera_with_aim to 0? I think, when the local minä dies, the camera might move to the other players, when setting those values to 1 after minä died. Would be a nice feature?!
As discussed with @ofoxsmith we decided to implement a different approach. We're going to have a serialisation and compression of a whole entity within his children and all components, which then is shot over network to server. Clients eentity will be destroyed. Server then sends this chunk of squeezed entity to all other clients, which then spawns the entity, if it is in range (camera bounds) There will be pitfalls like:
@ofoxsmith I created a branch based on develop!
I thought about, how to implement syncing rootEntities and all below, like children and components. This is my result: Pseudo code:
local entitiesInRadius = EntityGetInRadius(pos_x, pos_y, radius) or {}
for entitiesInRadius do
if entityInRadius[i] == EntityGetRootEntity(entity_id) then
-- get all attributes of root entity
-- todo
-- get all components of root
local rootComponents = EntityGetAllComponents(entityInRadius[i]) or {}
for rootComponents do
-- store comp type, name and value into a string, table or json
-- I am pretty sure we need a lookup table like: if component type == VariableStorageComponent then field_name = "name" etc pp
end
-- get all child entities
local children = EntityGetAllChildren(entityInRadius[i]) or {}
for children do
-- recursive getAllComponents and store in string, table or json
end
else
--skip children
end
So we need to get the root entity, but ignore children. If entity == root, (1)then get all attributes and store those, then iter all components and store type, field_name and value, then get all children and repeat (1).
[17:08]stefnotch: If we want to clearly communicate that to the players: Would it make sense to have an indicator that appears when you're further away from the host. As if to say "you're on your own, things that happen here are closer to singleplayer than multiplayer"?
If server is in range ask for spawn, if server isn't in range ask only for nuid. Check for entityData if other minäs are in range, if so send otherwise not. If anything comes in range, make sure to spawn the entity: think of an projectile flying millions of pixels!
Make sure all sendToPeer are put into functions. In addition do checks that parameters aren't empty. Global function in MinaUtils for distance between minas.
if any mina in range then
send serialized enitity to server
Server send to all clients
end
Every peer checks, if entity is in range
then spawn, if not ack only
Else if no mina in range, do nothing
Make sure entities are send immediatly, when spawned, no matter what tick is set, otherwise it's getting out of sync. Send entity data only on tick!
Add a list of entity names, which only be loaded once, like bosses. Can be modified by modders.
If client is in server minä range, remove entities.
Dextercd
np.SetGameModeDeterministic(true)
. This basically makes the game think it's a daily run. It makes it so all spells are available during the run and using spells does not count towards spell progress.
When needNuid is sent, serialise the entity and send it to the server. Remove then on client. Server will add nuid and sent spawned entity to the client.
GlobalsUtils
? GlobalsUtils.getNuid(entityId)
for instanceSendNewNuid
and SendNeedNuid
Might be that I could use some RE help. I never was depening on RE help so much.
The problem I have is: My concept is that the server holds the truth. Spawning, moving entities, everything. Thats why I remove all entities on client side. BUT... There is no Noita API function (or I dont know a specific one), which triggers spawning entities, therefore the client wont see any entitites spawning, when not following the servers player. I have no idea where to look in ghidra or even how to use it or if there is any Noita API function or a specific combination of components, which are needed.
I think I am going to create a 'wanted help' issue on github, because if this isnt fixed, multiplayer would mean to follow the servers player all the time and this sycks.
If I wont remove entities on client side, everything would be multiplied by amount of clients, which is even more sycking!
Anyone out there you can help me?
I still want to have a look on RegisterSpawnFunction, because I dont know it or used it before.
I really hope there will be a solution, because it's a big game changer!