Jump to content

the character's position is not synced on performing a custom action.


Recommended Posts

laggy.gif.1abe96deb1e2db46cb83d3d35ed31e02.gif

I created an action that works by pressing a key.

But As you see in the GIF, character teleports back to a point where it actually is in the server, which should have been synchronized.

Also, this is a prototype and It'll become a 'skill' that charge to the enemy. So before that, this issue must be solved.

 

Github Page

First, Add KeydownHandler to make it KeyPress and send RPC to the server.

TheInput:AddKeyDownHandler(_G["KEY_R"], function() 
	if inst == ThePlayer and not inst:HasTag("inskill") and not inst.HUD:IsConsoleScreenOpen() then
		SendModRPCToServer(MOD_RPC["sendi"]["rapier"]) 
	end
end) 

 

And the server sets net_var in classified where is attached to the character

function rapier(inst)
	inst.sendi_classified.rapier:set(true) 
end
AddModRPCHandler("sendi", "rapier", rapier)

In sendi_classified.lua, netvar definition and Regeistering NetListeners.

inst.rapier = net_bool(inst.GUID, "onrapier", "onrapierdirty")
inst.rapier:set(false)
local function RegisterNetListeners(inst)
	if TheWorld.ismastersim then
		inst._parent = inst.entity:GetParent()
	else
		
	end
	inst:ListenForEvent("onrapierdirty", Rapier)
end

 

When net_var changes, this event will be called.

local function Rapier(inst)
	local shouldtrigger = inst.rapier:value()
	if shouldtrigger then
		if TheWorld ~= nil and TheWorld.ismastersim then
			inst._parent.components.playercontroller:DoAction(BufferedAction(inst, nil, ACTIONS.RAPIER))
		end
	elseif inst._parent.components.playercontroller ~= nil then	
		inst._parent.components.playercontroller:Enable(true)
	end
end

I pushed BufferedAction via DoAction which will push action in both the client and the server. (Maybe function this could cause the issue)

 

Here's the Action StateGraph to be performed in the server.

local rapier_server = State { 
	name = "rapier",
	tags = { "busy", "doing", "attack", "skill", "pausepredict"},

	onenter = function(inst)
		inst:AddTag("inskill")
		inst.components.locomotor:Stop()
		inst.components.locomotor:Clear()
        inst:ClearBufferedAction()
		ForceStopHeavyLifting(inst)
		if inst.components.playercontroller ~= nil then
			inst.components.playercontroller:RemotePausePrediction()
			inst.components.playercontroller:Enable(false)
		end
		inst.AnimState:PlayAnimation("whip_pre")
        inst.AnimState:PushAnimation("whip", false)
		inst.sg:SetTimeout(1)
		inst.components.sendiskill:OnStartRapier()
		inst:PerformBufferedAction()
	end,

	timeline =
	{
		TimeEvent(4 * FRAMES, function(inst)
			inst.sg:RemoveStateTag("busy")
		end),
		TimeEvent(9 * FRAMES, function(inst)
			
		end),
		TimeEvent(18 * FRAMES, function(inst)
			--inst.Physics:Stop()
		end),
	},
	
	events = {
        EventHandler("animqueueover", function(inst)
            if inst.AnimState:AnimDone() then
                inst.sg:GoToState("idle")
            end
        end),
    },
	
	onupdate = function(inst)
		
	end,
	
	ontimeout = function(inst)
		inst:RemoveTag("inskill")
		inst.sg:GoToState("idle", inst.entity:FlattenMovementPrediction() and "noanim" or nil)
		inst.sendi_classified.rapier:set(false)
		if inst.components.playercontroller ~= nil then
            inst.components.playercontroller:Enable(true)
        end
	end,
	
	onexit = function(inst)	
		inst:RemoveTag("inskill")
		inst.sendi_classified.rapier:set(false)
	end,
}

in onenter, prevent the player to move because this will become a 'charge skill'(and non-cancelable).

then re-set the classified to make the players move again.

And the client version.

local rapier_client = State {
	name = "rapier",
	tags = { "doing", "attack", "skill" },

	onenter = function(inst)
		inst.components.locomotor:Stop()
        inst.components.locomotor:Clear()
		inst.entity:SetIsPredictingMovement(false)
		inst.entity:FlattenMovementPrediction()
		inst.AnimState:PlayAnimation("whip_pre")
		inst.AnimState:PushAnimation("whip", false)
		inst:PerformPreviewBufferedAction()
		inst.sg:SetTimeout(1)
	end,
	
	onupdate = function(inst)
		if inst.bufferedaction == nil then
			inst.sg:GoToState("idle", true)
		end
	end,
	
	ontimeout = function(inst)
		inst:ClearBufferedAction()
		inst.sg:GoToState("idle", inst.entity:FlattenMovementPrediction() and "noanim" or nil)
	end,
	
	onexit = function(inst)	
		inst.entity:SetIsPredictingMovement(true)
	end,
}

The codes I messed up in onenter, onexit, FlatternMovementPrediction thingies are what I have tried to prevent the issue, but none of these works...

And I don't know what SetIsPredictingMovement() actually do, maybe it's related to TheNet.

 

I think the point at which the character can control is a little faster than... the server's entity is ready to locomote.

How can I sync the player's position in right time? Or did I missed something?

Edited by YakumoYukari
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
 Share

×
  • Create New...