diff --git a/src/java/com/threerings/puzzle/client/PuzzleController.java b/src/java/com/threerings/puzzle/client/PuzzleController.java index 56f287e3..61dffaad 100644 --- a/src/java/com/threerings/puzzle/client/PuzzleController.java +++ b/src/java/com/threerings/puzzle/client/PuzzleController.java @@ -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()); diff --git a/src/java/com/threerings/puzzle/data/Board.java b/src/java/com/threerings/puzzle/data/Board.java index 3ebe20a7..bd8983ca 100644 --- a/src/java/com/threerings/puzzle/data/Board.java +++ b/src/java/com/threerings/puzzle/data/Board.java @@ -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 diff --git a/src/java/com/threerings/puzzle/server/PuzzleManager.java b/src/java/com/threerings/puzzle/server/PuzzleManager.java index 62aef0b4..42834bee 100644 --- a/src/java/com/threerings/puzzle/server/PuzzleManager.java +++ b/src/java/com/threerings/puzzle/server/PuzzleManager.java @@ -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.