Update stability and fix issues in lobby and network games.

- Fix closing the lobby/client so that it notifies the clients/server.
- Improve deck selection in lobby (no longer adds Planes to deck and saves)
- Improve responsiveness of lobby over network
- In 2-player game over network, always assign local player to slot 0
- Warn when starting a commander deck without a commander
- Put poison counters next to life total (frees up space in the details panel)
This commit is contained in:
elcnesh
2015-04-02 08:56:31 +00:00
parent d3bcc089e3
commit 6bc69d0935
12 changed files with 235 additions and 138 deletions

View File

@@ -5,4 +5,5 @@ import forge.match.GameLobby.GameLobbyData;
public interface ILobbyListener {
void message(String source, String message);
void update(GameLobbyData state, int slot);
void close();
}

View File

@@ -41,6 +41,7 @@ public abstract class GameLobby {
private final static int MAX_PLAYERS = 8;
private GameLobbyData data = new GameLobbyData();
private GameType currentGameType = GameType.Constructed;
private int lastArchenemy = 0;
private IUpdateable listener;
@@ -69,10 +70,10 @@ public abstract class GameLobby {
}
public GameType getGameType() {
return data.currentGameMode;
return currentGameType;
}
public void setGameType(final GameType type) {
data.currentGameMode = type;
currentGameType = type;
}
public boolean hasVariant(final GameType variant) {
@@ -90,7 +91,7 @@ public abstract class GameLobby {
}
public void applyToSlot(final int index, final UpdateLobbyPlayerEvent event) {
final LobbySlot slot = getSlot(index);
if (slot == null) {
if (slot == null || event == null) {
throw new NullPointerException();
}
@@ -130,10 +131,10 @@ public abstract class GameLobby {
}
public abstract boolean hasControl();
public abstract boolean mayEdit(final int index);
public abstract boolean mayControl(final int index);
public abstract boolean mayRemove(final int index);
protected abstract IGuiGame getGui(final int index);
public abstract boolean mayEdit(int index);
public abstract boolean mayControl(int index);
public abstract boolean mayRemove(int index);
protected abstract IGuiGame getGui(int index);
protected abstract void onGameStarted();
public void addSlot() {
@@ -142,6 +143,9 @@ public abstract class GameLobby {
addSlot(new LobbySlot(type, null, newIndex, newIndex, false, !allowNetworking, Collections.<AIOption>emptySet()));
}
protected final void addSlot(final LobbySlot slot) {
if (slot == null) {
throw new NullPointerException();
}
if (data.slots.size() >= MAX_PLAYERS) {
return;
}
@@ -197,7 +201,7 @@ public abstract class GameLobby {
}
public void applyVariant(final GameType variant) {
data.currentGameMode = variant;
setGameType(variant);
data.appliedVariants.add(variant);
//ensure other necessary variants are unchecked
@@ -231,17 +235,21 @@ public abstract class GameLobby {
}
public void removeVariant(final GameType variant) {
data.appliedVariants.remove(variant);
final boolean changed = data.appliedVariants.remove(variant);
if (!changed) {
return;
}
if (data.appliedVariants.isEmpty()) {
data.appliedVariants.add(GameType.Constructed);
}
if (variant == data.currentGameMode) {
if (variant == currentGameType) {
if (hasVariant(GameType.Commander)) {
data.currentGameMode = GameType.Commander;
currentGameType = GameType.Commander;
} else if (hasVariant(GameType.TinyLeaders)) {
data.currentGameMode = GameType.TinyLeaders;
currentGameType = GameType.TinyLeaders;
} else {
data.currentGameMode = GameType.Constructed;
currentGameType = GameType.Constructed;
}
}
updateView(true);
@@ -275,7 +283,7 @@ public abstract class GameLobby {
}
final List<LobbySlot> activeSlots = Lists.newArrayListWithCapacity(getNumberOfSlots());
for (final LobbySlot slot : data.getSlots()) {
for (final LobbySlot slot : data.slots) {
if (slot.getType() != LobbySlotType.OPEN) {
activeSlots.add(slot);
}
@@ -290,6 +298,12 @@ public abstract class GameLobby {
SOptionPane.showMessageDialog(String.format("Please specify a deck for %s", slot.getName()));
return;
}
if (hasVariant(GameType.Commander) || hasVariant(GameType.TinyLeaders)) {
if (!slot.getDeck().has(DeckSection.Commander)) {
SOptionPane.showMessageDialog(String.format("%s doesn't have a commander", slot.getName()));
return;
}
}
}
final Set<GameType> variantTypes = data.appliedVariants;
@@ -391,7 +405,7 @@ public abstract class GameLobby {
return;
}
}
schemes = schemePool.toFlatList();
schemes = schemePool == null ? Collections.<PaperCard>emptyList() : schemePool.toFlatList();
}
//Planechase
@@ -404,7 +418,7 @@ public abstract class GameLobby {
return;
}
}
planes = planePool.toFlatList();
planes = planePool == null ? Collections.<PaperCard>emptyList() : planePool.toFlatList();
}
//Vanguard
@@ -441,23 +455,12 @@ public abstract class GameLobby {
}
public final static class GameLobbyData implements Serializable {
private static final long serialVersionUID = -9038854736144187540L;
private static final long serialVersionUID = 9184758307999646864L;
private transient GameType currentGameMode = GameType.Constructed;
private final Set<GameType> appliedVariants = EnumSet.of(GameType.Constructed);
private final List<LobbySlot> slots = Lists.newArrayList();
public GameType getCurrentGameMode() {
return currentGameMode;
}
public void setCurrentGameMode(GameType currentGameMode) {
this.currentGameMode = currentGameMode;
}
public Set<GameType> getAppliedVariants() {
return Collections.unmodifiableSet(appliedVariants);
}
public List<LobbySlot> getSlots() {
return Collections.unmodifiableList(slots);
public GameLobbyData() {
}
}
}

View File

@@ -62,10 +62,11 @@ public final class LobbySlot implements Serializable {
setAiOptions(data.getAiOptions());
changed = true;
}
final Deck oldDeck = getDeck();
if (data.getDeck() != null) {
setDeck(data.getDeck());
} else if (getDeck() != null && data.getSection() != null && data.getCards() != null) {
getDeck().putSection(data.getSection(), data.getCards());
} else if (oldDeck != null && data.getSection() != null && data.getCards() != null) {
oldDeck.putSection(data.getSection(), data.getCards());
}
return changed;
}

View File

@@ -104,6 +104,10 @@ public class FGameClient implements IToServer {
}
}
public void close() {
channel.close();
}
@Override
public void send(final NetEvent event) {
System.out.println("Client sent " + event);
@@ -382,5 +386,13 @@ public class FGameClient implements IToServer {
}
super.channelRead(ctx, msg);
}
@Override
public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
for (final ILobbyListener listener : lobbyListeners) {
listener.close();
}
super.channelInactive(ctx);
}
}
}

View File

@@ -52,6 +52,7 @@ import com.google.common.collect.Maps;
public final class FServerManager {
private static FServerManager instance = null;
private boolean isHosting = false;
private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
private final Map<Channel, RemoteClient> clients = Maps.newTreeMap();
@@ -102,6 +103,7 @@ public final class FServerManager {
}
}).start();
isHosting = true;
} catch (final InterruptedException e) {
e.printStackTrace();
}
@@ -110,6 +112,11 @@ public final class FServerManager {
public void stopServer() {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
isHosting = false;
}
public boolean isHosting() {
return isHosting;
}
public void broadcast(final NetEvent event) {