changes to support multiplayer

This commit is contained in:
BetaSteward 2010-05-17 03:19:39 +00:00
parent d91c00d002
commit 79dbfca2ff
18 changed files with 144 additions and 59 deletions

View file

@ -3,13 +3,14 @@
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Config.xsd">
<server serverAddress="localhost" serverName="mage-server" port="17171" maxGameThreads="10" maxSecondsIdle="600"/>
<playerTypes>
<plugin name="Human" jar="Mage.Player.Human.jar" className="mage.player.human.HumanPlayer"/>
<plugin name="Computer - default" jar="Mage.Player.AI.jar" className="mage.player.ai.ComputerPlayer"/>
<playerType name="Human" jar="Mage.Player.Human.jar" className="mage.player.human.HumanPlayer"/>
<playerType name="Computer - default" jar="Mage.Player.AI.jar" className="mage.player.ai.ComputerPlayer"/>
</playerTypes>
<gameTypes>
<plugin name="Two Player Duel" jar="Mage.Game.TwoPlayerDuel.jar" className="mage.game.TwoPlayerGame"/>
<gameType name="Two Player Duel" jar="Mage.Game.TwoPlayerDuel.jar" className="mage.game.TwoPlayerDuel" typeName="mage.game.TwoPlayerDuelType"/>
<gameType name="Free For All" jar="Mage.Game.FreeForAll.jar" className="mage.game.FreeForAll" typeName="mage.game.FreeForAllType"/>
</gameTypes>
<deckTypes>
<plugin name="Constructed" jar="Mage.Deck.Constructed.jar" className="mage.deck.Constructed"/>
<deckType name="Constructed" jar="Mage.Deck.Constructed.jar" className="mage.deck.Constructed"/>
</deckTypes>
</config>

View file

@ -26,7 +26,8 @@ jar.compress=false
javac.classpath=\
${reference.Mage.jar}:\
${reference.Mage_Common.jar}:\
${reference.Mage_Sets.jar}
${reference.Mage_Sets.jar}:\
${reference.Mage_Player_AI.jar}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
@ -59,9 +60,11 @@ platform.active=default_platform
project.license=bsd
project.Mage=../Mage
project.Mage_Common=../Mage.Common
project.Mage_Player_AI=../Mage.Player.AI
project.Mage_Sets=../Mage.Sets
reference.Mage.jar=${project.Mage}/dist/Mage.jar
reference.Mage_Common.jar=${project.Mage_Common}/dist/Mage.Common.jar
reference.Mage_Player_AI.jar=${project.Mage_Player_AI}/dist/Mage.Player.AI.jar
reference.Mage_Sets.jar=${project.Mage_Sets}/dist/Mage.Sets.jar
run-sys-prop.java.endorsed.dirs=${jaxbwiz.endorsed.dirs}
run.classpath=\
@ -74,4 +77,4 @@ run.test.classpath=\
source.encoding=UTF-8
src.dir=src
test.src.dir=test
app.version=0.2
app.version=0.3

View file

@ -33,6 +33,14 @@
<clean-target>clean</clean-target>
<id>jar</id>
</reference>
<reference>
<foreign-project>Mage_Player_AI</foreign-project>
<artifact-type>jar</artifact-type>
<script>build.xml</script>
<target>jar</target>
<clean-target>clean</clean-target>
<id>jar</id>
</reference>
<reference>
<foreign-project>Mage_Sets</foreign-project>
<artifact-type>jar</artifact-type>

Binary file not shown.

View file

@ -33,11 +33,13 @@ import java.io.File;
import java.io.FilenameFilter;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.game.GameType;
import mage.server.game.DeckValidatorFactory;
import mage.server.game.GameFactory;
import mage.server.game.PlayerFactory;
import mage.server.util.ConfigSettings;
import mage.server.util.config.Plugin;
import mage.server.util.config.GamePlugin;
import mage.util.Copier;
import mage.util.Logging;
@ -64,8 +66,8 @@ public class Main {
logger.info("Logging level: " + Logging.getLevel(logger));
deleteSavedGames();
ConfigSettings config = ConfigSettings.getInstance();
for (Plugin plugin: config.getGameTypes()) {
GameFactory.getInstance().addGameType(plugin.getName(), loadPlugin(plugin));
for (GamePlugin plugin: config.getGameTypes()) {
GameFactory.getInstance().addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin));
}
for (Plugin plugin: config.getPlayerTypes()) {
PlayerFactory.getInstance().addPlayerType(plugin.getName(), loadPlugin(plugin));
@ -98,6 +100,19 @@ public class Main {
return null;
}
private static GameType loadGameType(GamePlugin plugin) {
try {
classLoader.addURL(new File(pluginFolder + "/" + plugin.getJar()).toURI().toURL());
logger.info("Loading game type: " + plugin.getClassName());
return (GameType) Class.forName(plugin.getTypeName(), true, classLoader).newInstance();
} catch (ClassNotFoundException ex) {
logger.log(Level.SEVERE, "Game type not found:" + plugin.getJar() + " - check plugin folder");
} catch (Exception ex) {
logger.log(Level.SEVERE, "Error loading game type " + plugin.getJar(), ex);
}
return null;
}
private static void deleteSavedGames() {
File directory = new File("saved/");
File[] files = directory.listFiles(

View file

@ -33,11 +33,12 @@ import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RemoteServer;
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.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists;
import mage.game.GameException;
import mage.interfaces.MageException;
@ -51,6 +52,7 @@ import mage.server.game.PlayerFactory;
import mage.server.game.ReplayManager;
import mage.server.game.TableManager;
import mage.util.Logging;
import mage.view.GameTypeView;
import mage.view.TableView;
/**
@ -101,9 +103,9 @@ public class ServerImpl extends RemoteServer implements Server {
}
@Override
public TableView createTable(UUID sessionId, UUID roomId, String gameType, String deckType, List<String> playerTypes) throws MageException {
public TableView createTable(UUID sessionId, UUID roomId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) throws MageException {
try {
TableView table = GamesRoomManager.getInstance().getRoom(roomId).createTable(sessionId, gameType, deckType, playerTypes);
TableView table = GamesRoomManager.getInstance().getRoom(roomId).createTable(sessionId, gameType, deckType, playerTypes, attackOption, range);
logger.info("Table " + table.getTableId() + " created");
return table;
}
@ -139,7 +141,7 @@ public class ServerImpl extends RemoteServer implements Server {
}
@Override
public Collection<TableView> getTables(UUID roomId) throws MageException {
public List<TableView> getTables(UUID roomId) throws MageException {
try {
return GamesRoomManager.getInstance().getRoom(roomId).getTables();
}
@ -244,6 +246,16 @@ public class ServerImpl extends RemoteServer implements Server {
return false;
}
@Override
public void swapSeats(UUID sessionId, UUID roomId, UUID tableId, int seatNum1, int seatNum2) throws RemoteException, MageException {
try {
TableManager.getInstance().swapSeats(tableId, sessionId, seatNum1, seatNum2);
}
catch (Exception ex) {
handleException(ex);
}
}
@Override
public void leaveTable(UUID sessionId, UUID roomId, UUID tableId) throws MageException {
try {
@ -419,9 +431,9 @@ public class ServerImpl extends RemoteServer implements Server {
}
@Override
public String[] getGameTypes() throws MageException {
public List<GameTypeView> getGameTypes() throws MageException {
try {
return GameFactory.getInstance().getGameTypes().toArray(new String[0]);
return GameFactory.getInstance().getGameTypes();
}
catch (Exception ex) {
handleException(ex);

View file

@ -29,14 +29,19 @@
package mage.server.game;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.game.Game;
import mage.server.Main;
import mage.util.Logging;
import mage.game.GameType;
import mage.view.GameTypeView;
/**
*
@ -47,7 +52,10 @@ public class GameFactory {
private final static GameFactory INSTANCE = new GameFactory();
private final static Logger logger = Logging.getLogger(GameFactory.class.getName());
private Map<String, Class> gameTypes = new HashMap<String, Class>();
private Map<String, Class<Game>> games = new HashMap<String, Class<Game>>();
private Map<String, GameType> gameTypes = new HashMap<String, GameType>();
private List<GameTypeView> gameTypeViews = new ArrayList<GameTypeView>();
public static GameFactory getInstance() {
return INSTANCE;
@ -55,13 +63,13 @@ public class GameFactory {
private GameFactory() {}
public Game createGame(String gameType) {
public Game createGame(String gameType, MultiplayerAttackOption attackOption, RangeOfInfluence range) {
Game game;
Constructor<?> con;
Constructor<Game> con;
try {
con = gameTypes.get(gameType).getConstructor(new Class[]{});
game = (Game)con.newInstance(new Object[] {});
con = games.get(gameType).getConstructor(new Class[]{MultiplayerAttackOption.class, RangeOfInfluence.class});
game = con.newInstance(new Object[] {attackOption, range});
} catch (Exception ex) {
logger.log(Level.SEVERE, null, ex);
return null;
@ -71,13 +79,16 @@ public class GameFactory {
return game;
}
public Set<String> getGameTypes() {
return gameTypes.keySet();
public List<GameTypeView> getGameTypes() {
return gameTypeViews;
}
public void addGameType(String name, Class gameType) {
if (gameType != null)
public void addGameType(String name, GameType gameType, Class game) {
if (game != null) {
this.games.put(name, game);
this.gameTypes.put(name, gameType);
this.gameTypeViews.add(new GameTypeView(gameType));
}
}
}

View file

@ -28,9 +28,10 @@
package mage.server.game;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists;
import mage.game.GameException;
import mage.view.TableView;
@ -41,9 +42,9 @@ import mage.view.TableView;
*/
public interface GamesRoom extends Room {
public Collection<TableView> getTables();
public List<TableView> getTables();
public boolean joinTable(UUID sessionId, UUID tableId, int seatNum, String name, DeckCardLists deckList) throws GameException;
public TableView createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes);
public TableView createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range);
public void removeTable(UUID sessionId, UUID tableId);
public TableView getTable(UUID tableId);
public void leaveTable(UUID sessionId, UUID tableId);

View file

@ -31,11 +31,12 @@ package mage.server.game;
import mage.game.Table;
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.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists;
import mage.game.GameException;
import mage.util.Logging;
@ -52,7 +53,7 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
private ConcurrentHashMap<UUID, Table> tables = new ConcurrentHashMap<UUID, Table>();
@Override
public Collection<TableView> getTables() {
public List<TableView> getTables() {
ArrayList<TableView> tableList = new ArrayList<TableView>();
for (Table table: tables.values()) {
tableList.add(new TableView(table));
@ -70,8 +71,8 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
}
@Override
public TableView createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes) {
Table table = TableManager.getInstance().createTable(sessionId, gameType, deckType, playerTypes);
public TableView createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) {
Table table = TableManager.getInstance().createTable(sessionId, gameType, deckType, playerTypes, attackOption, range);
tables.put(table.getId(), table);
return new TableView(table);
}

View file

@ -34,6 +34,7 @@ import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.Deck;
import mage.players.Player;
import mage.util.Logging;
@ -55,12 +56,12 @@ public class PlayerFactory {
private PlayerFactory() {}
public Player createPlayer(String playerType, String name, Deck deck) {
public Player createPlayer(String playerType, String name, Deck deck, RangeOfInfluence range) {
Player player;
Constructor<?> con;
try {
con = playerTypes.get(playerType).getConstructor(new Class[]{String.class, Deck.class});
player = (Player)con.newInstance(new Object[] {name, deck});
con = playerTypes.get(playerType).getConstructor(new Class[]{String.class, Deck.class, RangeOfInfluence.class});
player = (Player)con.newInstance(new Object[] {name, deck, range});
} catch (Exception ex) {
logger.log(Level.SEVERE, null, ex);
return null;

View file

@ -47,6 +47,8 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.Constants.TableState;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckCardLists;
@ -76,10 +78,10 @@ public class TableController {
private Game game;
private ConcurrentHashMap<UUID, UUID> sessionPlayerMap = new ConcurrentHashMap<UUID, UUID>();
public TableController(UUID sessionId, String gameType, String deckType, List<String> playerTypes) {
public TableController(UUID sessionId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) {
this.sessionId = sessionId;
chatId = ChatManager.getInstance().createChatSession();
game = GameFactory.getInstance().createGame(gameType);
game = GameFactory.getInstance().createGame(gameType, attackOption, range);
gameId = game.getId();
table = new Table(gameType, DeckValidatorFactory.getInstance().createDeckValidator(deckType), playerTypes);
}
@ -134,9 +136,8 @@ public class TableController {
}
private Player createPlayer(String name, Deck deck, String playerType) {
Player player = PlayerFactory.getInstance().createPlayer(playerType, name, deck);
Player player = PlayerFactory.getInstance().createPlayer(playerType, name, deck, game.getRangeOfInfluence());
logger.info("Player created " + player.getId());
// player.setDeck(deck);
return player;
}
@ -167,6 +168,19 @@ public class TableController {
game = null;
}
public void swapSeats(int seatNum1, int seatNum2) {
if (table.getState() == TableState.STARTING) {
if (seatNum1 >= 0 && seatNum2 >= 0 && seatNum1 < table.getSeats().length && seatNum2 < table.getSeats().length) {
Player swapPlayer = table.getSeats()[seatNum1].getPlayer();
String swapType = table.getSeats()[seatNum1].getPlayerType();
table.getSeats()[seatNum1].setPlayer(table.getSeats()[seatNum2].getPlayer());
table.getSeats()[seatNum1].setPlayerType(table.getSeats()[seatNum2].getPlayerType());
table.getSeats()[seatNum2].setPlayer(swapPlayer);
table.getSeats()[seatNum2].setPlayerType(swapType);
}
}
}
private void saveGame() {
try {
//use buffering

View file

@ -34,6 +34,8 @@ import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
import mage.Constants.MultiplayerAttackOption;
import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists;
import mage.game.GameException;
import mage.util.Logging;
@ -54,8 +56,8 @@ public class TableManager {
return INSTANCE;
}
public Table createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes) {
TableController tableController = new TableController(sessionId, gameType, deckType, playerTypes);
public Table createTable(UUID sessionId, String gameType, String deckType, List<String> playerTypes, MultiplayerAttackOption attackOption, RangeOfInfluence range) {
TableController tableController = new TableController(sessionId, gameType, deckType, playerTypes, attackOption, range);
controllers.put(tableController.getTable().getId(), tableController);
tables.put(tableController.getTable().getId(), tableController.getTable());
return tableController.getTable();
@ -117,4 +119,10 @@ public class TableManager {
public GameReplay createReplay(UUID tableId) {
return controllers.get(tableId).createReplay();
}
public void swapSeats(UUID tableId, UUID sessionId, int seatNum1, int seatNum2) {
if (isTableOwner(tableId, sessionId)) {
controllers.get(tableId).swapSeats(seatNum1, seatNum2);
}
}
}

View file

@ -37,6 +37,7 @@ import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import mage.server.util.config.Config;
import mage.server.util.config.Plugin;
import mage.server.util.config.GamePlugin;
import mage.util.Logging;
/**
*
@ -84,15 +85,15 @@ public class ConfigSettings {
}
public List<Plugin> getPlayerTypes() {
return config.getPlayerTypes().getPlugin();
return config.getPlayerTypes().getPlayerType();
}
public List<Plugin> getGameTypes() {
return config.getGameTypes().getPlugin();
public List<GamePlugin> getGameTypes() {
return config.getGameTypes().getGameType();
}
public List<Plugin> getDeckTypes() {
return config.getDeckTypes().getPlugin();
return config.getDeckTypes().getDeckType();
}
}

View file

@ -1,12 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../Config.xsd">
<server serverName="mage-server" port="17171" maxGameThreads="10" maxSecondsIdle="600"/>
<server serverAddress="localhost" serverName="mage-server" port="17171" maxGameThreads="10" maxSecondsIdle="600"/>
<playerTypes>
<plugin name="Human" jar="Mage.HumanPlayer.jar" className="mage.human.HumanPlayer"/>
<plugin name="Computer - default" jar="Mage.AI.jar" className="mage.ai.ComputerPlayer"/>
<playerType name="Human" jar="Mage.Player.Human.jar" className="mage.player.human.HumanPlayer"/>
<playerType name="Computer - default" jar="Mage.Player.AI.jar" className="mage.player.ai.ComputerPlayer"/>
</playerTypes>
<gameTypes>
<plugin name="Two Player Duel" jar="Mage.Game.TwoPlayerDuel.jar" className="mage.game.TwoPlayerGame"/>
<gameType name="Two Player Duel" jar="Mage.Game.TwoPlayerDuel.jar" className="mage.game.TwoPlayerDuel" typeName="mage.game.TwoPlayerDuelType"/>
</gameTypes>
<deckTypes>
<deckType name="Constructed" jar="Mage.Deck.Constructed.jar" className="mage.deck.Constructed"/>
</deckTypes>
</config>

View file

@ -23,18 +23,24 @@
</xs:complexType>
</xs:element>
<xs:element name="plugin">
<xs:complexType>
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="jar" type="xs:string"/>
<xs:attribute name="className" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:complexType name="plugin">
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="jar" type="xs:string"/>
<xs:attribute name="className" type="xs:string"/>
</xs:complexType>
<xs:complexType name="gamePlugin">
<xs:complexContent>
<xs:extension base="plugin">
<xs:attribute name="typeName" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="playerTypes">
<xs:complexType>
<xs:sequence>
<xs:element ref="plugin" maxOccurs="unbounded"/>
<xs:element name="playerType" type="plugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
@ -42,7 +48,7 @@
<xs:element name="gameTypes">
<xs:complexType>
<xs:sequence>
<xs:element ref="plugin" maxOccurs="unbounded"/>
<xs:element name="gameType" type="gamePlugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
@ -50,7 +56,7 @@
<xs:element name="deckTypes">
<xs:complexType>
<xs:sequence>
<xs:element ref="plugin" maxOccurs="unbounded"/>
<xs:element name="deckType" type="plugin" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>