package games.strategy.engine.gamePlayer; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Properties; import games.strategy.debug.ClientLogger; import games.strategy.engine.GameOverException; import games.strategy.engine.data.GameData; import games.strategy.engine.data.events.GameStepListener; import games.strategy.engine.delegate.IDelegate; import games.strategy.engine.delegate.IPersistentDelegate; import games.strategy.engine.framework.IGame; import games.strategy.engine.framework.ServerGame; import games.strategy.engine.message.IRemote; import games.strategy.engine.message.MessengerException; import games.strategy.engine.message.RemoteName; import games.strategy.engine.message.RemoteNotFoundException; /** * Default implementation of PlayerBridge. */ public class DefaultPlayerBridge implements IPlayerBridge { private final IGame m_game; private String m_currentStep; private String m_currentDelegate; /** Creates new DefaultPlayerBridge. */ public DefaultPlayerBridge(final IGame aGame) { m_game = aGame; final GameStepListener m_gameStepListener = (stepName, delegateName, player, round, displayName) -> { if (stepName == null) { throw new IllegalArgumentException("Null step"); } if (delegateName == null) { throw new IllegalArgumentException("Null delegate"); } m_currentStep = stepName; m_currentDelegate = delegateName; }; m_game.addGameStepListener(m_gameStepListener); } /** * Get the name of the current step being executed. */ @Override public String getStepName() { return m_currentStep; } @Override public boolean isGameOver() { return m_game.isGameOver(); } /** * Return the game data. */ @Override public GameData getGameData() { return m_game.getData(); } @Override public IRemote getRemoteDelegate() { if (m_game.isGameOver()) { throw new GameOverException("Game Over"); } try { m_game.getData().acquireReadLock(); try { final IDelegate delegate = m_game.getData().getDelegateList().getDelegate(m_currentDelegate); if (delegate == null) { final String errorMessage = "IDelegate in DefaultPlayerBridge.getRemote() cannot be null. CurrentStep: " + m_currentStep + ", and CurrentDelegate: " + m_currentDelegate; // for some reason, client isn't getting or seeing the errors, so make sure we print it to err // too System.err.println(errorMessage); // Veqryn: hope that this suffices...? throw new IllegalStateException(errorMessage); } final RemoteName remoteName; try { remoteName = ServerGame.getRemoteName(delegate); } catch (final Exception e) { ClientLogger.logQuietly(e); final String errorMessage = "IDelegate IRemote interface class returned null or was not correct interface. CurrentStep: " + m_currentStep + ", and CurrentDelegate: " + m_currentDelegate; // for some reason, client isn't getting or seeing the errors, so make sure we print it to err // too System.err.println(errorMessage); throw new IllegalStateException(errorMessage, e); } return getRemoteThatChecksForGameOver(m_game.getRemoteMessenger().getRemote(remoteName)); } finally { m_game.getData().releaseReadLock(); } } catch (final MessengerException me) { throw new GameOverException("Game Over!"); } } @Override public IRemote getRemotePersistentDelegate(final String name) { if (m_game.isGameOver()) { throw new GameOverException("Game Over"); } try { m_game.getData().acquireReadLock(); try { final IDelegate delegate = m_game.getData().getDelegateList().getDelegate(name); if (delegate == null) { final String errorMessage = "IDelegate in DefaultPlayerBridge.getRemote() cannot be null. Looking for delegate named: " + name; // for some reason, client isn't getting or seeing the errors, so make sure we print it to err System.err.println(errorMessage); // too throw new IllegalStateException(errorMessage); } if (!(delegate instanceof IPersistentDelegate)) { return null; } return getRemoteThatChecksForGameOver( m_game.getRemoteMessenger().getRemote(ServerGame.getRemoteName(delegate))); } finally { m_game.getData().releaseReadLock(); } } catch (final MessengerException me) { throw new GameOverException("Game Over!"); } } @Override public Properties getStepProperties() { return m_game.getData().getSequence().getStep().getProperties(); } private IRemote getRemoteThatChecksForGameOver(final IRemote implementor) { final Class<?>[] classes = implementor.getClass().getInterfaces(); final GameOverInvocationHandler goih = new GameOverInvocationHandler(implementor, m_game); return (IRemote) Proxy.newProxyInstance(implementor.getClass().getClassLoader(), classes, goih); } } class GameOverInvocationHandler implements InvocationHandler { private final Object m_delegate; private final IGame m_game; public GameOverInvocationHandler(final Object delegate, final IGame game) { m_delegate = delegate; m_game = game; } @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { try { return method.invoke(m_delegate, args); } catch (final InvocationTargetException ite) { if (!m_game.isGameOver()) { throw ite.getCause(); } else { throw new GameOverException("Game Over Exception!"); } } catch (final RemoteNotFoundException rnfe) { throw new GameOverException("Game Over!"); } } }