Merge branch 'multiplayer' into 'master'

Multiplayer

Closes #157

See merge request core-developers/forge!262
This commit is contained in:
Sol
2018-03-01 03:12:26 +00:00
10 changed files with 76 additions and 10 deletions

View File

@@ -21,7 +21,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3</version>
<version>3.7</version>
</dependency>
</dependencies>
</project>

View File

@@ -29,6 +29,7 @@ public class StaticData {
private final String blockDataFolder;
private final CardDb commonCards;
private final CardDb variantCards;
private final CardDb allCards;
private final TokenDb allTokens;
private final CardEdition.Collection editions;
@@ -54,6 +55,7 @@ public class StaticData {
lastInstance = this;
{
final Map<String, CardRules> allCardsMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
final Map<String, CardRules> regularCards = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
final Map<String, CardRules> variantsCards = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
@@ -61,6 +63,7 @@ public class StaticData {
if (null == card) continue;
final String cardName = card.getName();
allCardsMap.put(cardName, card);
if (card.isVariant()) {
variantsCards.put(cardName, card);
} else {
@@ -68,10 +71,12 @@ public class StaticData {
}
}
allCards = new CardDb(allCardsMap, editions);
commonCards = new CardDb(regularCards, editions);
variantCards = new CardDb(variantsCards, editions);
//muse initialize after establish field values for the sake of card image logic
//must initialize after establish field values for the sake of card image logic
allCards.initialize(false, false);
commonCards.initialize(false, false);
variantCards.initialize(false, false);
}
@@ -184,6 +189,8 @@ public class StaticData {
return variantCards;
}
public CardDb getAllCards() { return allCards; }
public TokenDb getAllTokens() { return allTokens; }
public PaperCard getCardByEditionDate(PaperCard card, Date editionDate) {

View File

@@ -212,7 +212,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
// default deserialization
ois.defaultReadObject();
final IPaperCard pc = StaticData.instance().getCommonCards().getCard(name, edition, artIndex);
final IPaperCard pc = StaticData.instance().getAllCards().getCard(name, edition, artIndex);
if (pc == null) {
throw new IOException(TextUtil.concatWithSpace("Card", name, "not found"));
}

View File

@@ -129,6 +129,12 @@ public class PlayerView extends GameEntityView {
}
final FCollectionView<PlayerView> opponents = getOpponents();
for (PlayerView opponent: opponents) {
if (opponent.getCommanders() == null) {
return Collections.emptyList();
}
}
final List<String> info = Lists.newArrayListWithExpectedSize(opponents.size());
info.add(TextUtil.concatWithSpace("Commanders:", Lang.joinHomogenous(commanders)));
for (final PlayerView p : Iterables.concat(Collections.singleton(this), opponents)) {

View File

@@ -91,7 +91,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3</version>
<version>3.7</version>
</dependency>
<dependency>
<groupId>xmlpull</groupId>

View File

@@ -228,7 +228,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3</version>
<version>3.7</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>

View File

@@ -94,7 +94,7 @@ public class VLobby implements ILobbyView {
private final VariantCheckBox vntArchenemy = new VariantCheckBox(GameType.Archenemy);
private final VariantCheckBox vntArchenemyRumble = new VariantCheckBox(GameType.ArchenemyRumble);
private final ImmutableList<VariantCheckBox> vntBoxes =
ImmutableList.of(vntVanguard, vntMomirBasic, vntCommander, vntTinyLeaders, vntPlanechase, vntArchenemy, vntArchenemyRumble);
ImmutableList.of(vntVanguard, vntMomirBasic, vntCommander, vntTinyLeaders /*, vntPlanechase, vntArchenemy, vntArchenemyRumble */);
// Player frame elements
private final JPanel playersFrame = new JPanel(new MigLayout("insets 0, gap 0 5, wrap, hidemode 3"));
@@ -302,7 +302,7 @@ public class VLobby implements ILobbyView {
}
void setReady(final int index, final boolean ready) {
if (ready && decks[index] == null) {
if (ready && decks[index] == null && !vntMomirBasic.isSelected()) {
SOptionPane.showErrorDialog("Select a deck before readying!");
update(false);
return;

View File

@@ -58,7 +58,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3</version>
<version>3.7</version>
</dependency>
<dependency>
<groupId>com.badlogicgames.gdx</groupId>

View File

@@ -49,7 +49,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.3</version>
<version>3.7</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>

View File

@@ -7,7 +7,10 @@ import forge.game.player.RegisteredPlayer;
import forge.interfaces.ILobbyListener;
import forge.match.LobbySlot;
import forge.player.LobbyPlayerHuman;
import forge.player.PlayerZoneUpdate;
import forge.player.PlayerZoneUpdates;
import forge.trackable.TrackableObject;
import forge.trackable.TrackableTypes;
import forge.trackable.Tracker;
import io.netty.channel.ChannelHandlerContext;
import forge.game.player.PlayerView;
@@ -88,6 +91,7 @@ final class GameClientHandler extends GameProtocolHandler<IGuiGame> {
}
if (!(this.tracker == null)) {
updateTrackers(args);
replicateProps(args);
}
}
@@ -99,12 +103,26 @@ final class GameClientHandler extends GameProtocolHandler<IGuiGame> {
private GameRules createGameRules(GameType gameType, GameView gameView) {
// FIXME: how do we know the rules are the same on each side???
GameRules gameRules = new GameRules(gameType);
// is this always safe to do?
gameRules.setAppliedVariants(Collections.singleton(gameType));
gameRules.setGamesPerMatch(gameView.getNumGamesInMatch());
gameRules.setPoisonCountersToLose(gameView.getPoisonCountersToLose());
return gameRules;
}
/**
* Retrieve the desired GameType from the Lobby
*
* @return GameType
*/
private GameType getGameType() {
List<ILobbyListener> lobbyListeners = client.getLobbyListeners();
ILobbyListener lobbyListener = lobbyListeners.get(0);
ClientGameLobby myLobby = lobbyListener.getLobby();
return myLobby.getGameType();
}
/**
* This method retrieves enough of the existing (incomplete) game state to
* recreate a new viable Match object
@@ -121,7 +139,7 @@ final class GameClientHandler extends GameProtocolHandler<IGuiGame> {
final IGuiGame gui = client.getGui();
GameView gameView = gui.getGameView();
final GameType gameType = gameView.getGameType();
final GameType gameType = getGameType();
final GameRules gameRules = createGameRules(gameType, gameView);
final List<RegisteredPlayer> registeredPlayers = createRegisteredPlayers(gameType);
@@ -231,6 +249,41 @@ final class GameClientHandler extends GameProtocolHandler<IGuiGame> {
}
}
private void replicateProps(final Object[] objs) {
for (Object obj: objs) {
if (obj instanceof PlayerView) {
replicatePlayerView((PlayerView) obj);
}
else if (obj instanceof PlayerZoneUpdate) {
replicatePlayerView(((PlayerZoneUpdate) obj).getPlayer());
}
else if (obj instanceof PlayerZoneUpdates) {
Iterator itrPlayerZoneUpdates = ((PlayerZoneUpdates) obj).iterator();
while (itrPlayerZoneUpdates.hasNext()) {
PlayerView newPlayerView = ((PlayerZoneUpdate)itrPlayerZoneUpdates.next()).getPlayer();
/**
* FIXME: this should be handled by the original call to updateTrackers
* However, PlayerZoneUpdates aren't a TrackableCollection.
* So, additional logic will be needed. Leaving here for now.
*/
updateTrackers(new Object[]{newPlayerView});
replicatePlayerView(newPlayerView);
}
}
/*
else {
System.err.println("replicateProps - did not handle : " + obj.getClass().toString());
}
*/
}
}
private void replicatePlayerView(final PlayerView newPlayerView) {
PlayerView existingPlayerView = tracker.getObj(TrackableTypes.PlayerViewType, newPlayerView.getId());
existingPlayerView.copyChangedProps(newPlayerView);
System.err.println("replicated PlayerView properties - " + existingPlayerView.toString());
}
@Override
public void channelActive(final ChannelHandlerContext ctx) {
// Don't use send() here, as this.channel is not yet set!