View Javadoc

1   /*
2    *   Magic-Project is a turn based strategy simulator
3    *   Copyright (C) 2003-2007 Fabrice Daugan
4    *
5    *   This program is free software; you can redistribute it and/or modify it 
6    * under the terms of the GNU General Public License as published by the Free 
7    * Software Foundation; either version 2 of the License, or (at your option) any
8    * later version.
9    *
10   *   This program is distributed in the hope that it will be useful, but WITHOUT 
11   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12   * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
13   * details.
14   *
15   *   You should have received a copy of the GNU General Public License along  
16   * with this program; if not, write to the Free Software Foundation, Inc., 
17   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18   */
19  package net.sf.magicproject.network;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  
24  import net.sf.magicproject.action.MessagingAction;
25  import net.sf.magicproject.action.MoveCard;
26  import net.sf.magicproject.action.PayMana;
27  import net.sf.magicproject.clickable.ability.UserAbility;
28  import net.sf.magicproject.clickable.mana.ManaPool;
29  import net.sf.magicproject.clickable.targetable.card.MCard;
30  import net.sf.magicproject.clickable.targetable.card.TriggeredCard;
31  import net.sf.magicproject.clickable.targetable.card.TriggeredCardChoice;
32  import net.sf.magicproject.clickable.targetable.player.Player;
33  import net.sf.magicproject.stack.StackManager;
34  import net.sf.magicproject.tools.Log;
35  import net.sf.magicproject.tools.MToolKit;
36  import net.sf.magicproject.ui.MagicUIComponents;
37  
38  /***
39   * This class is listening to the actions done by the opponent and apply the
40   * corresponding actions. These actions may be : click on cards, ability
41   * choosen, mana use and auto-options changment.
42   * 
43   * @author <a href="mailto:fabdouglas@users.sourceforge.net">Fabrice Daugan </a>
44   * @since 0.4
45   */
46  public final class MSocketListener extends Thread {
47  
48  	/***
49  	 * Private constructor used to create the unique instance of this class
50  	 */
51  	private MSocketListener() {
52  		super("SocketListener");
53  		start();
54  	}
55  
56  	/***
57  	 * Create a new instance of this class.
58  	 */
59  	public static void init() {
60  		instance = new MSocketListener();
61  	}
62  
63  	/***
64  	 * The unique instance of this class.
65  	 */
66  	private static MSocketListener instance;
67  
68  	/***
69  	 * Return the unique instance of this class.
70  	 * 
71  	 * @return the unique instance of this class.
72  	 */
73  	public static MSocketListener getInstance() {
74  		return instance;
75  	}
76  
77  	/***
78  	 * To read anew message
79  	 * 
80  	 * @param in
81  	 *          the input stram
82  	 * @throws IOException
83  	 */
84  	public void newMessage(InputStream in) throws IOException {
85  		virtualInput.newMessage(in);
86  	}
87  
88  	/***
89  	 * run this thread
90  	 * 
91  	 * @see IdMessages
92  	 */
93  	@Override
94  	public void run() {
95  		try {
96  			while (true) {
97  				Synchronizer.SYNCHRONIZER.take();
98  
99  				// Currently a simple "telnet-like" minimal code treating :
100 				synchronized (MBigPipe.LOCK) {
101 					int read = virtualInput.read();
102 					StackManager.noReplayToken.take();
103 					switch (read) {
104 					case IdMessages.MSG_CHOICE:
105 					case IdMessages.COLOR_ANSWER:
106 					case IdMessages.MSG_ANSWER:
107 					case IdMessages.INTEGER_ANSWER:
108 					case IdMessages.ZONE_ANSWER:
109 					case IdMessages.PROPERTY_ANSWER:
110 						final int optionAnswer = virtualInput.read();
111 						MessagingAction.finishedMessage(optionAnswer, virtualInput.read(),
112 								StackManager.getInstance().getAbilityContext(),
113 								StackManager.currentAbility, StackManager.actionManager
114 										.getActionContextNull());
115 						break;
116 					case IdMessages.MSG_SKIP:
117 						Log.debug("      ...-> manual skip");
118 						Player.unsetHandedPlayer();
119 						StackManager.actionManager.manualSkip();
120 						break;
121 					case IdMessages.MSG_CLICK_CARD:
122 						MCard.clickOn(virtualInput);
123 						break;
124 					case IdMessages.MSG_CLICK_ABILITY:
125 						UserAbility.clickOn(virtualInput);
126 						break;
127 					case IdMessages.MSG_CLICK_PLAYER:
128 						Player.clickOn(virtualInput);
129 						break;
130 					case IdMessages.MSG_CLICK_ACTION:
131 						MagicUIComponents.choosenCostPanel.clickOn(virtualInput);
132 						break;
133 					case IdMessages.MSG_CLICK_MANA:
134 						ManaPool.clickOn(virtualInput);
135 						break;
136 					case IdMessages.CLICK_MANA:
137 						PayMana.clickOn(virtualInput);
138 						break;
139 					case IdMessages.MSG_CLICK_TRIGGERED_CARD:
140 						TriggeredCard.clickOn(virtualInput);
141 						break;
142 					case -1:
143 						// disconnection
144 						ConnectionManager.notifyDisconnection();
145 						ConnectionManager.closeConnexions();
146 						break;
147 					case IdMessages.MOVE_ORDER_ANSWER:
148 						final int[] order = new int[virtualInput.read()];
149 						for (int i = 0; i < order.length; i++) {
150 							order[i] = virtualInput.read();
151 						}
152 						((MoveCard) StackManager.actionManager.currentAction)
153 								.receiveMoveOrder(order);
154 						break;
155 					case IdMessages.TRIGGERED_CARD_CHOICE:
156 						TriggeredCardChoice.finishedMessage(virtualInput.read());
157 						break;
158 					default:
159 						Log.debug("Unknown code " + read);
160 					}
161 					StackManager.noReplayToken.release();
162 				}
163 			}
164 		} catch (IOException e) {
165 			Log.debug(" **disconnection ** in socketlistener");
166 			ConnectionManager.notifyDisconnection();
167 			ConnectionManager.closeConnexions();
168 			return;
169 		} catch (Throwable e) {
170 			Log.fatal("In SocketListener, occurred exception", e);
171 			ConnectionManager.closeConnexions();
172 			return;
173 		} finally {
174 			StackManager.noReplayToken.release();
175 			virtualInput.reset();
176 		}
177 	}
178 
179 	/***
180 	 * Close connections.
181 	 */
182 	public void closeConnections() {
183 		virtualInput.reset();
184 	}
185 
186 	/***
187 	 * Read and return replacement answer.
188 	 * 
189 	 * @return the replacement answer.
190 	 */
191 	public int readReplacementAnswer() {
192 		try {
193 			int read = virtualInput.read();
194 			switch (read) {
195 			case IdMessages.REPLACEMENT_ANSWER:
196 				return MToolKit.readInt16(virtualInput);
197 			case -1:
198 				// disconnection
199 				ConnectionManager.notifyDisconnection();
200 				ConnectionManager.closeConnexions();
201 				break;
202 			default:
203 				Log.debug("Unknown code for a Non-Block read " + read);
204 			}
205 		} catch (IOException e) {
206 			Log.debug(" **disconnection ** in socketlistener");
207 			ConnectionManager.notifyDisconnection();
208 			ConnectionManager.closeConnexions();
209 		} catch (Throwable e) {
210 			Log.fatal("In SocketListener, occurred exception : ", e);
211 			ConnectionManager.closeConnexions();
212 		}
213 		return -1;
214 	}
215 
216 	private VirtualInputStream virtualInput = new VirtualInputStream();
217 
218 }