-
-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NetworkWeapon.fire()
is not within Inputs.
#253
Comments
Turns out netfox already has input prediction/extrapolation!The below function is in the class # buffer is either _states or _inputs
func _get_history(buffer: Dictionary, tick: int) -> Dictionary:
if buffer.has(tick):
return buffer[tick]
if buffer.is_empty():
return {}
var earliest = buffer.keys().min()
var latest = buffer.keys().max()
if tick < earliest:
return buffer[earliest]
#This is input prediction/extrapolation
#e.g. if input movement was moving to the right
#this will also move to the right for all future ticks (aka prediction)
if tick > latest:
return buffer[latest]
var before = buffer.keys() \
.filter(func (key): return key < tick) \
.max()
return buffer[before] Currently, if Kinda the same with jump not causing problems, if you are already in the air, it doesnt change state, and if you just pressed it a few ticks ago, you are already in the air so change doesn't state, so the problem wasn't noticed thus far. Basically, the input prediction/extrapolation should continue working as is, but every property should have a boolean "is extrapolateable" and if not, then have a default value (e.g. for movement, it would be Vector3.ZERO) |
How? You want the server to know you want to fire, so you call an RPC. Since it's using an RPC, there's no point to also send a bool, since the RPC does all the work. It is also not part of the rollback process indeed - I kept the projectiles out of the rollback loop to keep the code simple. Could you please elaborate on why the above design should be changed? And also how your suggestions would solve the above? They seem to be concerned with transmitting the input, but not with the whole firing sequence ( client requests, server approves and broadcasts, client reconciles based on server response ).
Kind of. If you try to grab a state or input for a tick that we don't have data for, it will try to find something that being the latest data up to that point. However, during rollback, we don't resimulate ticks that we don't have input for. |
The state changes without an input change. For example, a replay system cannot work by simply having the initial states, and all inputs. The input fire works locally, but isn't transmitted to others as a fire input.
Using the 1st suggestion of the OP: ## Try to fire the weapon and return the projectile.
##
## Returns null if the weapon can't be fired.
func fire() -> Node:
if not can_fire():
return null
var id: String = _generate_id()
var projectile = _spawn()
_save_projectile(projectile, id)
var data = _projectile_data[id]
if not is_multiplayer_authority():
_request_projectile.rpc_id(get_multiplayer_authority(), id, NetworkTime.tick, data)
else:
_accept_projectile.rpc(id, NetworkTime.tick, data)
_logger.debug("Calling after fire hook for %s" % [projectile.name])
_after_fire(projectile)
return projectile Using the 2nd suggestion of the OP:
3rd suggestion not included in the OP: Minor argument I forgot: For a game with many weapons, it would be clean to contain their firing/button press in the inputs. In the current game I'm making, most actions are integer mapped, so instead of 1 boolean for each button, its basically 1 integer which contains exclusively 1 action. Each input action is an enum. Simplifed example: const JUMP: int = 1
const FIRE1: int = 2
const FIRE2: int = 3
const BLOCK: int = 4 So if you press crouch and fire1 and fire2, it only includes one of these actions (crouch) and queues the next action (fire1 and fire2) for next tick(s) but perhaps this design isn't very compatible with netfox. |
Ah also, another argument to include it as input is that by implementing InputDelay or InputSlack, the firing of a (bomb) projectile isn't included at all. |
The function
fire()
directly changes state as it spawns a bomb projectile with velocity etc, yet the above function is exclusively a local input - it isn't shared to other players via RPCs, nor is it rollbacked.This is a design flaw.
Especially noticeable if a replay manager is to be implemented, because this forces to capture all states, instead of all inputs and the very first state.
There are 2 ways to solve this problem:
fire()
changes the state (same as current implementation), but also becomes a dictionary key to_inputs
I would suggest this key becoming
button_pressed
and its value to be an integer, so there can be mapped any amount of input buttons, for the same dictionary key. E.g. if there are 2 weapons to use, or more, this handles them all finely, with the condition that only 1 button can be pressed each tick (so you cannot fire both weapons at the same tick, the next weapon fire is queued for the next tick)fire()
changes the input directly, and the input itself is checked to spawn the bomb projectile. No idea if this will create bugs on existing code (by having the projectile spawn by state AND input, idk if there are proper checks already)^This is already half-implemented, as the input is changed, it just isn't passed into
_inputs
The text was updated successfully, but these errors were encountered: