@Override
	public void playerGamePlay(RSAService rsaService, ComService comServ,
			User gameUser, ArrayList<User> gameUsers, SigService sig,
			SearchGamesTask jgt) throws InvalidKeyException,
			InvalidKeySpecException, NoSuchAlgorithmException,
			NoSuchPaddingException, NoSuchProviderException,
			IllegalBlockSizeException, BadPaddingException, IOException,
			InterruptedException {

		EncryptedHand myHand;
		EncryptedCommunityCards encComCards;

		PublicKey gameHostsPubKey = gameUsers.get(0).getPublicKey();

		// take requests to decrypt a hand
		comServ.decryptEncryptedHands(rsaService, gameUsers.size() - 1);

		// need to pass in the game hosts public key... the game host
		comServ.waitEncryptedDeck(rsaService, gameHostsPubKey);
		System.out
				.println("Got encrypted deck and encrypted again with my key.");

		// wait for cards
		myHand = comServ.waitEncryptedHand();
		gameUser.setUsersOriginalHand(myHand);

		System.out.println("Got my cards!");
		
		//Add additional encryption on top of requests.... used to prevent replay attacks
		RSAService overEncryption = new RSAService(rsaService.getP(), rsaService.getQ());
		myHand = overEncryption.encryptEncHand(myHand);

		// copy and randomly shuffle the user list to distribute requests
		@SuppressWarnings("unchecked")
		ArrayList<User> tmpGameUsers = (ArrayList<User>) gameUsers.clone();
		Collections.shuffle(tmpGameUsers);
		for (Iterator<User> usr = tmpGameUsers.iterator(); usr.hasNext();) {
			User tmpUser = usr.next();
			if (!tmpUser.getID().equals(gameUser.getID())) {
				sig.createSignature(myHand);
				myHand = comServ.requestDecryptHand(myHand, tmpUser);
			}

		}

		myHand = rsaService.decyrptEncHand(myHand);
		Hand hand = overEncryption.decyrptHand(myHand);
		gameUser.setUsersHand(hand);

		String card1 = Character.toString(hand.data.get(0).cardType) + "-"
				+ new String(hand.data.get(0).suit);
		String card2 = Character.toString(hand.data.get(1).cardType) + "-"
				+ new String(hand.data.get(1).suit);
		System.out.println("My Cards: " + card1 + " " + card2);

		jgt.waitForInstructionsBuffer.put(card1);
		jgt.waitForInstructionsBuffer.put(card2);

		// subscribe to next lot of notification
		comServ.decryptCommunityCards(rsaService, gameUsers.size() - 1, false);

		// notify have hand and wait for community cards
		encComCards = comServ.listenForCommunityCards();

		// now stop decrypting hands
		comServ.stopDecryptingHands();

		// start decrypting the community cards
		for (Iterator<User> usr = gameUsers.iterator(); usr.hasNext();) {
			User tmpUser = usr.next();
			if (!tmpUser.getID().equals(gameUser.getID())) {
				sig.createSignature(encComCards);
				encComCards = comServ.requestDecryptComCards(encComCards,
						tmpUser);
			} else {
				User duplicateUser = new User(gameUser.getUsername(),
						gameUser.getID(), gameUser.getPublicKey());
				encComCards.addUserToDecryptedTable(duplicateUser);
			}

		}

		CommunityCards comCards = rsaService.decyrptComCards(encComCards);
		System.out.println("Community Cards:");
		String communityCardsToBeSentToJoiner = "";
		for (int i = 0; i < CommunityCards.NUM_CARDS; i++) {
			communityCardsToBeSentToJoiner = communityCardsToBeSentToJoiner
					.concat(Character.toString(comCards.data.get(i).cardType)
							+ "-" + new String(comCards.data.get(i).suit) + " ");
			System.out
					.println(Character.toString(comCards.data.get(i).cardType)
							+ "-" + new String(comCards.data.get(i).suit));
		}

		// start listening for users hands
		comServ.listenUsersHands();

		// verify community cards
		System.out.println("Verifying community cards!");
		comServ.verifyCommunityCards(comCards);
		System.out.println("Community cards verified!");

		// now stop decrypting community cards
		comServ.stopDecryptingComCards();

		jgt.waitForInstructionsBuffer.put(communityCardsToBeSentToJoiner);

		// now broadcast you hand and wait for other hands
		comServ.broadcastMyHand(gameUser);
		ArrayList<User> userHands = comServ.blockUntilHaveUsersHands();
		
		System.out.println("\nUsers Cards:");
		
		for (int i = 0; i < userHands.size(); i++) {
			User tmpUser = userHands.get(i);
			Hand tmpHand = tmpUser.getUsersHand();
			if (tmpUser.getID().equals(gameUser.getID())) {
				System.out.println("Username: Me");
			} else {
				System.out.println("Username: " + tmpUser.getUsername().toString());
			}
			System.out.println("First Card: "
					+ Character.toString(tmpHand.data.get(0).cardType) + "-"
					+ tmpHand.data.get(0).suit.toString());
			System.out.println("Second Card: "
					+ Character.toString(tmpHand.data.get(1).cardType) + "-"
					+ tmpHand.data.get(1).suit.toString());
		}

		// now determine the winner and check the winners cards
		User winner = determineWinner(comCards, userHands);

		if (!rsaService.checkWinnersHand(gameUser, userHands, winner,
				rsaService)) {
			comServ.callCheat(ComService.HAND_VERIFICATION_FAILED);
		}

		System.out.println("Winner was: " + new String(winner.getUsername()));
		jgt.waitForInstructionsBuffer.put(winner.getUsername());

	}