Add files via upload
This commit is contained in:
parent
71807d6c36
commit
f48ed32195
157
net/RemotePlayerClient.java
Normal file
157
net/RemotePlayerClient.java
Normal file
@ -0,0 +1,157 @@
|
||||
package ch.epfl.javass.net;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
|
||||
import ch.epfl.javass.jass.Card;
|
||||
import ch.epfl.javass.jass.CardSet;
|
||||
import ch.epfl.javass.jass.Player;
|
||||
import ch.epfl.javass.jass.PlayerId;
|
||||
import ch.epfl.javass.jass.Score;
|
||||
import ch.epfl.javass.jass.TeamId;
|
||||
import ch.epfl.javass.jass.Trick;
|
||||
import ch.epfl.javass.jass.TurnState;
|
||||
import ch.epfl.javass.jass.Card.Color;
|
||||
import static ch.epfl.javass.net.StringSerializer.*;
|
||||
|
||||
/**
|
||||
* A player that plays on a remote server.
|
||||
* @author Charles BEAUVILLE
|
||||
* @author Celia HOUSSIAUX
|
||||
*
|
||||
*/
|
||||
public final class RemotePlayerClient implements Player, AutoCloseable{
|
||||
|
||||
private final static int PORT_NUMBER = 5108;
|
||||
|
||||
private final Socket s;
|
||||
private final BufferedReader r;
|
||||
private final BufferedWriter w;
|
||||
|
||||
/**
|
||||
* Creates a player that plays on a given host server.
|
||||
* @param host a string the adress of the host server.
|
||||
* @throws UnknownHostException if the host ip is wrong.
|
||||
* @throws IOException if the signal has been interrupted.
|
||||
*/
|
||||
public RemotePlayerClient(String host) throws UnknownHostException, IOException {
|
||||
|
||||
this.s = new Socket(host, PORT_NUMBER);
|
||||
this.r =
|
||||
new BufferedReader(
|
||||
new InputStreamReader(s.getInputStream(),
|
||||
StandardCharsets.UTF_8));
|
||||
this.w =
|
||||
new BufferedWriter(
|
||||
new OutputStreamWriter(s.getOutputStream(),
|
||||
StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayers(PlayerId ownId, Map<PlayerId, String> playerNames) {
|
||||
String cmd = JassCommand.PLRS.toString();
|
||||
String id = serializeInt(ownId.ordinal());
|
||||
String[] names = new String[PlayerId.COUNT];
|
||||
|
||||
for (int i = 0; i < names.length; i++)
|
||||
names[i] = serializeString(playerNames.get(PlayerId.ALL.get(i)));
|
||||
|
||||
String combinedNames = combine(',', names);
|
||||
String[] msg = new String[]{cmd, id, combinedNames};
|
||||
|
||||
sendMsg(combineMsg(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWinningTeam(TeamId winningTeam) {
|
||||
String cmd = JassCommand.WINR.toString();
|
||||
String winningTeamIndex = serializeInt(winningTeam.ordinal());
|
||||
String[] msg = new String[]{cmd, winningTeamIndex};
|
||||
|
||||
sendMsg(combineMsg(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTrump(Color trump) {
|
||||
String cmd = JassCommand.TRMP.toString();
|
||||
String trumpIndex = serializeInt(trump.ordinal());
|
||||
String[] msg = new String[]{cmd, trumpIndex};
|
||||
|
||||
sendMsg(combineMsg(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHand(CardSet newHand) {
|
||||
String cmd = JassCommand.HAND.toString();
|
||||
String hand = serializeLong(newHand.packed());
|
||||
String[] msg = new String[]{cmd, hand};
|
||||
|
||||
sendMsg(combineMsg(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScore(Score score) {
|
||||
String cmd = JassCommand.SCOR.toString();
|
||||
String s = serializeLong(score.packed());
|
||||
String[] msg = new String[]{cmd, s};
|
||||
|
||||
sendMsg(combineMsg(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTrick(Trick newTrick) {
|
||||
String cmd = JassCommand.TRCK.toString();
|
||||
String trick = serializeInt(newTrick.packed());
|
||||
String[] msg = new String[]{cmd, trick};
|
||||
|
||||
sendMsg(combineMsg(msg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Card cardToPlay(TurnState state, CardSet hand) {
|
||||
String cmd = JassCommand.CARD.toString();
|
||||
String s = combine(',', new String[]{serializeLong(state.packedScore()), serializeLong(state.packedUnplayedCards()), serializeInt(state.packedTrick())});
|
||||
String h = serializeLong(hand.packed());
|
||||
String[] msg = new String[]{cmd, s, h};
|
||||
String c = "0";
|
||||
|
||||
sendMsg(combineMsg(msg));
|
||||
|
||||
try {
|
||||
c = r.readLine();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
return Card.ofPacked(deserializeInt(c));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
w.close();
|
||||
r.close();
|
||||
s.close();
|
||||
}
|
||||
|
||||
private String combineMsg(String[] strings) {
|
||||
return combine(' ', strings);
|
||||
}
|
||||
|
||||
private void sendMsg(String msg) {
|
||||
try {
|
||||
w.write(msg);
|
||||
w.newLine();
|
||||
w.flush();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
132
net/RemotePlayerServer.java
Normal file
132
net/RemotePlayerServer.java
Normal file
@ -0,0 +1,132 @@
|
||||
package ch.epfl.javass.net;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import static ch.epfl.javass.net.StringSerializer.*;
|
||||
|
||||
import ch.epfl.javass.jass.Card;
|
||||
import ch.epfl.javass.jass.Card.Color;
|
||||
import ch.epfl.javass.jass.CardSet;
|
||||
import ch.epfl.javass.jass.Player;
|
||||
import ch.epfl.javass.jass.PlayerId;
|
||||
import ch.epfl.javass.jass.Score;
|
||||
import ch.epfl.javass.jass.TeamId;
|
||||
import ch.epfl.javass.jass.Trick;
|
||||
import ch.epfl.javass.jass.TurnState;
|
||||
|
||||
/**
|
||||
* Connects to a remote client and executes functions according to the data
|
||||
* sent.
|
||||
*
|
||||
* @author Charles BEAUVILLE
|
||||
* @author Celia HOUSSIAUX
|
||||
*
|
||||
*/
|
||||
public final class RemotePlayerServer {
|
||||
|
||||
private static final int PORT_NUMBER = 5108;
|
||||
private static final int COMMAND_INDEX = 0;
|
||||
private static final int ARG_0_INDEX = 0;
|
||||
private static final int ARG_1_INDEX = 1;
|
||||
private static final int ARG_2_INDEX = 2;
|
||||
|
||||
private Player localPlayer;
|
||||
|
||||
/**
|
||||
* Connects to a remote client and executes functions of the given player
|
||||
* according to the data sent.
|
||||
*
|
||||
* @param p
|
||||
* the underlying player.
|
||||
*/
|
||||
public RemotePlayerServer(Player p) {
|
||||
this.localPlayer = p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the server on the port number.
|
||||
* @throws IOException
|
||||
*/
|
||||
public void run() throws IOException {
|
||||
@SuppressWarnings("resource")
|
||||
//Listens for a connection on the port number.
|
||||
ServerSocket s0 = new ServerSocket(PORT_NUMBER);
|
||||
Socket s = s0.accept();
|
||||
|
||||
//Sets up the buffers to read and to write on the socket.
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(
|
||||
s.getInputStream(), StandardCharsets.UTF_8));
|
||||
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(
|
||||
s.getOutputStream(), StandardCharsets.UTF_8));
|
||||
|
||||
|
||||
String command;
|
||||
|
||||
//Reads the commands wrote on the socket line per line
|
||||
while ((command = r.readLine()) != null) {
|
||||
String[] msg = split(' ', command);
|
||||
|
||||
switch (JassCommand.valueOf(msg[COMMAND_INDEX])) {
|
||||
|
||||
case PLRS:
|
||||
|
||||
//Creates the players map with the arguments and calls the setPlayers function of the underlyingPlayer.
|
||||
Map<PlayerId, String> players = new HashMap<>();
|
||||
for (int i = 0; i < PlayerId.COUNT; i++) {
|
||||
players.put(PlayerId.ALL.get(i),
|
||||
deserializeString(split(',', msg[ARG_2_INDEX])[i]));
|
||||
}
|
||||
localPlayer.setPlayers(PlayerId.ALL.get(deserializeInt(msg[ARG_1_INDEX])),
|
||||
players);
|
||||
break;
|
||||
|
||||
case CARD:
|
||||
|
||||
//Calls the cardToPlay function of the underlying function with the arguments of the message.
|
||||
String[] st = split(',', msg[ARG_1_INDEX]);
|
||||
TurnState state = TurnState.ofPackedComponents(
|
||||
deserializeLong(st[ARG_0_INDEX]), deserializeLong(st[ARG_1_INDEX]),
|
||||
deserializeInt(st[ARG_2_INDEX]));
|
||||
Card c = localPlayer.cardToPlay(state,
|
||||
CardSet.ofPacked(deserializeLong(msg[ARG_2_INDEX])));
|
||||
w.write(serializeInt(c.packed()));
|
||||
w.newLine();
|
||||
w.flush();
|
||||
break;
|
||||
|
||||
case HAND:
|
||||
localPlayer
|
||||
.updateHand(CardSet.ofPacked(deserializeLong(msg[ARG_1_INDEX])));
|
||||
break;
|
||||
|
||||
case TRMP:
|
||||
localPlayer.setTrump(Color.ALL.get(deserializeInt(msg[ARG_1_INDEX])));
|
||||
break;
|
||||
|
||||
case SCOR:
|
||||
localPlayer
|
||||
.updateScore(Score.ofPacked(deserializeLong(msg[ARG_1_INDEX])));
|
||||
break;
|
||||
|
||||
case TRCK:
|
||||
localPlayer.updateTrick(Trick.ofPacked(deserializeInt(msg[ARG_1_INDEX])));
|
||||
break;
|
||||
|
||||
case WINR:
|
||||
localPlayer
|
||||
.setWinningTeam(TeamId.ALL.get(deserializeInt(msg[ARG_1_INDEX])));
|
||||
break;
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
93
net/StringSerializer.java
Normal file
93
net/StringSerializer.java
Normal file
@ -0,0 +1,93 @@
|
||||
package ch.epfl.javass.net;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* Methods to serialize object into byte sequences to transmit them in a network.
|
||||
* @author Charles BEAUVILLE
|
||||
* @author Celia HOUSSIAUX
|
||||
*
|
||||
*/
|
||||
public final class StringSerializer {
|
||||
|
||||
private static final int HEX_RADIX = 16;
|
||||
|
||||
private StringSerializer() {}
|
||||
|
||||
/**
|
||||
* Serializes a given {@link Integer} into its base 16 textual representation.
|
||||
* @param i the {@link Integer} to serialize
|
||||
* @return a {@link String} the base 16 representation of the given int.
|
||||
*/
|
||||
public static String serializeInt(int i) {
|
||||
return Integer.toUnsignedString(i, HEX_RADIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a the string representation of an int and returns the actual {@link Integer}.
|
||||
* @param s the string that needs to be deserialized into an {@link Integer}.
|
||||
* @return the {@link Integer} represented by the string.
|
||||
*/
|
||||
public static int deserializeInt(String s) {
|
||||
return Integer.parseUnsignedInt(s, HEX_RADIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes a given {@link Long} into its base 16 textual representation.
|
||||
* @param l the {@link Long} to serialize.
|
||||
* @return a {@link String} the base 16 representation of the given long.
|
||||
*/
|
||||
public static String serializeLong(long l) {
|
||||
return Long.toUnsignedString(l, HEX_RADIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a the string representation of an int and returns the actual {@link Long}.
|
||||
* @param s the string that needs to be deserialized into an {@link Long}.
|
||||
* @return the {@link Long} represented by the string.
|
||||
*/
|
||||
public static long deserializeLong(String s) {
|
||||
return Long.parseLong(s, HEX_RADIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the given string to base 64.
|
||||
* @param s the string to encode.
|
||||
* @return the encoded string.
|
||||
*/
|
||||
public static String serializeString(String s) {
|
||||
Base64.Encoder e = Base64.getEncoder();
|
||||
return e.encodeToString(s.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the given string from base 64.
|
||||
* @param s the string to decode.
|
||||
* @return the decoded string.
|
||||
*/
|
||||
public static String deserializeString(String s) {
|
||||
Base64.Decoder d = Base64.getDecoder();
|
||||
return new String(d.decode(s), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the strings given in the array, separated by the given character.
|
||||
* @param c the character to separate the strings.
|
||||
* @param strings the array of strings to be combined.
|
||||
* @return a string constiting of the strings of the array separated by the given character.
|
||||
*/
|
||||
public static String combine(char c, String[] strings) {
|
||||
return String.join(String.valueOf(c), strings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits at the given character a string into an array of strings.
|
||||
* @param c the character that separates the strings.
|
||||
* @param s the string to be split.
|
||||
* @return the array of the strings in between the given character.
|
||||
*/
|
||||
public static String[] split(char c, String s) {
|
||||
return s.split(String.valueOf(c));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user