From 334ad729a81a43b721aa0bcc9e5879f79bf47323 Mon Sep 17 00:00:00 2001 From: ingmargoudt Date: Wed, 22 Mar 2017 20:49:12 +0100 Subject: [PATCH 1/4] remove usermap by name, introduced more optionals --- .../main/java/mage/server/ChatManager.java | 37 ++++---- .../main/java/mage/server/MageServerImpl.java | 55 +++++------ .../src/main/java/mage/server/Session.java | 91 ++++++++++--------- .../main/java/mage/server/SessionManager.java | 6 +- .../main/java/mage/server/UserManager.java | 83 ++++++++--------- 5 files changed, 132 insertions(+), 140 deletions(-) diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java index c48de3f0c8d..e77b9b12dd1 100644 --- a/Mage.Server/src/main/java/mage/server/ChatManager.java +++ b/Mage.Server/src/main/java/mage/server/ChatManager.java @@ -106,27 +106,28 @@ public enum ChatManager { ChatSession chatSession = chatSessions.get(chatId); if (chatSession != null) { if (message.startsWith("\\") || message.startsWith("/")) { - User user = UserManager.instance.getUserByName(userName); - if (user != null) { - if (!performUserCommand(user, message, chatId, false)) { - performUserCommand(user, message, chatId, true); + Optional user = UserManager.instance.getUserByName(userName); + if (user.isPresent()) { + if (!performUserCommand(user.get(), message, chatId, false)) { + performUserCommand(user.get(), message, chatId, true); } return; } } if (messageType != MessageType.GAME) { - User user = UserManager.instance.getUserByName(userName); - if (message != null && userName != null && !userName.isEmpty()) { + Optional u = UserManager.instance.getUserByName(userName); + if (u.isPresent()) { + User user = u.get(); if (message.equals(userMessages.get(userName))) { // prevent identical messages String informUser = "Your message appears to be identical to your last message"; chatSessions.get(chatId).broadcastInfoToUser(user, informUser); return; } - - if (message.length() > 500) { + + if (message.length() > 500) { message = message.replaceFirst("^(.{500}).*", "$1 (rest of message truncated)"); } @@ -157,10 +158,9 @@ public enum ChatManager { } userMessages.put(userName, message); - } - if (messageType == MessageType.TALK) { - if (user != null) { + + if (messageType == MessageType.TALK) { if (user.getChatLockedUntil() != null) { if (user.getChatLockedUntil().compareTo(Calendar.getInstance().getTime()) > 0) { chatSessions.get(chatId).broadcastInfoToUser(user, "Your chat is muted until " + SystemUtil.dateFormat.format(user.getChatLockedUntil())); @@ -169,11 +169,12 @@ public enum ChatManager { user.setChatLockedUntil(null); } } - } - } + } + + } + chatSession.broadcast(userName, message, color, withTime, messageType, soundToPlay); } - chatSession.broadcast(userName, message, color, withTime, messageType, soundToPlay); } } @@ -213,9 +214,9 @@ public enum ChatManager { if (first > 1) { String userToName = rest.substring(0, first); rest = rest.substring(first + 1).trim(); - User userTo = UserManager.instance.getUserByName(userToName); - if (userTo != null) { - if (!chatSessions.get(chatId).broadcastWhisperToUser(user, userTo, rest)) { + Optional userTo = UserManager.instance.getUserByName(userToName); + if (userTo.isPresent()) { + if (!chatSessions.get(chatId).broadcastWhisperToUser(user, userTo.get(), rest)) { message += new StringBuilder("
User ").append(userToName).append(" not found").toString(); chatSessions.get(chatId).broadcastInfoToUser(user, message); } @@ -244,7 +245,7 @@ public enum ChatManager { * @param color */ public void broadcast(UUID userId, String message, MessageColor color) throws UserNotFoundException { - UserManager.instance.getUser(userId).ifPresent(user-> { + UserManager.instance.getUser(userId).ifPresent(user -> { chatSessions.values() .stream() .filter(chat -> chat.hasUser(userId)) diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index 996a568c0de..0c28c809177 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -1071,12 +1071,11 @@ public class MageServerImpl implements MageServer { @Override public void muteUser(final String sessionId, final String userName, final long durationMinutes) throws MageException { execute("muteUser", sessionId, () -> { - User user = UserManager.instance.getUserByName(userName); - if (user != null) { + UserManager.instance.getUserByName(userName).ifPresent(user -> { Date muteUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE)); user.showUserMessage("Admin info", "You were muted for chat messages until " + SystemUtil.dateFormat.format(muteUntil) + '.'); user.setChatLockedUntil(muteUntil); - } + }); }); } @@ -1084,15 +1083,14 @@ public class MageServerImpl implements MageServer { @Override public void lockUser(final String sessionId, final String userName, final long durationMinutes) throws MageException { execute("lockUser", sessionId, () -> { - User user = UserManager.instance.getUserByName(userName); - if (user != null) { + UserManager.instance.getUserByName(userName).ifPresent(user -> { Date lockUntil = new Date(Calendar.getInstance().getTimeInMillis() + (durationMinutes * Timer.ONE_MINUTE)); user.showUserMessage("Admin info", "Your user profile was locked until " + SystemUtil.dateFormat.format(lockUntil) + '.'); user.setLockedUntil(lockUntil); if (user.isConnected()) { SessionManager.instance.disconnectUser(sessionId, user.getSessionId()); } - } + }); }); } @@ -1101,8 +1099,9 @@ public class MageServerImpl implements MageServer { public void setActivation(final String sessionId, final String userName, boolean active) throws MageException { execute("setActivation", sessionId, () -> { AuthorizedUser authorizedUser = AuthorizedUserRepository.instance.getByName(userName); - User user = UserManager.instance.getUserByName(userName); - if (user != null) { + Optional u = UserManager.instance.getUserByName(userName); + if (u.isPresent()) { + User user = u.get(); user.setActive(active); if (!user.isActive() && user.isConnected()) { SessionManager.instance.disconnectUser(sessionId, user.getSessionId()); @@ -1117,16 +1116,14 @@ public class MageServerImpl implements MageServer { @Override public void toggleActivation(final String sessionId, final String userName) throws MageException { - execute("toggleActivation", sessionId, () -> { - User user = UserManager.instance.getUserByName(userName); - if (user != null) { - user.setActive(!user.isActive()); - if (!user.isActive() && user.isConnected()) { - SessionManager.instance.disconnectUser(sessionId, user.getSessionId()); - } - } - - }); + execute("toggleActivation", sessionId, () -> + UserManager.instance.getUserByName(userName).ifPresent(user -> + { + user.setActive(!user.isActive()); + if (!user.isActive() && user.isConnected()) { + SessionManager.instance.disconnectUser(sessionId, user.getSessionId()); + } + })); } @Override @@ -1144,13 +1141,10 @@ public class MageServerImpl implements MageServer { @Override public void removeTable(final String sessionId, final UUID tableId) throws MageException { execute("removeTable", sessionId, () -> { - Optional session = SessionManager.instance.getSession(sessionId); - if (!session.isPresent()) { - logger.error("Session not found : " + sessionId); - } else { - UUID userId = session.get().getUserId(); + SessionManager.instance.getSession(sessionId).ifPresent(session -> { + UUID userId = session.getUserId(); TableManager.instance.removeTable(userId, tableId); - } + }); }); } @@ -1162,15 +1156,12 @@ public class MageServerImpl implements MageServer { @Override public void sendFeedbackMessage(final String sessionId, final String username, final String title, final String type, final String message, final String email) throws MageException { if (title != null && message != null) { - execute("sendFeedbackMessage", sessionId, () -> { - Optional session = SessionManager.instance.getSession(sessionId); - if (!session.isPresent()) { - logger.error(String.format("Session not found: %s", sessionId)); - } else { - FeedbackServiceImpl.instance.feedback(username, title, type, message, email, session.get().getHost()); + execute("sendFeedbackMessage", sessionId, () -> + SessionManager.instance.getSession(sessionId).ifPresent( + session -> FeedbackServiceImpl.instance.feedback(username, title, type, message, email, session.getHost()) - } - }); + + )); } } diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index e18a28630f5..f01adb59ae9 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -217,55 +217,59 @@ public class Session { if (authorizedUser.lockedUntil.compareTo(Calendar.getInstance().getTime()) > 0) { return "Your profile is deactivated until " + SystemUtil.dateFormat.format(authorizedUser.lockedUntil); } else { - User user = UserManager.instance.createUser(userName, host, authorizedUser); - if (user != null && authorizedUser.lockedUntil != null) { - user.setLockedUntil(null); + UserManager.instance.createUser(userName, host, authorizedUser).ifPresent(user -> + user.setLockedUntil(null) + ); + + } + Optional selectUser = UserManager.instance.createUser(userName, host, authorizedUser); + boolean reconnect = false; + if (!selectUser.isPresent()) { // user already exists + selectUser = UserManager.instance.getUserByName(userName); + if (selectUser.isPresent()) { + User user = selectUser.get(); + // If authentication is not activated, check the identity using IP address. + if (ConfigSettings.instance.isAuthenticationActivated() || user.getHost().equals(host)) { + user.updateLastActivity(null); // minimizes possible expiration + this.userId = user.getId(); + if (user.getSessionId().isEmpty()) { + logger.info("Reconnecting session for " + userName); + reconnect = true; + } else { + //disconnect previous session + logger.info("Disconnecting another user instance: " + userName); + SessionManager.instance.disconnect(user.getSessionId(), DisconnectReason.ConnectingOtherInstance); + } + } else { + return "User name " + userName + " already in use (or your IP address changed)"; + } } } - } - } - User user = UserManager.instance.createUser(userName, host, authorizedUser); - boolean reconnect = false; - if (user == null) { // user already exists - user = UserManager.instance.getUserByName(userName); - // If authentication is not activated, check the identity using IP address. - if (ConfigSettings.instance.isAuthenticationActivated() || user.getHost().equals(host)) { - user.updateLastActivity(null); // minimizes possible expiration - this.userId = user.getId(); - if (user.getSessionId().isEmpty()) { - logger.info("Reconnecting session for " + userName); - reconnect = true; - } else { - //disconnect previous session - logger.info("Disconnecting another user instance: " + userName); - SessionManager.instance.disconnect(user.getSessionId(), DisconnectReason.ConnectingOtherInstance); + User user = selectUser.get(); + if (!UserManager.instance.connectToSession(sessionId, user.getId())) { + return "Error connecting " + userName; + } + this.userId = user.getId(); + if (reconnect) { // must be connected to receive the message + Optional room = GamesRoomManager.instance.getRoom(GamesRoomManager.instance.getMainRoomId()); + if (!room.isPresent()) { + logger.error("main room not found"); + return null; + } + ChatManager.instance.joinChat(room.get().getChatId(), userId); + ChatManager.instance.sendReconnectMessage(userId); } - } else { - return "User name " + userName + " already in use (or your IP address changed)"; } } - if (!UserManager.instance.connectToSession(sessionId, user.getId())) { - return "Error connecting " + userName; - } - this.userId = user.getId(); - if (reconnect) { // must be connected to receive the message - Optional room = GamesRoomManager.instance.getRoom(GamesRoomManager.instance.getMainRoomId()); - if (!room.isPresent()) { - logger.error("main room not found"); - return null; - } - ChatManager.instance.joinChat(room.get().getChatId(), userId); - ChatManager.instance.sendReconnectMessage(userId); - } return null; + } public void connectAdmin() { this.isAdmin = true; - User user = UserManager.instance.createUser("Admin", host, null); - if (user == null) { - user = UserManager.instance.getUserByName("Admin"); - } + User user = UserManager.instance.createUser("Admin", host, null).orElse( + UserManager.instance.getUserByName("Admin").get()); + UserData adminUserData = UserData.getDefaultUserDataView(); adminUserData.setGroupId(UserGroup.ADMIN.getGroupId()); user.setUserData(adminUserData); @@ -276,8 +280,8 @@ public class Session { } public boolean setUserData(String userName, UserData userData, String clientVersion, String userIdStr) { - User user = UserManager.instance.getUserByName(userName); - if (user != null) { + Optional _user = UserManager.instance.getUserByName(userName); + _user.ifPresent(user -> { if (clientVersion != null) { user.setClientVersion(clientVersion); } @@ -294,9 +298,8 @@ public class Session { if (user.getUserData().getAvatarId() == 11) { user.getUserData().setAvatarId(updateAvatar(user.getName())); } - return true; - } - return false; + }); + return _user.isPresent(); } private int updateAvatar(String userName) { diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManager.java index 1a8abc9f9d7..b1df7969f38 100644 --- a/Mage.Server/src/main/java/mage/server/SessionManager.java +++ b/Mage.Server/src/main/java/mage/server/SessionManager.java @@ -51,7 +51,11 @@ public enum SessionManager { public Optional getSession(@Nonnull String sessionId) { Session session = sessions.get(sessionId); - if (session != null && session.getUserId() != null && UserManager.instance.getUser(session.getUserId()) == null) { + if(session == null){ + logger.error("Session with sessionId " + sessionId + " is not found"); + return Optional.empty(); + } + if (session.getUserId() != null && UserManager.instance.getUser(session.getUserId()) == null) { logger.error("User for session " + sessionId + " with userId " + session.getUserId() + " is missing. Session removed."); // can happen if user from same host signs in multiple time with multiple clients, after he disconnects with one client disconnect(sessionId, DisconnectReason.ConnectingOtherInstance); diff --git a/Mage.Server/src/main/java/mage/server/UserManager.java b/Mage.Server/src/main/java/mage/server/UserManager.java index bd7634435bd..18d45fb7fac 100644 --- a/Mage.Server/src/main/java/mage/server/UserManager.java +++ b/Mage.Server/src/main/java/mage/server/UserManager.java @@ -42,7 +42,7 @@ import java.util.concurrent.*; * * @author BetaSteward_at_googlemail.com */ -public enum UserManager { +public enum UserManager { instance; protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor(); @@ -50,7 +50,6 @@ public enum UserManager { private static final Logger LOGGER = Logger.getLogger(UserManager.class); private final ConcurrentHashMap users = new ConcurrentHashMap<>(); - private final ConcurrentHashMap usersByName = new ConcurrentHashMap<>(); private static final ExecutorService USER_EXECUTOR = ThreadExecutor.getInstance().getCallExecutor(); @@ -58,32 +57,36 @@ public enum UserManager { expireExecutor.scheduleAtFixedRate(this::checkExpired, 60, 60, TimeUnit.SECONDS); } - public User createUser(String userName, String host, AuthorizedUser authorizedUser) { - if (getUserByName(userName) != null) { - return null; //user already exists + public Optional createUser(String userName, String host, AuthorizedUser authorizedUser) { + if (getUserByName(userName).isPresent()) { + return Optional.empty(); //user already exists } User user = new User(userName, host, authorizedUser); users.put(user.getId(), user); - usersByName.put(userName, user); - return user; + return Optional.of(user); } public Optional getUser(UUID userId) { - if (users.get(userId) == null) { + if (!users.containsKey(userId)) { LOGGER.error(String.format("User with id %s could not be found", userId)); + return Optional.empty(); } else { return Optional.of(users.get(userId)); } - /* if (userId != null) { - return users.get(userId); - } - return null; - */ } - public User getUserByName(String userName) { - return usersByName.get(userName); + public Optional getUserByName(String userName) { + Optional u = users.values().stream().filter(user -> user.getName().equals(userName)) + .findFirst(); + if (u.isPresent()) { + return u; + } else { + + LOGGER.error("User with name " + userName + " could not be found"); + return Optional.empty(); + + } } public Collection getUsers() { @@ -103,12 +106,9 @@ public enum UserManager { public void disconnect(UUID userId, DisconnectReason reason) { if (userId != null) { - User user = users.get(userId); - if (user != null) { - user.setSessionId(""); // Session will be set again with new id if user reconnects - } - ChatManager.instance.removeUser(userId, reason); + getUser(userId).ifPresent(user -> user.setSessionId(""));// Session will be set again with new id if user reconnects } + ChatManager.instance.removeUser(userId, reason); } public boolean isAdmin(UUID userId) { @@ -123,25 +123,21 @@ public enum UserManager { public void removeUser(final UUID userId, final DisconnectReason reason) { if (userId != null) { - final User user = users.get(userId); - if (user != null) { - USER_EXECUTOR.execute( - () -> { - try { - LOGGER.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId + " [" + user.getGameInfo() + ']'); - user.remove(reason); - LOGGER.debug("USER REMOVE END - " + user.getName()); - } catch (Exception ex) { - handleException(ex); - } finally { - users.remove(userId); - usersByName.remove(user.getName()); + getUser(userId).ifPresent(user -> + USER_EXECUTOR.execute( + () -> { + try { + LOGGER.info("USER REMOVE - " + user.getName() + " (" + reason.toString() + ") userId: " + userId + " [" + user.getGameInfo() + ']'); + user.remove(reason); + LOGGER.debug("USER REMOVE END - " + user.getName()); + } catch (Exception ex) { + handleException(ex); + } finally { + users.remove(userId); + } } - } - ); - } else { - LOGGER.warn("Trying to remove userId: " + userId + " - but it does not exist."); - } + )); + } } @@ -183,9 +179,9 @@ public enum UserManager { } public String getUserHistory(String userName) { - User user = getUserByName(userName); - if (user != null) { - return "History of user " + userName + " - " + user.getUserData().getHistory(); + Optional user = getUserByName(userName); + if (user.isPresent()) { + return "History of user " + userName + " - " + user.get().getUserData().getHistory(); } UserStats userStats = UserStatsRepository.instance.getUser(userName); @@ -199,10 +195,7 @@ public enum UserManager { public void updateUserHistory() { USER_EXECUTOR.execute(() -> { for (String updatedUser : UserStatsRepository.instance.updateUserStats()) { - User user = getUserByName(updatedUser); - if (user != null) { - user.resetUserStats(); - } + getUserByName(updatedUser).ifPresent(User::resetUserStats); } }); } From 57efb1000336771a0a39a3f01fc3a7948ac9e5d5 Mon Sep 17 00:00:00 2001 From: drmDev Date: Thu, 23 Mar 2017 11:21:38 -0400 Subject: [PATCH 2/4] fixing tokens exiled at end of combat - not at end step --- Mage.Sets/src/mage/cards/g/GeistOfSaintTraft.java | 2 +- .../src/mage/cards/i/InvocationOfSaintTraft.java | 2 +- Mage.Sets/src/mage/cards/k/KariZevSkyshipRaider.java | 2 +- .../abilities/effects/common/CreateTokenEffect.java | 12 ++++++++++++ 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Mage.Sets/src/mage/cards/g/GeistOfSaintTraft.java b/Mage.Sets/src/mage/cards/g/GeistOfSaintTraft.java index 956bea71f34..80759f534b7 100644 --- a/Mage.Sets/src/mage/cards/g/GeistOfSaintTraft.java +++ b/Mage.Sets/src/mage/cards/g/GeistOfSaintTraft.java @@ -89,7 +89,7 @@ class GeistOfSaintTraftEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null && effect.apply(game, source)) { - effect.exileTokensCreatedAtNextEndStep(game, source); + effect.exileTokensCreatedAtEndOfCombat(game, source); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/i/InvocationOfSaintTraft.java b/Mage.Sets/src/mage/cards/i/InvocationOfSaintTraft.java index e0c45d5e6e3..17a6278ea3c 100644 --- a/Mage.Sets/src/mage/cards/i/InvocationOfSaintTraft.java +++ b/Mage.Sets/src/mage/cards/i/InvocationOfSaintTraft.java @@ -97,7 +97,7 @@ class InvocationOfSaintTraftEffect extends OneShotEffect { CreateTokenEffect effect = new CreateTokenEffect(new AngelToken(), 1, true, true); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && (effect.apply(game, source))) { - effect.exileTokensCreatedAtNextEndStep(game, source); + effect.exileTokensCreatedAtEndOfCombat(game, source); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/k/KariZevSkyshipRaider.java b/Mage.Sets/src/mage/cards/k/KariZevSkyshipRaider.java index 9883c36222b..d9ac3f53f1b 100644 --- a/Mage.Sets/src/mage/cards/k/KariZevSkyshipRaider.java +++ b/Mage.Sets/src/mage/cards/k/KariZevSkyshipRaider.java @@ -94,7 +94,7 @@ class KariZevSkyshipRaiderEffect extends OneShotEffect { CreateTokenEffect effect = new CreateTokenEffect(new RagavanToken(), 1, true, true); Player controller = game.getPlayer(source.getControllerId()); if (controller != null && effect.apply(game, source)) { - effect.exileTokensCreatedAtNextEndStep(game, source); + effect.exileTokensCreatedAtEndOfCombat(game, source); return true; } return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java index 964fa5f99df..025cebb7acc 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; +import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; @@ -124,6 +125,17 @@ public class CreateTokenEffect extends OneShotEffect { } } + public void exileTokensCreatedAtEndOfCombat(Game game, Ability source) { + for (UUID tokenId : this.getLastAddedTokenIds()) { + Permanent tokenPermanent = game.getPermanent(tokenId); + if (tokenPermanent != null) { + ExileTargetEffect exileEffect = new ExileTargetEffect(null, "", Zone.BATTLEFIELD); + exileEffect.setTargetPointer(new FixedTarget(tokenPermanent, game)); + game.addDelayedTriggeredAbility(new AtTheEndOfCombatDelayedTriggeredAbility(exileEffect), source); + } + } + } + private void setText() { StringBuilder sb = new StringBuilder("create "); if (amount.toString().equals("1")) { From 8bcb2d1d2d57dc75c58b84d1df4aaf40e1913015 Mon Sep 17 00:00:00 2001 From: Achilles Date: Thu, 23 Mar 2017 15:13:13 -0500 Subject: [PATCH 3/4] - Added Quicksilver Fountain --- .../src/mage/cards/q/QuicksilverFountain.java | 187 ++++++++++++++++++ Mage.Sets/src/mage/sets/Mirrodin.java | 1 + 2 files changed, 188 insertions(+) create mode 100644 Mage.Sets/src/mage/cards/q/QuicksilverFountain.java diff --git a/Mage.Sets/src/mage/cards/q/QuicksilverFountain.java b/Mage.Sets/src/mage/cards/q/QuicksilverFountain.java new file mode 100644 index 00000000000..e4ea73af408 --- /dev/null +++ b/Mage.Sets/src/mage/cards/q/QuicksilverFountain.java @@ -0,0 +1,187 @@ +/* + * 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.cards.q; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.BecomesBasicLandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.Target; +import mage.target.common.TargetLandPermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author jeffwadsworth + */ +public class QuicksilverFountain extends CardImpl { + + public QuicksilverFountain(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); + + // At the beginning of each player's upkeep, that player puts a flood counter on target non-Island land he or she controls of his or her choice. That land is an Island for as long as it has a flood counter on it. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, new QuicksilverFountainEffect(), TargetController.ANY, false, true)); + + // At the beginning of each end step, if all lands on the battlefield are Islands, remove all flood counters from them. + Condition condition = new AllLandsAreSubtypeCondition("Island"); + this.addAbility(new BeginningOfEndStepTriggeredAbility(Zone.BATTLEFIELD, new QuicksilverFountainEffect2(), TargetController.ANY, condition, false)); + + } + + public QuicksilverFountain(final QuicksilverFountain card) { + super(card); + } + + @Override + public QuicksilverFountain copy() { + return new QuicksilverFountain(this); + } +} + +class QuicksilverFountainEffect extends OneShotEffect { + + static final private FilterLandPermanent filterNonIslandLand = new FilterLandPermanent("non-Island land"); + + static { + filterNonIslandLand.add(Predicates.not(new SubtypePredicate("Island"))); + } + + public QuicksilverFountainEffect() { + super(Outcome.Neutral); + staticText = "that player puts a flood counter on target non-Island land he or she controls of his or her choice. That land is an Island for as long as it has a flood counter on it"; + } + + public QuicksilverFountainEffect(final QuicksilverFountainEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(targetPointer.getFirst(game, source)); + Target targetNonIslandLand = new TargetLandPermanent(filterNonIslandLand); + if (player != null) { + if (player.choose(Outcome.Neutral, targetNonIslandLand, source.getId(), game)) { + Permanent landChosen = game.getPermanent(targetNonIslandLand.getFirstTarget()); + landChosen.addCounters(CounterType.FLOOD.createInstance(), source, game); + ConditionalContinuousEffect effect = new ConditionalContinuousEffect(new BecomesBasicLandTargetEffect(Duration.OneUse, "Island"), new LandHasFloodCounterCondition(this), staticText); + this.setTargetPointer(new FixedTarget(landChosen, game)); + effect.setTargetPointer(new FixedTarget(landChosen, game)); + game.addEffect(effect, source); + return true; + } + } + return false; + } + + @Override + public QuicksilverFountainEffect copy() { + return new QuicksilverFountainEffect(this); + } +} + +class QuicksilverFountainEffect2 extends OneShotEffect { + + public QuicksilverFountainEffect2() { + super(Outcome.Neutral); + staticText = "remove all flood counters from them"; + } + + public QuicksilverFountainEffect2(final QuicksilverFountainEffect2 effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent land : game.getBattlefield().getAllActivePermanents(CardType.LAND)) { + land.removeCounters(CounterType.FLOOD.createInstance(land.getCounters(game).getCount(CounterType.FLOOD)), game); + } + return true; + } + + @Override + public QuicksilverFountainEffect2 copy() { + return new QuicksilverFountainEffect2(this); + } +} + +class AllLandsAreSubtypeCondition implements Condition { + + private final String subtype; + + public AllLandsAreSubtypeCondition(String subtype) { + this.subtype = subtype; + } + + @Override + public boolean apply(Game game, Ability source) { + FilterLandPermanent filterLand = new FilterLandPermanent(); + filterLand.add(new SubtypePredicate(subtype)); + int landCount = game.getBattlefield().getAllActivePermanents(CardType.LAND).size(); + return game.getBattlefield().getAllActivePermanents(filterLand, game).size() == landCount; + } + + @Override + public String toString() { + return "if all lands on the battlefield are " + subtype + "s"; + } +} + +class LandHasFloodCounterCondition implements Condition { + + private final Effect effect; + + public LandHasFloodCounterCondition(Effect effect) { + this.effect = effect; + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = game.getPermanent(effect.getTargetPointer().getFirst(game, source)); + return permanent != null + && permanent.getCounters(game).getCount(CounterType.FLOOD) > 0; + } +} diff --git a/Mage.Sets/src/mage/sets/Mirrodin.java b/Mage.Sets/src/mage/sets/Mirrodin.java index d35973de0a5..b839f531d86 100644 --- a/Mage.Sets/src/mage/sets/Mirrodin.java +++ b/Mage.Sets/src/mage/sets/Mirrodin.java @@ -208,6 +208,7 @@ public class Mirrodin extends ExpansionSet { cards.add(new SetCardInfo("Psychogenic Probe", 231, Rarity.RARE, mage.cards.p.PsychogenicProbe.class)); cards.add(new SetCardInfo("Pyrite Spellbomb", 232, Rarity.COMMON, mage.cards.p.PyriteSpellbomb.class)); cards.add(new SetCardInfo("Quicksilver Elemental", 47, Rarity.RARE, mage.cards.q.QuicksilverElemental.class)); + cards.add(new SetCardInfo("Quicksilver Fountain", 233, Rarity.RARE, mage.cards.q.QuicksilverFountain.class)); cards.add(new SetCardInfo("Raise the Alarm", 16, Rarity.COMMON, mage.cards.r.RaiseTheAlarm.class)); cards.add(new SetCardInfo("Razor Barrier", 17, Rarity.COMMON, mage.cards.r.RazorBarrier.class)); cards.add(new SetCardInfo("Regress", 48, Rarity.COMMON, mage.cards.r.Regress.class)); From 1e8216c5c59eb0354ed2516cb177c7bfb57d1ca6 Mon Sep 17 00:00:00 2001 From: spjspj Date: Fri, 24 Mar 2017 08:14:17 +1100 Subject: [PATCH 4/4] Change for id str --- .../java/mage/client/dialog/ConnectDialog.java | 8 +++++++- Mage.Common/src/mage/remote/Connection.java | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java index 91324908844..291f53a9c1d 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java @@ -45,6 +45,7 @@ import java.io.InputStreamReader; import java.io.Writer; import java.net.InetSocketAddress; import java.net.Proxy; +import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.URL; import java.net.UnknownHostException; @@ -391,7 +392,12 @@ public class ConnectDialog extends MageDialog { connection.setUsername(this.txtUserName.getText().trim()); connection.setPassword(this.txtPassword.getText().trim()); connection.setForceDBComparison(this.chkForceUpdateDB.isSelected()); - connection.setUserIdStr(System.getProperty("user.name") + ':' + MagePreferences.getUserNames()); + String allMAC = ""; + try { + allMAC = connection.getMAC(); + } catch (SocketException ex) { + } + connection.setUserIdStr(System.getProperty("user.name") + ":" + System.getProperty("os.name") + ":" + MagePreferences.getUserNames() + ":" + allMAC); MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem()); PreferencesDialog.setProxyInformation(connection); diff --git a/Mage.Common/src/mage/remote/Connection.java b/Mage.Common/src/mage/remote/Connection.java index a5cac723360..855404ec87f 100644 --- a/Mage.Common/src/mage/remote/Connection.java +++ b/Mage.Common/src/mage/remote/Connection.java @@ -258,6 +258,24 @@ public class Connection { return null; } + public static String getMAC() throws SocketException { + StringBuilder allMACs = new StringBuilder(); + for (Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements();) { + NetworkInterface iface = interfaces.nextElement(); + byte[] mac = iface.getHardwareAddress(); + + if (mac != null) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < mac.length; i++) { + sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : "")); + } + sb.append(';'); + allMACs.append(sb.toString()); + } + } + return allMACs.toString(); + } + public void setUserData(UserData userData) { this.userData = userData; }