Skip to content

Instantly share code, notes, and snippets.

@asofold
Last active April 25, 2017 22:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asofold/b05c0a17c605e7c69bb30ee5e79a6e7b to your computer and use it in GitHub Desktop.
Save asofold/b05c0a17c605e7c69bb30ee5e79a6e7b to your computer and use it in GitHub Desktop.
NoCheatPlus moving checks: Adjust a set-back location (SurvivalFly).

Adjust a set-back location, using a hook. This should be a short round up on what can / should / shouldn't be done.

Related commits (at the time of writing this):

It's enough to use MovingData.setTeleported to override the set-back location of a player. However this should only be done if IViolationData.willCancel() returns true - don't cancel violation processing just for adjusting a set-back, don't teleport the player, just determine where to put and call that one method. This will be in from build 1088 on.

You may still want to exclude some pitfalls, like not setting players into blocks - in this case reading on could be useful. Otherwise just forget about the rest that's written below.

BASIC SAFETY

-> Slightly incorrect, despite not setting into blocks making sense - continue with SPOILER.

  • multiMoveCount indicates if a move has been split into two, and what/which a given PlayerMoveData is representing. 0: Ordinary move, 1: first (from->loc), 2: second (loc->to).
  • This allows checking MovingData.playerMoves during violation processing (thisMove should be set, firstPastMove is the previous one).
  • It's suggested to NOT use the from-location of the second split move, because it could be a position slightly inside of a block, resulting from a previous micro move, potentially resulting in bypassing the passable check for the case of pulling the player to ground there. EDIT: This is partly wrong, because in case of a not passable block the first move should get cancelled, so there is no second one to process (...) - if you want to consistently use the original PlayerMoveEvent.getFrom() location, then checking playerMoves within MovingData will help here.
  • Instead, if thisMove.multiMoveCount is 2, use the firstPastMove.from instead.

On older builds you would have the flag mightBeMultipleMoves instead of multiMoveCount - you could skip adjusting the locaton, if that flag is set, because during violation processing you can't distinguish if this is the first or second part of a split move.

An alternative heuristic is to check if the box is passable at the suggested location.

  • You either need a BlockCache (fetchable via MCAccess, fetchable via NoCheatPlusApi.getGenericInstance) and use BlockProperties.isPassableBox.
  • Or you'd need to use a PlayerMoveInfo instance from AUXMoving (fetchable via GenericInstanceRegistry), then set(player, suggestedLoc, null +-), then check with moveInfo.from.isPassableBox() for best convenience, afterwards aux.returnMoveInfo (does cleanup). Slightly heavier, but doesn't need sorting of coordinates :p. On request a isPassableBoxShuffled may be added, to allow mixing up min/max.
  • (For an even more advanced thing, you would probably collect initially and legitimately colliding blocks, to be able to have those ignored.)

SPOILER

Since build 1088 you'll just use MovingData.setTeleported(adjustedLocation).

UNTIL THEN

To avoid conflicts you could also try to just update the location NCP will set back to in the most smooth way:

  • During hook processing, store the adjusted location for use by a PlayerMoveEvent listener on EventPriority.HIGHEST (not MONITOR, not LOWEST). Do not cancel violation processing for altering set back locations.
  • The move event listener then can check if this is a set back by NCP (for real).
    • Detail: MovingConfig.playerSetBackMethod determines how this is done in particular, in theory it's even configurable.
    • In practice pre 1.9: event.setTo is used, check data.isTeleported(Position)(event.getTo()). A teleport will result before other moving events are processed.
    • In practice 1.9 and later: check (event.setCancelled(true) && data.isTeleported(event.getFrom())). In this case a teleport should follow, but it might happen it doesn't and the set back is confirmed with the next move.
    • In addition the player could be scheduled to be set back just in case, but that only applies if teleported position is set. So that wouldn't conflict, because you'll set it to your stored location.
  • If it's a set back by NCP...
    • note that now the thisMove has been added to pastMoves and all playerMoves are invalidated or set to the NCP set back, thus calculations must already have happened in the hook on a violation (IViolationData.willCancel() returns true).
    • data.setTeleported(stored location).
    • For an extra medal, you could use NCPAPIProvider.getNoCheatPlusAPI().getGenericInstance(MovingAux.class).resetPositionAndMediumProperties(... with stored location) - for performance store a handle during setup.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment