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