Make piece prediction harder.
Since the client & server share RNGs, many puzzles (e.g. yohoho's swordfighting) wind up lending themselves to easy piece prediction; the board is set up with a seed, and the RNG is only ever used to generate pieces. Someone snooping that could (and people have) pre-generate all the pieces in order, letting you snoop ahead. Now, Board implementations can choose to use certain events to pull bits from the RNG so that the actual ACTIONS taken perturb things, making things branch to the point that prediction is prohibitively hard. A while back, I'd wanted to do this across the board for all actions, but unfortunately in yohoho we have various non-board-altering events that come in and are executed in different orders on client and server, so things fell out of sync pretty quickly. The thought rattled around in my head again, so I'm doing it again. This time, Boards have to explicitly opt in on each event, so they can be sure to restrict it to those that are safe to use. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@896 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -713,6 +713,8 @@ public abstract class PuzzleController extends GameController
|
||||
return;
|
||||
}
|
||||
|
||||
getBoard().seedFromEvent(getPlayerIndex(), event);
|
||||
|
||||
_events.add(Integer.valueOf(event));
|
||||
if (isSyncingBoards()) {
|
||||
_states.add((board == null) ? null : board.clone());
|
||||
|
||||
@@ -85,6 +85,40 @@ public abstract class Board
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows puzzles to add extra noise to their random number generators based on the specific
|
||||
* events sent from the client to make it more difficult for a hacked client to predict things
|
||||
* such as piece generation.
|
||||
*
|
||||
* @param pidx the player index that submitted the progress event.
|
||||
* @param gevent the progress event itself.
|
||||
*/
|
||||
public void seedFromEvent (int pidx, int gevent)
|
||||
{
|
||||
if (isSeedingEvent(pidx, gevent)) {
|
||||
_rando.next(getSeedForEvent(pidx, gevent));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this event is the sort of thing we should use to generate extra noise on
|
||||
* our random number generator.
|
||||
*/
|
||||
protected boolean isSeedingEvent (int pidx, int gevent)
|
||||
{
|
||||
return false; // By default, nothing is
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a number of bits to read off the random number generator for this event.
|
||||
* Subclasses can replace this with something that better understands the formats of its
|
||||
* particular events if desired.
|
||||
*/
|
||||
protected int getSeedForEvent (int pidx, int gevent)
|
||||
{
|
||||
return (pidx ^ gevent) % 7;
|
||||
}
|
||||
|
||||
/** Used to generate random numbers. */
|
||||
protected static class BoardRandom extends Random
|
||||
implements Cloneable
|
||||
|
||||
@@ -371,6 +371,8 @@ public abstract class PuzzleManager extends GameManager
|
||||
compareBoards(pidx, cboard, gevent, before);
|
||||
}
|
||||
|
||||
_boards[pidx].seedFromEvent(pidx, gevent);
|
||||
|
||||
// apply the event to the player's board
|
||||
if (!applyProgressEvent(pidx, gevent, cboard)) {
|
||||
log.warning("Unknown event", "puzzle", where(), "pidx", pidx, "event", gevent);
|
||||
@@ -426,7 +428,7 @@ public abstract class PuzzleManager extends GameManager
|
||||
*
|
||||
* @param pidx the player index that submitted the progress event.
|
||||
* @param gevent the progress event itself.
|
||||
* @param cboard a snapshot of the board on the client iff the client has board syncing
|
||||
* @param cboard a snapshot of the board on the client if the client has board syncing
|
||||
* enabled (which is only enabled when debugging).
|
||||
*
|
||||
* @return true to indicate that the event was handled.
|
||||
|
||||
Reference in New Issue
Block a user