Skip to content

Commit

Permalink
Code changes for readability
Browse files Browse the repository at this point in the history
  • Loading branch information
lscgh committed Feb 9, 2024
1 parent 1dd82b2 commit ddcd20c
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 107 deletions.
19 changes: 5 additions & 14 deletions mavenmcserver/src/main/java/mavenmcserver/Plugin.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package mavenmcserver;

import java.util.HashSet;

import org.bukkit.plugin.java.JavaPlugin;

import mavenmcserver.command.CommandTicTacToe;
import mavenmcserver.command.CommandTicTacToeAccept;
import mavenmcserver.game.Game;
import mavenmcserver.game.Game.GameEndCause;

public class Plugin extends JavaPlugin {

Expand All @@ -19,21 +16,15 @@ public void onLoad() {
@Override
public void onEnable() {
// Register command /tictactoe
new CommandTicTacToe(this);
new CommandTicTacToeAccept(this);
new CommandTicTacToe(this).registerToPlugin();
// Register command /tictactoeaccept
new CommandTicTacToeAccept(this).registerToPlugin();
}

@Override
public void onDisable() {

// Cancel all running games
HashSet<Game> runningGames = new HashSet<Game>();
runningGames.addAll(Game.runningGames.values());

for(Game runningGame: runningGames) {
runningGame.end(GameEndCause.CANCEL);
}

this.getLogger().info("TicTacToe disabled! Cancelling all games...");
Game.cancelAllGames();
}

}
181 changes: 104 additions & 77 deletions mavenmcserver/src/main/java/mavenmcserver/command/CommandTicTacToe.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,19 @@ public class CommandTicTacToe implements CommandExecutor, TabCompleter {
public static int SIZE_Z_INDEX = 2;
public static int WIN_REQUIRED_AMOUNT_INDEX = 3;

public static String CANCEL_KEYWORD = "cancel";
public static String REQUEST_RETURN_MATCH_KEYWORD = "requestReturnMatch";

public static int NO_AVAILABLE_PLAYERS_MIN_ARG_COUNT = 3;
public static String NO_AVAILABLE_PLAYERS_ARGS[] = {"(no", "available", "players)"};

private Plugin plugin;

public CommandTicTacToe(Plugin plugin) {
this.plugin = plugin;

}

public void registerToPlugin() {
this.plugin.getCommand(CommandTicTacToe.COMMAND_NAME).setExecutor(this);
this.plugin.getCommand(CommandTicTacToe.COMMAND_NAME).setTabCompleter(this);
}
Expand All @@ -49,94 +57,113 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
return true;
}

if(args.length > 0) {

boolean playerIsCurrentlyInAGame = Game.runningGames.containsKey((Player)sender);
if(playerIsCurrentlyInAGame && args[0].equals("cancel")) {
Game.runningGames.get((Player)sender).end(GameEndCause.CANCEL);
return true;
}
if(args.length < CommandTicTacToe.MIN_VALID_ARG_COUNT) {
return false;
}

if(args.length > CommandTicTacToe.MAX_VALID_ARG_COUNT) {
sender.sendMessage(ChatColor.RED + "Too many arguments for command '/" + label + "'!" + ChatColor.RESET);
return false;
}
boolean playerIsCurrentlyInAGame = Game.runningGames.containsKey((Player)sender);
boolean playerProvidedCancelKeyword = args[CommandTicTacToe.OPPONENT_ARG_INDEX].equals(CommandTicTacToe.CANCEL_KEYWORD);
if(playerIsCurrentlyInAGame && playerProvidedCancelKeyword) {
Game gameToCancel = Game.runningGames.get((Player)sender);
gameToCancel.end(GameEndCause.CANCEL);
return true;
}

if(args.length > CommandTicTacToe.MAX_VALID_ARG_COUNT) {
sender.sendMessage(ChatColor.RED + "Too many arguments for command '/" + label + "'!" + ChatColor.RESET);
return false;
}

if(CommandTicTacToe.isNoAvailablePlayersPlaceholder(args)) {
return true;
}

if(args[CommandTicTacToe.OPPONENT_ARG_INDEX].equals(CommandTicTacToe.REQUEST_RETURN_MATCH_KEYWORD)) {

int noAvailablePlayersMinArgCount = 3;
if(args.length >= noAvailablePlayersMinArgCount) {
String noAvailablePlayersPlaceholder[] = {"(no", "available", "players)"};
if(args[0].equals(noAvailablePlayersPlaceholder[0]) && args[1].equals(noAvailablePlayersPlaceholder[1]) && args[2].equals(noAvailablePlayersPlaceholder[2])) return true;
}
GameConfig configOfReturnMatch = Game.lostGames.get((Player)sender);

if(args[0].equals("requestReturnMatch")) {
if(configOfReturnMatch != null) {

GameConfig returnConfig = Game.lostGames.get((Player)sender);
// Show the confirmation to the player
sender.sendMessage("You've just asked " + ChatColor.AQUA + ChatColor.BOLD + configOfReturnMatch.opponentPlayer.getName() + ChatColor.RESET + " to play a return match with you!");

if(returnConfig != null) {

// Show the confirmation to the player
sender.sendMessage("You've just asked " + ChatColor.AQUA + ChatColor.BOLD + returnConfig.opponentPlayer.getName() + ChatColor.RESET + " to play a return match with you!");

// Remove config from list!
Game.lostGames.remove((Player)sender);
Game.lostGames.remove(returnConfig.opponentPlayer);

new Game(returnConfig, this.plugin, true);
return true;
}
}

// Create the game's config from the command's args
GameConfig config;

try {
config = this.createGameConfigFromCommand((Player)sender, args);
} catch(InvalidArgCountException | OpponentPlayerNotFoundException | OpponentIsMainPlayerException e) {
sender.sendMessage(ChatColor.RED + e.getMessage() + ChatColor.RESET);
return true;
} catch(NumberFormatException e) {
String nonNumberString = e.getMessage().substring(19, e.getMessage().length() - 1);
sender.sendMessage(ChatColor.RED + "Error: expected number at '" + nonNumberString + "'." + ChatColor.RESET);
return true;
}

// Check for errors in the game's config
List<String> configErrors = config.validate();
if(!configErrors.isEmpty()) {
for(String error: configErrors) {
sender.sendMessage(ChatColor.RED + error + ChatColor.RESET);
}
// Remove config from list!
Game.lostGames.remove((Player)sender);
Game.lostGames.remove(configOfReturnMatch.opponentPlayer);

// Don't continue on error
new Game(configOfReturnMatch, this.plugin, true);
return true;
}
}

// Create the game's config from the command's args
GameConfig config;

try {

ArrayList<Game> queuedGames = new ArrayList<Game>();
queuedGames.addAll(Game.queuedGames.values());
config = this.createGameConfigFromCommand((Player)sender, args);

for(Game queuedGame: queuedGames) {
if(queuedGame.config.mainPlayer == config.mainPlayer) {
Game.queuedGames.remove(queuedGame.uuid);

String revokeMessage;
if(queuedGame.config.opponentPlayer == config.opponentPlayer) {
revokeMessage = ChatColor.AQUA + "" + ChatColor.BOLD + config.mainPlayer.getName() + ChatColor.RESET + " has updated their tic-tac-toe-game request. See below.";
} else {
revokeMessage = ChatColor.AQUA + "" + ChatColor.BOLD + config.mainPlayer.getName() + ChatColor.RESET + " has revoked their tic-tac-toe-game request to you.";
}

queuedGame.config.opponentPlayer.sendMessage(revokeMessage);
}
} catch(InvalidArgCountException | OpponentPlayerNotFoundException | OpponentIsMainPlayerException e) {
sender.sendMessage(ChatColor.RED + e.getMessage() + ChatColor.RESET);
return true;
} catch(NumberFormatException e) {
String nonNumberString = e.getMessage().substring(19, e.getMessage().length() - 1);
sender.sendMessage(ChatColor.RED + "Error: expected number at '" + nonNumberString + "'." + ChatColor.RESET);
return true;
}

// Check for errors in the game's config
List<String> configErrors = config.validateReturningErrors();
if(!configErrors.isEmpty()) {
for(String error: configErrors) {
sender.sendMessage(ChatColor.RED + error + ChatColor.RESET);
}

// Show the confirmation to the player
sender.sendMessage("You've just asked " + ChatColor.AQUA + ChatColor.BOLD + config.opponentPlayer.getName() + ChatColor.RESET + " to play a game of tic-tac-toe with you!");

new Game(config, this.plugin, false);
// Don't continue on error
return true;
}

this.tellAffectedPlayersThatPlayerChangedTheirRequest(config);

// Show the confirmation to the player
sender.sendMessage("You've just asked " + ChatColor.AQUA + ChatColor.BOLD + config.opponentPlayer.getName() + ChatColor.RESET + " to play a game of tic-tac-toe with you!");

new Game(config, this.plugin, false);

return false;
}

private static boolean isNoAvailablePlayersPlaceholder(String[] args) {
if(args.length < CommandTicTacToe.NO_AVAILABLE_PLAYERS_MIN_ARG_COUNT) {
return false;
}

boolean shouldShowUsage = args.length <= 0;
return !shouldShowUsage;
boolean firstArgumentIsPlaceholder = args[0].equals(CommandTicTacToe.NO_AVAILABLE_PLAYERS_ARGS[0]);
boolean secondArgumentIsPlaceholder = args[1].equals(CommandTicTacToe.NO_AVAILABLE_PLAYERS_ARGS[1]);
boolean thirdArgumentIsPlaceholder = args[2].equals(CommandTicTacToe.NO_AVAILABLE_PLAYERS_ARGS[2]);
boolean argumentsArePlaceholder = firstArgumentIsPlaceholder && secondArgumentIsPlaceholder && thirdArgumentIsPlaceholder;

return argumentsArePlaceholder;
}

private void tellAffectedPlayersThatPlayerChangedTheirRequest(GameConfig config) {
ArrayList<Game> queuedGames = new ArrayList<Game>();
queuedGames.addAll(Game.queuedGames.values());

for(Game queuedGame: queuedGames) {
if(queuedGame.config.mainPlayer == config.mainPlayer) {
Game.queuedGames.remove(queuedGame.uuid);

String revokeMessage;
if(queuedGame.config.opponentPlayer == config.opponentPlayer) {
revokeMessage = ChatColor.AQUA + "" + ChatColor.BOLD + config.mainPlayer.getName() + ChatColor.RESET + " has updated their tic-tac-toe-game request. See below.";
} else {
revokeMessage = ChatColor.AQUA + "" + ChatColor.BOLD + config.mainPlayer.getName() + ChatColor.RESET + " has revoked their tic-tac-toe-game request to you.";
}

queuedGame.config.opponentPlayer.sendMessage(revokeMessage);
}
}
}

@Override
Expand All @@ -151,7 +178,7 @@ public List<String> onTabComplete(CommandSender sender, Command command, String
boolean playerIsCurrentlyInAGame = Game.runningGames.containsKey((Player)sender);
if(playerIsCurrentlyInAGame) {
if(argList.size() == CommandTicTacToe.OPPONENT_ARG_INDEX + 1) {
completions.add("cancel");
completions.add(CommandTicTacToe.CANCEL_KEYWORD);
}
} else {
if(argList.size() == CommandTicTacToe.OPPONENT_ARG_INDEX + 1) {
Expand All @@ -162,7 +189,7 @@ public List<String> onTabComplete(CommandSender sender, Command command, String
}

if(Game.lostGames.containsKey((Player)sender)) {
completions.add("requestReturnMatch");
completions.add(CommandTicTacToe.REQUEST_RETURN_MATCH_KEYWORD);
}

if(completions.isEmpty()) completions.add("(no available players)");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,15 @@ public class CommandTicTacToeAccept implements CommandExecutor, TabCompleter {
public static int PLAYER_NAME_ARG_INDEX = 0;
public static String ERROR_EXECUTION_IS_ONLY_ALLOWED_BY_PLAYERS = ChatColor.RED + "this command may only be executed by players" + ChatColor.RESET;

private Plugin plugin;

public CommandTicTacToeAccept(Plugin plugin) {
plugin.getCommand(CommandTicTacToeAccept.COMMAND_NAME).setExecutor(this);
plugin.getCommand(CommandTicTacToeAccept.COMMAND_NAME).setTabCompleter(this);
this.plugin = plugin;
}

public void registerToPlugin() {
this.plugin.getCommand(CommandTicTacToeAccept.COMMAND_NAME).setExecutor(this);
this.plugin.getCommand(CommandTicTacToeAccept.COMMAND_NAME).setTabCompleter(this);
}

@Override
Expand Down
10 changes: 10 additions & 0 deletions mavenmcserver/src/main/java/mavenmcserver/game/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;

Expand Down Expand Up @@ -78,6 +79,15 @@ public static Game getQueuedGameByUUID(String uuidString) throws IllegalArgument
/// Contains all games that are currently running in connection to their players (every game is in this map twice!)
public static HashMap<Player, Game> runningGames = new HashMap<Player, Game>();

public static void cancelAllGames() {
HashSet<Game> runningGames = new HashSet<Game>();
runningGames.addAll(Game.runningGames.values());

for(Game runningGame: runningGames) {
runningGame.end(GameEndCause.CANCEL);
}
}

/// Contains a list of game setups (value) that were lost by player (key) (ties count as well).
public static HashMap<Player, GameConfig> lostGames = new HashMap<Player, GameConfig>();

Expand Down
22 changes: 16 additions & 6 deletions mavenmcserver/src/main/java/mavenmcserver/game/GameConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

public class GameConfig {

public static int MIN_DIMENSION_SIZE = 1;

/**
* The minimum X and Z size of a game
*/
Expand Down Expand Up @@ -55,7 +57,7 @@ public GameConfig(Player mainPlayer, Player opponentPlayer, Vector3i size, int w
* Checks the config for errors.
* @return a list with all errors found on this config. If no errors are found, an empty list is returned.
*/
public List<String> validate() {
public List<String> validateReturningErrors() {
ArrayList<String> errors = new ArrayList<String>();

if(this.mainPlayer == null) {
Expand All @@ -78,7 +80,7 @@ public List<String> validate() {
return errors;
}

errors.addAll(this.validateNumbers());
errors.addAll(this.validateNumbersReturningErrors());

return errors;
}
Expand All @@ -87,24 +89,32 @@ public List<String> validate() {
* Checks the config for errors with the size and winRequiredAmount (part of validate()).
* @return a list with all errors found on this config regarding the number values. If no errors are found, an empty list is returned.
*/
List<String> validateNumbers() {
List<String> validateNumbersReturningErrors() {
ArrayList<String> errors = new ArrayList<String>();

if(Math.min(this.size.x, Math.min(this.size.y, this.size.z)) <= 0) {
errors.add("No dimension of the game can be smaller than 1. The smallest possible game is (" + GameConfig.MIN_X_Z_SIZE + ", " + GameConfig.MIN_HEIGHT + ", " + GameConfig.MIN_X_Z_SIZE + ").");
if(this.getSmallestDimension() < GameConfig.MIN_DIMENSION_SIZE) {
errors.add("No dimension of the game can be smaller than " + GameConfig.MIN_DIMENSION_SIZE + ". The smallest possible game is (" + GameConfig.MIN_X_Z_SIZE + ", " + GameConfig.MIN_HEIGHT + ", " + GameConfig.MIN_X_Z_SIZE + ").");
}

if(Math.min(this.size.x, this.size.z) < GameConfig.MIN_X_Z_SIZE) {
errors.add("The X and Z size of the game must not be smaller than " + GameConfig.MIN_X_Z_SIZE + ".");
}

if(this.winRequiredAmount > Math.max(this.size.x, Math.max(this.size.y, this.size.z))) {
if(this.winRequiredAmount > this.getLargestDimension()) {
errors.add(GameConfig.ERROR_WIN_REQUIRED_AMOUNT_TOO_LARGE);
}

return errors;
}

public int getSmallestDimension() {
return Math.min(this.size.x, Math.min(this.size.y, this.size.z));
}

public int getLargestDimension() {
return Math.max(this.size.x, Math.max(this.size.y, this.size.z));
}


@Override
public String toString() {
Expand Down
11 changes: 8 additions & 3 deletions mavenmcserver/src/main/resources/classes.uml
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,22 @@ class FieldPoint {
+{static}int MIN_X_Z_SIZE
+{static}int MIN_HEIGHT
{static}String ERROR_MAIN_PLAYER_NULL
{static}String ERROR_OPPONENT_PLAYER_NULL
{static}String ERROR_PLAYER_ALREADY_IN_GAME
{static}String ERROR_WIN_REQUIRED_AMOUNT_TOO_LARGE

.. Fields ..
+{final}Player mainPlayer
+Player mainPlayer
+Player opponentPlayer
+Vector3i size
+int winRequiredAmount

.. Methods ..
+GameConfig(Player mainPlayer, Player opponentPlayer, Vector3i size, int winRequiredAmount)
+List<String> validate() /' Returns a list of errors in the config! Empty means OK '/
List<String> validateNumbers() /' sub-part of validate() '/
+List<String> validateReturningErrors() /' Returns a list of errors in the config! Empty means OK '/
List<String> validateNumbersReturningErrors() /' sub-part of validateReturningErrors() '/
+int getSmallestDimenson()
+int getLargestDimension()
}


Expand Down
Loading

0 comments on commit ddcd20c

Please sign in to comment.