diff --git a/Mage.Server/src/mage/server/Main.java b/Mage.Server/src/mage/server/Main.java index 1e92cada92..ba76b86a7a 100644 --- a/Mage.Server/src/mage/server/Main.java +++ b/Mage.Server/src/mage/server/Main.java @@ -28,16 +28,16 @@ package mage.server; +import mage.server.util.PluginClassLoader; import java.io.File; -import java.net.URL; -import java.net.URLClassLoader; import java.util.logging.Level; import java.util.logging.Logger; -import mage.interfaces.Server; +import mage.server.game.DeckValidatorFactory; import mage.server.game.GameFactory; import mage.server.game.PlayerFactory; import mage.server.util.ConfigSettings; import mage.server.util.config.Plugin; +import mage.util.Copier; import mage.util.Logging; /** @@ -49,8 +49,10 @@ public class Main { private static Logger logger = Logging.getLogger(Main.class.getName()); private final static String testModeArg = "-testMode="; + private final static String pluginFolder = "plugins"; - private static Server server; + public static PluginClassLoader classLoader = new PluginClassLoader(); + public static ServerImpl server; /** * @param args the command line arguments @@ -58,6 +60,7 @@ public class Main { public static void main(String[] args) { logger.info("Starting MAGE server version " + Main.class.getPackage().getImplementationVersion()); + logger.info("Logging level: " + logger.getLevel()); ConfigSettings config = ConfigSettings.getInstance(); for (Plugin plugin: config.getGameTypes()) { GameFactory.getInstance().addGameType(plugin.getName(), loadPlugin(plugin)); @@ -65,12 +68,16 @@ public class Main { for (Plugin plugin: config.getPlayerTypes()) { PlayerFactory.getInstance().addPlayerType(plugin.getName(), loadPlugin(plugin)); } + for (Plugin plugin: config.getDeckTypes()) { + DeckValidatorFactory.getInstance().addDeckType(plugin.getName(), loadPlugin(plugin)); + } boolean testMode = false; for (String arg: args) { if (arg.startsWith(testModeArg)) { testMode = Boolean.valueOf(arg.replace(testModeArg, "")); } } + Copier.setLoader(classLoader); System.setProperty("java.rmi.server.hostname", config.getServerAddress()); server = new ServerImpl(config.getPort(), config.getServerName(), testMode); @@ -78,10 +85,11 @@ public class Main { private static Class loadPlugin(Plugin plugin) { try { - File jarFile = new File("plugins/" + plugin.getJar()); - URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[] { jarFile.toURI().toURL() }, Main.class.getClassLoader()); - logger.info("Loaded plugin: " + plugin.getClassName()); - return Class.forName(plugin.getClassName(), true, urlClassLoader); + classLoader.addURL(new File(pluginFolder + "/" + plugin.getJar()).toURI().toURL()); + logger.info("Loading plugin: " + plugin.getClassName()); + return Class.forName(plugin.getClassName(), true, classLoader); + } catch (ClassNotFoundException ex) { + logger.log(Level.SEVERE, "Plugin not Found:" + plugin.getJar() + " - check plugin folder"); } catch (Exception ex) { logger.log(Level.SEVERE, "Error loading plugin " + plugin.getJar(), ex); } diff --git a/Mage.Server/src/mage/server/ServerImpl.java b/Mage.Server/src/mage/server/ServerImpl.java index 5c363c7502..39eeb4feca 100644 --- a/Mage.Server/src/mage/server/ServerImpl.java +++ b/Mage.Server/src/mage/server/ServerImpl.java @@ -38,11 +38,12 @@ import java.util.List; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; -import mage.Constants.DeckType; import mage.cards.decks.DeckCardLists; +import mage.game.GameException; import mage.interfaces.MageException; import mage.interfaces.Server; import mage.interfaces.callback.ClientCallback; +import mage.server.game.DeckValidatorFactory; import mage.server.game.GameFactory; import mage.server.game.GameManager; import mage.server.game.GamesRoomManager; @@ -70,11 +71,15 @@ public class ServerImpl extends RemoteServer implements Server { reg.rebind(name, stub); this.testMode = testMode; logger.info("Started MAGE server - listening on port " + port); - logger.info("MAGE server running in test mode"); + if (testMode) + logger.info("MAGE server running in test mode"); } catch (RemoteException ex) { logger.log(Level.SEVERE, "Failed to start RMI server at port " + port, ex); } + } + public boolean isTestMode() { + return testMode; } @Override @@ -82,16 +87,6 @@ public class ServerImpl extends RemoteServer implements Server { return SessionManager.getInstance().getSession(sessionId).callback(); } -// @Override -// public String getClientIp() throws RemoteException, MageException { -// try { -// return getClientHost(); -// } catch (Exception ex) { -// handleException(ex); -// } -// return null; -// } - @Override public UUID registerClient(String userName, UUID clientId) throws MageException, RemoteException { @@ -106,7 +101,7 @@ public class ServerImpl extends RemoteServer implements Server { } @Override - public TableView createTable(UUID sessionId, UUID roomId, String gameType, DeckType deckType, List playerTypes) throws MageException { + public TableView createTable(UUID sessionId, UUID roomId, String gameType, String deckType, List playerTypes) throws MageException { try { TableView table = GamesRoomManager.getInstance().getRoom(roomId).createTable(sessionId, gameType, deckType, playerTypes); logger.info("Table " + table.getTableId() + " created"); @@ -129,13 +124,15 @@ public class ServerImpl extends RemoteServer implements Server { } @Override - public boolean joinTable(UUID sessionId, UUID roomId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws MageException { + public boolean joinTable(UUID sessionId, UUID roomId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws MageException, GameException { try { boolean ret = GamesRoomManager.getInstance().getRoom(roomId).joinTable(sessionId, tableId, seatNum, name, deckList); logger.info("Session " + sessionId + " joined table " + tableId); return ret; } catch (Exception ex) { + if (ex instanceof GameException) + throw (GameException)ex; handleException(ex); } return false; @@ -443,6 +440,17 @@ public class ServerImpl extends RemoteServer implements Server { return null; } + @Override + public String[] getDeckTypes() throws MageException { + try { + return DeckValidatorFactory.getInstance().getDeckTypes().toArray(new String[0]); + } + catch (Exception ex) { + handleException(ex); + } + return null; + } + @Override public void cheat(UUID gameId, UUID sessionId, DeckCardLists deckList) throws MageException { try { diff --git a/Mage.Server/src/mage/server/game/DeckValidatorFactory.java b/Mage.Server/src/mage/server/game/DeckValidatorFactory.java new file mode 100644 index 0000000000..2065535ff9 --- /dev/null +++ b/Mage.Server/src/mage/server/game/DeckValidatorFactory.java @@ -0,0 +1,83 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.server.game; + +import java.lang.reflect.Constructor; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import mage.cards.decks.*; +import java.util.logging.Logger; +import mage.Constants; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class DeckValidatorFactory { + + private final static DeckValidatorFactory INSTANCE = new DeckValidatorFactory(); + private final static Logger logger = Logging.getLogger(DeckValidatorFactory.class.getName()); + + private Map deckTypes = new HashMap(); + + public static DeckValidatorFactory getInstance() { + return INSTANCE; + } + + private DeckValidatorFactory() {} + + public DeckValidator createDeckValidator(String deckType) { + + DeckValidator validator; + Constructor con; + try { + con = deckTypes.get(deckType).getConstructor(new Class[]{}); + validator = (DeckValidator)con.newInstance(new Object[] {}); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + return null; + } + logger.info("Deck validator created: " + validator.getName()); + + return validator; + } + + public Set getDeckTypes() { + return deckTypes.keySet(); + } + + public void addDeckType(String name, Class deckType) { + if (deckType != null) + this.deckTypes.put(name, deckType); + } + +} diff --git a/Mage.Server/src/mage/server/game/GameController.java b/Mage.Server/src/mage/server/game/GameController.java index 3f906c251b..9993872886 100644 --- a/Mage.Server/src/mage/server/game/GameController.java +++ b/Mage.Server/src/mage/server/game/GameController.java @@ -36,6 +36,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.logging.Level; import java.util.logging.Logger; +import mage.abilities.Ability; import mage.abilities.ActivatedAbility; import mage.cards.Card; import mage.cards.Cards; @@ -48,7 +49,6 @@ import mage.server.ChatManager; import mage.server.util.ThreadExecutor; import mage.game.events.Listener; import mage.game.events.PlayerQueryEvent; -import mage.human.HumanPlayer; import mage.players.Player; import mage.util.Logging; import mage.view.AbilityPickerView; @@ -94,7 +94,7 @@ public class GameController implements GameCallback { break; case INFO: ChatManager.getInstance().broadcast(chatId, "", event.getMessage()); - logger.fine(game.getId() + " " + event.getMessage()); + logger.finest(game.getId() + " " + event.getMessage()); break; } } @@ -111,6 +111,9 @@ public class GameController implements GameCallback { case PICK_TARGET: target(event.getPlayerId(), event.getMessage(), event.getCards(), event.isRequired()); break; + case PICK_ABILITY: + target(event.getPlayerId(), event.getMessage(), event.getAbilities(), event.isRequired()); + break; case SELECT: select(event.getPlayerId(), event.getMessage()); break; @@ -160,7 +163,7 @@ public class GameController implements GameCallback { private boolean allJoined() { for (Player player: game.getPlayers().values()) { - if (player instanceof HumanPlayer && gameSessions.get(player.getId()) == null) { + if (player.isHuman() && gameSessions.get(player.getId()) == null) { return false; } } @@ -204,10 +207,6 @@ public class GameController implements GameCallback { updateGame(); } -// public void timeout(UUID sessionId) { -// kill(sessionId); -// } - public void kill(UUID sessionId) { if (sessionPlayerMap.containsKey(sessionId)) { gameSessions.get(sessionPlayerMap.get(sessionId)).setKilled(); @@ -277,7 +276,7 @@ public class GameController implements GameCallback { gameSessions.get(playerId).ask(question, getGameView(playerId)); } - private void chooseAbility(UUID playerId, Collection choices) { + private void chooseAbility(UUID playerId, Collection choices) { informOthers(playerId); gameSessions.get(playerId).chooseAbility(new AbilityPickerView(choices)); } @@ -289,7 +288,12 @@ public class GameController implements GameCallback { private void target(UUID playerId, String question, Cards cards, boolean required) { informOthers(playerId); - gameSessions.get(playerId).target(question, getCardView(cards), required, getGameView(playerId)); + gameSessions.get(playerId).target(question, new CardsView(cards), required, getGameView(playerId)); + } + + private void target(UUID playerId, String question, Collection abilities, boolean required) { + informOthers(playerId); + gameSessions.get(playerId).target(question, new CardsView(abilities, game), required, getGameView(playerId)); } private void select(UUID playerId, String message) { @@ -314,7 +318,7 @@ public class GameController implements GameCallback { private void revealCards(String name, Cards cards) { for (GameSession session: gameSessions.values()) { - session.revealCards(name, getCardView(cards)); + session.revealCards(name, new CardsView(cards)); } } @@ -336,16 +340,10 @@ public class GameController implements GameCallback { private GameView getGameView(UUID playerId) { GameView gameView = new GameView(game.getState()); - gameView.setHand(getCardView(game.getPlayer(playerId).getHand())); + gameView.setHand(new CardsView(game.getPlayer(playerId).getHand())); return gameView; } - private CardsView getCardView(Cards cards) { - if (cards == null) - return null; - return new CardsView(cards.values()); - } - @Override public void gameResult(String result) { endGame(result); diff --git a/Mage.Server/src/mage/server/game/GameFactory.java b/Mage.Server/src/mage/server/game/GameFactory.java index cbf0a0c8e8..4326928702 100644 --- a/Mage.Server/src/mage/server/game/GameFactory.java +++ b/Mage.Server/src/mage/server/game/GameFactory.java @@ -35,6 +35,7 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import mage.game.Game; +import mage.server.Main; import mage.util.Logging; /** @@ -68,7 +69,6 @@ public class GameFactory { logger.info("Game created: " + game.getId().toString()); return game; - } public Set getGameTypes() { @@ -76,7 +76,8 @@ public class GameFactory { } public void addGameType(String name, Class gameType) { - this.gameTypes.put(name, gameType); + if (gameType != null) + this.gameTypes.put(name, gameType); } } diff --git a/Mage.Server/src/mage/server/game/GameSession.java b/Mage.Server/src/mage/server/game/GameSession.java index b684a68aef..fe3da1a1c9 100644 --- a/Mage.Server/src/mage/server/game/GameSession.java +++ b/Mage.Server/src/mage/server/game/GameSession.java @@ -67,20 +67,6 @@ public class GameSession extends GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameAsk", new GameClientMessage(gameView, question))); } -// setupTimeout(); -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.ask(question, gameView); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); -// } } public void target(final String question, final CardsView cardView, final boolean required, final GameView gameView) { @@ -89,21 +75,6 @@ public class GameSession extends GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameTarget", new GameClientMessage(gameView, question, cardView, required))); } -// if (!killed) { -// setupTimeout(); -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.target(question, cardView, required, gameView); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); -// } } public void select(final String message, final GameView gameView) { @@ -112,21 +83,6 @@ public class GameSession extends GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameSelect", new GameClientMessage(gameView, message))); } -// if (!killed) { -// setupTimeout(); -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.select(message, gameView); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); -// } } public void chooseAbility(final AbilityPickerView abilities) { @@ -135,21 +91,6 @@ public class GameSession extends GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameChooseAbility", abilities)); } -// if (!killed) { -// setupTimeout(); -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.chooseAbility(abilities); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); -// } } public void choose(final String message, final String[] choices) { @@ -158,21 +99,6 @@ public class GameSession extends GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameChoose", new GameClientMessage(choices, message))); } -// if (!killed) { -// setupTimeout(); -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.choose(message, choices); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); -// } } public void playMana(final String message, final GameView gameView) { @@ -181,21 +107,6 @@ public class GameSession extends GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gamePlayMana", new GameClientMessage(gameView, message))); } -// if (!killed) { -// setupTimeout(); -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.playMana(message, gameView); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); -// } } public void playXMana(final String message, final GameView gameView) { @@ -204,21 +115,6 @@ public class GameSession extends GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gamePlayXMana", new GameClientMessage(gameView, message))); } -// if (!killed) { -// setupTimeout(); -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.playXMana(message, gameView); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); -// } } public void getAmount(final String message, final int min, final int max) { @@ -227,21 +123,6 @@ public class GameSession extends GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameSelectAmount", new GameClientMessage(message, min, max))); } -// if (!killed) { -// setupTimeout(); -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.getAmount(min, max); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); -// } } public void revealCards(final String name, final CardsView cardView) { @@ -250,20 +131,6 @@ public class GameSession extends GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameReveal", new GameClientMessage(cardView, name))); } -// if (!killed) { -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.revealCards(name, cardView); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); -// } } diff --git a/Mage.Server/src/mage/server/game/GameWatcher.java b/Mage.Server/src/mage/server/game/GameWatcher.java index c70949448a..337e9045fd 100644 --- a/Mage.Server/src/mage/server/game/GameWatcher.java +++ b/Mage.Server/src/mage/server/game/GameWatcher.java @@ -45,7 +45,6 @@ import mage.view.GameView; */ public class GameWatcher { -// protected static ExecutorService rmiExecutor = ThreadExecutor.getInstance().getRMIExecutor(); protected final static Logger logger = Logging.getLogger(GameWatcher.class.getName()); protected UUID sessionId; @@ -63,18 +62,6 @@ public class GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameInit", gameView)); } -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.init(gameView); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); } public void update(final GameView gameView) { @@ -83,18 +70,6 @@ public class GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameUpdate", gameView)); } -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.update(gameView); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); } public void inform(final String message, final GameView gameView) { @@ -103,18 +78,6 @@ public class GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameInform", new GameClientMessage(gameView, message))); } -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.inform(message, gameView); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); } public void gameOver(final String message) { @@ -123,18 +86,6 @@ public class GameWatcher { if (session != null) session.fireCallback(new ClientCallback("gameOver", message)); } -// rmiExecutor.submit( -// new Runnable() { -// @Override -// public void run() { -// try { -// client.gameOver(message); -// } catch (RemoteException ex) { -// handleRemoteException(ex); -// } -// } -// } -// ); } protected void handleRemoteException(RemoteException ex) { diff --git a/Mage.Server/src/mage/server/game/GamesRoom.java b/Mage.Server/src/mage/server/game/GamesRoom.java index 2a681be20f..cdf6887cfa 100644 --- a/Mage.Server/src/mage/server/game/GamesRoom.java +++ b/Mage.Server/src/mage/server/game/GamesRoom.java @@ -31,8 +31,8 @@ package mage.server.game; import java.util.Collection; import java.util.List; import java.util.UUID; -import mage.Constants.DeckType; import mage.cards.decks.DeckCardLists; +import mage.game.GameException; import mage.view.TableView; /** @@ -42,8 +42,8 @@ import mage.view.TableView; public interface GamesRoom extends Room { public Collection getTables(); - public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList); - public TableView createTable(UUID sessionId, String gameType, DeckType deckType, List playerTypes); + public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws GameException; + public TableView createTable(UUID sessionId, String gameType, String deckType, List playerTypes); public void removeTable(UUID sessionId, UUID tableId); public TableView getTable(UUID tableId); public void leaveTable(UUID sessionId, UUID tableId); diff --git a/Mage.Server/src/mage/server/game/GamesRoomImpl.java b/Mage.Server/src/mage/server/game/GamesRoomImpl.java index 6e9caac353..a86ae813ec 100644 --- a/Mage.Server/src/mage/server/game/GamesRoomImpl.java +++ b/Mage.Server/src/mage/server/game/GamesRoomImpl.java @@ -35,8 +35,8 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; -import mage.Constants.DeckType; import mage.cards.decks.DeckCardLists; +import mage.game.GameException; import mage.game.Table; import mage.util.Logging; import mage.view.TableView; @@ -61,7 +61,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { } @Override - public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) { + public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws GameException { if (tables.containsKey(tableId)) { return TableManager.getInstance().joinTable(sessionId, tableId, seatNum, name, deckList); } else { @@ -70,7 +70,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { } @Override - public TableView createTable(UUID sessionId, String gameType, DeckType deckType, List playerTypes) { + public TableView createTable(UUID sessionId, String gameType, String deckType, List playerTypes) { Table table = TableManager.getInstance().createTable(sessionId, gameType, deckType, playerTypes); tables.put(table.getId(), table); return new TableView(table); diff --git a/Mage.Server/src/mage/server/game/PlayerFactory.java b/Mage.Server/src/mage/server/game/PlayerFactory.java index 559484bf6a..80013e808c 100644 --- a/Mage.Server/src/mage/server/game/PlayerFactory.java +++ b/Mage.Server/src/mage/server/game/PlayerFactory.java @@ -72,8 +72,9 @@ public class PlayerFactory { return playerTypes.keySet(); } - public void addPlayerType(String name, Class gameType) { - this.playerTypes.put(name, gameType); + public void addPlayerType(String name, Class playerType) { + if (playerType != null) + this.playerTypes.put(name, playerType); } } diff --git a/Mage.Server/src/mage/server/game/TableController.java b/Mage.Server/src/mage/server/game/TableController.java index bccb59f8ae..3152dc3aed 100644 --- a/Mage.Server/src/mage/server/game/TableController.java +++ b/Mage.Server/src/mage/server/game/TableController.java @@ -34,7 +34,6 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; -import mage.Constants.DeckType; import mage.Constants.TableState; import mage.cards.decks.Deck; import mage.cards.decks.DeckCardLists; @@ -44,6 +43,7 @@ import mage.game.Seat; import mage.game.Table; import mage.players.Player; import mage.server.ChatManager; +import mage.server.Main; import mage.server.SessionManager; import mage.util.Logging; @@ -61,38 +61,31 @@ public class TableController { private Game game; private ConcurrentHashMap sessionPlayerMap = new ConcurrentHashMap(); - public TableController(UUID sessionId, String gameType, DeckType deckType, List playerTypes) { + public TableController(UUID sessionId, String gameType, String deckType, List playerTypes) { this.sessionId = sessionId; chatId = ChatManager.getInstance().createChatSession(); game = GameFactory.getInstance().createGame(gameType); - table = new Table(game, deckType, playerTypes); + table = new Table(game, DeckValidatorFactory.getInstance().createDeckValidator(deckType), playerTypes); } - public synchronized boolean joinTable(UUID sessionId, int seatNum, String name, DeckCardLists deckList) { + public synchronized boolean joinTable(UUID sessionId, int seatNum, String name, DeckCardLists deckList) throws GameException { if (table.getState() != TableState.WAITING) { return false; } - try { - Seat seat = table.getSeats()[seatNum]; - Deck deck = Deck.load(deckList); - if (validDeck(deck)) { - Player player = createPlayer(name, deck, seat.getPlayerType()); - table.joinTable(player, seatNum); - logger.info("player joined " + player.getId()); - //only add human players to sessionPlayerMap - if (table.getSeats()[seatNum].getPlayerType().equals("Human")) { - //TODO: add isHuman property to Player and check that instead - sessionPlayerMap.put(sessionId, player.getId()); - } - } - else { - throw new GameException("Invalid deck type"); - } - - } catch (GameException ex) { - logger.warning(ex.getMessage()); - return false; + Seat seat = table.getSeats()[seatNum]; + Deck deck = Deck.load(deckList); + if (!Main.server.isTestMode() && !validDeck(deck)) { + throw new GameException(name + " has an invalid deck for this format"); } + + Player player = createPlayer(name, deck, seat.getPlayerType()); + table.joinTable(player, seatNum); + logger.info("player joined " + player.getId()); + //only add human players to sessionPlayerMap + if (table.getSeats()[seatNum].getPlayer().isHuman()) { + sessionPlayerMap.put(sessionId, player.getId()); + } + return true; } diff --git a/Mage.Server/src/mage/server/game/TableManager.java b/Mage.Server/src/mage/server/game/TableManager.java index a1333ea185..089045d602 100644 --- a/Mage.Server/src/mage/server/game/TableManager.java +++ b/Mage.Server/src/mage/server/game/TableManager.java @@ -33,8 +33,8 @@ import java.util.List; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; -import mage.Constants.DeckType; import mage.cards.decks.DeckCardLists; +import mage.game.GameException; import mage.game.Table; import mage.util.Logging; @@ -54,7 +54,7 @@ public class TableManager { return INSTANCE; } - public Table createTable(UUID sessionId, String gameType, DeckType deckType, List playerTypes) { + public Table createTable(UUID sessionId, String gameType, String deckType, List playerTypes) { TableController tableController = new TableController(sessionId, gameType, deckType, playerTypes); controllers.put(tableController.getTable().getId(), tableController); tables.put(tableController.getTable().getId(), tableController.getTable()); @@ -69,7 +69,7 @@ public class TableManager { return tables.values(); } - public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) { + public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws GameException { return controllers.get(tableId).joinTable(sessionId, seatNum, name, deckList); } diff --git a/Mage.Server/src/mage/server/util/Config.xsd b/Mage.Server/src/mage/server/util/Config.xsd index 8a7a7c67fa..20c7319dea 100644 --- a/Mage.Server/src/mage/server/util/Config.xsd +++ b/Mage.Server/src/mage/server/util/Config.xsd @@ -8,12 +8,14 @@ + + @@ -44,5 +46,13 @@ - + + + + + + + + + diff --git a/Mage.Server/src/mage/server/util/ConfigSettings.java b/Mage.Server/src/mage/server/util/ConfigSettings.java index bc2df66a6f..c5c1e098de 100644 --- a/Mage.Server/src/mage/server/util/ConfigSettings.java +++ b/Mage.Server/src/mage/server/util/ConfigSettings.java @@ -91,4 +91,8 @@ public class ConfigSettings { return config.getGameTypes().getPlugin(); } + public List getDeckTypes() { + return config.getDeckTypes().getPlugin(); + } + } diff --git a/Mage.Server/src/mage/server/util/PluginClassLoader.java b/Mage.Server/src/mage/server/util/PluginClassLoader.java new file mode 100644 index 0000000000..4d58e989be --- /dev/null +++ b/Mage.Server/src/mage/server/util/PluginClassLoader.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.server.util; + +import java.net.URL; +import java.net.URLClassLoader; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PluginClassLoader extends URLClassLoader { + + public PluginClassLoader(){ + super(new URL[0], PluginClassLoader.class.getClassLoader()); + } + + @Override + public void addURL(URL url) { + super.addURL(url); + } + + @Override + public Class loadClass(String name) throws ClassNotFoundException { + // First check whether it's already been loaded, if so use it + Class loadedClass = findLoadedClass(name); + + // Not loaded, try to load it + if (loadedClass == null) { + try { + // Ignore parent delegation and just try to load locally + loadedClass = findClass(name); + } catch (ClassNotFoundException e) { + // Swallow exception - does not exist locally + } + + // If not found locally, use normal parent delegation in URLClassloader + if (loadedClass == null) { + // throws ClassNotFoundException if not found in delegation hierarchy at all + loadedClass = super.loadClass(name); + } + } + // will never return null (ClassNotFoundException will be thrown) + return loadedClass; + } + + +}