game-client

Play TicTacToe and Reversi
Log | Files | Refs

GameClientBase.java (3578B)


      1 package nl.isygameclient.network;
      2 
      3 import java.io.BufferedReader;
      4 import java.io.IOException;
      5 import java.io.InputStreamReader;
      6 import java.io.OutputStream;
      7 import java.net.Socket;
      8 import java.util.Arrays;
      9 import java.util.LinkedList;
     10 
     11 public abstract class GameClientBase extends Socket {
     12 	private final OutputStream	 outputStream;
     13 	private final BufferedReader inputBuffer;
     14 
     15 	private final LinkedList<Event>  eventQueue	  = new LinkedList<>();
     16 	private final LinkedList<String> eventLineQueue = new LinkedList<>();
     17 
     18 	public GameClientBase(String host, int port) throws IOException {
     19 		super(host, port);
     20 		outputStream = getOutputStream();
     21 		inputBuffer	 = new BufferedReader(new InputStreamReader(getInputStream()));
     22 
     23 		try {
     24 			Thread.sleep(100);
     25 			while (inputBuffer.ready()) {
     26 				inputBuffer.readLine();
     27 				Thread.sleep(100);
     28 			}
     29 		} catch (InterruptedException exc) {
     30 			throw new GameClientException("socket initiation failed: " + exc.getMessage());
     31 		}
     32 	}
     33 
     34 	public void send(String command, String... arguments) throws IOException {
     35 		var requestBuilder = new StringBuilder(command);
     36 		for (var argument : arguments) {
     37 			requestBuilder.append(' ');
     38 			requestBuilder.append(argument);
     39 		}
     40 
     41 		requestBuilder.append('\n');
     42 		outputStream.write(requestBuilder.toString().getBytes());
     43 
     44 		String response;
     45 		for (;;) {
     46 			response = inputBuffer.readLine();
     47 			if (response.startsWith("ERR "))
     48 				throw new GameClientException(response.substring(4));
     49 			else if (response.startsWith("SVR ")) {
     50 				eventLineQueue.add(response);
     51 				continue;
     52 			} else if (response.equals("OK"))
     53 				break;
     54 			throw new GameClientException("invalid server response: '" + response + "'");
     55 		}
     56 	}
     57 
     58 	public Event event(EventType... target) throws IOException {
     59 		return event(1, true, target);
     60 	}
     61 
     62 	public Event event(double timeout, EventType... target) throws IOException {
     63 		return event(timeout, true, target);
     64 	}
     65 
     66 	public Event event(double timeout, boolean consume, EventType... target) throws IOException {
     67 		var targetList = Arrays.asList(target);
     68 		if (!eventQueue.isEmpty()) {
     69 			if (target == null)
     70 				return eventQueue.poll();
     71 
     72 			for (int i = 0; i < eventQueue.size(); i++) {
     73 				if (targetList.contains(eventQueue.get(i).type))
     74 					return consume ? eventQueue.remove(i) : eventQueue.get(i);
     75 			}
     76 		}
     77 
     78 		long   start = System.currentTimeMillis();
     79 		Event  result;
     80 		String line;
     81 
     82 		do {
     83 			if (eventLineQueue.isEmpty()) {
     84 				try {
     85 					Thread.sleep(100);
     86 					if (!inputBuffer.ready())
     87 						continue;
     88 					line = inputBuffer.readLine();
     89 				} catch (InterruptedException exc) {
     90 					throw new GameClientException("event-pulling interrupted");
     91 				}
     92 			} else {
     93 				line = eventLineQueue.poll();
     94 			}
     95 
     96 			if (!line.startsWith("SVR "))
     97 				throw new GameClientException("invalid server response: '" + line + "'");
     98 
     99 
    100 			result = null;
    101 			for (var evt : EventType.values()) {
    102 				if (line.startsWith(evt.identifier, 4)) {
    103 					result = new Event(evt, new EventParser(line.substring(evt.identifier.length() + 4)).parseData());
    104 					break;
    105 				}
    106 			}
    107 
    108 			if (result == null)
    109 				throw new GameClientException("invalid server response: unknown event '" + line + "'");
    110 
    111 
    112 			if (target.length == 0 || target.length > 0 && targetList.contains(result.type)) {
    113 				if (!consume)
    114 					eventQueue.push(result);
    115 				return result;
    116 			}
    117 
    118 			eventQueue.push(result);
    119 		} while (timeout == -1 || System.currentTimeMillis() - start < timeout * 1000);
    120 
    121 		return null;
    122 	}
    123 
    124 	@Override
    125 	public void close() throws IOException {
    126 		outputStream.write("logout\n".getBytes());
    127 		super.close();
    128 	}
    129 }