diff --git a/Mage.Server/build.xml b/Mage.Server/build.xml new file mode 100644 index 00000000000..467d482a0f7 --- /dev/null +++ b/Mage.Server/build.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + Builds, tests, and runs the project Mage.Server. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Server/catalog.xml b/Mage.Server/catalog.xml new file mode 100644 index 00000000000..2db64342c3e --- /dev/null +++ b/Mage.Server/catalog.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml new file mode 100644 index 00000000000..5b6dbf522bb --- /dev/null +++ b/Mage.Server/config/config.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/Mage.Server/manifest.mf b/Mage.Server/manifest.mf new file mode 100644 index 00000000000..1574df4a2de --- /dev/null +++ b/Mage.Server/manifest.mf @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +X-COMMENT: Main-Class will be added automatically by build + diff --git a/Mage.Server/nbproject/build-impl.xml b/Mage.Server/nbproject/build-impl.xml new file mode 100644 index 00000000000..5f9f8012a6b --- /dev/null +++ b/Mage.Server/nbproject/build-impl.xml @@ -0,0 +1,713 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + + + + + + java -cp "${run.classpath.with.dist.jar}" ${main.class} + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Server/nbproject/genfiles.properties b/Mage.Server/nbproject/genfiles.properties new file mode 100644 index 00000000000..d1a8818d3cb --- /dev/null +++ b/Mage.Server/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=0771c912 +build.xml.script.CRC32=7fe29de1 +build.xml.stylesheet.CRC32=958a1d3e@1.26.2.45 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=c70740ce +nbproject/build-impl.xml.script.CRC32=5b9b3297 +nbproject/build-impl.xml.stylesheet.CRC32=5c621a33@1.26.2.45 diff --git a/Mage.Server/nbproject/project.properties b/Mage.Server/nbproject/project.properties new file mode 100644 index 00000000000..810bafcdbdc --- /dev/null +++ b/Mage.Server/nbproject/project.properties @@ -0,0 +1,83 @@ +application.title=MageServer +application.vendor=BetaSteward_at_googlemail.com +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/Mage.Server.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +includes=** +jar.compress=false +javac.classpath=\ + ${reference.Mage.jar}:\ + ${reference.Mage_Common.jar}:\ + ${reference.Mage_Sets.jar}:\ + ${reference.Mage_HumanPlayer.jar}:\ + ${reference.Mage_AI.jar} +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.source=1.6 +javac.target=1.6 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir}:\ + ${libs.junit.classpath}:\ + ${libs.junit_4.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +jaxbwiz.endorsed.dirs="${netbeans.home}/../ide9/modules/ext/jaxb/api" +jaxbwiz.gensrc.classpath=${libs.jaxb.classpath} +jaxbwiz.xjcdef.classpath=${libs.jaxb.classpath} +jaxbwiz.xjcrun.classpath=${libs.jaxb.classpath} +main.class=mage.server.Main +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +platform.active=default_platform +project.license=bsd +project.Mage=../Mage +project.Mage_AI=../Mage.AI +project.Mage_Common=../Mage.Common +project.Mage_HumanPlayer=../Mage.HumanPlayer +project.Mage_Sets=../Mage.Sets +reference.Mage.jar=${project.Mage}/dist/Mage.jar +reference.Mage_AI.jar=${project.Mage_AI}/dist/Mage.AI.jar +reference.Mage_Common.jar=${project.Mage_Common}/dist/Mage.Common.jar +reference.Mage_HumanPlayer.jar=${project.Mage_HumanPlayer}/dist/Mage.HumanPlayer.jar +reference.Mage_Sets.jar=${project.Mage_Sets}/dist/Mage.Sets.jar +run-sys-prop.java.endorsed.dirs=${jaxbwiz.endorsed.dirs} +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +run.jvmargs=-server -Djava.security.policy=src/security.policy +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test +app.version=0.1 diff --git a/Mage.Server/nbproject/project.xml b/Mage.Server/nbproject/project.xml new file mode 100644 index 00000000000..b27cd85f4b4 --- /dev/null +++ b/Mage.Server/nbproject/project.xml @@ -0,0 +1,62 @@ + + + org.netbeans.modules.java.j2seproject + + + + + + + + Mage.Server + + + + + + + + + + Mage + jar + + jar + clean + jar + + + Mage_AI + jar + + jar + clean + jar + + + Mage_Common + jar + + jar + clean + jar + + + Mage_HumanPlayer + jar + + jar + clean + jar + + + Mage_Sets + jar + + jar + clean + jar + + + + diff --git a/Mage.Server/nbproject/xml_binding_build.xml b/Mage.Server/nbproject/xml_binding_build.xml new file mode 100644 index 00000000000..ce85c83ccba --- /dev/null +++ b/Mage.Server/nbproject/xml_binding_build.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Server/nbproject/xml_binding_cfg.xml b/Mage.Server/nbproject/xml_binding_cfg.xml new file mode 100644 index 00000000000..e5b5a0afa0a --- /dev/null +++ b/Mage.Server/nbproject/xml_binding_cfg.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Mage.Server/plugins/Mage.AI.jar b/Mage.Server/plugins/Mage.AI.jar new file mode 100644 index 00000000000..37fa8d3e691 Binary files /dev/null and b/Mage.Server/plugins/Mage.AI.jar differ diff --git a/Mage.Server/plugins/Mage.Game.TwoPlayerDuel.jar b/Mage.Server/plugins/Mage.Game.TwoPlayerDuel.jar new file mode 100644 index 00000000000..bb8b8945d08 Binary files /dev/null and b/Mage.Server/plugins/Mage.Game.TwoPlayerDuel.jar differ diff --git a/Mage.Server/plugins/Mage.HumanPlayer.jar b/Mage.Server/plugins/Mage.HumanPlayer.jar new file mode 100644 index 00000000000..52da76d553d Binary files /dev/null and b/Mage.Server/plugins/Mage.HumanPlayer.jar differ diff --git a/Mage.Server/release/startServer.bat b/Mage.Server/release/startServer.bat new file mode 100644 index 00000000000..830b85d48c2 --- /dev/null +++ b/Mage.Server/release/startServer.bat @@ -0,0 +1 @@ +start java -jar .\MageServer.jar \ No newline at end of file diff --git a/Mage.Server/src/mage/server/ChatManager.java b/Mage.Server/src/mage/server/ChatManager.java new file mode 100644 index 00000000000..00ed91f0c64 --- /dev/null +++ b/Mage.Server/src/mage/server/ChatManager.java @@ -0,0 +1,72 @@ +/* +* 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; + +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import mage.interfaces.ChatClient; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ChatManager { + + private final static ChatManager INSTANCE = new ChatManager(); + + public static ChatManager getInstance() { + return INSTANCE; + } + + private ChatManager() {} + + private ConcurrentHashMap chatSessions = new ConcurrentHashMap(); + + public UUID createChatSession() { + ChatSession chatSession = new ChatSession(); + chatSessions.put(chatSession.getChatId(), chatSession); + return chatSession.getChatId(); + } + + public void joinChat(UUID chatId, ChatClient client) { + chatSessions.get(chatId).join(client); + } + + public void leaveChat(UUID chatId, UUID clientId) { + chatSessions.get(chatId).leave(clientId); + } + + public void destroyChatSession(UUID chatId) { + chatSessions.remove(chatId); + } + + public void broadcast(UUID chatId, String userName, String message) { + chatSessions.get(chatId).broadcast(userName, message); + } +} diff --git a/Mage.Server/src/mage/server/ChatSession.java b/Mage.Server/src/mage/server/ChatSession.java new file mode 100644 index 00000000000..6fe7c4559c2 --- /dev/null +++ b/Mage.Server/src/mage/server/ChatSession.java @@ -0,0 +1,119 @@ +/* +* 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; + +import mage.server.util.ThreadExecutor; +import java.rmi.RemoteException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.GregorianCalendar; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.interfaces.ChatClient; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ChatSession { + + private static ExecutorService executor = ThreadExecutor.getInstance().getRMIExecutor(); + private final static Logger logger = Logging.getLogger(ChatSession.class.getName()); + private ConcurrentHashMap clients = new ConcurrentHashMap(); + private UUID chatId; + private DateFormat timeFormatter = SimpleDateFormat.getTimeInstance(SimpleDateFormat.SHORT); + + //TODO: use sessionId for chatting - prevents sending without being part of the chat + + public ChatSession() { + chatId = UUID.randomUUID(); + } + + public void join(ChatClient client) { + try { + logger.log(Level.INFO, "joining chat " + chatId); + clients.put(client.getId(), client); + broadcast(client.getName(), " has joined"); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + public void leave(UUID clientId) { + if (clients.contains(clientId)) { + String clientName = ""; + try { + clientName = clients.get(clientId).getName(); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + } + kill(clientId); + broadcast(clientName, " has left"); + } + } + + public void kill(UUID clientId) { + if (clients.contains(clientId)) + clients.remove(clientId); + } + + public void broadcast(final String userName, final String message) { + Calendar cal = new GregorianCalendar(); + final String msg = timeFormatter.format(cal.getTime()) + " " + userName + ":" + message; + for (final Entry entry: clients.entrySet()) { + executor.submit( + new Runnable() { + public void run() { + try { + entry.getValue().receiveMessage(msg); + } + catch (RemoteException ex) { + logger.log(Level.WARNING, ex.getMessage()); + kill(entry.getKey()); + } + } + } + ); + } + } + + /** + * @return the chatId + */ + public UUID getChatId() { + return chatId; + } + +} diff --git a/Mage.Server/src/mage/server/Main.java b/Mage.Server/src/mage/server/Main.java new file mode 100644 index 00000000000..0d977934254 --- /dev/null +++ b/Mage.Server/src/mage/server/Main.java @@ -0,0 +1,80 @@ +/* +* 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; + +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.GameFactory; +import mage.server.game.PlayerFactory; +import mage.server.util.ConfigSettings; +import mage.server.util.config.Plugin; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Main { + + private static Logger logger = Logging.getLogger(Main.class.getName()); + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + + logger.info("Starting MAGE server version " + Main.class.getPackage().getImplementationVersion()); + ConfigSettings config = ConfigSettings.getInstance(); + for (Plugin plugin: config.getGameTypes()) { + GameFactory.getInstance().addGameType(plugin.getName(), loadPlugin(plugin)); + } + for (Plugin plugin: config.getPlayerTypes()) { + PlayerFactory.getInstance().addPlayerType(plugin.getName(), loadPlugin(plugin)); + } + Server server = new ServerImpl(config.getPort(), config.getServerName()); + + } + + 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); + } catch (Exception ex) { + logger.log(Level.SEVERE, "Error loading plugin " + plugin.getJar(), ex); + } + return null; + } + +} diff --git a/Mage.Server/src/mage/server/ServerImpl.java b/Mage.Server/src/mage/server/ServerImpl.java new file mode 100644 index 00000000000..dd256302698 --- /dev/null +++ b/Mage.Server/src/mage/server/ServerImpl.java @@ -0,0 +1,440 @@ +/* +* 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; + +import java.rmi.RemoteException; +import java.rmi.registry.LocateRegistry; +import java.rmi.registry.Registry; +import java.rmi.server.UnicastRemoteObject; +import java.util.Collection; +import java.util.List; +import java.util.UUID; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.Constants.DeckType; +import mage.interfaces.ChatClient; +import mage.interfaces.Client; +import mage.cards.decks.DeckCardLists; +import mage.interfaces.GameClient; +import mage.interfaces.GameReplayClient; +import mage.interfaces.MageException; +import mage.interfaces.Server; +import mage.server.game.GameFactory; +import mage.server.game.GameManager; +import mage.server.game.GamesRoomManager; +import mage.server.game.PlayerFactory; +import mage.server.game.ReplayManager; +import mage.server.game.TableManager; +import mage.util.Logging; +import mage.view.TableView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ServerImpl implements Server { + + private final static Logger logger = Logging.getLogger("Mage Server"); + + public ServerImpl(int port, String name) { + try { + System.setSecurityManager(null); + Registry reg = LocateRegistry.createRegistry(port); + Server server = (Server) UnicastRemoteObject.exportObject(this, 0); + reg.rebind(name, server); + logger.info("Started MAGE server - listening on port " + port); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, "Failed to start RMI server at port " + port, ex); + } + + } + + @Override + public UUID registerClient(Client c) throws RemoteException { + + UUID sessionId = SessionManager.getInstance().createSession(c); + logger.info("Session " + sessionId + " created for client " + c.getId()); + return sessionId; + + } + + @Override + public TableView createTable(UUID sessionId, UUID roomId, String gameType, DeckType deckType, List playerTypes) throws MageException { + try { + TableView table = GamesRoomManager.getInstance().getRoom(roomId).createTable(sessionId, gameType, deckType, playerTypes); + logger.info("Table " + table.getTableId() + " created"); + return table; + } + catch (Exception ex) { + handleException(ex); + } + return null; + } + + @Override + public void removeTable(UUID sessionId, UUID roomId, UUID tableId) throws MageException { + try { + GamesRoomManager.getInstance().getRoom(roomId).removeTable(sessionId, tableId); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public boolean joinTable(UUID sessionId, UUID roomId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws MageException { + 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) { + handleException(ex); + } + return false; + } + + @Override + public Collection getTables(UUID roomId) throws MageException { + try { + return GamesRoomManager.getInstance().getRoom(roomId).getTables(); + } + catch (Exception ex) { + handleException(ex); + } + return null; + } + + @Override + public TableView getTable(UUID roomId, UUID tableId) throws MageException { + try { + return GamesRoomManager.getInstance().getRoom(roomId).getTable(tableId); + } + catch (Exception ex) { + handleException(ex); + } + return null; + } + + @Override + public void deregisterClient(UUID sessionId) throws MageException { + try { + SessionManager.getInstance().getSession(sessionId).kill(); + logger.info("Client deregistered ..."); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void startGame(UUID sessionId, UUID roomId, UUID tableId) throws MageException { + try { + TableManager.getInstance().startGame(sessionId, roomId, tableId); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void sendChatMessage(UUID chatId, String userName, String message) throws MageException { + try { + ChatManager.getInstance().broadcast(chatId, userName, message); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void joinChat(UUID chatId, ChatClient chatClient) throws MageException { + try { + ChatManager.getInstance().joinChat(chatId, chatClient); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void leaveChat(UUID chatId, UUID clientId) throws MageException { + try { + ChatManager.getInstance().leaveChat(chatId, clientId); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public UUID getMainRoomId() throws MageException { + try { + return GamesRoomManager.getInstance().getMainRoomId(); + } + catch (Exception ex) { + handleException(ex); + } + return null; + } + + @Override + public UUID getRoomChatId(UUID roomId) throws MageException { + try { + return GamesRoomManager.getInstance().getRoom(roomId).getChatId(); + } + catch (Exception ex) { + handleException(ex); + } + return null; + } + + @Override + public boolean isTableOwner(UUID sessionId, UUID roomId, UUID tableId) throws MageException { + try { + return TableManager.getInstance().isTableOwner(tableId, sessionId); + } + catch (Exception ex) { + handleException(ex); + } + return false; + } + + @Override + public void leaveTable(UUID sessionId, UUID roomId, UUID tableId) throws MageException { + try { + GamesRoomManager.getInstance().getRoom(roomId).leaveTable(sessionId, tableId); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public UUID getTableChatId(UUID tableId) throws MageException { + try { + return TableManager.getInstance().getChatId(tableId); + } + catch (Exception ex) { + handleException(ex); + } + return null; + } + + @Override + public void joinGame(UUID gameId, UUID sessionId, GameClient gameClient) throws MageException { + try { + GameManager.getInstance().joinGame(gameId, sessionId, gameClient); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public UUID getGameChatId(UUID gameId) throws MageException { + try { + return GameManager.getInstance().getChatId(gameId); + } + catch (Exception ex) { + handleException(ex); + } + return null; + } + + @Override + public void sendPlayerUUID(UUID gameId, UUID sessionId, UUID data) throws MageException { + try { + GameManager.getInstance().sendPlayerUUID(gameId, sessionId, data); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void sendPlayerString(UUID gameId, UUID sessionId, String data) throws MageException { + try { + GameManager.getInstance().sendPlayerString(gameId, sessionId, data); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void sendPlayerBoolean(UUID gameId, UUID sessionId, Boolean data) throws MageException { + try { + GameManager.getInstance().sendPlayerBoolean(gameId, sessionId, data); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void sendPlayerInteger(UUID gameId, UUID sessionId, Integer data) throws RemoteException, MageException { + try { + GameManager.getInstance().sendPlayerInteger(gameId, sessionId, data); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void concedeGame(UUID gameId, UUID sessionId) throws MageException { + try { + GameManager.getInstance().concedeGame(gameId, sessionId); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public boolean watchTable(UUID sessionId, UUID roomId, UUID tableId) throws MageException { + try { + return GamesRoomManager.getInstance().getRoom(roomId).watchTable(sessionId, tableId); + } + catch (Exception ex) { + handleException(ex); + } + return false; + } + + @Override + public void watchGame(UUID gameId, UUID sessionId, GameClient gameClient) throws MageException { + try { + GameManager.getInstance().watchGame(gameId, sessionId, gameClient); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void stopWatching(UUID gameId, UUID clientId) throws MageException { + try { + GameManager.getInstance().stopWatching(gameId, clientId); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void replayGame(UUID gameId, UUID sessionId, GameReplayClient replayClient) throws MageException { + try { + ReplayManager.getInstance().startReplay(sessionId, replayClient); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void stopReplay(UUID sessionId) throws MageException { + try { + ReplayManager.getInstance().stopReplay(sessionId); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void nextPlay(UUID sessionId) throws MageException { + try { + ReplayManager.getInstance().nextPlay(sessionId); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public void previousPlay(UUID sessionId) throws MageException { + try { + ReplayManager.getInstance().previousPlay(sessionId); + } + catch (Exception ex) { + handleException(ex); + } + } + + @Override + public boolean replayTable(UUID sessionId, UUID roomId, UUID tableId) throws MageException { + try { + return TableManager.getInstance().replayTable(sessionId, tableId); + } + catch (Exception ex) { + handleException(ex); + } + return false; + } + + @Override + public String[] getGameTypes() throws MageException { + try { + return GameFactory.getInstance().getGameTypes().toArray(new String[0]); + } + catch (Exception ex) { + handleException(ex); + } + return null; + } + + @Override + public String[] getPlayerTypes() throws MageException { + try { + return PlayerFactory.getInstance().getPlayerTypes().toArray(new String[0]); + } + catch (Exception ex) { + handleException(ex); + } + return null; + } + + @Override + public void cheat(UUID gameId, UUID sessionId, DeckCardLists deckList) throws MageException { + try { +// GameManager.getInstance().cheat(gameId, sessionId, deckList); + } + catch (Exception ex) { + handleException(ex); + } + } + + public void handleException(Exception ex) throws MageException { + logger.log(Level.SEVERE, "", ex); + throw new MageException("Server error"); + } + +} diff --git a/Mage.Server/src/mage/server/Session.java b/Mage.Server/src/mage/server/Session.java new file mode 100644 index 00000000000..5fde382c3a8 --- /dev/null +++ b/Mage.Server/src/mage/server/Session.java @@ -0,0 +1,132 @@ +/* +* 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; + +import mage.server.util.ThreadExecutor; +import java.rmi.RemoteException; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.interfaces.Client; +import mage.server.game.GameManager; +import mage.server.game.TableManager; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Session { + + private static ExecutorService executor = ThreadExecutor.getInstance().getRMIExecutor(); + private final static Logger logger = Logging.getLogger(Session.class.getName()); + + private UUID sessionId; + private String username; + private Client client; + + public Session(Client client) { + sessionId = UUID.randomUUID(); + try { + username = client.getUserName(); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + } + this.client = client; + } + + public UUID getId() { + return sessionId; + } + + public void kill() { + SessionManager.getInstance().removeSession(sessionId); + TableManager.getInstance().removeSession(sessionId); + GameManager.getInstance().removeSession(sessionId); + + } + + public void gameStarted(final UUID gameId, final UUID playerId) { + executor.submit( + new Runnable() { + @Override + public void run() { + try { + client.gameStarted(gameId, playerId); + logger.info("game started for player " + playerId); + } + catch (RemoteException ex) { + logger.log(Level.WARNING, ex.getMessage()); + kill(); + } + } + } + ); + } + + public void watchGame(final UUID gameId) { + executor.submit( + new Runnable() { + @Override + public void run() { + try { + client.watchGame(gameId); + } + catch (RemoteException ex) { + logger.log(Level.WARNING, ex.getMessage()); + kill(); + } + } + } + ); + } + + public void replayGame(final UUID gameId) { + executor.submit( + new Runnable() { + @Override + public void run() { + try { + client.replayGame(gameId); + } + catch (RemoteException ex) { + logger.log(Level.WARNING, ex.getMessage()); + kill(); + } + } + } + ); + } + + public String getUsername() { + return username; + } + +} diff --git a/Mage.Server/src/mage/server/SessionManager.java b/Mage.Server/src/mage/server/SessionManager.java new file mode 100644 index 00000000000..61255fe1d65 --- /dev/null +++ b/Mage.Server/src/mage/server/SessionManager.java @@ -0,0 +1,64 @@ +/* +* 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; + +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import mage.interfaces.Client; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class SessionManager { + + private final static SessionManager INSTANCE = new SessionManager(); + + public static SessionManager getInstance() { + return INSTANCE; + } + + private ConcurrentHashMap sessions = new ConcurrentHashMap(); + + public Session getSession(UUID sessionId) { + return sessions.get(sessionId); + } + + public UUID createSession(Client c) { + Session session = new Session(c); + sessions.put(session.getId(), session); + return session.getId(); + } + + public void removeSession(UUID sessionId) { + sessions.remove(sessionId); + } + + +} diff --git a/Mage.Server/src/mage/server/game/GameCallback.java b/Mage.Server/src/mage/server/game/GameCallback.java new file mode 100644 index 00000000000..49cccafbf1a --- /dev/null +++ b/Mage.Server/src/mage/server/game/GameCallback.java @@ -0,0 +1,39 @@ +/* +* 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; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public interface GameCallback { + + public void gameResult(String result); + +} diff --git a/Mage.Server/src/mage/server/game/GameController.java b/Mage.Server/src/mage/server/game/GameController.java new file mode 100644 index 00000000000..e36443085fd --- /dev/null +++ b/Mage.Server/src/mage/server/game/GameController.java @@ -0,0 +1,354 @@ +/* +* 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.util.Collection; +import java.util.Map.Entry; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.abilities.ActivatedAbility; +import mage.cards.Card; +import mage.cards.Cards; +import mage.cards.decks.Deck; +import mage.cards.decks.DeckCardLists; +import mage.game.Game; +import mage.game.GameReplay; +import mage.game.events.TableEvent; +import mage.interfaces.GameClient; +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; +import mage.view.CardsView; +import mage.view.GameView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GameController implements GameCallback { + + private static ExecutorService gameExecutor = ThreadExecutor.getInstance().getGameExecutor(); + private final static Logger logger = Logging.getLogger(GameController.class.getName()); + + private ConcurrentHashMap gameSessions = new ConcurrentHashMap(); + private ConcurrentHashMap watchers = new ConcurrentHashMap(); + private ConcurrentHashMap sessionPlayerMap; + private UUID gameSessionId; + private Game game; + private UUID chatId; + private UUID tableId; + private Future gameFuture; + + + public GameController(Game game, ConcurrentHashMap sessionPlayerMap, UUID tableId) { + gameSessionId = UUID.randomUUID(); + this.sessionPlayerMap = sessionPlayerMap; + chatId = ChatManager.getInstance().createChatSession(); + this.game = game; + this.tableId = tableId; + init(); + } + + private void init() { + game.addTableEventListener( + new Listener () { + @Override + public void event(TableEvent event) { + switch (event.getEventType()) { + case UPDATE: + updateGame(); + break; + case INFO: + ChatManager.getInstance().broadcast(chatId, "", event.getMessage()); + logger.info(game.getId() + " " + event.getMessage()); + break; + } + } + } + ); + game.addPlayerQueryEventListener( + new Listener () { + @Override + public void event(PlayerQueryEvent event) { + switch (event.getQueryType()) { + case ASK: + ask(event.getPlayerId(), event.getMessage()); + break; + case PICK_TARGET: + target(event.getPlayerId(), event.getMessage(), event.getCards(), event.isRequired()); + break; + case SELECT: + select(event.getPlayerId(), event.getMessage()); + break; + case PLAY_MANA: + playMana(event.getPlayerId(), event.getMessage()); + break; + case PLAY_X_MANA: + playXMana(event.getPlayerId(), event.getMessage()); + break; + case CHOOSE_ABILITY: + chooseAbility(event.getPlayerId(), event.getAbilities()); + break; + case CHOOSE: + choose(event.getPlayerId(), event.getMessage(), event.getChoices()); + break; + case AMOUNT: + amount(event.getPlayerId(), event.getMessage(), event.getMin(), event.getMax()); + break; + } + } + } + ); + } + + private UUID getPlayerId(UUID sessionId) { + return sessionPlayerMap.get(sessionId); + } + + public void join(UUID sessionId, GameClient client) { + UUID playerId = sessionPlayerMap.get(sessionId); + GameSession gameSession = new GameSession(client, game, sessionId, playerId); + gameSessions.put(playerId, gameSession); + logger.log(Level.INFO, "player " + playerId + " has joined game " + game.getId()); + gameSession.init(getGameView(playerId)); + ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(playerId).getName() + " has joined the game"); + if (allJoined()) { + startGame(); + } + } + + private synchronized void startGame() { + if (gameFuture == null) { + GameWorker worker = new GameWorker(game, this); + gameFuture = gameExecutor.submit(worker); + } + } + + private boolean allJoined() { + for (Player player: game.getPlayers().values()) { + if (player instanceof HumanPlayer && gameSessions.get(player.getId()) == null) { + return false; + } + } + return true; + } + + public void watch(UUID sessionId, GameClient client) { + GameWatcher gameWatcher = new GameWatcher(client, sessionId, game.getId()); + watchers.put(sessionId, gameWatcher); + gameWatcher.init(getGameView()); + ChatManager.getInstance().broadcast(chatId, "", " has started watching"); + } + + public GameReplay createReplay() { + if (game.isGameOver()) { + return new GameReplay(game.getGameStates()); + } + return null; + } + + public void stopWatching(UUID sessionId) { + watchers.remove(sessionId); + ChatManager.getInstance().broadcast(chatId, "", " has stopped watching"); + } + + public void concede(UUID sessionId) { + game.concede(getPlayerId(sessionId)); + } + + private void leave(UUID sessionId) { + game.quit(getPlayerId(sessionId)); + } + + public void cheat(UUID sessionId, DeckCardLists deckList) { + Player player = game.getPlayer(getPlayerId(sessionId)); + Deck deck = Deck.load(deckList); + deck.setOwnerId(player.getId()); + for (Card card: deck.getCards().values()) { + player.putOntoBattlefield(card, game); + } + updateGame(); + } + +// public void timeout(UUID sessionId) { +// kill(sessionId); +// } + + public void kill(UUID sessionId) { + if (sessionPlayerMap.containsKey(sessionId)) { + gameSessions.get(sessionPlayerMap.get(sessionId)).setKilled(); + gameSessions.remove(sessionPlayerMap.get(sessionId)); + leave(sessionId); + sessionPlayerMap.remove(sessionId); + } + if (watchers.containsKey(sessionId)) { + watchers.get(sessionId).setKilled(); + watchers.remove(sessionId); + } + } + + public void timeout(UUID sessionId) { + if (sessionPlayerMap.containsKey(sessionId)) { + ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(sessionPlayerMap.get(sessionId)).getName() + " has timed out. Auto concede."); + concede(sessionId); + } + } + + public void endGame(final String message) { + for (final GameSession gameSession: gameSessions.values()) { + gameSession.gameOver(message); + } + for (final GameWatcher gameWatcher: watchers.values()) { + gameWatcher.gameOver(message); + } + TableManager.getInstance().endGame(tableId); + } + + public UUID getSessionId() { + return this.gameSessionId; + } + + public UUID getChatId() { + return chatId; + } + + public void sendPlayerUUID(UUID sessionId, UUID data) { + gameSessions.get(sessionPlayerMap.get(sessionId)).sendPlayerUUID(data); + } + + public void sendPlayerString(UUID sessionId, String data) { + gameSessions.get(sessionPlayerMap.get(sessionId)).sendPlayerString(data); + } + + public void sendPlayerBoolean(UUID sessionId, Boolean data) { + gameSessions.get(sessionPlayerMap.get(sessionId)).sendPlayerBoolean(data); + } + + public void sendPlayerInteger(UUID sessionId, Integer data) { + gameSessions.get(sessionPlayerMap.get(sessionId)).sendPlayerInteger(data); + } + + private void updateGame() { + + for (final Entry entry: gameSessions.entrySet()) { + entry.getValue().update(getGameView(entry.getKey())); + } + for (final GameWatcher gameWatcher: watchers.values()) { + gameWatcher.update(getGameView()); + } + } + + private void ask(UUID playerId, String question) { + informOthers(playerId); + gameSessions.get(playerId).ask(question, getGameView(playerId)); + } + + private void chooseAbility(UUID playerId, Collection choices) { + informOthers(playerId); + gameSessions.get(playerId).chooseAbility(new AbilityPickerView(choices)); + } + + private void choose(UUID playerId, String message, String[] choices) { + informOthers(playerId); + gameSessions.get(playerId).choose(message, choices); + } + + private void target(UUID playerId, String question, Cards cards, boolean required) { + informOthers(playerId); + gameSessions.get(playerId).target(question, getCardView(cards), required, getGameView(playerId)); + } + + private void select(UUID playerId, String message) { + informOthers(playerId); + gameSessions.get(playerId).select(message, getGameView(playerId)); + } + + private void playMana(UUID playerId, String message) { + informOthers(playerId); + gameSessions.get(playerId).playMana(message, getGameView(playerId)); + } + + private void playXMana(UUID playerId, String message) { + informOthers(playerId); + gameSessions.get(playerId).playXMana(message, getGameView(playerId)); + } + + private void amount(UUID playerId, String message, int min, int max) { + informOthers(playerId); + gameSessions.get(playerId).getAmount(message, min, max); + } + + private void revealCards(String name, Cards cards) { + for (GameSession session: gameSessions.values()) { + session.revealCards(name, getCardView(cards)); + } + } + + private void informOthers(UUID playerId) { + final String message = "Waiting for " + game.getPlayer(playerId).getName(); + for (final Entry entry: gameSessions.entrySet()) { + if (!entry.getKey().equals(playerId)) { + entry.getValue().inform(message, getGameView(entry.getKey())); + } + } + for (final GameWatcher watcher: watchers.values()) { + watcher.inform(message, getGameView()); + } + } + + private GameView getGameView() { + return new GameView(game.getState()); + } + + private GameView getGameView(UUID playerId) { + GameView gameView = new GameView(game.getState()); + gameView.setHand(getCardView(game.getPlayer(playerId).getHand())); + return gameView; + } + + private CardsView getCardView(Cards cards) { + if (cards == null) + return null; + return new CardsView(cards.values()); + } + + 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 new file mode 100644 index 00000000000..cbf0a0c8e8f --- /dev/null +++ b/Mage.Server/src/mage/server/game/GameFactory.java @@ -0,0 +1,82 @@ +/* +* 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 java.util.logging.Logger; +import mage.game.Game; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GameFactory { + + private final static GameFactory INSTANCE = new GameFactory(); + private final static Logger logger = Logging.getLogger(GameFactory.class.getName()); + + private Map gameTypes = new HashMap(); + + public static GameFactory getInstance() { + return INSTANCE; + } + + private GameFactory() {} + + public Game createGame(String gameType) { + + Game game; + Constructor con; + try { + con = gameTypes.get(gameType).getConstructor(new Class[]{}); + game = (Game)con.newInstance(new Object[] {}); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + return null; + } + logger.info("Game created: " + game.getId().toString()); + + return game; + + } + + public Set getGameTypes() { + return gameTypes.keySet(); + } + + public void addGameType(String name, Class gameType) { + this.gameTypes.put(name, gameType); + } + +} diff --git a/Mage.Server/src/mage/server/game/GameManager.java b/Mage.Server/src/mage/server/game/GameManager.java new file mode 100644 index 00000000000..9ea25bcafa7 --- /dev/null +++ b/Mage.Server/src/mage/server/game/GameManager.java @@ -0,0 +1,125 @@ +/* +* 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.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import mage.cards.decks.DeckCardLists; +import mage.game.Game; +import mage.game.GameReplay; +import mage.interfaces.GameClient; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GameManager { + private final static GameManager INSTANCE = new GameManager(); + + public static GameManager getInstance() { + return INSTANCE; + } + + private GameManager() {} + + private ConcurrentHashMap gameControllers = new ConcurrentHashMap(); + + public UUID createGameSession(Game game, ConcurrentHashMap sessionPlayerMap, UUID tableId) { + GameController gameController = new GameController(game, sessionPlayerMap, tableId); + gameControllers.put(game.getId(), gameController); + return gameController.getSessionId(); + } + + public void joinGame(UUID gameId, UUID sessionId, GameClient client) { + gameControllers.get(gameId).join(sessionId, client); + } + +// public void leaveGame(UUID gameId, UUID clientId) { +// gameControllers.get(gameId).leave(clientId); +// } + + public void destroyChatSession(UUID gameId) { + gameControllers.remove(gameId); + } + + public UUID getChatId(UUID gameId) { + return gameControllers.get(gameId).getChatId(); + } + + public void sendPlayerUUID(UUID gameId, UUID sessionId, UUID data) { + gameControllers.get(gameId).sendPlayerUUID(sessionId, data); + } + + public void sendPlayerString(UUID gameId, UUID sessionId, String data) { + gameControllers.get(gameId).sendPlayerString(sessionId, data); + } + + public void sendPlayerBoolean(UUID gameId, UUID sessionId, Boolean data) { + gameControllers.get(gameId).sendPlayerBoolean(sessionId, data); + } + + public void sendPlayerInteger(UUID gameId, UUID sessionId, Integer data) { + gameControllers.get(gameId).sendPlayerInteger(sessionId, data); + } + + public void concedeGame(UUID gameId, UUID sessionId) { + gameControllers.get(gameId).concede(sessionId); + } + + public void watchGame(UUID gameId, UUID sessionId, GameClient client) { + gameControllers.get(gameId).watch(sessionId, client); + } + + public void stopWatching(UUID gameId, UUID clientId) { + gameControllers.get(gameId).stopWatching(clientId); + } + + public void removeSession(UUID sessionId) { + for (GameController controller: gameControllers.values()) { + controller.kill(sessionId); + } + } + + public void kill(UUID gameId, UUID sessionId) { + gameControllers.get(gameId).kill(sessionId); + } + + public GameReplay createReplay(UUID gameId) { + return gameControllers.get(gameId).createReplay(); + } + + public void cheat(UUID gameId, UUID sessionId, DeckCardLists deckList) { + gameControllers.get(gameId).cheat(sessionId, deckList); + } + + void timeout(UUID gameId, UUID sessionId) { + gameControllers.get(gameId).timeout(sessionId); + } + +} diff --git a/Mage.Server/src/mage/server/game/GameSession.java b/Mage.Server/src/mage/server/game/GameSession.java new file mode 100644 index 00000000000..3ccea1b32af --- /dev/null +++ b/Mage.Server/src/mage/server/game/GameSession.java @@ -0,0 +1,262 @@ +/* +* 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.rmi.RemoteException; +import java.util.UUID; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; +import mage.game.Game; +import mage.interfaces.GameClient; +import mage.server.util.ConfigSettings; +import mage.server.util.ThreadExecutor; +import mage.view.AbilityPickerView; +import mage.view.CardsView; +import mage.view.GameView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GameSession extends GameWatcher { + + private Game game; + private UUID playerId; + + private ScheduledFuture futureTimeout; + protected static ScheduledExecutorService timeoutExecutor = ThreadExecutor.getInstance().getTimeoutExecutor(); + + public GameSession(GameClient client, Game game, UUID sessionId, UUID playerId) { + super(client, sessionId, game.getId()); + this.game = game; + this.playerId = playerId; + } + + public void ask(final String question, final GameView gameView) { + if (!killed) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + if (!killed) { + rmiExecutor.submit( + new Runnable() { + @Override + public void run() { + try { + client.revealCards(name, cardView); + } catch (RemoteException ex) { + handleRemoteException(ex); + } + } + } + ); + } + } + + + private synchronized void setupTimeout() { + cancelTimeout(); + futureTimeout = timeoutExecutor.schedule( + new Runnable() { + @Override + public void run() { + GameManager.getInstance().timeout(gameId, sessionId); + } + }, + ConfigSettings.getInstance().getMaxSecondsIdle(), TimeUnit.SECONDS + ); + } + + private synchronized void cancelTimeout() { + if (futureTimeout != null) { + futureTimeout.cancel(false); + } + } + + public void sendPlayerUUID(UUID data) { + cancelTimeout(); + game.getPlayer(playerId).setResponseUUID(data); + } + + public void sendPlayerString(String data) { + cancelTimeout(); + game.getPlayer(playerId).setResponseString(data); + } + + public void sendPlayerBoolean(Boolean data) { + cancelTimeout(); + game.getPlayer(playerId).setResponseBoolean(data); + } + + public void sendPlayerInteger(Integer data) { + cancelTimeout(); + game.getPlayer(playerId).setResponseInteger(data); + } +} diff --git a/Mage.Server/src/mage/server/game/GameWatcher.java b/Mage.Server/src/mage/server/game/GameWatcher.java new file mode 100644 index 00000000000..dcb9d666f9e --- /dev/null +++ b/Mage.Server/src/mage/server/game/GameWatcher.java @@ -0,0 +1,135 @@ +/* +* 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.rmi.RemoteException; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.interfaces.GameClient; +import mage.server.util.ThreadExecutor; +import mage.util.Logging; +import mage.view.GameView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GameWatcher { + + protected static ExecutorService rmiExecutor = ThreadExecutor.getInstance().getRMIExecutor(); + protected final static Logger logger = Logging.getLogger(GameWatcher.class.getName()); + + protected GameClient client; + + protected UUID sessionId; + protected UUID gameId; + protected boolean killed = false; + + public GameWatcher(GameClient client, UUID sessionId, UUID gameId) { + this.client = client; + this.sessionId = sessionId; + this.gameId = gameId; + } + + public void init(final GameView gameView) { + if (!killed) + rmiExecutor.submit( + new Runnable() { + @Override + public void run() { + try { + client.init(gameView); + } catch (RemoteException ex) { + handleRemoteException(ex); + } + } + } + ); + } + + public void update(final GameView gameView) { + if (!killed) + 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) { + if (!killed) + rmiExecutor.submit( + new Runnable() { + @Override + public void run() { + try { + client.inform(message, gameView); + } catch (RemoteException ex) { + handleRemoteException(ex); + } + } + } + ); + } + + public void gameOver(final String message) { + if (!killed) + rmiExecutor.submit( + new Runnable() { + @Override + public void run() { + try { + client.gameOver(message); + } catch (RemoteException ex) { + handleRemoteException(ex); + } + } + } + ); + } + + protected void handleRemoteException(RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + GameManager.getInstance().kill(gameId, sessionId); + } + + public void setKilled() { + killed = true; + } + +} diff --git a/Mage.Server/src/mage/server/game/GameWorker.java b/Mage.Server/src/mage/server/game/GameWorker.java new file mode 100644 index 00000000000..124df4e996d --- /dev/null +++ b/Mage.Server/src/mage/server/game/GameWorker.java @@ -0,0 +1,64 @@ +/* +* 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.util.concurrent.Callable; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.game.Game; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GameWorker implements Callable { + + private final static Logger logger = Logging.getLogger(GameWorker.class.getName()); + + private GameCallback result; + private Game game; + + public GameWorker(Game game, GameCallback result) { + this.game = game; + this.result = result; + } + + @Override + public Object call() { + try { + game.start(); + result.gameResult(game.getWinner()); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + } + return null; + } + +} diff --git a/Mage.Server/src/mage/server/game/GamesRoom.java b/Mage.Server/src/mage/server/game/GamesRoom.java new file mode 100644 index 00000000000..2a681be20ff --- /dev/null +++ b/Mage.Server/src/mage/server/game/GamesRoom.java @@ -0,0 +1,53 @@ +/* +* 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.util.Collection; +import java.util.List; +import java.util.UUID; +import mage.Constants.DeckType; +import mage.cards.decks.DeckCardLists; +import mage.view.TableView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +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 void removeTable(UUID sessionId, UUID tableId); + public TableView getTable(UUID tableId); + public void leaveTable(UUID sessionId, UUID tableId); + + public boolean watchTable(UUID sessionId, UUID tableId); + +} diff --git a/Mage.Server/src/mage/server/game/GamesRoomImpl.java b/Mage.Server/src/mage/server/game/GamesRoomImpl.java new file mode 100644 index 00000000000..6e9caac3533 --- /dev/null +++ b/Mage.Server/src/mage/server/game/GamesRoomImpl.java @@ -0,0 +1,101 @@ +/* +* 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.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +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.Table; +import mage.util.Logging; +import mage.view.TableView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { + + private final static Logger logger = Logging.getLogger(GamesRoomImpl.class.getName()); + + private ConcurrentHashMap tables = new ConcurrentHashMap(); + + @Override + public Collection getTables() { + ArrayList tableList = new ArrayList(); + for (Table table: tables.values()) { + tableList.add(new TableView(table)); + } + return tableList; + } + + @Override + public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) { + if (tables.containsKey(tableId)) { + return TableManager.getInstance().joinTable(sessionId, tableId, seatNum, name, deckList); + } else { + return false; + } + } + + @Override + public TableView createTable(UUID sessionId, String gameType, DeckType deckType, List playerTypes) { + Table table = TableManager.getInstance().createTable(sessionId, gameType, deckType, playerTypes); + tables.put(table.getId(), table); + return new TableView(table); + } + + @Override + public TableView getTable(UUID tableId) { + return new TableView(tables.get(tableId)); + } + + @Override + public void removeTable(UUID sessionId, UUID tableId) { + if (TableManager.getInstance().removeTable(sessionId, tableId)) { + tables.remove(tableId); + } + } + + @Override + public void leaveTable(UUID sessionId, UUID tableId) { + TableManager.getInstance().leaveTable(sessionId, tableId); + } + + @Override + public boolean watchTable(UUID sessionId, UUID tableId) { + return TableManager.getInstance().watchTable(sessionId, tableId); + } + +} diff --git a/Mage.Server/src/mage/server/game/GamesRoomManager.java b/Mage.Server/src/mage/server/game/GamesRoomManager.java new file mode 100644 index 00000000000..c0cfd0278d0 --- /dev/null +++ b/Mage.Server/src/mage/server/game/GamesRoomManager.java @@ -0,0 +1,72 @@ +/* +* 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.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Logger; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class GamesRoomManager { + + private final static GamesRoomManager INSTANCE = new GamesRoomManager(); + private final static Logger logger = Logging.getLogger(GamesRoomManager.class.getName()); + + private ConcurrentHashMap rooms = new ConcurrentHashMap(); + private UUID mainRoomId; + + public static GamesRoomManager getInstance() { + return INSTANCE; + } + + private GamesRoomManager() { + GamesRoom mainRoom = new GamesRoomImpl(); + mainRoomId = mainRoom.getRoomId(); + rooms.put(mainRoomId, mainRoom); + } + + public UUID createRoom() { + GamesRoom room = new GamesRoomImpl(); + rooms.put(room.getRoomId(), room); + return room.getRoomId(); + } + + public UUID getMainRoomId() { + return mainRoomId; + } + + public GamesRoom getRoom(UUID roomId) { + return rooms.get(roomId); + } + +} diff --git a/Mage.Server/src/mage/server/game/PlayerFactory.java b/Mage.Server/src/mage/server/game/PlayerFactory.java new file mode 100644 index 00000000000..81914a83700 --- /dev/null +++ b/Mage.Server/src/mage/server/game/PlayerFactory.java @@ -0,0 +1,79 @@ +/* +* 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 java.util.logging.Logger; +import mage.players.Player; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class PlayerFactory { + + private final static PlayerFactory INSTANCE = new PlayerFactory(); + private final static Logger logger = Logging.getLogger(PlayerFactory.class.getName()); + + private Map playerTypes = new HashMap(); + + public static PlayerFactory getInstance() { + return INSTANCE; + } + + private PlayerFactory() {} + + public Player createPlayer(String playerType, String name) { + Player player; + Constructor con; + try { + con = playerTypes.get(playerType).getConstructor(new Class[]{String.class}); + player = (Player)con.newInstance(new Object[] {name}); + } catch (Exception ex) { + logger.log(Level.SEVERE, null, ex); + return null; + } + logger.info("Player created: " + player.getId().toString()); + return player; + } + + public Set getPlayerTypes() { + return playerTypes.keySet(); + } + + public void addPlayerType(String name, Class gameType) { + this.playerTypes.put(name, gameType); + } + +} diff --git a/Mage.Server/src/mage/server/game/ReplayManager.java b/Mage.Server/src/mage/server/game/ReplayManager.java new file mode 100644 index 00000000000..c341be00a09 --- /dev/null +++ b/Mage.Server/src/mage/server/game/ReplayManager.java @@ -0,0 +1,73 @@ +/* +* 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.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import mage.interfaces.GameReplayClient; +import mage.server.SessionManager; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ReplayManager { + private final static ReplayManager INSTANCE = new ReplayManager(); + + public static ReplayManager getInstance() { + return INSTANCE; + } + + private ReplayManager() {} + + private ConcurrentHashMap replaySessions = new ConcurrentHashMap(); + + public void replayGame(UUID sessionId, UUID gameId) { + ReplaySession replaySession = new ReplaySession(gameId); + replaySessions.put(sessionId, replaySession); + SessionManager.getInstance().getSession(sessionId).replayGame(gameId); + } + + public void startReplay(UUID sessionId, GameReplayClient replayClient) { + replaySessions.get(sessionId).replay(replayClient); + } + + public void stopReplay(UUID sessionId) { + replaySessions.get(sessionId).stop(); + } + + public void nextPlay(UUID sessionId) { + replaySessions.get(sessionId).next(); + } + + public void previousPlay(UUID sessionId) { + replaySessions.get(sessionId).previous(); + } + +} diff --git a/Mage.Server/src/mage/server/game/ReplaySession.java b/Mage.Server/src/mage/server/game/ReplaySession.java new file mode 100644 index 00000000000..11583cea9cc --- /dev/null +++ b/Mage.Server/src/mage/server/game/ReplaySession.java @@ -0,0 +1,115 @@ +/* +* 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.rmi.RemoteException; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.game.GameReplay; +import mage.game.GameState; +import mage.interfaces.GameReplayClient; +import mage.server.util.ThreadExecutor; +import mage.util.Logging; +import mage.view.GameView; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ReplaySession implements GameCallback { + + protected static ExecutorService rmiExecutor = ThreadExecutor.getInstance().getRMIExecutor(); + private final static Logger logger = Logging.getLogger(ReplaySession.class.getName()); + + private GameReplay game; + private GameReplayClient client; + + ReplaySession(UUID gameId) { + this.game = GameManager.getInstance().createReplay(gameId); + } + + public void replay(GameReplayClient replayClient) { + this.client = replayClient; + game.start(); + rmiExecutor.submit( + new Runnable() { + public void run() { + try { + client.init(new GameView(game.next())); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + } + ); + } + + public void stop() { + gameResult("stopped replay"); + } + + public synchronized void next() { + updateGame(game.next()); + } + + public synchronized void previous() { + updateGame(game.previous()); + } + + public void gameResult(final String result) { + rmiExecutor.submit( + new Runnable() { + public void run() { + try { + client.gameOver(result); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + } + ); + } + + private void updateGame(final GameState state) { + rmiExecutor.submit( + new Runnable() { + public void run() { + try { + client.update(new GameView(state)); + } catch (RemoteException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + } + ); + } + +} diff --git a/Mage.Server/src/mage/server/game/Room.java b/Mage.Server/src/mage/server/game/Room.java new file mode 100644 index 00000000000..61b42108721 --- /dev/null +++ b/Mage.Server/src/mage/server/game/Room.java @@ -0,0 +1,41 @@ +/* +* 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.rmi.Remote; +import java.util.UUID; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public interface Room extends Remote { + public UUID getChatId(); + public UUID getRoomId(); +} diff --git a/Mage.Server/src/mage/server/game/RoomImpl.java b/Mage.Server/src/mage/server/game/RoomImpl.java new file mode 100644 index 00000000000..f1391caa428 --- /dev/null +++ b/Mage.Server/src/mage/server/game/RoomImpl.java @@ -0,0 +1,66 @@ +/* +* 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.util.UUID; +import mage.server.ChatManager; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public abstract class RoomImpl implements Room { + + private UUID chatId; + private UUID roomId; + + public RoomImpl() { + roomId = UUID.randomUUID(); + chatId = ChatManager.getInstance().createChatSession(); + } + + /** + * @return the chatId + */ + @Override + public UUID getChatId() { + return chatId; + } + + /** + * @return the roomId + */ + @Override + public UUID getRoomId() { + return roomId; + } + + + +} diff --git a/Mage.Server/src/mage/server/game/TableController.java b/Mage.Server/src/mage/server/game/TableController.java new file mode 100644 index 00000000000..066013b1752 --- /dev/null +++ b/Mage.Server/src/mage/server/game/TableController.java @@ -0,0 +1,156 @@ +/* +* 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.util.List; +import java.util.Map.Entry; +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; +import mage.game.Game; +import mage.game.GameException; +import mage.game.Seat; +import mage.game.Table; +import mage.players.Player; +import mage.server.ChatManager; +import mage.server.SessionManager; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class TableController { + + private final static Logger logger = Logging.getLogger(TableController.class.getName()); + + private UUID sessionId; + private UUID chatId; + private Table table; + private Game game; + private ConcurrentHashMap sessionPlayerMap = new ConcurrentHashMap(); + + public TableController(UUID sessionId, String gameType, DeckType deckType, List playerTypes) { + this.sessionId = sessionId; + chatId = ChatManager.getInstance().createChatSession(); + game = GameFactory.getInstance().createGame(gameType); + table = new Table(game, deckType, playerTypes); + } + + public synchronized boolean joinTable(UUID sessionId, int seatNum, String name, DeckCardLists deckList) { + 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.log(Level.WARNING, ex.getMessage()); + return false; + } + return true; + } + + public boolean watchTable(UUID sessionId) { + SessionManager.getInstance().getSession(sessionId).watchGame(game.getId()); + return true; + } + + public boolean replayTable(UUID sessionId) { + ReplayManager.getInstance().replayGame(sessionId, game.getId()); + return true; + } + + private boolean validDeck(Deck deck) { + return table.getValidator().validate(deck); + } + + private Player createPlayer(String name, Deck deck, String playerType) { + Player player = PlayerFactory.getInstance().createPlayer(playerType, name); + logger.info("Player created " + player.getId()); + player.setDeck(deck); + return player; + } + + public synchronized void leaveTable(UUID sessionId) { + if (table.getState() == TableState.WAITING) + table.leaveTable(sessionPlayerMap.get(sessionId)); + } + + public synchronized void startGame(UUID sessionId) { + if (sessionId.equals(this.sessionId) && table.getState() == TableState.STARTING) { + try { + table.initGame(); + } catch (GameException ex) { + logger.log(Level.SEVERE, null, ex); + } + GameManager.getInstance().createGameSession(game, sessionPlayerMap, table.getId()); + SessionManager sessionManager = SessionManager.getInstance(); + for (Entry entry: sessionPlayerMap.entrySet()) { + sessionManager.getSession(entry.getKey()).gameStarted(game.getId(), entry.getValue()); + } + } + } + + public void endGame() { + table.endGame(); + } + + public boolean isOwner(UUID sessionId) { + return sessionId.equals(this.sessionId); + } + + public Table getTable() { + return table; + } + + public UUID getChatId() { + return chatId; + } + +} diff --git a/Mage.Server/src/mage/server/game/TableManager.java b/Mage.Server/src/mage/server/game/TableManager.java new file mode 100644 index 00000000000..a1333ea185e --- /dev/null +++ b/Mage.Server/src/mage/server/game/TableManager.java @@ -0,0 +1,116 @@ +/* +* 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.util.Collection; +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.Table; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class TableManager { + + private final static TableManager INSTANCE = new TableManager(); + private final static Logger logger = Logging.getLogger(TableManager.class.getName()); + + private ConcurrentHashMap controllers = new ConcurrentHashMap(); + private ConcurrentHashMap tables = new ConcurrentHashMap(); + + public static TableManager getInstance() { + return INSTANCE; + } + + public Table createTable(UUID sessionId, String gameType, DeckType deckType, List playerTypes) { + TableController tableController = new TableController(sessionId, gameType, deckType, playerTypes); + controllers.put(tableController.getTable().getId(), tableController); + tables.put(tableController.getTable().getId(), tableController.getTable()); + return tableController.getTable(); + } + + public Table getTable(UUID tableId) { + return tables.get(tableId); + } + + public Collection getTables() { + return tables.values(); + } + + public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) { + return controllers.get(tableId).joinTable(sessionId, seatNum, name, deckList); + } + + public void removeSession(UUID sessionId) { + // TODO: search through tables and remove session + } + + public boolean isTableOwner(UUID tableId, UUID sessionId) { + return controllers.get(tableId).isOwner(sessionId); + } + + public boolean removeTable(UUID sessionId, UUID tableId) { + if (isTableOwner(tableId, sessionId)) { + controllers.remove(tableId); + tables.remove(tableId); + return true; + } + return false; + } + + public void leaveTable(UUID sessionId, UUID tableId) { + controllers.get(tableId).leaveTable(sessionId); + } + + public UUID getChatId(UUID tableId) { + return controllers.get(tableId).getChatId(); + } + + public void startGame(UUID sessionId, UUID roomId, UUID tableId) { + controllers.get(tableId).startGame(sessionId); + } + + public boolean watchTable(UUID sessionId, UUID tableId) { + return controllers.get(tableId).watchTable(sessionId); + } + + public boolean replayTable(UUID sessionId, UUID tableId) { + return controllers.get(tableId).replayTable(sessionId); + } + + public void endGame(UUID tableId) { + controllers.get(tableId).endGame(); + } +} diff --git a/Mage.Server/src/mage/server/util/Config.java b/Mage.Server/src/mage/server/util/Config.java new file mode 100644 index 00000000000..ff020a26354 --- /dev/null +++ b/Mage.Server/src/mage/server/util/Config.java @@ -0,0 +1,63 @@ +/* +* 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.io.IOException; +import java.util.Properties; +import java.util.logging.Level; +import java.util.logging.Logger; +import mage.util.Logging; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class Config { + + private final static Logger logger = Logging.getLogger(Config.class.getName()); + + static { + Properties p = new Properties(); + try { + p.load(Config.class.getResourceAsStream("resources/config.properties")); + } catch (IOException ex) { + logger.log(Level.SEVERE, null, ex); + } + port = Integer.parseInt(p.getProperty("port")); + remoteServer = p.getProperty("remote-server"); + maxGameThreads = Integer.parseInt(p.getProperty("max-game-threads")); + maxSecondsIdle = Integer.parseInt(p.getProperty("max-seconds-idle")); + } + + public static final String remoteServer; + public static final int port; + public static final int maxGameThreads; + public static final int maxSecondsIdle; + +} diff --git a/Mage.Server/src/mage/server/util/Config.xsd b/Mage.Server/src/mage/server/util/Config.xsd new file mode 100644 index 00000000000..8a7a7c67fa0 --- /dev/null +++ b/Mage.Server/src/mage/server/util/Config.xsd @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mage.Server/src/mage/server/util/ConfigSettings.java b/Mage.Server/src/mage/server/util/ConfigSettings.java new file mode 100644 index 00000000000..1052a889fb8 --- /dev/null +++ b/Mage.Server/src/mage/server/util/ConfigSettings.java @@ -0,0 +1,90 @@ +/* +* 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.io.File; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import mage.server.util.config.Config; +import mage.server.util.config.Plugin; +import mage.util.Logging; +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ConfigSettings { + + private final static Logger logger = Logging.getLogger(ConfigSettings.class.getName()); + private final static ConfigSettings INSTANCE = new ConfigSettings(); + + private Config config; + + public static ConfigSettings getInstance() { + return INSTANCE; + } + + private ConfigSettings() { + try { + JAXBContext jaxbContext = JAXBContext.newInstance("mage.server.util.config"); + Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); + config = (Config) unmarshaller.unmarshal(new File("config/config.xml")); + } catch (JAXBException ex) { + logger.log(Level.SEVERE, null, ex); + } + } + + public String getServerName() { + return config.getServer().getServerName(); + } + + public int getPort() { + return config.getServer().getPort().intValue(); + } + + public int getMaxGameThreads() { + return config.getServer().getMaxGameThreads().intValue(); + } + + public int getMaxSecondsIdle() { + return config.getServer().getMaxSecondsIdle().intValue(); + } + + public List getPlayerTypes() { + return config.getPlayerTypes().getPlugin(); + } + + public List getGameTypes() { + return config.getGameTypes().getPlugin(); + } + +} diff --git a/Mage.Server/src/mage/server/util/ThreadExecutor.java b/Mage.Server/src/mage/server/util/ThreadExecutor.java new file mode 100644 index 00000000000..4576d130870 --- /dev/null +++ b/Mage.Server/src/mage/server/util/ThreadExecutor.java @@ -0,0 +1,65 @@ +/* +* 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.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +/** + * + * @author BetaSteward_at_googlemail.com + */ +public class ThreadExecutor { + + private static ExecutorService rmiExecutor = Executors.newCachedThreadPool(); + private static ExecutorService gameExecutor = Executors.newFixedThreadPool(ConfigSettings.getInstance().getMaxGameThreads()); + private static ScheduledExecutorService timeoutExecutor = Executors.newScheduledThreadPool(5); + + private final static ThreadExecutor INSTANCE = new ThreadExecutor(); + + public static ThreadExecutor getInstance() { + return INSTANCE; + } + + private ThreadExecutor() {} + + public ExecutorService getRMIExecutor() { + return rmiExecutor; + } + + public ExecutorService getGameExecutor() { + return gameExecutor; + } + + public ScheduledExecutorService getTimeoutExecutor() { + return timeoutExecutor; + } + +} diff --git a/Mage.Server/src/mage/server/util/resources/config.xml b/Mage.Server/src/mage/server/util/resources/config.xml new file mode 100644 index 00000000000..5b6dbf522bb --- /dev/null +++ b/Mage.Server/src/mage/server/util/resources/config.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/Mage.Server/src/security.policy b/Mage.Server/src/security.policy new file mode 100644 index 00000000000..dda47ba9183 --- /dev/null +++ b/Mage.Server/src/security.policy @@ -0,0 +1,3 @@ +grant { + permission java.security.AllPermission; +}; \ No newline at end of file diff --git a/Mage.Server/xml-resources/jaxb/Config/Config.xsd b/Mage.Server/xml-resources/jaxb/Config/Config.xsd new file mode 100644 index 00000000000..8a7a7c67fa0 --- /dev/null +++ b/Mage.Server/xml-resources/jaxb/Config/Config.xsd @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +