Multiplayer using kryonet in TCP. Players updates should be done in UDP instead, but Kyronet wiki says it could cause some problems. Map is shared between all clients and clients can see how other players are positioned and rotated. Code could be refactored in a much nicer form. Some bugs have to be fixed
parent
5565615a8a
commit
c50222a749
|
@ -6,9 +6,11 @@ import com.badlogic.gdx.Game;
|
|||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.InputMultiplexer;
|
||||
import com.badlogic.gdx.graphics.FPSLogger;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.badlogic.gdx.physics.bullet.Bullet;
|
||||
import com.emamaker.amazeing.manager.GameManager;
|
||||
import com.emamaker.amazeing.manager.GameType;
|
||||
import com.emamaker.amazeing.manager.network.GameClient;
|
||||
import com.emamaker.amazeing.manager.network.GameServer;
|
||||
import com.emamaker.amazeing.ui.UIManager;
|
||||
import com.emamaker.voxelengine.VoxelWorld;
|
||||
|
||||
|
@ -17,61 +19,75 @@ public class AMazeIng extends Game {
|
|||
public VoxelWorld world = new VoxelWorld();
|
||||
FPSLogger fps = new FPSLogger();
|
||||
boolean generated = false;
|
||||
boolean gui=false;
|
||||
boolean gui = false;
|
||||
Random rand = new Random();
|
||||
|
||||
public UIManager uiManager;
|
||||
public GameManager gameManager;
|
||||
public InputMultiplexer multiplexer = new InputMultiplexer();
|
||||
|
||||
/* Local manager for local games and server host in multiplayer games */
|
||||
public GameServer server;
|
||||
public GameClient client;
|
||||
|
||||
@Override
|
||||
public void create() {
|
||||
//Bullet init for physics
|
||||
// Bullet init for physics
|
||||
Bullet.init();
|
||||
|
||||
//Set windowed resolution
|
||||
|
||||
// Set windowed resolution
|
||||
Gdx.graphics.setWindowedMode(1280, 720);
|
||||
|
||||
//Voxel engine init. Call everything after this
|
||||
|
||||
// Voxel engine init. Call everything after this
|
||||
world.init(this);
|
||||
world.worldManager.generateChunks = false;
|
||||
world.worldManager.updateChunks = true;
|
||||
|
||||
//Disable VoxelEngines's integrated camera input processor
|
||||
|
||||
// Disable VoxelEngines's integrated camera input processor
|
||||
Gdx.input.setInputProcessor(multiplexer);
|
||||
|
||||
|
||||
generated = false;
|
||||
setupGUI();
|
||||
setupGameManager();
|
||||
}
|
||||
|
||||
|
||||
public void setupGUI() {
|
||||
System.out.println("Setup UI Manager");
|
||||
uiManager = new UIManager(this);
|
||||
}
|
||||
|
||||
|
||||
public void setupGameManager() {
|
||||
System.out.println("Setup Game Manager");
|
||||
gameManager = new GameManager(this);
|
||||
System.out.println("Setup Game Managers");
|
||||
gameManager = new GameManager(this, GameType.LOCAL);
|
||||
|
||||
server = new GameServer(this);
|
||||
client = new GameClient(this);
|
||||
}
|
||||
|
||||
float delta;
|
||||
|
||||
@Override
|
||||
public void render() {
|
||||
super.render();
|
||||
if(gameManager != null) gameManager.update();
|
||||
server.update();
|
||||
client.update();
|
||||
if (gameManager != null)
|
||||
gameManager.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
world.dispose();
|
||||
gameManager.dispose();
|
||||
client.stop();
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resize(int width, int height) {
|
||||
world.resize(width, height);
|
||||
this.getScreen().resize(width, height);
|
||||
if (this.getScreen() != null)
|
||||
this.getScreen().resize(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -83,5 +99,5 @@ public class AMazeIng extends Game {
|
|||
public void resume() {
|
||||
world.resume();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,186 +0,0 @@
|
|||
package com.emamaker.amazeing.manager;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.Net.Protocol;
|
||||
import com.badlogic.gdx.net.Socket;
|
||||
import com.badlogic.gdx.net.SocketHints;
|
||||
import com.emamaker.amazeing.AMazeIng;
|
||||
import com.emamaker.amazeing.player.MazePlayer;
|
||||
import com.emamaker.amazeing.player.MazePlayerLocal;
|
||||
import com.emamaker.amazeing.player.MazePlayerRemote;
|
||||
|
||||
public class GameClient {
|
||||
|
||||
public AMazeIng main;
|
||||
Thread clientThread;
|
||||
volatile boolean clientRunning = false;
|
||||
|
||||
public String addr;
|
||||
public int port;
|
||||
public Socket socket;
|
||||
|
||||
volatile String nextMessage = "";
|
||||
String map = "", s1 = "", rMsg = "", playerList = "";
|
||||
|
||||
UUID uuid;
|
||||
int connectionStep;
|
||||
|
||||
BufferedReader buffer;
|
||||
|
||||
// Hashtable of remote players present in the match. This will be used to update
|
||||
// other players' transform when server reports about it
|
||||
Hashtable<UUID, MazePlayerRemote> remotePlayers = new Hashtable<>();
|
||||
ArrayList<MazePlayer> players = new ArrayList<MazePlayer>();
|
||||
|
||||
public GameClient(AMazeIng main_) {
|
||||
main = main_;
|
||||
}
|
||||
|
||||
public void start(String addr_, int port_) {
|
||||
port = port_;
|
||||
addr = addr_;
|
||||
clientThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
clientRunning = true;
|
||||
while (clientRunning) {
|
||||
if (socket == null) {
|
||||
SocketHints socketHints = new SocketHints();
|
||||
socketHints.connectTimeout = 10000;
|
||||
socket = Gdx.net.newClientSocket(Protocol.TCP, addr, port, socketHints);
|
||||
buffer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
|
||||
sendMessageToSocket(socket, "AO");
|
||||
connectionStep = 0;
|
||||
} else {
|
||||
if (socket.isConnected()) {
|
||||
rMsg = receiveMessageFromSocket();
|
||||
|
||||
if (rMsg.startsWith("UUID")) {
|
||||
// UUID received from server, go on
|
||||
// it doesn't matter if this already happened, just start again
|
||||
// No new UUID will be generated
|
||||
s1 = rMsg.replace("UUID", "");
|
||||
uuid = UUID.fromString(s1);
|
||||
connectionStep = 1;
|
||||
System.out.println("Got UUID from server: " + uuid.toString());
|
||||
sendMessageToSocket(socket, "AO2");
|
||||
}
|
||||
if (rMsg.equals("AO3")) {
|
||||
if (connectionStep == 1) {
|
||||
connectionStep = 2;
|
||||
sendMessageToSocket(socket, "AO4");
|
||||
System.out.println("Connected with server!");
|
||||
}
|
||||
}
|
||||
if (rMsg.startsWith("Players"))
|
||||
playerList = rMsg.replace("Players", "");
|
||||
if (rMsg.startsWith("Map"))
|
||||
map = rMsg.replace("Map", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
clientThread.start();
|
||||
}
|
||||
|
||||
// Update must be called from Main thread and used for applications on main
|
||||
// thread
|
||||
public void update() {
|
||||
if (!playerList.equals("")) {
|
||||
// Build up player list
|
||||
String[] uuids = playerList.split("!");
|
||||
for (String s : uuids) {
|
||||
// System.out.println(s);
|
||||
if (!s.equals(uuid.toString()))
|
||||
remotePlayers.put(UUID.fromString(s), new MazePlayerRemote(main, UUID.fromString(s)));
|
||||
}
|
||||
playerList = "";
|
||||
}
|
||||
if (!map.equals("")) {
|
||||
// Build up map
|
||||
for (UUID u : remotePlayers.keySet()) {
|
||||
if (!u.equals(uuid))
|
||||
players.add(remotePlayers.get(u));
|
||||
}
|
||||
players.add(new MazePlayerLocal(main, Keys.W, Keys.S, Keys.A, Keys.D));
|
||||
|
||||
main.gameManager.generateMaze(new HashSet<MazePlayer>(players),
|
||||
main.gameManager.mazeGen.runLenghtDecode(map));
|
||||
main.gameManager.setShowGame(true);
|
||||
map = "";
|
||||
}
|
||||
}
|
||||
|
||||
public void sendMessagetoServer(String s) {
|
||||
nextMessage += (s + "\n");
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
clientRunning = false;
|
||||
}
|
||||
|
||||
void sendMessageToSocket(Socket s, String msg) {
|
||||
if (s != null && s.isConnected())
|
||||
try {
|
||||
// write our entered message to the stream
|
||||
System.out.println("Client sending msg: " + msg + " to " + s);
|
||||
s.getOutputStream().write((msg + "\n").getBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
String tmprs;
|
||||
|
||||
String receiveMessageFromSocket() {
|
||||
if (socket != null && socket.isConnected())
|
||||
// Receive messages from the client
|
||||
try {
|
||||
if (socket.getInputStream().available() > 0) {
|
||||
// Read to the next newline (\n) and display that text on labelMessage
|
||||
tmprs = buffer.readLine();
|
||||
System.out.println("Client received message! " + tmprs);
|
||||
return tmprs;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// // Receive messages from the server
|
||||
// try {
|
||||
// if (socket.getInputStream().available() > 0) {
|
||||
// BufferedReader buffer = new BufferedReader(
|
||||
// new InputStreamReader(socket.getInputStream()));
|
||||
//
|
||||
// // Read to the next newline (\n) and display that text on labelMessage
|
||||
// s = buffer.readLine().toString();
|
||||
// //System.out.println("Received message from server: " + socket + "!\n" + s);
|
||||
// if(s.startsWith("Map")) {
|
||||
// s1 = s.replace("Map", "");
|
||||
// main.gameManager.generateMaze(main.gameManager.mazeGen.runLenghtDecode(s1));
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// } catch (IOException e) {
|
||||
// }
|
||||
// // Send messages to the client
|
||||
// if (!nextMessage.equals(""))
|
||||
// try {
|
||||
// // write our entered message to the stream
|
||||
// socket.getOutputStream().write((nextMessage + "\n").getBytes());
|
||||
// } catch (IOException e) {
|
||||
//// e.printStackTrace();
|
||||
// }
|
||||
}
|
|
@ -16,48 +16,50 @@ public class GameManager {
|
|||
|
||||
AMazeIng main;
|
||||
public MazeGenerator mazeGen;
|
||||
|
||||
/* Local manager for local games and server host in multiplayer games */
|
||||
public GameServer server;
|
||||
public GameClient client;
|
||||
|
||||
|
||||
public boolean gameStarted = false;
|
||||
public boolean showGame = true;
|
||||
Random rand = new Random();
|
||||
|
||||
ArrayList<MazePlayer> players = new ArrayList<MazePlayer>();
|
||||
GameType type = GameType.LOCAL;
|
||||
|
||||
public GameManager(Game main_) {
|
||||
public ArrayList<MazePlayer> players = new ArrayList<MazePlayer>();
|
||||
|
||||
public GameManager(Game main_, GameType t) {
|
||||
main = (AMazeIng) main_;
|
||||
gameStarted = false;
|
||||
server = new GameServer(main);
|
||||
client = new GameClient(main);
|
||||
// Maze Generation
|
||||
|
||||
type = t;
|
||||
setShowGame(type != GameType.SERVER);
|
||||
|
||||
mazeGen = new MazeGenerator(main, MazeSettings.MAZEX, MazeSettings.MAZEZ);
|
||||
}
|
||||
|
||||
boolean anyoneWon = false;
|
||||
|
||||
public void update() {
|
||||
server.update();
|
||||
client.update();
|
||||
|
||||
if (gameStarted) {
|
||||
main.world.cam.position.set(mazeGen.w / 2, (MazeSettings.MAZEX + MazeSettings.MAZEZ) * 0.45f,
|
||||
mazeGen.h / 2);
|
||||
main.world.cam.lookAt(MazeSettings.MAZEX / 2, 0, MazeSettings.MAZEX / 2);
|
||||
main.world.cam.update();
|
||||
if(showGame) main.world.render();
|
||||
if (getShowGame())
|
||||
main.world.render();
|
||||
|
||||
main.world.modelBatch.begin(main.world.cam);
|
||||
if (players != null) {
|
||||
for (MazePlayer p : players) {
|
||||
if(showGame) p.render(main.world.modelBatch, main.world.environment);
|
||||
if (getShowGame())
|
||||
p.render(main.world.modelBatch, main.world.environment);
|
||||
|
||||
anyoneWon = false;
|
||||
if (checkWin(p)) {
|
||||
anyoneWon = true;
|
||||
gameStarted = false;
|
||||
break;
|
||||
if(type != GameType.CLIENT) {
|
||||
if (checkWin(p)) {
|
||||
anyoneWon = true;
|
||||
gameStarted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,24 +71,27 @@ public class GameManager {
|
|||
}
|
||||
|
||||
ArrayList<MazePlayer> toDelete = new ArrayList<MazePlayer>();
|
||||
|
||||
public void generateMaze(Set<MazePlayer> pl, int todraw[][]) {
|
||||
main.setScreen(null);
|
||||
anyoneWon = false;
|
||||
|
||||
gameStarted = true;
|
||||
// Only add new players and dispose the old ones
|
||||
//Check if actually there are players to be deleted
|
||||
if(pl != null) {
|
||||
// Check if actually there are players to be deleted
|
||||
if (pl != null) {
|
||||
for (MazePlayer p : players)
|
||||
if (!pl.contains(p))
|
||||
toDelete.add(p);
|
||||
|
||||
//Check if new players have to be added
|
||||
|
||||
// Check if new players have to be added
|
||||
for (MazePlayer p : pl)
|
||||
if (!players.contains(p))
|
||||
players.add(p);
|
||||
|
||||
//Fianlly delete players. A separated step is needed to remove the risk of a ConcurrentModificationException
|
||||
for(MazePlayer p : toDelete) {
|
||||
|
||||
// Fianlly delete players. A separated step is needed to remove the risk of a
|
||||
// ConcurrentModificationException
|
||||
for (MazePlayer p : toDelete) {
|
||||
p.dispose();
|
||||
players.remove(p);
|
||||
}
|
||||
|
@ -105,16 +110,16 @@ public class GameManager {
|
|||
|
||||
mazeGen.setMazeSize(MazeSettings.MAZEX, MazeSettings.MAZEZ);
|
||||
mazeGen.generateMaze();
|
||||
|
||||
spreadPlayers();
|
||||
mazeGen.setupEndPoint();
|
||||
|
||||
if(todraw != null) {
|
||||
mazeGen.show(todraw);
|
||||
|
||||
if (type != GameType.CLIENT) {
|
||||
spreadPlayers();
|
||||
mazeGen.setupEndPoint();
|
||||
}
|
||||
|
||||
|
||||
gameStarted = true;
|
||||
|
||||
if (todraw != null && showGame == true) {
|
||||
mazeGen.show(todraw);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void spreadPlayers() {
|
||||
|
@ -123,9 +128,8 @@ public class GameManager {
|
|||
do {
|
||||
x = (Math.abs(rand.nextInt() - 1) % (mazeGen.w));
|
||||
z = (Math.abs(rand.nextInt() - 1) % (mazeGen.h));
|
||||
// System.out.println(thereIsPlayerInPos(x, z) + " - " + mazeGen.occupiedSpot(x,
|
||||
// z) + " --- " + x + ", " + z);
|
||||
// while there's a wall in current location pick new location
|
||||
System.out.println(thereIsPlayerInPos(x, z) + " - " + mazeGen.occupiedSpot(x,
|
||||
z) + " --- " + x + ", " + z);
|
||||
} while (thereIsPlayerInPos(x, z) || mazeGen.occupiedSpot(x, z));
|
||||
p.setPlaying();
|
||||
p.setPos(x + 0.5f, 2f, z + 0.5f);
|
||||
|
@ -142,9 +146,6 @@ public class GameManager {
|
|||
do {
|
||||
x = (Math.abs(rand.nextInt() - 1) % (mazeGen.w));
|
||||
z = (Math.abs(rand.nextInt() - 1) % (mazeGen.h));
|
||||
// System.out.println(thereIsPlayerInPos(x, z) + " - " + mazeGen.occupiedSpot(x,
|
||||
// z) + " --- " + x + ", " + z);
|
||||
// while there's a wall in current location pick new location
|
||||
} while (thereIsPlayerInPos(x, z) || mazeGen.occupiedSpot(x, z));
|
||||
if (name.equalsIgnoreCase(""))
|
||||
return new Player(kup, kdown, ksx, kdx, x + 0.5f, 4f, z + 0.5f);
|
||||
|
@ -152,11 +153,6 @@ public class GameManager {
|
|||
return new Player(kup, kdown, ksx, kdx, x + 0.5f, 4f, z + 0.5f, name);
|
||||
}
|
||||
|
||||
// public void destroyPlayers() {
|
||||
// for (MazePlayer p : players)
|
||||
// p.dispose();
|
||||
// players.clear();
|
||||
// }
|
||||
|
||||
public boolean checkWin(MazePlayer p) {
|
||||
if ((int) p.getPos().x == mazeGen.WINX && (int) p.getPos().z == mazeGen.WINZ) {
|
||||
|
@ -186,12 +182,12 @@ public class GameManager {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean getShowGame() {
|
||||
|
||||
boolean getShowGame() {
|
||||
return showGame;
|
||||
}
|
||||
|
||||
public void setShowGame(boolean g) {
|
||||
|
||||
void setShowGame(boolean g) {
|
||||
showGame = g;
|
||||
}
|
||||
|
||||
|
@ -202,17 +198,13 @@ public class GameManager {
|
|||
public void generateMaze(int todraw[][]) {
|
||||
generateMaze(null, todraw);
|
||||
}
|
||||
|
||||
|
||||
public void generateMaze(Set<MazePlayer> pl) {
|
||||
generateMaze(pl, null);
|
||||
}
|
||||
|
||||
|
||||
public void dispose() {
|
||||
client.stop();
|
||||
server.stop();
|
||||
for (MazePlayer p : players)
|
||||
p.dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,273 +0,0 @@
|
|||
package com.emamaker.amazeing.manager;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.Net.Protocol;
|
||||
import com.badlogic.gdx.net.ServerSocket;
|
||||
import com.badlogic.gdx.net.ServerSocketHints;
|
||||
import com.badlogic.gdx.net.Socket;
|
||||
import com.badlogic.gdx.net.SocketHints;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
import com.emamaker.amazeing.AMazeIng;
|
||||
import com.emamaker.amazeing.player.MazePlayer;
|
||||
import com.emamaker.amazeing.player.MazePlayerLocal;
|
||||
import com.emamaker.amazeing.player.MazePlayerRemote;
|
||||
|
||||
public class GameServer {
|
||||
|
||||
public AMazeIng main;
|
||||
|
||||
volatile boolean serverRunning = false;
|
||||
volatile String nextMessage = "";
|
||||
volatile String rMsg;
|
||||
|
||||
public ServerSocket serverSocket = null;
|
||||
public int port;
|
||||
UUID uuid ;
|
||||
|
||||
Socket s;
|
||||
Thread serverThread;
|
||||
|
||||
// An HashTable that stores remote players, starting from a UUID and the
|
||||
// relative socket
|
||||
// Player must be added here only once received the last acknowledgment message
|
||||
// from client
|
||||
volatile Hashtable<Socket, FullPlayerEntry> remotePlayers = new Hashtable<>();
|
||||
// An HashTable that stores remote players waiting to be accepted, starting from
|
||||
// a UUID and the
|
||||
// relative socket. The integer is needed to store the current phase the
|
||||
// acknowledgment is at (Starting from 0), if it's not equals to the expected
|
||||
// one the connectiond gets dropped and socket removed from here
|
||||
volatile Hashtable<Socket, TmpPlayerEntry> tmpPlayers = new Hashtable<>();
|
||||
// New players to be added into remotePlayers in the main thread, holds Sockets
|
||||
// used to get player info from tmpPlayers
|
||||
volatile ArrayList<Socket> newPlayers = new ArrayList<>();
|
||||
|
||||
volatile TmpPlayerEntry currentTmpEntry;
|
||||
|
||||
SocketHints socketHints = new SocketHints();
|
||||
ServerSocketHints serverSocketHint = new ServerSocketHints();
|
||||
|
||||
public GameServer(AMazeIng main_) {
|
||||
main = main_;
|
||||
uuid = UUID.randomUUID();
|
||||
}
|
||||
|
||||
public void startServer(int port_) {
|
||||
port = port_;
|
||||
serverSocketHint.acceptTimeout = 1000;
|
||||
socketHints.connectTimeout = 10000;
|
||||
serverThread = new Thread(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
serverRunning = true;
|
||||
while (serverRunning) {
|
||||
if (serverSocket == null) {
|
||||
|
||||
serverSocket = Gdx.net.newServerSocket(Protocol.TCP, port, serverSocketHint);
|
||||
System.out.println("Server started and listening for connections!");
|
||||
}
|
||||
|
||||
try {
|
||||
Socket socket = serverSocket.accept(socketHints);
|
||||
if (socket != null && !tmpPlayers.contains(socket)
|
||||
&& !remotePlayers.keySet().contains(socket)) {
|
||||
tmpPlayers.put(socket, new TmpPlayerEntry(socket, UUID.randomUUID(), 0));
|
||||
System.out.println(
|
||||
"Accepted new tmp client: " + socket + " with ip " + socket.getRemoteAddress());
|
||||
}
|
||||
} catch (GdxRuntimeException se) {
|
||||
// System.out.println("No new clients connected in the last 1000 milliseconds");
|
||||
}
|
||||
|
||||
// System.out.println(Arrays.toString(tmpPlayers.keySet().toArray()));
|
||||
// System.out.println(Arrays.toString(remotePlayers.keySet().toArray()));
|
||||
if (!main.gameManager.gameStarted) {
|
||||
for (Socket s : tmpPlayers.keySet()) {
|
||||
if (s.isConnected()) {
|
||||
rMsg = receiveMessageFromSocket(s);
|
||||
System.out.println(rMsg);
|
||||
if (rMsg.equals("AO")) {
|
||||
// Step 0
|
||||
if (tmpPlayers.get(s).step == 0) {
|
||||
// We're at the right step, send uuid to client
|
||||
sendMessageToSocket(s, "UUID" + tmpPlayers.get(s).uuid.toString());
|
||||
} else {
|
||||
// Wrong step
|
||||
System.out.println("Client already connected, ignoring request");
|
||||
}
|
||||
// If receiving multiple AOs, just start back from this point
|
||||
tmpPlayers.get(s).step = 1;
|
||||
} else if (rMsg.equals("AO2")) {
|
||||
if (tmpPlayers.get(s).step == 1) {
|
||||
System.out.println("Client " + s + " accepted uuid");
|
||||
sendMessageToSocket(s, "AO3");
|
||||
tmpPlayers.get(s).step = 2;
|
||||
}
|
||||
} else if (rMsg.equals("AO4")) {
|
||||
if (tmpPlayers.get(s).step == 2) {
|
||||
// Player can now be added to the remote player list, but this has to be done
|
||||
// inside the main thread, and this bit of code is executed outside, so pass it
|
||||
// to another function for use
|
||||
newPlayers.add(s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Cliented timed out, remove it from the list :(
|
||||
tmpPlayers.remove(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nextMessage = "";
|
||||
if (!messages.isEmpty())
|
||||
nextMessage = messages.remove();
|
||||
for (Socket s : remotePlayers.keySet()) {
|
||||
if (s.isConnected()) {
|
||||
if (!nextMessage.equals("")) {
|
||||
sendMessageToSocket(s, nextMessage);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Cliented timed out, remove it from the list :(
|
||||
remotePlayers.remove(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
serverThread.start();
|
||||
|
||||
//Also start client to play on the local machine
|
||||
main.gameManager.client.start("localhost", port);
|
||||
}
|
||||
|
||||
// Update must be called from Main thread and used for applications on main
|
||||
// thread, such as spawning new players
|
||||
public void update() {
|
||||
// Spawn new players if needed
|
||||
for (Socket s : newPlayers) {
|
||||
remotePlayers.put(s,
|
||||
new FullPlayerEntry(s, tmpPlayers.get(s).uuid, new MazePlayerRemote(main, tmpPlayers.get(s).uuid)));
|
||||
System.out.println("Accepted new player: " + s.toString() + " " + tmpPlayers.get(s).uuid.toString());
|
||||
tmpPlayers.remove(s);
|
||||
}
|
||||
newPlayers.clear();
|
||||
}
|
||||
|
||||
// Once the server has started accepting connections from other players, the
|
||||
// host should decide when to start the gmae
|
||||
// A proper ui should be added, but for now we can just start the game without
|
||||
// showing any players and just show the map across all the clients
|
||||
public void startGame() {
|
||||
update();
|
||||
ArrayList<MazePlayer> players = new ArrayList<>();
|
||||
for (FullPlayerEntry p : remotePlayers.values())
|
||||
players.add(p.player);
|
||||
sendMessagetoClients("Players" + buildUUIDList());
|
||||
|
||||
main.gameManager.generateMaze(new HashSet<MazePlayer>(players));
|
||||
main.gameManager.setShowGame(false);
|
||||
|
||||
sendMessagetoClients("Map" + main.gameManager.mazeGen.runLenghtEncode());
|
||||
}
|
||||
|
||||
public String buildUUIDList() {
|
||||
String s = uuid.toString() + "!";
|
||||
for (FullPlayerEntry p : remotePlayers.values()) {
|
||||
s += p.uuid.toString() + "!";
|
||||
}
|
||||
System.out.println(s);
|
||||
return s;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (serverSocket != null) {
|
||||
serverSocket.dispose();
|
||||
serverSocket = null;
|
||||
}
|
||||
serverRunning = false;
|
||||
}
|
||||
|
||||
Queue<String> messages = new LinkedList<>();
|
||||
|
||||
public void sendMessagetoClients(String s) {
|
||||
messages.add(s + "\n");
|
||||
System.out.println("Sending message to clients: " + nextMessage);
|
||||
}
|
||||
|
||||
void sendMessageToSocket(Socket s, String msg) {
|
||||
if (s != null && s.isConnected())
|
||||
if (!msg.equals(""))
|
||||
try {
|
||||
// write our entered message to the stream
|
||||
System.out.println("Server sending msg: " + msg + " to " + s);
|
||||
s.getOutputStream().write((msg + "\n").getBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
String tmprs;
|
||||
|
||||
String receiveMessageFromSocket(Socket s) {
|
||||
if (s != null && s.isConnected()) {
|
||||
// Receive messages from the client
|
||||
try {
|
||||
if (s.getInputStream().available() > 0) {
|
||||
BufferedReader buffer = new BufferedReader(new InputStreamReader(s.getInputStream()));
|
||||
// Read to the next newline (\n) and display that text on labelMessage
|
||||
tmprs = buffer.readLine();
|
||||
System.out.println("Server received message From: " + s + "! " + tmprs);
|
||||
return tmprs;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
class TmpPlayerEntry {
|
||||
public UUID uuid;
|
||||
public Socket socket;
|
||||
public int step = 0;
|
||||
public long lastTimeHeard;
|
||||
/*
|
||||
* (Look at the notes) Step 0: AO client->server first request Step 1: UUID
|
||||
* server->client response with uuid Step 2: AO2 client->server client accepted
|
||||
* uuid Step 3: AO3 server->client server accepted client
|
||||
*/
|
||||
|
||||
public TmpPlayerEntry(Socket s, UUID u, int t) {
|
||||
uuid = u;
|
||||
socket = s;
|
||||
step = t;
|
||||
lastTimeHeard = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
class FullPlayerEntry {
|
||||
public UUID uuid;
|
||||
public Socket socket;
|
||||
public MazePlayer player;
|
||||
|
||||
public FullPlayerEntry(Socket s, UUID u, MazePlayer p) {
|
||||
uuid = u;
|
||||
socket = s;
|
||||
player = p;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.emamaker.amazeing.manager;
|
||||
|
||||
public enum GameType {
|
||||
LOCAL, CLIENT, SERVER
|
||||
}
|
|
@ -0,0 +1,222 @@
|
|||
package com.emamaker.amazeing.manager.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.math.Quaternion;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.emamaker.amazeing.AMazeIng;
|
||||
import com.emamaker.amazeing.manager.GameManager;
|
||||
import com.emamaker.amazeing.manager.GameType;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.AddNewPlayer;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.LoginAO;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.LoginAO2;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.RemovePlayer;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.StartGame;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.UpdateMap;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.UpdatePlayerTransform;
|
||||
import com.emamaker.amazeing.player.MazePlayer;
|
||||
import com.emamaker.amazeing.player.MazePlayerLocal;
|
||||
import com.emamaker.amazeing.player.MazePlayerRemote;
|
||||
import com.esotericsoftware.kryonet.Client;
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
|
||||
public class GameClient {
|
||||
|
||||
public AMazeIng main;
|
||||
volatile boolean clientRunning = false;
|
||||
|
||||
public String addr;
|
||||
public int port;
|
||||
|
||||
boolean startGame = false;
|
||||
String map = "";
|
||||
|
||||
// Hashtable of remote players present in the match. This will be used to update
|
||||
// other players' transform when server reports about it
|
||||
Hashtable<String, MazePlayerRemote> remotePlayers = new Hashtable<>();
|
||||
// Hashtable<String, MazePlayerLocal> localPlayers = new Hashtable<>();
|
||||
MazePlayerLocal player;
|
||||
|
||||
ArrayList<MazePlayer> players = new ArrayList<MazePlayer>();
|
||||
|
||||
volatile HashSet<String> toAdd = new HashSet<>();
|
||||
volatile HashSet<String> toRemove = new HashSet<>();
|
||||
|
||||
GameManager gameManager;
|
||||
Client client;
|
||||
// UUID is represented using a string, for kryonet ease of use
|
||||
String uuid = "";
|
||||
|
||||
public GameClient(AMazeIng main_) {
|
||||
main = main_;
|
||||
}
|
||||
|
||||
public void start(String addr_, int port_) {
|
||||
port = port_;
|
||||
addr = addr_;
|
||||
|
||||
clientRunning = true;
|
||||
startGame = false;
|
||||
client = new Client();
|
||||
client.start();
|
||||
uuid = "";
|
||||
player = new MazePlayerLocal(main, Keys.W, Keys.S, Keys.A, Keys.D);
|
||||
remotePlayers.clear();
|
||||
|
||||
NetworkCommon.register(client);
|
||||
|
||||
client.addListener(new Listener() {
|
||||
public void connected(Connection connection) {
|
||||
}
|
||||
|
||||
public void received(Connection connection, Object object) {
|
||||
if (object instanceof LoginAO2) {
|
||||
uuid = ((LoginAO2) object).uuid;
|
||||
client.sendTCP(object);
|
||||
System.out.println("Received UUID " + uuid.toString() + " from server, giving confirmation!");
|
||||
} else if (object instanceof AddNewPlayer) {
|
||||
AddNewPlayer msg = (AddNewPlayer) object;
|
||||
if ((!msg.uuid.equals(uuid))) {
|
||||
toAdd.add(msg.uuid);
|
||||
System.out
|
||||
.println("Remote player with uuid " + msg.uuid.toString() + " has joined the game :)");
|
||||
}
|
||||
} else if (object instanceof RemovePlayer) {
|
||||
RemovePlayer msg = (RemovePlayer) object;
|
||||
if ((!msg.uuid.equals(uuid))) {
|
||||
toRemove.add(msg.uuid);
|
||||
System.out
|
||||
.println("Remote player with uuid " + msg.uuid.toString() + " is leaving the game :(");
|
||||
}
|
||||
} else if (object instanceof NetworkCommon.UpdatePlayerTransformServer) {
|
||||
NetworkCommon.UpdatePlayerTransformServer s = (NetworkCommon.UpdatePlayerTransformServer) object;
|
||||
System.out.println("Received a forced position update for self!");
|
||||
if(s.uuid.equals(uuid)) {
|
||||
player.setPlaying();
|
||||
player.setTransform(s.tx, s.ty, s.tz, s.rx, s.ry, s.rz, s.rw);
|
||||
}else {
|
||||
remotePlayers.get(s.uuid).setPlaying();
|
||||
remotePlayers.get(s.uuid).setTransform(s.tx, s.ty, s.tz, s.rx, s.ry, s.rz, s.rw);
|
||||
}
|
||||
} else if (object instanceof UpdatePlayerTransform) {
|
||||
UpdatePlayerTransform msg = (UpdatePlayerTransform) object;
|
||||
if (!msg.uuid.equals(uuid)) {
|
||||
remotePlayers.get(msg.uuid).setPlaying();
|
||||
remotePlayers.get(msg.uuid).setTransform(msg.tx, msg.ty, msg.tz, msg.rx, msg.ry, msg.rz, msg.rw);
|
||||
System.out.println("R: " + msg.tx + ", " + msg.ty + ", " + msg.tz);
|
||||
System.out.println("Updating remote player with uuid " + msg.uuid.toString());
|
||||
}
|
||||
} else if (object instanceof UpdateMap) {
|
||||
map = ((UpdateMap) object).map;
|
||||
System.out.println("Map update!");
|
||||
} else if (object instanceof StartGame) {
|
||||
startGame = true;
|
||||
map = ((StartGame) object).map;
|
||||
System.out.println("Starting the online game!");
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnected(Connection connection) {
|
||||
for (MazePlayerRemote p : remotePlayers.values()) {
|
||||
p.dispose();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
client.connect(5000, addr, port);
|
||||
if (uuid.equals("")) {
|
||||
client.sendTCP(new LoginAO());
|
||||
System.out.println("Connecting to server...");
|
||||
} else {
|
||||
System.out.println("Already connected, to need to connect again");
|
||||
}
|
||||
// Server communication after connection can go here, or in
|
||||
// Listener#connected().
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Update must be called from Main thread and used for applications on main
|
||||
// thread
|
||||
public void update() {
|
||||
if (clientRunning) {
|
||||
try {
|
||||
for (String s : toAdd) {
|
||||
if (!s.equals(uuid))
|
||||
remotePlayers.put(s, new MazePlayerRemote(main, s));
|
||||
}
|
||||
toAdd.clear();
|
||||
for (String s : toRemove) {
|
||||
remotePlayers.get(s).dispose();
|
||||
remotePlayers.remove(s);
|
||||
}
|
||||
toRemove.clear();
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
if (startGame) {
|
||||
gameManager = new GameManager(main, GameType.CLIENT);
|
||||
for (MazePlayerRemote p : remotePlayers.values())
|
||||
if (!players.contains(p))
|
||||
players.add(p);
|
||||
|
||||
// for (MazePlayerLocal p : localPlayers.values())
|
||||
// if (!players.contains(p))
|
||||
// players.add(p);
|
||||
|
||||
players.add(player);
|
||||
|
||||
main.getScreen().hide();
|
||||
main.setScreen(null);
|
||||
|
||||
for(MazePlayer p : players) p.setPlaying();
|
||||
System.out.println(Arrays.toString(players.toArray()));
|
||||
|
||||
gameManager.generateMaze(new HashSet<MazePlayer>(players));
|
||||
startGame = false;
|
||||
}
|
||||
if (!map.equals("")) {
|
||||
System.out.println("Setting map");
|
||||
gameManager.mazeGen.runLenghtDecode(map);
|
||||
map = "";
|
||||
}
|
||||
if (gameManager != null)
|
||||
gameManager.update();
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLocalPlayer(MazePlayerLocal p) {
|
||||
if (this.gameManager != null && this.gameManager.gameStarted && clientRunning && p.isPlaying()) {
|
||||
UpdatePlayerTransform pu = new UpdatePlayerTransform();
|
||||
Vector3 pos = p.ghostObject.getWorldTransform().getTranslation(new Vector3());
|
||||
Quaternion rot = p.ghostObject.getWorldTransform().getRotation(new Quaternion());
|
||||
pu.tx = pos.x;
|
||||
pu.ty = pos.y;
|
||||
pu.tz = pos.z;
|
||||
pu.rx = rot.x;
|
||||
pu.ry = rot.y;
|
||||
pu.rz = rot.z;
|
||||
pu.rw = rot.w;
|
||||
pu.uuid = uuid;
|
||||
|
||||
client.sendTCP(pu);
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
if (clientRunning) {
|
||||
client.stop();
|
||||
clientRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,225 @@
|
|||
package com.emamaker.amazeing.manager.network;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.badlogic.gdx.math.Quaternion;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.emamaker.amazeing.AMazeIng;
|
||||
import com.emamaker.amazeing.manager.GameManager;
|
||||
import com.emamaker.amazeing.manager.GameType;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.AddNewPlayer;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.LoginAO;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.LoginAO2;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.RemovePlayer;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.StartGame;
|
||||
import com.emamaker.amazeing.manager.network.NetworkCommon.UpdatePlayerTransform;
|
||||
import com.emamaker.amazeing.player.MazePlayer;
|
||||
import com.emamaker.amazeing.player.MazePlayerRemote;
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
import com.esotericsoftware.kryonet.Server;
|
||||
|
||||
public class GameServer {
|
||||
|
||||
public AMazeIng main;
|
||||
|
||||
volatile boolean serverRunning = false;
|
||||
public int port;
|
||||
UUID uuid;
|
||||
|
||||
GameManager gameManager;
|
||||
Server server;
|
||||
|
||||
// Hashtable of remote players present in the match. This will be used to update
|
||||
// other players' transform when server reports about it
|
||||
Hashtable<String, MazePlayerRemote> remotePlayers = new Hashtable<>();
|
||||
|
||||
public GameServer(AMazeIng main_) {
|
||||
main = main_;
|
||||
uuid = UUID.randomUUID();
|
||||
}
|
||||
|
||||
public void startServer(int port_) {
|
||||
port = port_;
|
||||
serverRunning = true;
|
||||
try {
|
||||
server = new Server() {
|
||||
protected Connection newConnection() {
|
||||
// By providing our own connection implementation, we can store per
|
||||
// connection state without a connection ID to state look up.
|
||||
return new ConnectionPlayer();
|
||||
}
|
||||
};
|
||||
|
||||
// For consistency, the classes to be sent over the network are
|
||||
// registered by the same method for both the client and server.
|
||||
NetworkCommon.register(server);
|
||||
|
||||
server.addListener(new Listener() {
|
||||
public void received(Connection c, Object object) {
|
||||
ConnectionPlayer connection = (ConnectionPlayer) c;
|
||||
|
||||
if (object instanceof LoginAO) {
|
||||
// Ignore this if player already is in the list
|
||||
if (connection.uuid != null)
|
||||
return;
|
||||
|
||||
// Give player its UUID and wait for response. Once the LoginAO2 response is
|
||||
// received, move the
|
||||
// UUID to the list of players, create a new one and notify clients about it
|
||||
connection.uuid = UUID.randomUUID().toString();
|
||||
|
||||
LoginAO2 response = new LoginAO2();
|
||||
response.uuid = connection.uuid;
|
||||
System.out.println("Server received connection request! Giving client UUID " + connection.uuid);
|
||||
c.sendTCP(response);
|
||||
} else if (object instanceof LoginAO2) {
|
||||
// Ignore is there's no uuid or it's different from the login message one
|
||||
if (connection.uuid == null || !connection.uuid.equals(((LoginAO2) object).uuid))
|
||||
return;
|
||||
// Otherwise add a new player and notify all clients about it
|
||||
remotePlayers.put(((LoginAO2) object).uuid,
|
||||
new MazePlayerRemote(main, ((LoginAO2) object).uuid, false));
|
||||
AddNewPlayer response = new AddNewPlayer();
|
||||
response.uuid = ((LoginAO2) object).uuid;
|
||||
|
||||
System.out.println("Client with UUID " + response.uuid + " is connected and ready to play :)");
|
||||
server.sendToAllTCP(response);
|
||||
|
||||
for (String s : remotePlayers.keySet()) {
|
||||
response.uuid = s;
|
||||
c.sendTCP(response);
|
||||
}
|
||||
|
||||
} else if (object instanceof RemovePlayer) {
|
||||
// Ignore is there's no uuid or it's different from the login message one
|
||||
if (connection.uuid == null || !connection.uuid.equals(((RemovePlayer) object).uuid))
|
||||
return;
|
||||
// Otherwise remove the player and notify all clients about it
|
||||
remotePlayers.get(((RemovePlayer) object).uuid).dispose();
|
||||
remotePlayers.remove(((RemovePlayer) object).uuid);
|
||||
|
||||
System.out.println("Client with UUID " + connection.uuid + " is leaving the server :(");
|
||||
|
||||
server.sendToAllTCP(object);
|
||||
|
||||
} else if (object instanceof UpdatePlayerTransform) {
|
||||
UpdatePlayerTransform transform = (UpdatePlayerTransform) object;
|
||||
// Ignore is there's no uuid or it's different from the login message one
|
||||
if (connection.uuid == null || !connection.uuid.equals(transform.uuid))
|
||||
return;
|
||||
|
||||
if (gameManager.gameStarted) {
|
||||
// Otherwise Update the transport and notify clients about it
|
||||
MazePlayerRemote player = remotePlayers.get((transform.uuid));
|
||||
player.setTransform(transform.tx, transform.ty, transform.tz, transform.rx, transform.ry,
|
||||
transform.rz, transform.rw);
|
||||
updatePlayer(transform.uuid, remotePlayers.get(transform.uuid), false);
|
||||
System.out.println("Updating client " + connection.uuid + " position!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnected(Connection c) {
|
||||
ConnectionPlayer connection = (ConnectionPlayer) c;
|
||||
if (connection.uuid != null) {
|
||||
remotePlayers.get(connection.uuid).dispose();
|
||||
remotePlayers.remove(connection.uuid);
|
||||
|
||||
RemovePlayer remove = new RemovePlayer();
|
||||
remove.uuid = connection.uuid;
|
||||
server.sendToAllTCP(remove);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
server.bind(port);
|
||||
server.start();
|
||||
System.out.println("Server registered and running on port " + port);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Update must be called from Main thread and used for applications on main
|
||||
// thread, such as spawning new players
|
||||
public void update() {
|
||||
if (serverRunning) {
|
||||
if (gameManager != null) {
|
||||
gameManager.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Once the server has started accepting connections from other players, the
|
||||
// host should decide when to start the gmae
|
||||
// A proper ui should be added, but for now we can just start the game without
|
||||
// showing any players and just show the map across all the clients
|
||||
public void startGame() {
|
||||
if (serverRunning) {
|
||||
update();
|
||||
// Start game stuff
|
||||
this.gameManager = new GameManager(main, GameType.SERVER);
|
||||
this.gameManager.generateMaze(new HashSet<MazePlayer>(remotePlayers.values()));
|
||||
StartGame request = new StartGame();
|
||||
request.map = this.gameManager.mazeGen.runLenghtEncode();
|
||||
server.sendToAllTCP(request);
|
||||
|
||||
if (gameManager.gameStarted)
|
||||
for (String p : remotePlayers.keySet())
|
||||
updatePlayer(p, remotePlayers.get(p), true);
|
||||
} else {
|
||||
System.out.println("Server not started yet, game cannot start");
|
||||
}
|
||||
}
|
||||
|
||||
public void updatePlayer(String uuid, MazePlayerRemote p, boolean force) {
|
||||
if (serverRunning && this.gameManager != null && this.gameManager.gameStarted) {
|
||||
if (force) {
|
||||
NetworkCommon.UpdatePlayerTransformServer pu = new NetworkCommon.UpdatePlayerTransformServer();
|
||||
Vector3 pos = p.getPos();
|
||||
Quaternion rot = p.getRotation();
|
||||
pu.tx = pos.x;
|
||||
pu.ty = pos.y;
|
||||
pu.tz = pos.z;
|
||||
pu.rx = rot.x;
|
||||
pu.ry = rot.y;
|
||||
pu.rz = rot.z;
|
||||
pu.rw = rot.w;
|
||||
pu.uuid = uuid;
|
||||
System.out.println("Forcing position update to all clients for player " + uuid);
|
||||
server.sendToAllTCP(pu);
|
||||
} else {
|
||||
UpdatePlayerTransform pu = new UpdatePlayerTransform();
|
||||
Vector3 pos = p.getPos();
|
||||
Quaternion rot = p.getRotation();
|
||||
pu.tx = pos.x;
|
||||
pu.ty = pos.y;
|
||||
pu.tz = pos.z;
|
||||
pu.rx = rot.x;
|
||||
pu.ry = rot.y;
|
||||
pu.rz = rot.z;
|
||||
pu.rw = rot.w;
|
||||
pu.uuid = uuid;
|
||||
System.out.println("Sending position update to all clients for player " + uuid);
|
||||
server.sendToAllTCP(pu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
for (MazePlayerRemote p : remotePlayers.values())
|
||||
p.dispose();
|
||||
if (serverRunning) {
|
||||
server.stop();
|
||||
serverRunning = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ConnectionPlayer extends Connection {
|
||||
public String uuid;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.emamaker.amazeing.manager.network;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryonet.EndPoint;
|
||||
|
||||
public class NetworkCommon {
|
||||
|
||||
|
||||
// This registers objects that are going to be sent over the network.
|
||||
static public void register(EndPoint endPoint) {
|
||||
Kryo kryo = endPoint.getKryo();
|
||||
kryo.register(LoginAO.class);
|
||||
kryo.register(LoginAO2.class);
|
||||
kryo.register(LoginUUID.class);
|
||||
kryo.register(AddNewPlayer.class);
|
||||
kryo.register(RemovePlayer.class);
|
||||
kryo.register(UpdatePlayerTransform.class);
|
||||
kryo.register(UpdatePlayerTransformServer.class);
|
||||
kryo.register(StartGame.class);
|
||||
kryo.register(UpdateMap.class);
|
||||
}
|
||||
|
||||
//Login stuff
|
||||
static public class LoginAO {
|
||||
}
|
||||
static public class LoginAO2 {
|
||||
String uuid;
|
||||
}
|
||||
static public class LoginUUID {
|
||||
String uuid;
|
||||
}
|
||||
|
||||
//Player stuff
|
||||
static public class AddNewPlayer {
|
||||
String uuid;
|
||||
}
|
||||
static public class RemovePlayer {
|
||||
String uuid;
|
||||
}
|
||||
static public class UpdatePlayerTransform {
|
||||
String uuid;
|
||||
float tx, ty, tz, rx, ry, rz, rw;
|
||||
}
|
||||
static public class UpdatePlayerTransformServer {
|
||||
String uuid;
|
||||
float tx, ty, tz, rx, ry, rz, rw;
|
||||
}
|
||||
|
||||
static public class StartGame{
|
||||
//Use this to notify clients of a newly started game
|
||||
//A Run-lenght-encoded representation of the map can be appended, this can be avoided but it's not recommended
|
||||
String map;
|
||||
}
|
||||
static public class UpdateMap{
|
||||
//Run-lenght-encoded representation of the map
|
||||
String map;
|
||||
}
|
||||
|
||||
}
|
|
@ -31,8 +31,8 @@ public class MazeGenerator {
|
|||
}
|
||||
|
||||
public void setMazeSize(int w_, int h_) {
|
||||
w = w_ + (1 - w % 2);
|
||||
h = h_ + (1 - h % 2);
|
||||
w = w_;
|
||||
h = h_;
|
||||
W = (w - 1) / 2;
|
||||
H = (h - 1) / 2;
|
||||
|
||||
|
@ -170,15 +170,16 @@ public class MazeGenerator {
|
|||
* from the current index and get the block type, repeated for how many times the count number says
|
||||
*/
|
||||
public int[][] runLenghtDecode(String s) {
|
||||
int[][] todraw = null;
|
||||
int[][] todraw_ = null;
|
||||
int count, type, totalcount = 0;
|
||||
|
||||
//Split the various rows
|
||||
String[] rows = s.split("-");
|
||||
System.out.println(Arrays.deepToString(rows));
|
||||
//Mazes are always squares
|
||||
todraw = new int[rows.length][rows.length];
|
||||
setMazeSize(rows.length, rows.length);
|
||||
//Temporarely patch to the calculation errors in setMazeSize
|
||||
todraw_=new int[rows.length][rows.length];
|
||||
|
||||
for(int i = 0; i < rows.length; i++) {
|
||||
totalcount = 0;
|
||||
|
@ -187,13 +188,13 @@ public class MazeGenerator {
|
|||
type = ((int) (rows[i].charAt(j+1))) - 65;
|
||||
|
||||
for(int k = totalcount; k < totalcount+count; k++) {
|
||||
todraw[i][k] = type;
|
||||
todraw_[i][k] = type;
|
||||
}
|
||||
totalcount += count;
|
||||
}
|
||||
}
|
||||
|
||||
return todraw;
|
||||
show(todraw_);
|
||||
return todraw_;
|
||||
}
|
||||
|
||||
public void prepareShow() {
|
||||
|
|
|
@ -13,6 +13,7 @@ import com.badlogic.gdx.graphics.g3d.ModelInstance;
|
|||
import com.badlogic.gdx.graphics.g3d.model.Node;
|
||||
import com.badlogic.gdx.graphics.g3d.utils.MeshPartBuilder;
|
||||
import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
|
||||
import com.badlogic.gdx.math.Quaternion;
|
||||
import com.badlogic.gdx.math.Vector3;
|
||||
import com.emamaker.amazeing.AMazeIng;
|
||||
import com.emamaker.voxelengine.physics.GameObject;
|
||||
|
@ -32,25 +33,37 @@ public abstract class MazePlayer {
|
|||
public GameObject obj;
|
||||
String name;
|
||||
boolean disposing = false;
|
||||
boolean playing = false;
|
||||
boolean show = true;
|
||||
|
||||
MazePlayer(Game main_) {
|
||||
this(main_, String.valueOf((char) (65 + rand.nextInt(26))));
|
||||
Vector3 pos = new Vector3();
|
||||
Quaternion rot = new Quaternion();
|
||||
|
||||
MazePlayer(Game main_, boolean s) {
|
||||
this(main_, String.valueOf((char) (65 + rand.nextInt(26))), s);
|
||||
disposing = false;
|
||||
playing = false;
|
||||
}
|
||||
|
||||
MazePlayer(Game main_, String name) {
|
||||
MazePlayer(Game main_, String name, boolean s) {
|
||||
main = (AMazeIng) main_;
|
||||
|
||||
show = s;
|
||||
setName(name);
|
||||
buildModel();
|
||||
if (show)
|
||||
buildModel();
|
||||
}
|
||||
|
||||
public Vector3 getPos() {
|
||||
return instance.transform.getTranslation(new Vector3());
|
||||
return pos;
|
||||
}
|
||||
|
||||
public Quaternion getRotation() {
|
||||
return rot;
|
||||
}
|
||||
|
||||
public void setPlaying() {
|
||||
disposing = false;
|
||||
playing = true;
|
||||
}
|
||||
|
||||
public void setPos(Vector3 v) {
|
||||
|
@ -64,8 +77,11 @@ public abstract class MazePlayer {
|
|||
}
|
||||
|
||||
public void setTransform(float x, float y, float z, float i, float j, float k, float l) {
|
||||
if (!disposing)
|
||||
instance.transform.set(x, y, z, i, j, k, l);
|
||||
if (!disposing ) {
|
||||
pos.set(x, y, z);
|
||||
rot.set(i, j, k, l);
|
||||
if(show) instance.transform.set(x, y, z, i, j, k, l);
|
||||
}
|
||||
}
|
||||
|
||||
public void setName(String name_) {
|
||||
|
@ -77,9 +93,10 @@ public abstract class MazePlayer {
|
|||
}
|
||||
|
||||
public void render(ModelBatch b, Environment e) {
|
||||
if (!disposing) {
|
||||
if (!disposing && playing) {
|
||||
update();
|
||||
b.render(instance, e);
|
||||
if (show)
|
||||
b.render(instance, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,6 +113,11 @@ public abstract class MazePlayer {
|
|||
}
|
||||
|
||||
public void dispose() {
|
||||
playing =false;
|
||||
}
|
||||
|
||||
public boolean isPlaying() {
|
||||
return playing;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class MazePlayerLocal extends MazePlayer {
|
|||
|
||||
public MazePlayerLocal(Game main_, int up_, int down_, int sx_, int dx_, float startx, float starty, float startz,
|
||||
String name) {
|
||||
super(main_, name);
|
||||
super(main_, name, true);
|
||||
this.kup = up_;
|
||||
this.kdown = down_;
|
||||
this.ksx = sx_;
|
||||
|
@ -72,7 +72,7 @@ public class MazePlayerLocal extends MazePlayer {
|
|||
}
|
||||
|
||||
public MazePlayerLocal(Game main_, Controller ctrl_, float startx, float starty, float startz, String name) {
|
||||
super(main_);
|
||||
super(main_, true);
|
||||
this.ctrl = ctrl_;
|
||||
|
||||
this.startx = startx;
|
||||
|
@ -129,28 +129,29 @@ public class MazePlayerLocal extends MazePlayer {
|
|||
// And fetch the new transformation of the character (this will make the model
|
||||
// be rendered correctly)
|
||||
ghostObject.getWorldTransform(characterTransform);
|
||||
|
||||
if (main.gameManager.client.socket != null && main.gameManager.client.socket.isConnected()) {
|
||||
main.gameManager.client.sendMessagetoServer(characterTransform.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
inputs();
|
||||
main.client.updateLocalPlayer(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPos(Vector3 v) {
|
||||
if (!disposing)
|
||||
this.setPos(v.x, v.y, v.z);
|
||||
|
||||
this.setPos(v.x, v.y, v.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPos(float x, float y, float z) {
|
||||
if (!disposing)
|
||||
setTransform(x, y, z, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTransform(float x, float y, float z, float i, float j, float k, float l) {
|
||||
if (!disposing) {
|
||||
characterTransform.set(x, y, z, 0, 0, 0, 0);
|
||||
characterTransform.set(x, y, z, i, j, k, l);
|
||||
ghostObject.setWorldTransform(characterTransform);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.emamaker.amazeing.player;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.badlogic.gdx.Game;
|
||||
import com.emamaker.amazeing.AMazeIng;
|
||||
|
@ -14,18 +13,18 @@ public class MazePlayerRemote extends MazePlayer{
|
|||
|
||||
String name;
|
||||
AMazeIng main;
|
||||
UUID uuid;
|
||||
//UUID is stored a string, for kryonet ease of use
|
||||
public String uuid;
|
||||
|
||||
boolean disposing = false;
|
||||
|
||||
public MazePlayerRemote(Game main_, UUID u) {
|
||||
super(main_);
|
||||
uuid = u;
|
||||
public MazePlayerRemote(Game main_, String u) {
|
||||
this(main_, u, true);
|
||||
}
|
||||
|
||||
public void updateRemoteTransform(String s) {
|
||||
float x = 0, y = 0, z = 0, i = 0, j = 0, k = 0, l = 0;
|
||||
setTransform(x, y, z, i, j, k, l);
|
||||
public MazePlayerRemote(Game main_, String u, boolean b) {
|
||||
super(main_, b);
|
||||
uuid = u;
|
||||
}
|
||||
|
||||
public void setName(String name_) {
|
||||
|
@ -36,10 +35,6 @@ public class MazePlayerRemote extends MazePlayer{
|
|||
return name;
|
||||
}
|
||||
|
||||
public void setPlaying() {
|
||||
disposing = false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
|
|
|
@ -46,7 +46,7 @@ public class ServerJoinScreen implements Screen {
|
|||
@Override
|
||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
|
||||
hide();
|
||||
uiManager.main.gameManager.client.stop();
|
||||
uiManager.main.client.stop();
|
||||
uiManager.main.setScreen(uiManager.titleScreen);
|
||||
return true;
|
||||
}
|
||||
|
@ -62,11 +62,11 @@ public class ServerJoinScreen implements Screen {
|
|||
@Override
|
||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
|
||||
try {
|
||||
uiManager.main.gameManager.client.start(srvIp.getText(), Integer.valueOf(srvPort.getText()));
|
||||
}catch(Exception e) {
|
||||
uiManager.main.client.start(srvIp.getText(), Integer.valueOf(srvPort.getText()));
|
||||
} catch (Exception e) {
|
||||
System.out.println("Please input a valid ip address and port");
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -46,7 +46,7 @@ public class ServerLaunchScreen implements Screen {
|
|||
@Override
|
||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
|
||||
hide();
|
||||
uiManager.main.gameManager.server.stop();
|
||||
uiManager.main.server.stop();
|
||||
uiManager.main.setScreen(uiManager.titleScreen);
|
||||
return true;
|
||||
}
|
||||
|
@ -61,14 +61,14 @@ public class ServerLaunchScreen implements Screen {
|
|||
connectBtn.addListener(new InputListener() {
|
||||
@Override
|
||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
|
||||
uiManager.main.gameManager.server.startServer(Integer.valueOf(srvPort.getText()));
|
||||
uiManager.main.server.startServer(Integer.valueOf(srvPort.getText()));
|
||||
return true;
|
||||
}
|
||||
});
|
||||
gameBtn.addListener(new InputListener() {
|
||||
@Override
|
||||
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
|
||||
uiManager.main.gameManager.server.startGame();
|
||||
uiManager.main.server.startGame();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,7 @@
|
|||
# Temporary Files
|
||||
*~
|
||||
.*.swp
|
||||
.DS_STORE
|
||||
|
||||
bin/
|
||||
target/
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,247 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.chat;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.DefaultListSelectionModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import com.esotericsoftware.kryonet.Client;
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
import com.esotericsoftware.kryonet.examples.chat.Network.ChatMessage;
|
||||
import com.esotericsoftware.kryonet.examples.chat.Network.RegisterName;
|
||||
import com.esotericsoftware.kryonet.examples.chat.Network.UpdateNames;
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
|
||||
public class ChatClient {
|
||||
ChatFrame chatFrame;
|
||||
Client client;
|
||||
String name;
|
||||
|
||||
public ChatClient () {
|
||||
client = new Client();
|
||||
client.start();
|
||||
|
||||
// For consistency, the classes to be sent over the network are
|
||||
// registered by the same method for both the client and server.
|
||||
Network.register(client);
|
||||
|
||||
client.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
RegisterName registerName = new RegisterName();
|
||||
registerName.name = name;
|
||||
client.sendTCP(registerName);
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof UpdateNames) {
|
||||
UpdateNames updateNames = (UpdateNames)object;
|
||||
chatFrame.setNames(updateNames.names);
|
||||
return;
|
||||
}
|
||||
|
||||
if (object instanceof ChatMessage) {
|
||||
ChatMessage chatMessage = (ChatMessage)object;
|
||||
chatFrame.addMessage(chatMessage.text);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnected (Connection connection) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run () {
|
||||
// Closing the frame calls the close listener which will stop the client's update thread.
|
||||
chatFrame.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Request the host from the user.
|
||||
String input = (String)JOptionPane.showInputDialog(null, "Host:", "Connect to chat server", JOptionPane.QUESTION_MESSAGE,
|
||||
null, null, "localhost");
|
||||
if (input == null || input.trim().length() == 0) System.exit(1);
|
||||
final String host = input.trim();
|
||||
|
||||
// Request the user's name.
|
||||
input = (String)JOptionPane.showInputDialog(null, "Name:", "Connect to chat server", JOptionPane.QUESTION_MESSAGE, null,
|
||||
null, "Test");
|
||||
if (input == null || input.trim().length() == 0) System.exit(1);
|
||||
name = input.trim();
|
||||
|
||||
// All the ugly Swing stuff is hidden in ChatFrame so it doesn't clutter the KryoNet example code.
|
||||
chatFrame = new ChatFrame(host);
|
||||
// This listener is called when the send button is clicked.
|
||||
chatFrame.setSendListener(new Runnable() {
|
||||
public void run () {
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.text = chatFrame.getSendText();
|
||||
client.sendTCP(chatMessage);
|
||||
}
|
||||
});
|
||||
// This listener is called when the chat window is closed.
|
||||
chatFrame.setCloseListener(new Runnable() {
|
||||
public void run () {
|
||||
client.stop();
|
||||
}
|
||||
});
|
||||
chatFrame.setVisible(true);
|
||||
|
||||
// We'll do the connect on a new thread so the ChatFrame can show a progress bar.
|
||||
// Connecting to localhost is usually so fast you won't see the progress bar.
|
||||
new Thread("Connect") {
|
||||
public void run () {
|
||||
try {
|
||||
client.connect(5000, host, Network.port);
|
||||
// Server communication after connection can go here, or in Listener#connected().
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
static private class ChatFrame extends JFrame {
|
||||
CardLayout cardLayout;
|
||||
JProgressBar progressBar;
|
||||
JList messageList;
|
||||
JTextField sendText;
|
||||
JButton sendButton;
|
||||
JList nameList;
|
||||
|
||||
public ChatFrame (String host) {
|
||||
super("Chat Client");
|
||||
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
setSize(640, 200);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
Container contentPane = getContentPane();
|
||||
cardLayout = new CardLayout();
|
||||
contentPane.setLayout(cardLayout);
|
||||
{
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
contentPane.add(panel, "progress");
|
||||
panel.add(new JLabel("Connecting to " + host + "..."));
|
||||
{
|
||||
panel.add(progressBar = new JProgressBar(), BorderLayout.SOUTH);
|
||||
progressBar.setIndeterminate(true);
|
||||
}
|
||||
}
|
||||
{
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
contentPane.add(panel, "chat");
|
||||
{
|
||||
JPanel topPanel = new JPanel(new GridLayout(1, 2));
|
||||
panel.add(topPanel);
|
||||
{
|
||||
topPanel.add(new JScrollPane(messageList = new JList()));
|
||||
messageList.setModel(new DefaultListModel());
|
||||
}
|
||||
{
|
||||
topPanel.add(new JScrollPane(nameList = new JList()));
|
||||
nameList.setModel(new DefaultListModel());
|
||||
}
|
||||
DefaultListSelectionModel disableSelections = new DefaultListSelectionModel() {
|
||||
public void setSelectionInterval (int index0, int index1) {
|
||||
}
|
||||
};
|
||||
messageList.setSelectionModel(disableSelections);
|
||||
nameList.setSelectionModel(disableSelections);
|
||||
}
|
||||
{
|
||||
JPanel bottomPanel = new JPanel(new GridBagLayout());
|
||||
panel.add(bottomPanel, BorderLayout.SOUTH);
|
||||
bottomPanel.add(sendText = new JTextField(), new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.CENTER,
|
||||
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
|
||||
bottomPanel.add(sendButton = new JButton("Send"), new GridBagConstraints(1, 0, 1, 1, 0, 0,
|
||||
GridBagConstraints.CENTER, 0, new Insets(0, 0, 0, 0), 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
sendText.addActionListener(new ActionListener() {
|
||||
public void actionPerformed (ActionEvent e) {
|
||||
sendButton.doClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setSendListener (final Runnable listener) {
|
||||
sendButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed (ActionEvent evt) {
|
||||
if (getSendText().length() == 0) return;
|
||||
listener.run();
|
||||
sendText.setText("");
|
||||
sendText.requestFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setCloseListener (final Runnable listener) {
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosed (WindowEvent evt) {
|
||||
listener.run();
|
||||
}
|
||||
|
||||
public void windowActivated (WindowEvent evt) {
|
||||
sendText.requestFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String getSendText () {
|
||||
return sendText.getText().trim();
|
||||
}
|
||||
|
||||
public void setNames (final String[] names) {
|
||||
// This listener is run on the client's update thread, which was started by client.start().
|
||||
// We must be careful to only interact with Swing components on the Swing event thread.
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run () {
|
||||
cardLayout.show(getContentPane(), "chat");
|
||||
DefaultListModel model = (DefaultListModel)nameList.getModel();
|
||||
model.removeAllElements();
|
||||
for (String name : names)
|
||||
model.addElement(name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void addMessage (final String message) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run () {
|
||||
DefaultListModel model = (DefaultListModel)messageList.getModel();
|
||||
model.addElement(message);
|
||||
messageList.ensureIndexIsVisible(model.size() - 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void main (String[] args) {
|
||||
Log.set(Log.LEVEL_DEBUG);
|
||||
new ChatClient();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.chat;
|
||||
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
import com.esotericsoftware.kryonet.Server;
|
||||
import com.esotericsoftware.kryonet.examples.chat.Network.ChatMessage;
|
||||
import com.esotericsoftware.kryonet.examples.chat.Network.RegisterName;
|
||||
import com.esotericsoftware.kryonet.examples.chat.Network.UpdateNames;
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
|
||||
public class ChatServer {
|
||||
Server server;
|
||||
|
||||
public ChatServer () throws IOException {
|
||||
server = new Server() {
|
||||
protected Connection newConnection () {
|
||||
// By providing our own connection implementation, we can store per
|
||||
// connection state without a connection ID to state look up.
|
||||
return new ChatConnection();
|
||||
}
|
||||
};
|
||||
|
||||
// For consistency, the classes to be sent over the network are
|
||||
// registered by the same method for both the client and server.
|
||||
Network.register(server);
|
||||
|
||||
server.addListener(new Listener() {
|
||||
public void received (Connection c, Object object) {
|
||||
// We know all connections for this server are actually ChatConnections.
|
||||
ChatConnection connection = (ChatConnection)c;
|
||||
|
||||
if (object instanceof RegisterName) {
|
||||
// Ignore the object if a client has already registered a name. This is
|
||||
// impossible with our client, but a hacker could send messages at any time.
|
||||
if (connection.name != null) return;
|
||||
// Ignore the object if the name is invalid.
|
||||
String name = ((RegisterName)object).name;
|
||||
if (name == null) return;
|
||||
name = name.trim();
|
||||
if (name.length() == 0) return;
|
||||
// Store the name on the connection.
|
||||
connection.name = name;
|
||||
// Send a "connected" message to everyone except the new client.
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.text = name + " connected.";
|
||||
server.sendToAllExceptTCP(connection.getID(), chatMessage);
|
||||
// Send everyone a new list of connection names.
|
||||
updateNames();
|
||||
return;
|
||||
}
|
||||
|
||||
if (object instanceof ChatMessage) {
|
||||
// Ignore the object if a client tries to chat before registering a name.
|
||||
if (connection.name == null) return;
|
||||
ChatMessage chatMessage = (ChatMessage)object;
|
||||
// Ignore the object if the chat message is invalid.
|
||||
String message = chatMessage.text;
|
||||
if (message == null) return;
|
||||
message = message.trim();
|
||||
if (message.length() == 0) return;
|
||||
// Prepend the connection's name and send to everyone.
|
||||
chatMessage.text = connection.name + ": " + message;
|
||||
server.sendToAllTCP(chatMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnected (Connection c) {
|
||||
ChatConnection connection = (ChatConnection)c;
|
||||
if (connection.name != null) {
|
||||
// Announce to everyone that someone (with a registered name) has left.
|
||||
ChatMessage chatMessage = new ChatMessage();
|
||||
chatMessage.text = connection.name + " disconnected.";
|
||||
server.sendToAllTCP(chatMessage);
|
||||
updateNames();
|
||||
}
|
||||
}
|
||||
});
|
||||
server.bind(Network.port);
|
||||
server.start();
|
||||
|
||||
// Open a window to provide an easy way to stop the server.
|
||||
JFrame frame = new JFrame("Chat Server");
|
||||
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosed (WindowEvent evt) {
|
||||
server.stop();
|
||||
}
|
||||
});
|
||||
frame.getContentPane().add(new JLabel("Close to stop the chat server."));
|
||||
frame.setSize(320, 200);
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
void updateNames () {
|
||||
// Collect the names for each connection.
|
||||
Connection[] connections = server.getConnections();
|
||||
ArrayList names = new ArrayList(connections.length);
|
||||
for (int i = connections.length - 1; i >= 0; i--) {
|
||||
ChatConnection connection = (ChatConnection)connections[i];
|
||||
names.add(connection.name);
|
||||
}
|
||||
// Send the names to everyone.
|
||||
UpdateNames updateNames = new UpdateNames();
|
||||
updateNames.names = (String[])names.toArray(new String[names.size()]);
|
||||
server.sendToAllTCP(updateNames);
|
||||
}
|
||||
|
||||
// This holds per connection state.
|
||||
static class ChatConnection extends Connection {
|
||||
public String name;
|
||||
}
|
||||
|
||||
public static void main (String[] args) throws IOException {
|
||||
Log.set(Log.LEVEL_DEBUG);
|
||||
new ChatServer();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.chat;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryonet.EndPoint;
|
||||
|
||||
// This class is a convenient place to keep things common to both the client and server.
|
||||
public class Network {
|
||||
static public final int port = 54555;
|
||||
|
||||
// This registers objects that are going to be sent over the network.
|
||||
static public void register (EndPoint endPoint) {
|
||||
Kryo kryo = endPoint.getKryo();
|
||||
kryo.register(RegisterName.class);
|
||||
kryo.register(String[].class);
|
||||
kryo.register(UpdateNames.class);
|
||||
kryo.register(ChatMessage.class);
|
||||
}
|
||||
|
||||
static public class RegisterName {
|
||||
public String name;
|
||||
}
|
||||
|
||||
static public class UpdateNames {
|
||||
public String[] names;
|
||||
}
|
||||
|
||||
static public class ChatMessage {
|
||||
public String text;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.chatrmi;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.CardLayout;
|
||||
import java.awt.Container;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.DefaultListSelectionModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import com.esotericsoftware.kryonet.Client;
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
import com.esotericsoftware.kryonet.rmi.ObjectSpace;
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
|
||||
// This class is the client for a simple chat client/server example that uses RMI.
|
||||
// It is recommended to review the non-RMI chat example first.
|
||||
// While this example uses only RMI, RMI can be mixed with non-RMI KryoNet usage.
|
||||
// RMI has more overhead (usually 4 bytes) then just sending an object.
|
||||
public class ChatRmiClient {
|
||||
ChatFrame chatFrame;
|
||||
Client client;
|
||||
IPlayer player;
|
||||
|
||||
public ChatRmiClient () {
|
||||
client = new Client();
|
||||
client.start();
|
||||
|
||||
// Register the classes that will be sent over the network.
|
||||
Network.register(client);
|
||||
|
||||
// Get the Player on the other end of the connection.
|
||||
// This allows the client to call methods on the server.
|
||||
player = ObjectSpace.getRemoteObject(client, Network.PLAYER, IPlayer.class);
|
||||
|
||||
client.addListener(new Listener() {
|
||||
public void disconnected (Connection connection) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run () {
|
||||
// Closing the frame calls the close listener which will stop the client's update thread.
|
||||
chatFrame.dispose();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Request the host from the user.
|
||||
String input = (String)JOptionPane.showInputDialog(null, "Host:", "Connect to chat server", JOptionPane.QUESTION_MESSAGE,
|
||||
null, null, "localhost");
|
||||
if (input == null || input.trim().length() == 0) System.exit(1);
|
||||
final String host = input.trim();
|
||||
|
||||
// Request the user's name.
|
||||
input = (String)JOptionPane.showInputDialog(null, "Name:", "Connect to chat server", JOptionPane.QUESTION_MESSAGE, null,
|
||||
null, "Test");
|
||||
if (input == null || input.trim().length() == 0) System.exit(1);
|
||||
final String name = input.trim();
|
||||
|
||||
// The chat frame contains all the Swing stuff.
|
||||
chatFrame = new ChatFrame(host);
|
||||
// Register the chat frame so the server can call methods on it.
|
||||
new ObjectSpace(client).register(Network.CHAT_FRAME, chatFrame);
|
||||
// This listener is called when the send button is clicked.
|
||||
chatFrame.setSendListener(new Runnable() {
|
||||
public void run () {
|
||||
player.sendMessage(chatFrame.getSendText());
|
||||
}
|
||||
});
|
||||
// This listener is called when the chat window is closed.
|
||||
chatFrame.setCloseListener(new Runnable() {
|
||||
public void run () {
|
||||
client.stop();
|
||||
}
|
||||
});
|
||||
chatFrame.setVisible(true);
|
||||
|
||||
// We'll do the connect on a new thread so the ChatFrame can show a progress bar.
|
||||
// Connecting to localhost is usually so fast you won't see the progress bar.
|
||||
new Thread("Connect") {
|
||||
public void run () {
|
||||
try {
|
||||
client.connect(5000, host, Network.port);
|
||||
// Server communication after connection can go here, or in Listener#connected().
|
||||
player.registerName(name);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
// This is the JFrame for the client. It implments IChatFrame so the server can call methods on it.
|
||||
static private class ChatFrame extends JFrame implements IChatFrame {
|
||||
CardLayout cardLayout;
|
||||
JProgressBar progressBar;
|
||||
JList messageList;
|
||||
JTextField sendText;
|
||||
JButton sendButton;
|
||||
JList nameList;
|
||||
|
||||
public ChatFrame (String host) {
|
||||
super("Chat RMI Client");
|
||||
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
setSize(640, 200);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
Container contentPane = getContentPane();
|
||||
cardLayout = new CardLayout();
|
||||
contentPane.setLayout(cardLayout);
|
||||
{
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
contentPane.add(panel, "progress");
|
||||
panel.add(new JLabel("Connecting to " + host + "..."));
|
||||
{
|
||||
panel.add(progressBar = new JProgressBar(), BorderLayout.SOUTH);
|
||||
progressBar.setIndeterminate(true);
|
||||
}
|
||||
}
|
||||
{
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
contentPane.add(panel, "chat");
|
||||
{
|
||||
JPanel topPanel = new JPanel(new GridLayout(1, 2));
|
||||
panel.add(topPanel);
|
||||
{
|
||||
topPanel.add(new JScrollPane(messageList = new JList()));
|
||||
messageList.setModel(new DefaultListModel());
|
||||
}
|
||||
{
|
||||
topPanel.add(new JScrollPane(nameList = new JList()));
|
||||
nameList.setModel(new DefaultListModel());
|
||||
}
|
||||
DefaultListSelectionModel disableSelections = new DefaultListSelectionModel() {
|
||||
public void setSelectionInterval (int index0, int index1) {
|
||||
}
|
||||
};
|
||||
messageList.setSelectionModel(disableSelections);
|
||||
nameList.setSelectionModel(disableSelections);
|
||||
}
|
||||
{
|
||||
JPanel bottomPanel = new JPanel(new GridBagLayout());
|
||||
panel.add(bottomPanel, BorderLayout.SOUTH);
|
||||
bottomPanel.add(sendText = new JTextField(), new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.CENTER,
|
||||
GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
|
||||
bottomPanel.add(sendButton = new JButton("Send"), new GridBagConstraints(1, 0, 1, 1, 0, 0,
|
||||
GridBagConstraints.CENTER, 0, new Insets(0, 0, 0, 0), 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
sendText.addActionListener(new ActionListener() {
|
||||
public void actionPerformed (ActionEvent e) {
|
||||
sendButton.doClick();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setSendListener (final Runnable listener) {
|
||||
sendButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed (ActionEvent evt) {
|
||||
if (getSendText().length() == 0) return;
|
||||
listener.run();
|
||||
sendText.setText("");
|
||||
sendText.requestFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setCloseListener (final Runnable listener) {
|
||||
addWindowListener(new WindowAdapter() {
|
||||
public void windowClosed (WindowEvent evt) {
|
||||
listener.run();
|
||||
}
|
||||
|
||||
public void windowActivated (WindowEvent evt) {
|
||||
sendText.requestFocus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String getSendText () {
|
||||
return sendText.getText().trim();
|
||||
}
|
||||
|
||||
// The server calls this method as needed.
|
||||
public void setNames (final String[] names) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run () {
|
||||
cardLayout.show(getContentPane(), "chat");
|
||||
DefaultListModel model = (DefaultListModel)nameList.getModel();
|
||||
model.removeAllElements();
|
||||
for (String name : names)
|
||||
model.addElement(name);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// The server calls this method as needed.
|
||||
public void addMessage (final String message) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run () {
|
||||
DefaultListModel model = (DefaultListModel)messageList.getModel();
|
||||
model.addElement(message);
|
||||
messageList.ensureIndexIsVisible(model.size() - 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void main (String[] args) {
|
||||
Log.set(Log.LEVEL_DEBUG);
|
||||
new ChatRmiClient();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.chatrmi;
|
||||
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
import com.esotericsoftware.kryonet.Server;
|
||||
import com.esotericsoftware.kryonet.rmi.ObjectSpace;
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
|
||||
// This class is the server for a simple chat client/server example that uses RMI.
|
||||
// It is recommended to review the non-RMI chat example first.
|
||||
// While this example uses only RMI, RMI can be mixed with non-RMI KryoNet usage.
|
||||
// RMI has more overhead (usually 4 bytes) then just sending an object.
|
||||
public class ChatRmiServer {
|
||||
Server server;
|
||||
ArrayList<Player> players = new ArrayList();
|
||||
|
||||
public ChatRmiServer () throws IOException {
|
||||
server = new Server() {
|
||||
protected Connection newConnection () {
|
||||
// Each connection represents a player and has fields
|
||||
// to store state and methods to perform actions.
|
||||
Player player = new Player();
|
||||
players.add(player);
|
||||
return player;
|
||||
}
|
||||
};
|
||||
|
||||
// Register the classes that will be sent over the network.
|
||||
Network.register(server);
|
||||
|
||||
server.addListener(new Listener() {
|
||||
public void disconnected (Connection connection) {
|
||||
Player player = (Player)connection;
|
||||
players.remove(player);
|
||||
if (player.name != null) {
|
||||
// Announce to everyone that someone (with a registered name) has left.
|
||||
String message = player.name + " disconnected.";
|
||||
for (Player p : players)
|
||||
p.frame.addMessage(message);
|
||||
updateNames();
|
||||
}
|
||||
}
|
||||
});
|
||||
server.bind(Network.port);
|
||||
server.start();
|
||||
|
||||
// Open a window to provide an easy way to stop the server.
|
||||
JFrame frame = new JFrame("Chat RMI Server");
|
||||
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
public void windowClosed (WindowEvent evt) {
|
||||
server.stop();
|
||||
}
|
||||
});
|
||||
frame.getContentPane().add(new JLabel("Close to stop the chat server."));
|
||||
frame.setSize(320, 200);
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
void updateNames () {
|
||||
// Collect the names of each player.
|
||||
ArrayList namesList = new ArrayList(players.size());
|
||||
for (Player player : players)
|
||||
if (player.name != null) namesList.add(player.name);
|
||||
// Set the names on everyone's chat frame.
|
||||
String[] names = (String[])namesList.toArray(new String[namesList.size()]);
|
||||
for (Player player : players)
|
||||
player.frame.setNames(names);
|
||||
}
|
||||
|
||||
class Player extends Connection implements IPlayer {
|
||||
IChatFrame frame;
|
||||
String name;
|
||||
|
||||
public Player () {
|
||||
// Each connection has an ObjectSpace containing the Player.
|
||||
// This allows the other end of the connection to call methods on the Player.
|
||||
new ObjectSpace(this).register(Network.PLAYER, this);
|
||||
// Get the ChatFrame on the other end of the connection.
|
||||
// This allows the server to call methods on the client.
|
||||
frame = ObjectSpace.getRemoteObject(this, Network.CHAT_FRAME, IChatFrame.class);
|
||||
}
|
||||
|
||||
public void registerName (String name) {
|
||||
// Do nothing if the player already registered a name.
|
||||
if (this.name != null) return;
|
||||
// Do nothing if the name is invalid.
|
||||
if (name == null) return;
|
||||
name = name.trim();
|
||||
if (name.length() == 0) return;
|
||||
// Store the player's name.
|
||||
this.name = name;
|
||||
// Add a "connected" message to everyone's chat frame, except the new player.
|
||||
String message = name + " connected.";
|
||||
for (Player player : players)
|
||||
if (player != this) player.frame.addMessage(message);
|
||||
// Set the names on everyone's chat frame.
|
||||
updateNames();
|
||||
}
|
||||
|
||||
public void sendMessage (String message) {
|
||||
// Do nothing if a player tries to chat before registering a name.
|
||||
if (this.name == null) return;
|
||||
// Do nothing if the chat message is invalid.
|
||||
if (message == null) return;
|
||||
message = message.trim();
|
||||
if (message.length() == 0) return;
|
||||
// Prepend the player's name and add to everyone's chat frame.
|
||||
message = this.name + ": " + message;
|
||||
for (Player player : players)
|
||||
player.frame.addMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
public static void main (String[] args) throws IOException {
|
||||
Log.set(Log.LEVEL_DEBUG);
|
||||
new ChatRmiServer();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.chatrmi;
|
||||
|
||||
// This class represents the chat window on the client.
|
||||
public interface IChatFrame {
|
||||
public void addMessage (String message);
|
||||
|
||||
public void setNames (String[] names);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.chatrmi;
|
||||
|
||||
// This class represents a player on the server.
|
||||
public interface IPlayer {
|
||||
public void registerName (String name);
|
||||
|
||||
public void sendMessage (String message);
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.chatrmi;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryonet.EndPoint;
|
||||
import com.esotericsoftware.kryonet.rmi.ObjectSpace;
|
||||
|
||||
public class Network {
|
||||
static public final int port = 54777;
|
||||
|
||||
// These IDs are used to register objects in ObjectSpaces.
|
||||
static public final short PLAYER = 1;
|
||||
static public final short CHAT_FRAME = 2;
|
||||
|
||||
// This registers objects that are going to be sent over the network.
|
||||
static public void register (EndPoint endPoint) {
|
||||
Kryo kryo = endPoint.getKryo();
|
||||
// This must be called in order to use ObjectSpaces.
|
||||
ObjectSpace.registerClasses(kryo);
|
||||
// The interfaces that will be used as remote objects must be registered.
|
||||
kryo.register(IPlayer.class);
|
||||
kryo.register(IChatFrame.class);
|
||||
// The classes of all method parameters and return values
|
||||
// for remote objects must also be registered.
|
||||
kryo.register(String[].class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.position;
|
||||
|
||||
public class Character {
|
||||
public String name;
|
||||
public String otherStuff;
|
||||
public int id, x, y;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.position;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryonet.EndPoint;
|
||||
|
||||
// This class is a convenient place to keep things common to both the client and server.
|
||||
public class Network {
|
||||
static public final int port = 54555;
|
||||
|
||||
// This registers objects that are going to be sent over the network.
|
||||
static public void register (EndPoint endPoint) {
|
||||
Kryo kryo = endPoint.getKryo();
|
||||
kryo.register(Login.class);
|
||||
kryo.register(RegistrationRequired.class);
|
||||
kryo.register(Register.class);
|
||||
kryo.register(AddCharacter.class);
|
||||
kryo.register(UpdateCharacter.class);
|
||||
kryo.register(RemoveCharacter.class);
|
||||
kryo.register(Character.class);
|
||||
kryo.register(MoveCharacter.class);
|
||||
}
|
||||
|
||||
static public class Login {
|
||||
public String name;
|
||||
}
|
||||
|
||||
static public class RegistrationRequired {
|
||||
}
|
||||
|
||||
static public class Register {
|
||||
public String name;
|
||||
public String otherStuff;
|
||||
}
|
||||
|
||||
static public class UpdateCharacter {
|
||||
public int id, x, y;
|
||||
}
|
||||
|
||||
static public class AddCharacter {
|
||||
public Character character;
|
||||
}
|
||||
|
||||
static public class RemoveCharacter {
|
||||
public int id;
|
||||
}
|
||||
|
||||
static public class MoveCharacter {
|
||||
public int x, y;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.position;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import com.esotericsoftware.kryonet.Client;
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
import com.esotericsoftware.kryonet.Listener.ThreadedListener;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.AddCharacter;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.Login;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.MoveCharacter;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.Register;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.RegistrationRequired;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.RemoveCharacter;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.UpdateCharacter;
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
|
||||
public class PositionClient {
|
||||
UI ui;
|
||||
Client client;
|
||||
String name;
|
||||
|
||||
public PositionClient () {
|
||||
client = new Client();
|
||||
client.start();
|
||||
|
||||
// For consistency, the classes to be sent over the network are
|
||||
// registered by the same method for both the client and server.
|
||||
Network.register(client);
|
||||
|
||||
// ThreadedListener runs the listener methods on a different thread.
|
||||
client.addListener(new ThreadedListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof RegistrationRequired) {
|
||||
Register register = new Register();
|
||||
register.name = name;
|
||||
register.otherStuff = ui.inputOtherStuff();
|
||||
client.sendTCP(register);
|
||||
}
|
||||
|
||||
if (object instanceof AddCharacter) {
|
||||
AddCharacter msg = (AddCharacter)object;
|
||||
ui.addCharacter(msg.character);
|
||||
return;
|
||||
}
|
||||
|
||||
if (object instanceof UpdateCharacter) {
|
||||
ui.updateCharacter((UpdateCharacter)object);
|
||||
return;
|
||||
}
|
||||
|
||||
if (object instanceof RemoveCharacter) {
|
||||
RemoveCharacter msg = (RemoveCharacter)object;
|
||||
ui.removeCharacter(msg.id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnected (Connection connection) {
|
||||
System.exit(0);
|
||||
}
|
||||
}));
|
||||
|
||||
ui = new UI();
|
||||
|
||||
String host = ui.inputHost();
|
||||
try {
|
||||
client.connect(5000, host, Network.port);
|
||||
// Server communication after connection can go here, or in Listener#connected().
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
name = ui.inputName();
|
||||
Login login = new Login();
|
||||
login.name = name;
|
||||
client.sendTCP(login);
|
||||
|
||||
while (true) {
|
||||
int ch;
|
||||
try {
|
||||
ch = System.in.read();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
break;
|
||||
}
|
||||
|
||||
MoveCharacter msg = new MoveCharacter();
|
||||
switch (ch) {
|
||||
case 'w':
|
||||
msg.y = -1;
|
||||
break;
|
||||
case 's':
|
||||
msg.y = 1;
|
||||
break;
|
||||
case 'a':
|
||||
msg.x = -1;
|
||||
break;
|
||||
case 'd':
|
||||
msg.x = 1;
|
||||
break;
|
||||
default:
|
||||
msg = null;
|
||||
}
|
||||
if (msg != null) client.sendTCP(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static class UI {
|
||||
HashMap<Integer, Character> characters = new HashMap();
|
||||
|
||||
public String inputHost () {
|
||||
String input = (String)JOptionPane.showInputDialog(null, "Host:", "Connect to server", JOptionPane.QUESTION_MESSAGE,
|
||||
null, null, "localhost");
|
||||
if (input == null || input.trim().length() == 0) System.exit(1);
|
||||
return input.trim();
|
||||
}
|
||||
|
||||
public String inputName () {
|
||||
String input = (String)JOptionPane.showInputDialog(null, "Name:", "Connect to server", JOptionPane.QUESTION_MESSAGE,
|
||||
null, null, "Test");
|
||||
if (input == null || input.trim().length() == 0) System.exit(1);
|
||||
return input.trim();
|
||||
}
|
||||
|
||||
public String inputOtherStuff () {
|
||||
String input = (String)JOptionPane.showInputDialog(null, "Other Stuff:", "Create account", JOptionPane.QUESTION_MESSAGE,
|
||||
null, null, "other stuff");
|
||||
if (input == null || input.trim().length() == 0) System.exit(1);
|
||||
return input.trim();
|
||||
}
|
||||
|
||||
public void addCharacter (Character character) {
|
||||
characters.put(character.id, character);
|
||||
System.out.println(character.name + " added at " + character.x + ", " + character.y);
|
||||
}
|
||||
|
||||
public void updateCharacter (UpdateCharacter msg) {
|
||||
Character character = characters.get(msg.id);
|
||||
if (character == null) return;
|
||||
character.x = msg.x;
|
||||
character.y = msg.y;
|
||||
System.out.println(character.name + " moved to " + character.x + ", " + character.y);
|
||||
}
|
||||
|
||||
public void removeCharacter (int id) {
|
||||
Character character = characters.remove(id);
|
||||
if (character != null) System.out.println(character.name + " removed");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main (String[] args) {
|
||||
Log.set(Log.LEVEL_DEBUG);
|
||||
new PositionClient();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.examples.position;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
import com.esotericsoftware.kryonet.Server;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.AddCharacter;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.Login;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.MoveCharacter;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.Register;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.RegistrationRequired;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.RemoveCharacter;
|
||||
import com.esotericsoftware.kryonet.examples.position.Network.UpdateCharacter;
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
|
||||
public class PositionServer {
|
||||
Server server;
|
||||
HashSet<Character> loggedIn = new HashSet();
|
||||
|
||||
public PositionServer () throws IOException {
|
||||
server = new Server() {
|
||||
protected Connection newConnection () {
|
||||
// By providing our own connection implementation, we can store per
|
||||
// connection state without a connection ID to state look up.
|
||||
return new CharacterConnection();
|
||||
}
|
||||
};
|
||||
|
||||
// For consistency, the classes to be sent over the network are
|
||||
// registered by the same method for both the client and server.
|
||||
Network.register(server);
|
||||
|
||||
server.addListener(new Listener() {
|
||||
public void received (Connection c, Object object) {
|
||||
// We know all connections for this server are actually CharacterConnections.
|
||||
CharacterConnection connection = (CharacterConnection)c;
|
||||
Character character = connection.character;
|
||||
|
||||
if (object instanceof Login) {
|
||||
// Ignore if already logged in.
|
||||
if (character != null) return;
|
||||
|
||||
// Reject if the name is invalid.
|
||||
String name = ((Login)object).name;
|
||||
if (!isValid(name)) {
|
||||
c.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reject if already logged in.
|
||||
for (Character other : loggedIn) {
|
||||
if (other.name.equals(name)) {
|
||||
c.close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
character = loadCharacter(name);
|
||||
|
||||
// Reject if couldn't load character.
|
||||
if (character == null) {
|
||||
c.sendTCP(new RegistrationRequired());
|
||||
return;
|
||||
}
|
||||
|
||||
loggedIn(connection, character);
|
||||
return;
|
||||
}
|
||||
|
||||
if (object instanceof Register) {
|
||||
// Ignore if already logged in.
|
||||
if (character != null) return;
|
||||
|
||||
Register register = (Register)object;
|
||||
|
||||
// Reject if the login is invalid.
|
||||
if (!isValid(register.name)) {
|
||||
c.close();
|
||||
return;
|
||||
}
|
||||
if (!isValid(register.otherStuff)) {
|
||||
c.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// Reject if character alread exists.
|
||||
if (loadCharacter(register.name) != null) {
|
||||
c.close();
|
||||
return;
|
||||
}
|
||||
|
||||
character = new Character();
|
||||
character.name = register.name;
|
||||
character.otherStuff = register.otherStuff;
|
||||
character.x = 0;
|
||||
character.y = 0;
|
||||
if (!saveCharacter(character)) {
|
||||
c.close();
|
||||
return;
|
||||
}
|
||||
|
||||
loggedIn(connection, character);
|
||||
return;
|
||||
}
|
||||
|
||||
if (object instanceof MoveCharacter) {
|
||||
// Ignore if not logged in.
|
||||
if (character == null) return;
|
||||
|
||||
MoveCharacter msg = (MoveCharacter)object;
|
||||
|
||||
// Ignore if invalid move.
|
||||
if (Math.abs(msg.x) != 1 && Math.abs(msg.y) != 1) return;
|
||||
|
||||
character.x += msg.x;
|
||||
character.y += msg.y;
|
||||
if (!saveCharacter(character)) {
|
||||
connection.close();
|
||||
return;
|
||||
}
|
||||
|
||||
UpdateCharacter update = new UpdateCharacter();
|
||||
update.id = character.id;
|
||||
update.x = character.x;
|
||||
update.y = character.y;
|
||||
server.sendToAllTCP(update);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValid (String value) {
|
||||
if (value == null) return false;
|
||||
value = value.trim();
|
||||
if (value.length() == 0) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void disconnected (Connection c) {
|
||||
CharacterConnection connection = (CharacterConnection)c;
|
||||
if (connection.character != null) {
|
||||
loggedIn.remove(connection.character);
|
||||
|
||||
RemoveCharacter removeCharacter = new RemoveCharacter();
|
||||
removeCharacter.id = connection.character.id;
|
||||
server.sendToAllTCP(removeCharacter);
|
||||
}
|
||||
}
|
||||
});
|
||||
server.bind(Network.port);
|
||||
server.start();
|
||||
}
|
||||
|
||||
void loggedIn (CharacterConnection c, Character character) {
|
||||
c.character = character;
|
||||
|
||||
// Add existing characters to new logged in connection.
|
||||
for (Character other : loggedIn) {
|
||||
AddCharacter addCharacter = new AddCharacter();
|
||||
addCharacter.character = other;
|
||||
c.sendTCP(addCharacter);
|
||||
}
|
||||
|
||||
loggedIn.add(character);
|
||||
|
||||
// Add logged in character to all connections.
|
||||
AddCharacter addCharacter = new AddCharacter();
|
||||
addCharacter.character = character;
|
||||
server.sendToAllTCP(addCharacter);
|
||||
}
|
||||
|
||||
boolean saveCharacter (Character character) {
|
||||
File file = new File("characters", character.name.toLowerCase());
|
||||
file.getParentFile().mkdirs();
|
||||
|
||||
if (character.id == 0) {
|
||||
String[] children = file.getParentFile().list();
|
||||
if (children == null) return false;
|
||||
character.id = children.length + 1;
|
||||
}
|
||||
|
||||
DataOutputStream output = null;
|
||||
try {
|
||||
output = new DataOutputStream(new FileOutputStream(file));
|
||||
output.writeInt(character.id);
|
||||
output.writeUTF(character.otherStuff);
|
||||
output.writeInt(character.x);
|
||||
output.writeInt(character.y);
|
||||
return true;
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
} finally {
|
||||
try {
|
||||
output.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Character loadCharacter (String name) {
|
||||
File file = new File("characters", name.toLowerCase());
|
||||
if (!file.exists()) return null;
|
||||
DataInputStream input = null;
|
||||
try {
|
||||
input = new DataInputStream(new FileInputStream(file));
|
||||
Character character = new Character();
|
||||
character.id = input.readInt();
|
||||
character.name = name;
|
||||
character.otherStuff = input.readUTF();
|
||||
character.x = input.readInt();
|
||||
character.y = input.readInt();
|
||||
input.close();
|
||||
return character;
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
if (input != null) input.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This holds per connection state.
|
||||
static class CharacterConnection extends Connection {
|
||||
public Character character;
|
||||
}
|
||||
|
||||
public static void main (String[] args) throws IOException {
|
||||
Log.set(Log.LEVEL_DEBUG);
|
||||
new PositionServer();
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,10 @@
|
|||
Copyright (c) 2008, Nathan Sweet
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,4 @@
|
|||
version: 2.18
|
||||
---
|
||||
Build.build(project);
|
||||
Build.oneJAR(project);
|
|
@ -0,0 +1,500 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.CancelledKeyException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.security.AccessControlException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.DiscoverHost;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.RegisterTCP;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.RegisterUDP;
|
||||
|
||||
import static com.esotericsoftware.minlog.Log.*;
|
||||
|
||||
/** Represents a TCP and optionally a UDP connection to a {@link Server}.
|
||||
* @author Nathan Sweet <misc@n4te.com> */
|
||||
public class Client extends Connection implements EndPoint {
|
||||
static {
|
||||
try {
|
||||
// Needed for NIO selectors on Android 2.2.
|
||||
System.setProperty("java.net.preferIPv6Addresses", "false");
|
||||
} catch (AccessControlException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private final Serialization serialization;
|
||||
private Selector selector;
|
||||
private int emptySelects;
|
||||
private volatile boolean tcpRegistered, udpRegistered;
|
||||
private Object tcpRegistrationLock = new Object();
|
||||
private Object udpRegistrationLock = new Object();
|
||||
private volatile boolean shutdown;
|
||||
private final Object updateLock = new Object();
|
||||
private Thread updateThread;
|
||||
private int connectTimeout;
|
||||
private InetAddress connectHost;
|
||||
private int connectTcpPort;
|
||||
private int connectUdpPort;
|
||||
private boolean isClosed;
|
||||
|
||||
/** Creates a Client with a write buffer size of 8192 and an object buffer size of 2048. */
|
||||
public Client () {
|
||||
this(8192, 2048);
|
||||
}
|
||||
|
||||
/** @param writeBufferSize One buffer of this size is allocated. Objects are serialized to the write buffer where the bytes are
|
||||
* queued until they can be written to the TCP socket.
|
||||
* <p>
|
||||
* Normally the socket is writable and the bytes are written immediately. If the socket cannot be written to and
|
||||
* enough serialized objects are queued to overflow the buffer, then the connection will be closed.
|
||||
* <p>
|
||||
* The write buffer should be sized at least as large as the largest object that will be sent, plus some head room to
|
||||
* allow for some serialized objects to be queued in case the buffer is temporarily not writable. The amount of head
|
||||
* room needed is dependent upon the size of objects being sent and how often they are sent.
|
||||
* @param objectBufferSize One (using only TCP) or three (using both TCP and UDP) buffers of this size are allocated. These
|
||||
* buffers are used to hold the bytes for a single object graph until it can be sent over the network or
|
||||
* deserialized.
|
||||
* <p>
|
||||
* The object buffers should be sized at least as large as the largest object that will be sent or received. */
|
||||
public Client (int writeBufferSize, int objectBufferSize) {
|
||||
this(writeBufferSize, objectBufferSize, new KryoSerialization());
|
||||
}
|
||||
|
||||
public Client (int writeBufferSize, int objectBufferSize, Serialization serialization) {
|
||||
super();
|
||||
endPoint = this;
|
||||
|
||||
this.serialization = serialization;
|
||||
|
||||
initialize(serialization, writeBufferSize, objectBufferSize);
|
||||
|
||||
try {
|
||||
selector = Selector.open();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Error opening selector.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Serialization getSerialization () {
|
||||
return serialization;
|
||||
}
|
||||
|
||||
public Kryo getKryo () {
|
||||
return ((KryoSerialization)serialization).getKryo();
|
||||
}
|
||||
|
||||
/** Opens a TCP only client.
|
||||
* @see #connect(int, InetAddress, int, int) */
|
||||
public void connect (int timeout, String host, int tcpPort) throws IOException {
|
||||
connect(timeout, InetAddress.getByName(host), tcpPort, -1);
|
||||
}
|
||||
|
||||
/** Opens a TCP and UDP client.
|
||||
* @see #connect(int, InetAddress, int, int) */
|
||||
public void connect (int timeout, String host, int tcpPort, int udpPort) throws IOException {
|
||||
connect(timeout, InetAddress.getByName(host), tcpPort, udpPort);
|
||||
}
|
||||
|
||||
/** Opens a TCP only client.
|
||||
* @see #connect(int, InetAddress, int, int) */
|
||||
public void connect (int timeout, InetAddress host, int tcpPort) throws IOException {
|
||||
connect(timeout, host, tcpPort, -1);
|
||||
}
|
||||
|
||||
/** Opens a TCP and UDP client. Blocks until the connection is complete or the timeout is reached.
|
||||
* <p>
|
||||
* Because the framework must perform some minimal communication before the connection is considered successful,
|
||||
* {@link #update(int)} must be called on a separate thread during the connection process.
|
||||
* @throws IllegalStateException if called from the connection's update thread.
|
||||
* @throws IOException if the client could not be opened or connecting times out. */
|
||||
public void connect (int timeout, InetAddress host, int tcpPort, int udpPort) throws IOException {
|
||||
if (host == null) throw new IllegalArgumentException("host cannot be null.");
|
||||
if (Thread.currentThread() == getUpdateThread())
|
||||
throw new IllegalStateException("Cannot connect on the connection's update thread.");
|
||||
this.connectTimeout = timeout;
|
||||
this.connectHost = host;
|
||||
this.connectTcpPort = tcpPort;
|
||||
this.connectUdpPort = udpPort;
|
||||
close();
|
||||
if (INFO) {
|
||||
if (udpPort != -1)
|
||||
info("Connecting: " + host + ":" + tcpPort + "/" + udpPort);
|
||||
else
|
||||
info("Connecting: " + host + ":" + tcpPort);
|
||||
}
|
||||
id = -1;
|
||||
try {
|
||||
if (udpPort != -1) udp = new UdpConnection(serialization, tcp.readBuffer.capacity());
|
||||
|
||||
long endTime;
|
||||
synchronized (updateLock) {
|
||||
tcpRegistered = false;
|
||||
selector.wakeup();
|
||||
endTime = System.currentTimeMillis() + timeout;
|
||||
tcp.connect(selector, new InetSocketAddress(host, tcpPort), 5000);
|
||||
}
|
||||
|
||||
// Wait for RegisterTCP.
|
||||
synchronized (tcpRegistrationLock) {
|
||||
while (!tcpRegistered && System.currentTimeMillis() < endTime) {
|
||||
try {
|
||||
tcpRegistrationLock.wait(100);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
if (!tcpRegistered) {
|
||||
throw new SocketTimeoutException("Connected, but timed out during TCP registration.\n"
|
||||
+ "Note: Client#update must be called in a separate thread during connect.");
|
||||
}
|
||||
}
|
||||
|
||||
if (udpPort != -1) {
|
||||
InetSocketAddress udpAddress = new InetSocketAddress(host, udpPort);
|
||||
synchronized (updateLock) {
|
||||
udpRegistered = false;
|
||||
selector.wakeup();
|
||||
udp.connect(selector, udpAddress);
|
||||
}
|
||||
|
||||
// Wait for RegisterUDP reply.
|
||||
synchronized (udpRegistrationLock) {
|
||||
while (!udpRegistered && System.currentTimeMillis() < endTime) {
|
||||
RegisterUDP registerUDP = new RegisterUDP();
|
||||
registerUDP.connectionID = id;
|
||||
udp.send(this, registerUDP, udpAddress);
|
||||
try {
|
||||
udpRegistrationLock.wait(100);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
if (!udpRegistered)
|
||||
throw new SocketTimeoutException("Connected, but timed out during UDP registration: " + host + ":" + udpPort);
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
close();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
/** Calls {@link #connect(int, InetAddress, int) connect} with the values last passed to connect.
|
||||
* @throws IllegalStateException if connect has never been called. */
|
||||
public void reconnect () throws IOException {
|
||||
reconnect(connectTimeout);
|
||||
}
|
||||
|
||||
/** Calls {@link #connect(int, InetAddress, int) connect} with the specified timeout and the other values last passed to
|
||||
* connect.
|
||||
* @throws IllegalStateException if connect has never been called. */
|
||||
public void reconnect (int timeout) throws IOException {
|
||||
if (connectHost == null) throw new IllegalStateException("This client has never been connected.");
|
||||
connect(connectTimeout, connectHost, connectTcpPort, connectUdpPort);
|
||||
}
|
||||
|
||||
/** Reads or writes any pending data for this client. Multiple threads should not call this method at the same time.
|
||||
* @param timeout Wait for up to the specified milliseconds for data to be ready to process. May be zero to return immediately
|
||||
* if there is no data to process. */
|
||||
public void update (int timeout) throws IOException {
|
||||
updateThread = Thread.currentThread();
|
||||
synchronized (updateLock) { // Blocks to avoid a select while the selector is used to bind the server connection.
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
int select = 0;
|
||||
if (timeout > 0) {
|
||||
select = selector.select(timeout);
|
||||
} else {
|
||||
select = selector.selectNow();
|
||||
}
|
||||
if (select == 0) {
|
||||
emptySelects++;
|
||||
if (emptySelects == 100) {
|
||||
emptySelects = 0;
|
||||
// NIO freaks and returns immediately with 0 sometimes, so try to keep from hogging the CPU.
|
||||
long elapsedTime = System.currentTimeMillis() - startTime;
|
||||
try {
|
||||
if (elapsedTime < 25) Thread.sleep(25 - elapsedTime);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
emptySelects = 0;
|
||||
isClosed = false;
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
synchronized (keys) {
|
||||
for (Iterator<SelectionKey> iter = keys.iterator(); iter.hasNext();) {
|
||||
SelectionKey selectionKey = iter.next();
|
||||
iter.remove();
|
||||
try {
|
||||
int ops = selectionKey.readyOps();
|
||||
if ((ops & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
|
||||
if (selectionKey.attachment() == tcp) {
|
||||
while (true) {
|
||||
Object object = tcp.readObject(this);
|
||||
if (object == null) break;
|
||||
if (!tcpRegistered) {
|
||||
if (object instanceof RegisterTCP) {
|
||||
id = ((RegisterTCP)object).connectionID;
|
||||
synchronized (tcpRegistrationLock) {
|
||||
tcpRegistered = true;
|
||||
tcpRegistrationLock.notifyAll();
|
||||
if (TRACE) trace("kryonet", this + " received TCP: RegisterTCP");
|
||||
if (udp == null) setConnected(true);
|
||||
}
|
||||
if (udp == null) notifyConnected();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (udp != null && !udpRegistered) {
|
||||
if (object instanceof RegisterUDP) {
|
||||
synchronized (udpRegistrationLock) {
|
||||
udpRegistered = true;
|
||||
udpRegistrationLock.notifyAll();
|
||||
if (TRACE) trace("kryonet", this + " received UDP: RegisterUDP");
|
||||
if (DEBUG) {
|
||||
debug("kryonet", "Port " + udp.datagramChannel.socket().getLocalPort()
|
||||
+ "/UDP connected to: " + udp.connectedAddress);
|
||||
}
|
||||
setConnected(true);
|
||||
}
|
||||
notifyConnected();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!isConnected) continue;
|
||||
keepAlive();
|
||||
if (DEBUG) {
|
||||
String objectString = object == null ? "null" : object.getClass().getSimpleName();
|
||||
if (!(object instanceof FrameworkMessage)) {
|
||||
debug("kryonet", this + " received TCP: " + objectString);
|
||||
} else if (TRACE) {
|
||||
trace("kryonet", this + " received TCP: " + objectString);
|
||||
}
|
||||
}
|
||||
notifyReceived(object);
|
||||
}
|
||||
} else {
|
||||
if (udp.readFromAddress() == null) continue;
|
||||
Object object = udp.readObject(this);
|
||||
if (object == null) continue;
|
||||
keepAlive();
|
||||
if (DEBUG) {
|
||||
String objectString = object == null ? "null" : object.getClass().getSimpleName();
|
||||
debug("kryonet", this + " received UDP: " + objectString);
|
||||
}
|
||||
notifyReceived(object);
|
||||
}
|
||||
}
|
||||
if ((ops & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE) tcp.writeOperation();
|
||||
} catch (CancelledKeyException ignored) {
|
||||
// Connection is closed.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isConnected) {
|
||||
long time = System.currentTimeMillis();
|
||||
if (tcp.isTimedOut(time)) {
|
||||
if (DEBUG) debug("kryonet", this + " timed out.");
|
||||
close();
|
||||
} else {
|
||||
keepAlive();
|
||||
}
|
||||
if (isIdle()) notifyIdle();
|
||||
}
|
||||
}
|
||||
|
||||
void keepAlive () {
|
||||
if (!isConnected) return;
|
||||
long time = System.currentTimeMillis();
|
||||
if (tcp.needsKeepAlive(time)) sendTCP(FrameworkMessage.keepAlive);
|
||||
if (udp != null && udpRegistered && udp.needsKeepAlive(time)) sendUDP(FrameworkMessage.keepAlive);
|
||||
}
|
||||
|
||||
public void run () {
|
||||
if (TRACE) trace("kryonet", "Client thread started.");
|
||||
shutdown = false;
|
||||
while (!shutdown) {
|
||||
try {
|
||||
update(250);
|
||||
} catch (IOException ex) {
|
||||
if (TRACE) {
|
||||
if (isConnected)
|
||||
trace("kryonet", "Unable to update connection: " + this, ex);
|
||||
else
|
||||
trace("kryonet", "Unable to update connection.", ex);
|
||||
} else if (DEBUG) {
|
||||
if (isConnected)
|
||||
debug("kryonet", this + " update: " + ex.getMessage());
|
||||
else
|
||||
debug("kryonet", "Unable to update connection: " + ex.getMessage());
|
||||
}
|
||||
close();
|
||||
} catch (KryoNetException ex) {
|
||||
if (ERROR) {
|
||||
if (isConnected)
|
||||
error("kryonet", "Error updating connection: " + this, ex);
|
||||
else
|
||||
error("kryonet", "Error updating connection.", ex);
|
||||
}
|
||||
close();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
if (TRACE) trace("kryonet", "Client thread stopped.");
|
||||
}
|
||||
|
||||
public void start () {
|
||||
// Try to let any previous update thread stop.
|
||||
if (updateThread != null) {
|
||||
shutdown = true;
|
||||
try {
|
||||
updateThread.join(5000);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
updateThread = new Thread(this, "Client");
|
||||
updateThread.setDaemon(true);
|
||||
updateThread.start();
|
||||
}
|
||||
|
||||
public void stop () {
|
||||
if (shutdown) return;
|
||||
close();
|
||||
if (TRACE) trace("kryonet", "Client thread stopping.");
|
||||
shutdown = true;
|
||||
selector.wakeup();
|
||||
}
|
||||
|
||||
public void close () {
|
||||
super.close();
|
||||
// Select one last time to complete closing the socket.
|
||||
synchronized (updateLock) {
|
||||
if (!isClosed) {
|
||||
isClosed = true;
|
||||
selector.wakeup();
|
||||
try {
|
||||
selector.selectNow();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener (Listener listener) {
|
||||
super.addListener(listener);
|
||||
if (TRACE) trace("kryonet", "Client listener added.");
|
||||
}
|
||||
|
||||
public void removeListener (Listener listener) {
|
||||
super.removeListener(listener);
|
||||
if (TRACE) trace("kryonet", "Client listener removed.");
|
||||
}
|
||||
|
||||
/** An empty object will be sent if the UDP connection is inactive more than the specified milliseconds. Network hardware may
|
||||
* keep a translation table of inside to outside IP addresses and a UDP keep alive keeps this table entry from expiring. Set to
|
||||
* zero to disable. Defaults to 19000. */
|
||||
public void setKeepAliveUDP (int keepAliveMillis) {
|
||||
if (udp == null) throw new IllegalStateException("Not connected via UDP.");
|
||||
udp.keepAliveMillis = keepAliveMillis;
|
||||
}
|
||||
|
||||
public Thread getUpdateThread () {
|
||||
return updateThread;
|
||||
}
|
||||
|
||||
private void broadcast (int udpPort, DatagramSocket socket) throws IOException {
|
||||
ByteBuffer dataBuffer = ByteBuffer.allocate(64);
|
||||
serialization.write(null, dataBuffer, new DiscoverHost());
|
||||
dataBuffer.flip();
|
||||
byte[] data = new byte[dataBuffer.limit()];
|
||||
dataBuffer.get(data);
|
||||
for (NetworkInterface iface : Collections.list(NetworkInterface.getNetworkInterfaces())) {
|
||||
for (InetAddress address : Collections.list(iface.getInetAddresses())) {
|
||||
// Java 1.5 doesn't support getting the subnet mask, so try the two most common.
|
||||
byte[] ip = address.getAddress();
|
||||
ip[3] = -1; // 255.255.255.0
|
||||
try {
|
||||
socket.send(new DatagramPacket(data, data.length, InetAddress.getByAddress(ip), udpPort));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
ip[2] = -1; // 255.255.0.0
|
||||
try {
|
||||
socket.send(new DatagramPacket(data, data.length, InetAddress.getByAddress(ip), udpPort));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (DEBUG) debug("kryonet", "Broadcasted host discovery on port: " + udpPort);
|
||||
}
|
||||
|
||||
/** Broadcasts a UDP message on the LAN to discover any running servers. The address of the first server to respond is returned.
|
||||
* @param udpPort The UDP port of the server.
|
||||
* @param timeoutMillis The number of milliseconds to wait for a response.
|
||||
* @return the first server found, or null if no server responded. */
|
||||
public InetAddress discoverHost (int udpPort, int timeoutMillis) {
|
||||
DatagramSocket socket = null;
|
||||
try {
|
||||
socket = new DatagramSocket();
|
||||
broadcast(udpPort, socket);
|
||||
socket.setSoTimeout(timeoutMillis);
|
||||
DatagramPacket packet = new DatagramPacket(new byte[0], 0);
|
||||
try {
|
||||
socket.receive(packet);
|
||||
} catch (SocketTimeoutException ex) {
|
||||
if (INFO) info("kryonet", "Host discovery timed out.");
|
||||
return null;
|
||||
}
|
||||
if (INFO) info("kryonet", "Discovered server: " + packet.getAddress());
|
||||
return packet.getAddress();
|
||||
} catch (IOException ex) {
|
||||
if (ERROR) error("kryonet", "Host discovery failed.", ex);
|
||||
return null;
|
||||
} finally {
|
||||
if (socket != null) socket.close();
|
||||
}
|
||||
}
|
||||
|
||||
/** Broadcasts a UDP message on the LAN to discover any running servers.
|
||||
* @param udpPort The UDP port of the server.
|
||||
* @param timeoutMillis The number of milliseconds to wait for a response. */
|
||||
public List<InetAddress> discoverHosts (int udpPort, int timeoutMillis) {
|
||||
List<InetAddress> hosts = new ArrayList<InetAddress>();
|
||||
DatagramSocket socket = null;
|
||||
try {
|
||||
socket = new DatagramSocket();
|
||||
broadcast(udpPort, socket);
|
||||
socket.setSoTimeout(timeoutMillis);
|
||||
while (true) {
|
||||
DatagramPacket packet = new DatagramPacket(new byte[0], 0);
|
||||
try {
|
||||
socket.receive(packet);
|
||||
} catch (SocketTimeoutException ex) {
|
||||
if (INFO) info("kryonet", "Host discovery timed out.");
|
||||
return hosts;
|
||||
}
|
||||
if (INFO) info("kryonet", "Discovered server: " + packet.getAddress());
|
||||
hosts.add(packet.getAddress());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
if (ERROR) error("kryonet", "Host discovery failed.", ex);
|
||||
return hosts;
|
||||
} finally {
|
||||
if (socket != null) socket.close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,312 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.Ping;
|
||||
|
||||
import static com.esotericsoftware.minlog.Log.*;
|
||||
|
||||
// BOZO - Layer to handle handshake state.
|
||||
|
||||
/** Represents a TCP and optionally a UDP connection between a {@link Client} and a {@link Server}. If either underlying connection
|
||||
* is closed or errors, both connections are closed.
|
||||
* @author Nathan Sweet <misc@n4te.com> */
|
||||
public class Connection {
|
||||
int id = -1;
|
||||
private String name;
|
||||
EndPoint endPoint;
|
||||
TcpConnection tcp;
|
||||
UdpConnection udp;
|
||||
InetSocketAddress udpRemoteAddress;
|
||||
private Listener[] listeners = {};
|
||||
private Object listenerLock = new Object();
|
||||
private int lastPingID;
|
||||
private long lastPingSendTime;
|
||||
private int returnTripTime;
|
||||
volatile boolean isConnected;
|
||||
|
||||
protected Connection () {
|
||||
}
|
||||
|
||||
void initialize (Serialization serialization, int writeBufferSize, int objectBufferSize) {
|
||||
tcp = new TcpConnection(serialization, writeBufferSize, objectBufferSize);
|
||||
}
|
||||
|
||||
/** Returns the server assigned ID. Will return -1 if this connection has never been connected or the last assigned ID if this
|
||||
* connection has been disconnected. */
|
||||
public int getID () {
|
||||
return id;
|
||||
}
|
||||
|
||||
/** Returns true if this connection is connected to the remote end. Note that a connection can become disconnected at any time. */
|
||||
public boolean isConnected () {
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
/** Sends the object over the network using TCP.
|
||||
* @return The number of bytes sent.
|
||||
* @see Kryo#register(Class, com.esotericsoftware.kryo.Serializer) */
|
||||
public int sendTCP (Object object) {
|
||||
if (object == null) throw new IllegalArgumentException("object cannot be null.");
|
||||
try {
|
||||
int length = tcp.send(this, object);
|
||||
if (length == 0) {
|
||||
if (TRACE) trace("kryonet", this + " TCP had nothing to send.");
|
||||
} else if (DEBUG) {
|
||||
String objectString = object == null ? "null" : object.getClass().getSimpleName();
|
||||
if (!(object instanceof FrameworkMessage)) {
|
||||
debug("kryonet", this + " sent TCP: " + objectString + " (" + length + ")");
|
||||
} else if (TRACE) {
|
||||
trace("kryonet", this + " sent TCP: " + objectString + " (" + length + ")");
|
||||
}
|
||||
}
|
||||
return length;
|
||||
} catch (IOException ex) {
|
||||
if (DEBUG) debug("kryonet", "Unable to send TCP with connection: " + this, ex);
|
||||
close();
|
||||
return 0;
|
||||
} catch (KryoNetException ex) {
|
||||
if (ERROR) error("kryonet", "Unable to send TCP with connection: " + this, ex);
|
||||
close();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/** Sends the object over the network using UDP.
|
||||
* @return The number of bytes sent.
|
||||
* @see Kryo#register(Class, com.esotericsoftware.kryo.Serializer)
|
||||
* @throws IllegalStateException if this connection was not opened with both TCP and UDP. */
|
||||
public int sendUDP (Object object) {
|
||||
if (object == null) throw new IllegalArgumentException("object cannot be null.");
|
||||
SocketAddress address = udpRemoteAddress;
|
||||
if (address == null && udp != null) address = udp.connectedAddress;
|
||||
if (address == null && isConnected) throw new IllegalStateException("Connection is not connected via UDP.");
|
||||
|
||||
try {
|
||||
if (address == null) throw new SocketException("Connection is closed.");
|
||||
|
||||
int length = udp.send(this, object, address);
|
||||
if (length == 0) {
|
||||
if (TRACE) trace("kryonet", this + " UDP had nothing to send.");
|
||||
} else if (DEBUG) {
|
||||
if (length != -1) {
|
||||
String objectString = object == null ? "null" : object.getClass().getSimpleName();
|
||||
if (!(object instanceof FrameworkMessage)) {
|
||||
debug("kryonet", this + " sent UDP: " + objectString + " (" + length + ")");
|
||||
} else if (TRACE) {
|
||||
trace("kryonet", this + " sent UDP: " + objectString + " (" + length + ")");
|
||||
}
|
||||
} else
|
||||
debug("kryonet", this + " was unable to send, UDP socket buffer full.");
|
||||
}
|
||||
return length;
|
||||
} catch (IOException ex) {
|
||||
if (DEBUG) debug("kryonet", "Unable to send UDP with connection: " + this, ex);
|
||||
close();
|
||||
return 0;
|
||||
} catch (KryoNetException ex) {
|
||||
if (ERROR) error("kryonet", "Unable to send UDP with connection: " + this, ex);
|
||||
close();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void close () {
|
||||
boolean wasConnected = isConnected;
|
||||
isConnected = false;
|
||||
tcp.close();
|
||||
if (udp != null && udp.connectedAddress != null) udp.close();
|
||||
if (wasConnected) {
|
||||
notifyDisconnected();
|
||||
if (INFO) info("kryonet", this + " disconnected.");
|
||||
}
|
||||
setConnected(false);
|
||||
}
|
||||
|
||||
/** Requests the connection to communicate with the remote computer to determine a new value for the
|
||||
* {@link #getReturnTripTime() return trip time}. When the connection receives a {@link FrameworkMessage.Ping} object with
|
||||
* {@link Ping#isReply isReply} set to true, the new return trip time is available. */
|
||||
public void updateReturnTripTime () {
|
||||
Ping ping = new Ping();
|
||||
ping.id = lastPingID++;
|
||||
lastPingSendTime = System.currentTimeMillis();
|
||||
sendTCP(ping);
|
||||
}
|
||||
|
||||
/** Returns the last calculated TCP return trip time, or -1 if {@link #updateReturnTripTime()} has never been called or the
|
||||
* {@link FrameworkMessage.Ping} response has not yet been received. */
|
||||
public int getReturnTripTime () {
|
||||
return returnTripTime;
|
||||
}
|
||||
|
||||
/** An empty object will be sent if the TCP connection has not sent an object within the specified milliseconds. Periodically
|
||||
* sending a keep alive ensures that an abnormal close is detected in a reasonable amount of time (see {@link #setTimeout(int)}
|
||||
* ). Also, some network hardware will close a TCP connection that ceases to transmit for a period of time (typically 1+
|
||||
* minutes). Set to zero to disable. Defaults to 8000. */
|
||||
public void setKeepAliveTCP (int keepAliveMillis) {
|
||||
tcp.keepAliveMillis = keepAliveMillis;
|
||||
}
|
||||
|
||||
/** If the specified amount of time passes without receiving an object over TCP, the connection is considered closed. When a TCP
|
||||
* socket is closed normally, the remote end is notified immediately and this timeout is not needed. However, if a socket is
|
||||
* closed abnormally (eg, power loss), KryoNet uses this timeout to detect the problem. The timeout should be set higher than
|
||||
* the {@link #setKeepAliveTCP(int) TCP keep alive} for the remote end of the connection. The keep alive ensures that the remote
|
||||
* end of the connection will be constantly sending objects, and setting the timeout higher than the keep alive allows for
|
||||
* network latency. Set to zero to disable. Defaults to 12000. */
|
||||
public void setTimeout (int timeoutMillis) {
|
||||
tcp.timeoutMillis = timeoutMillis;
|
||||
}
|
||||
|
||||
/** If the listener already exists, it is not added again. */
|
||||
public void addListener (Listener listener) {
|
||||
if (listener == null) throw new IllegalArgumentException("listener cannot be null.");
|
||||
synchronized (listenerLock) {
|
||||
Listener[] listeners = this.listeners;
|
||||
int n = listeners.length;
|
||||
for (int i = 0; i < n; i++)
|
||||
if (listener == listeners[i]) return;
|
||||
Listener[] newListeners = new Listener[n + 1];
|
||||
newListeners[0] = listener;
|
||||
System.arraycopy(listeners, 0, newListeners, 1, n);
|
||||
this.listeners = newListeners;
|
||||
}
|
||||
if (TRACE) trace("kryonet", "Connection listener added: " + listener.getClass().getName());
|
||||
}
|
||||
|
||||
public void removeListener (Listener listener) {
|
||||
if (listener == null) throw new IllegalArgumentException("listener cannot be null.");
|
||||
synchronized (listenerLock) {
|
||||
Listener[] listeners = this.listeners;
|
||||
int n = listeners.length;
|
||||
if (n == 0) return;
|
||||
Listener[] newListeners = new Listener[n - 1];
|
||||
for (int i = 0, ii = 0; i < n; i++) {
|
||||
Listener copyListener = listeners[i];
|
||||
if (listener == copyListener) continue;
|
||||
if (ii == n - 1) return;
|
||||
newListeners[ii++] = copyListener;
|
||||
}
|
||||
this.listeners = newListeners;
|
||||
}
|
||||
if (TRACE) trace("kryonet", "Connection listener removed: " + listener.getClass().getName());
|
||||
}
|
||||
|
||||
void notifyConnected () {
|
||||
if (INFO) {
|
||||
SocketChannel socketChannel = tcp.socketChannel;
|
||||
if (socketChannel != null) {
|
||||
Socket socket = tcp.socketChannel.socket();
|
||||
if (socket != null) {
|
||||
InetSocketAddress remoteSocketAddress = (InetSocketAddress)socket.getRemoteSocketAddress();
|
||||
if (remoteSocketAddress != null) info("kryonet", this + " connected: " + remoteSocketAddress.getAddress());
|
||||
}
|
||||
}
|
||||
}
|
||||
Listener[] listeners = this.listeners;
|
||||
for (int i = 0, n = listeners.length; i < n; i++)
|
||||
listeners[i].connected(this);
|
||||
}
|
||||
|
||||
void notifyDisconnected () {
|
||||
Listener[] listeners = this.listeners;
|
||||
for (int i = 0, n = listeners.length; i < n; i++)
|
||||
listeners[i].disconnected(this);
|
||||
}
|
||||
|
||||
void notifyIdle () {
|
||||
Listener[] listeners = this.listeners;
|
||||
for (int i = 0, n = listeners.length; i < n; i++) {
|
||||
listeners[i].idle(this);
|
||||
if (!isIdle()) break;
|
||||
}
|
||||
}
|
||||
|
||||
void notifyReceived (Object object) {
|
||||
if (object instanceof Ping) {
|
||||
Ping ping = (Ping)object;
|
||||
if (ping.isReply) {
|
||||
if (ping.id == lastPingID - 1) {
|
||||
returnTripTime = (int)(System.currentTimeMillis() - lastPingSendTime);
|
||||
if (TRACE) trace("kryonet", this + " return trip time: " + returnTripTime);
|
||||
}
|
||||
} else {
|
||||
ping.isReply = true;
|
||||
sendTCP(ping);
|
||||
}
|
||||
}
|
||||
Listener[] listeners = this.listeners;
|
||||
for (int i = 0, n = listeners.length; i < n; i++)
|
||||
listeners[i].received(this, object);
|
||||
}
|
||||
|
||||
/** Returns the local {@link Client} or {@link Server} to which this connection belongs. */
|
||||
public EndPoint getEndPoint () {
|
||||
return endPoint;
|
||||
}
|
||||
|
||||
/** Returns the IP address and port of the remote end of the TCP connection, or null if this connection is not connected. */
|
||||
public InetSocketAddress getRemoteAddressTCP () {
|
||||
SocketChannel socketChannel = tcp.socketChannel;
|
||||
if (socketChannel != null) {
|
||||
Socket socket = tcp.socketChannel.socket();
|
||||
if (socket != null) {
|
||||
return (InetSocketAddress)socket.getRemoteSocketAddress();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Returns the IP address and port of the remote end of the UDP connection, or null if this connection is not connected. */
|
||||
public InetSocketAddress getRemoteAddressUDP () {
|
||||
InetSocketAddress connectedAddress = udp.connectedAddress;
|
||||
if (connectedAddress != null) return connectedAddress;
|
||||
return udpRemoteAddress;
|
||||
}
|
||||
|
||||
/** Workaround for broken NIO networking on Android 1.6. If true, the underlying NIO buffer is always copied to the beginning of
|
||||
* the buffer before being given to the SocketChannel for sending. The Harmony SocketChannel implementation in Android 1.6
|
||||
* ignores the buffer position, always copying from the beginning of the buffer. This is fixed in Android 2.0+. */
|
||||
public void setBufferPositionFix (boolean bufferPositionFix) {
|
||||
tcp.bufferPositionFix = bufferPositionFix;
|
||||
}
|
||||
|
||||
/** Sets the friendly name of this connection. This is returned by {@link #toString()} and is useful for providing application
|
||||
* specific identifying information in the logging. May be null for the default name of "Connection X", where X is the
|
||||
* connection ID. */
|
||||
public void setName (String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/** Returns the number of bytes that are waiting to be written to the TCP socket, if any. */
|
||||
public int getTcpWriteBufferSize () {
|
||||
return tcp.writeBuffer.position();
|
||||
}
|
||||
|
||||
/** @see #setIdleThreshold(float) */
|
||||
public boolean isIdle () {
|
||||
return tcp.writeBuffer.position() / (float)tcp.writeBuffer.capacity() < tcp.idleThreshold;
|
||||
}
|
||||
|
||||
/** If the percent of the TCP write buffer that is filled is less than the specified threshold,
|
||||
* {@link Listener#idle(Connection)} will be called for each network thread update. Default is 0.1. */
|
||||
public void setIdleThreshold (float idleThreshold) {
|
||||
tcp.idleThreshold = idleThreshold;
|
||||
}
|
||||
|
||||
public String toString () {
|
||||
if (name != null) return name;
|
||||
return "Connection " + id;
|
||||
}
|
||||
|
||||
void setConnected (boolean isConnected) {
|
||||
this.isConnected = isConnected;
|
||||
if (isConnected && name == null) name = "Connection " + id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
|
||||
/** Represents the local end point of a connection.
|
||||
* @author Nathan Sweet <misc@n4te.com> */
|
||||
public interface EndPoint extends Runnable {
|
||||
/** Gets the serialization instance that will be used to serialize and deserialize objects. */
|
||||
public Serialization getSerialization ();
|
||||
|
||||
/** If the listener already exists, it is not added again. */
|
||||
public void addListener (Listener listener);
|
||||
|
||||
public void removeListener (Listener listener);
|
||||
|
||||
/** Continually updates this end point until {@link #stop()} is called. */
|
||||
public void run ();
|
||||
|
||||
/** Starts a new thread that calls {@link #run()}. */
|
||||
public void start ();
|
||||
|
||||
/** Closes this end point and causes {@link #run()} to return. */
|
||||
public void stop ();
|
||||
|
||||
/** @see Client
|
||||
* @see Server */
|
||||
public void close ();
|
||||
|
||||
/** @see Client#update(int)
|
||||
* @see Server#update(int) */
|
||||
public void update (int timeout) throws IOException;
|
||||
|
||||
/** Returns the last thread that called {@link #update(int)} for this end point. This can be useful to detect when long running
|
||||
* code will be run on the update thread. */
|
||||
public Thread getUpdateThread ();
|
||||
|
||||
/** Gets the Kryo instance that will be used to serialize and deserialize objects. This is only valid if
|
||||
* {@link KryoSerialization} is being used, which is the default. */
|
||||
public Kryo getKryo ();
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
|
||||
/** Marker interface to denote that a message is used by the Ninja framework and is generally invisible to the developer. Eg, these
|
||||
* messages are only logged at the {@link Log#LEVEL_TRACE} level.
|
||||
* @author Nathan Sweet <misc@n4te.com> */
|
||||
public interface FrameworkMessage {
|
||||
static final FrameworkMessage.KeepAlive keepAlive = new KeepAlive();
|
||||
|
||||
/** Internal message to give the client the server assigned connection ID. */
|
||||
static public class RegisterTCP implements FrameworkMessage {
|
||||
public int connectionID;
|
||||
}
|
||||
|
||||
/** Internal message to give the server the client's UDP port. */
|
||||
static public class RegisterUDP implements FrameworkMessage {
|
||||
public int connectionID;
|
||||
}
|
||||
|
||||
/** Internal message to keep connections alive. */
|
||||
static public class KeepAlive implements FrameworkMessage {
|
||||
}
|
||||
|
||||
/** Internal message to discover running servers. */
|
||||
static public class DiscoverHost implements FrameworkMessage {
|
||||
}
|
||||
|
||||
/** Internal message to determine round trip time. */
|
||||
static public class Ping implements FrameworkMessage {
|
||||
public int id;
|
||||
public boolean isReply;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.esotericsoftware.jsonbeans.Json;
|
||||
import com.esotericsoftware.jsonbeans.JsonException;
|
||||
import com.esotericsoftware.kryo.io.ByteBufferInputStream;
|
||||
import com.esotericsoftware.kryo.io.ByteBufferOutputStream;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.DiscoverHost;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.KeepAlive;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.Ping;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.RegisterTCP;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.RegisterUDP;
|
||||
|
||||
import static com.esotericsoftware.minlog.Log.*;
|
||||
|
||||
public class JsonSerialization implements Serialization {
|
||||
private final Json json = new Json();
|
||||
private final ByteBufferInputStream byteBufferInputStream = new ByteBufferInputStream();
|
||||
private final ByteBufferOutputStream byteBufferOutputStream = new ByteBufferOutputStream();
|
||||
private final OutputStreamWriter writer = new OutputStreamWriter(byteBufferOutputStream);
|
||||
private boolean logging = true, prettyPrint = true;
|
||||
private byte[] logBuffer = {};
|
||||
|
||||
public JsonSerialization () {
|
||||
json.addClassTag("RegisterTCP", RegisterTCP.class);
|
||||
json.addClassTag("RegisterUDP", RegisterUDP.class);
|
||||
json.addClassTag("KeepAlive", KeepAlive.class);
|
||||
json.addClassTag("DiscoverHost", DiscoverHost.class);
|
||||
json.addClassTag("Ping", Ping.class);
|
||||
|
||||
json.setWriter(writer);
|
||||
}
|
||||
|
||||
public void setLogging (boolean logging, boolean prettyPrint) {
|
||||
this.logging = logging;
|
||||
this.prettyPrint = prettyPrint;
|
||||
}
|
||||
|
||||
public void write (Connection connection, ByteBuffer buffer, Object object) {
|
||||
byteBufferOutputStream.setByteBuffer(buffer);
|
||||
int start = buffer.position();
|
||||
try {
|
||||
json.writeValue(object, Object.class, null);
|
||||
writer.flush();
|
||||
} catch (Exception ex) {
|
||||
throw new JsonException("Error writing object: " + object, ex);
|
||||
}
|
||||
if (INFO && logging) {
|
||||
int end = buffer.position();
|
||||
buffer.position(start);
|
||||
buffer.limit(end);
|
||||
int length = end - start;
|
||||
if (logBuffer.length < length) logBuffer = new byte[length];
|
||||
buffer.get(logBuffer, 0, length);
|
||||
buffer.position(end);
|
||||
buffer.limit(buffer.capacity());
|
||||
String message = new String(logBuffer, 0, length);
|
||||
if (prettyPrint) message = json.prettyPrint(message);
|
||||
info("Wrote: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
public Object read (Connection connection, ByteBuffer buffer) {
|
||||
byteBufferInputStream.setByteBuffer(buffer);
|
||||
return json.fromJson(Object.class, byteBufferInputStream);
|
||||
}
|
||||
|
||||
public void writeLength (ByteBuffer buffer, int length) {
|
||||
buffer.putInt(length);
|
||||
}
|
||||
|
||||
public int readLength (ByteBuffer buffer) {
|
||||
return buffer.getInt();
|
||||
}
|
||||
|
||||
public int getLengthLength () {
|
||||
return 4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
public class KryoNetException extends RuntimeException {
|
||||
public KryoNetException () {
|
||||
super();
|
||||
}
|
||||
|
||||
public KryoNetException (String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public KryoNetException (String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public KryoNetException (Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.io.ByteBufferInputStream;
|
||||
import com.esotericsoftware.kryo.io.ByteBufferOutputStream;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.DiscoverHost;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.KeepAlive;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.Ping;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.RegisterTCP;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.RegisterUDP;
|
||||
|
||||
public class KryoSerialization implements Serialization {
|
||||
private final Kryo kryo;
|
||||
private final Input input;
|
||||
private final Output output;
|
||||
private final ByteBufferInputStream byteBufferInputStream = new ByteBufferInputStream();
|
||||
private final ByteBufferOutputStream byteBufferOutputStream = new ByteBufferOutputStream();
|
||||
|
||||
public KryoSerialization () {
|
||||
this(new Kryo());
|
||||
kryo.setReferences(false);
|
||||
kryo.setRegistrationRequired(true);
|
||||
}
|
||||
|
||||
public KryoSerialization (Kryo kryo) {
|
||||
this.kryo = kryo;
|
||||
|
||||
kryo.register(RegisterTCP.class);
|
||||
kryo.register(RegisterUDP.class);
|
||||
kryo.register(KeepAlive.class);
|
||||
kryo.register(DiscoverHost.class);
|
||||
kryo.register(Ping.class);
|
||||
|
||||
input = new Input(byteBufferInputStream, 512);
|
||||
output = new Output(byteBufferOutputStream, 512);
|
||||
}
|
||||
|
||||
public Kryo getKryo () {
|
||||
return kryo;
|
||||
}
|
||||
|
||||
public synchronized void write (Connection connection, ByteBuffer buffer, Object object) {
|
||||
byteBufferOutputStream.setByteBuffer(buffer);
|
||||
kryo.getContext().put("connection", connection);
|
||||
kryo.writeClassAndObject(output, object);
|
||||
output.flush();
|
||||
}
|
||||
|
||||
public synchronized Object read (Connection connection, ByteBuffer buffer) {
|
||||
byteBufferInputStream.setByteBuffer(buffer);
|
||||
input.setInputStream(byteBufferInputStream);
|
||||
kryo.getContext().put("connection", connection);
|
||||
return kryo.readClassAndObject(input);
|
||||
}
|
||||
|
||||
public void writeLength (ByteBuffer buffer, int length) {
|
||||
buffer.putInt(length);
|
||||
}
|
||||
|
||||
public int readLength (ByteBuffer buffer) {
|
||||
return buffer.getInt();
|
||||
}
|
||||
|
||||
public int getLengthLength () {
|
||||
return 4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static com.esotericsoftware.minlog.Log.*;
|
||||
|
||||
/** Used to be notified about connection events. */
|
||||
public class Listener {
|
||||
/** Called when the remote end has been connected. This will be invoked before any objects are received by
|
||||
* {@link #received(Connection, Object)}. This will be invoked on the same thread as {@link Client#update(int)} and
|
||||
* {@link Server#update(int)}. This method should not block for long periods as other network activity will not be processed
|
||||
* until it returns. */
|
||||
public void connected (Connection connection) {
|
||||
}
|
||||
|
||||
/** Called when the remote end is no longer connected. There is no guarantee as to what thread will invoke this method. */
|
||||
public void disconnected (Connection connection) {
|
||||
}
|
||||
|
||||
/** Called when an object has been received from the remote end of the connection. This will be invoked on the same thread as
|
||||
* {@link Client#update(int)} and {@link Server#update(int)}. This method should not block for long periods as other network
|
||||
* activity will not be processed until it returns. */
|
||||
public void received (Connection connection, Object object) {
|
||||
}
|
||||
|
||||
/** Called when the connection is below the {@link Connection#setIdleThreshold(float) idle threshold}. */
|
||||
public void idle (Connection connection) {
|
||||
}
|
||||
|
||||
/** Uses reflection to called "received(Connection, XXX)" on the listener, where XXX is the received object type. Note this
|
||||
* class uses a HashMap lookup and (cached) reflection, so is not as efficient as writing a series of "instanceof" statements. */
|
||||
static public class ReflectionListener extends Listener {
|
||||
private final HashMap<Class, Method> classToMethod = new HashMap();
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
Class type = object.getClass();
|
||||
Method method = classToMethod.get(type);
|
||||
if (method == null) {
|
||||
if (classToMethod.containsKey(type)) return; // Only fail on the first attempt to find the method.
|
||||
try {
|
||||
method = getClass().getMethod("received", new Class[] {Connection.class, type});
|
||||
} catch (SecurityException ex) {
|
||||
if (ERROR) error("kryonet", "Unable to access method: received(Connection, " + type.getName() + ")", ex);
|
||||
return;
|
||||
} catch (NoSuchMethodException ex) {
|
||||
if (DEBUG)
|
||||
debug("kryonet",
|
||||
"Unable to find listener method: " + getClass().getName() + "#received(Connection, " + type.getName() + ")");
|
||||
return;
|
||||
} finally {
|
||||
classToMethod.put(type, method);
|
||||
}
|
||||
}
|
||||
try {
|
||||
method.invoke(this, connection, object);
|
||||
} catch (Throwable ex) {
|
||||
if (ex instanceof InvocationTargetException && ex.getCause() != null) ex = ex.getCause();
|
||||
if (ex instanceof RuntimeException) throw (RuntimeException)ex;
|
||||
throw new RuntimeException("Error invoking method: " + getClass().getName() + "#received(Connection, "
|
||||
+ type.getName() + ")", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Wraps a listener and queues notifications as {@link Runnable runnables}. This allows the runnables to be processed on a
|
||||
* different thread, preventing the connection's update thread from being blocked. */
|
||||
static public abstract class QueuedListener extends Listener {
|
||||
final Listener listener;
|
||||
|
||||
public QueuedListener (Listener listener) {
|
||||
if (listener == null) throw new IllegalArgumentException("listener cannot be null.");
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void connected (final Connection connection) {
|
||||
queue(new Runnable() {
|
||||
public void run () {
|
||||
listener.connected(connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void disconnected (final Connection connection) {
|
||||
queue(new Runnable() {
|
||||
public void run () {
|
||||
listener.disconnected(connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void received (final Connection connection, final Object object) {
|
||||
queue(new Runnable() {
|
||||
public void run () {
|
||||
listener.received(connection, object);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void idle (final Connection connection) {
|
||||
queue(new Runnable() {
|
||||
public void run () {
|
||||
listener.idle(connection);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
abstract protected void queue (Runnable runnable);
|
||||
}
|
||||
|
||||
/** Wraps a listener and processes notification events on a separate thread. */
|
||||
static public class ThreadedListener extends QueuedListener {
|
||||
protected final ExecutorService threadPool;
|
||||
|
||||
/** Creates a single thread to process notification events. */
|
||||
public ThreadedListener (Listener listener) {
|
||||
this(listener, Executors.newFixedThreadPool(1));
|
||||
}
|
||||
|
||||
/** Uses the specified threadPool to process notification events. */
|
||||
public ThreadedListener (Listener listener, ExecutorService threadPool) {
|
||||
super(listener);
|
||||
if (threadPool == null) throw new IllegalArgumentException("threadPool cannot be null.");
|
||||
this.threadPool = threadPool;
|
||||
}
|
||||
|
||||
public void queue (Runnable runnable) {
|
||||
threadPool.execute(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
/** Delays the notification of the wrapped listener to simulate lag on incoming objects. Notification events are processed on a
|
||||
* separate thread after a delay. Note that only incoming objects are delayed. To delay outgoing objects, use a LagListener at
|
||||
* the other end of the connection. */
|
||||
static public class LagListener extends QueuedListener {
|
||||
private final ScheduledExecutorService threadPool;
|
||||
private final int lagMillisMin, lagMillisMax;
|
||||
final LinkedList<Runnable> runnables = new LinkedList();
|
||||
|
||||
public LagListener (int lagMillisMin, int lagMillisMax, Listener listener) {
|
||||
super(listener);
|
||||
this.lagMillisMin = lagMillisMin;
|
||||
this.lagMillisMax = lagMillisMax;
|
||||
threadPool = Executors.newScheduledThreadPool(1);
|
||||
}
|
||||
|
||||
public void queue (Runnable runnable) {
|
||||
synchronized (runnables) {
|
||||
runnables.addFirst(runnable);
|
||||
}
|
||||
int lag = lagMillisMin + (int)(Math.random() * (lagMillisMax - lagMillisMin));
|
||||
threadPool.schedule(new Runnable() {
|
||||
public void run () {
|
||||
Runnable runnable;
|
||||
synchronized (runnables) {
|
||||
runnable = runnables.removeLast();
|
||||
}
|
||||
runnable.run();
|
||||
}
|
||||
}, lag, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/** Controls how objects are transmitted over the network. */
|
||||
public interface Serialization {
|
||||
/** @param connection May be null. */
|
||||
public void write (Connection connection, ByteBuffer buffer, Object object);
|
||||
|
||||
public Object read (Connection connection, ByteBuffer buffer);
|
||||
|
||||
/** The fixed number of bytes that will be written by {@link #writeLength(ByteBuffer, int)} and read by
|
||||
* {@link #readLength(ByteBuffer)}. */
|
||||
public int getLengthLength ();
|
||||
|
||||
public void writeLength (ByteBuffer buffer, int length);
|
||||
|
||||
public int readLength (ByteBuffer buffer);
|
||||
}
|
|
@ -0,0 +1,560 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.CancelledKeyException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.util.IntMap;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.DiscoverHost;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.RegisterTCP;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.RegisterUDP;
|
||||
|
||||
import static com.esotericsoftware.minlog.Log.*;
|
||||
|
||||
/** Manages TCP and optionally UDP connections from many {@link Client Clients}.
|
||||
* @author Nathan Sweet <misc@n4te.com> */
|
||||
public class Server implements EndPoint {
|
||||
private final Serialization serialization;
|
||||
private final int writeBufferSize, objectBufferSize;
|
||||
private final Selector selector;
|
||||
private int emptySelects;
|
||||
private ServerSocketChannel serverChannel;
|
||||
private UdpConnection udp;
|
||||
private Connection[] connections = {};
|
||||
private IntMap<Connection> pendingConnections = new IntMap();
|
||||
Listener[] listeners = {};
|
||||
private Object listenerLock = new Object();
|
||||
private int nextConnectionID = 1;
|
||||
private volatile boolean shutdown;
|
||||
private Object updateLock = new Object();
|
||||
private Thread updateThread;
|
||||
private ByteBuffer emptyBuffer = ByteBuffer.allocate(0);
|
||||
|
||||
private Listener dispatchListener = new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
Listener[] listeners = Server.this.listeners;
|
||||
for (int i = 0, n = listeners.length; i < n; i++)
|
||||
listeners[i].connected(connection);
|
||||
}
|
||||
|
||||
public void disconnected (Connection connection) {
|
||||
removeConnection(connection);
|
||||
Listener[] listeners = Server.this.listeners;
|
||||
for (int i = 0, n = listeners.length; i < n; i++)
|
||||
listeners[i].disconnected(connection);
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
Listener[] listeners = Server.this.listeners;
|
||||
for (int i = 0, n = listeners.length; i < n; i++)
|
||||
listeners[i].received(connection, object);
|
||||
}
|
||||
|
||||
public void idle (Connection connection) {
|
||||
Listener[] listeners = Server.this.listeners;
|
||||
for (int i = 0, n = listeners.length; i < n; i++)
|
||||
listeners[i].idle(connection);
|
||||
}
|
||||
};
|
||||
|
||||
/** Creates a Server with a write buffer size of 16384 and an object buffer size of 2048. */
|
||||
public Server () {
|
||||
this(16384, 2048);
|
||||
}
|
||||
|
||||
/** @param writeBufferSize One buffer of this size is allocated for each connected client. Objects are serialized to the write
|
||||
* buffer where the bytes are queued until they can be written to the TCP socket.
|
||||
* <p>
|
||||
* Normally the socket is writable and the bytes are written immediately. If the socket cannot be written to and
|
||||
* enough serialized objects are queued to overflow the buffer, then the connection will be closed.
|
||||
* <p>
|
||||
* The write buffer should be sized at least as large as the largest object that will be sent, plus some head room to
|
||||
* allow for some serialized objects to be queued in case the buffer is temporarily not writable. The amount of head
|
||||
* room needed is dependent upon the size of objects being sent and how often they are sent.
|
||||
* @param objectBufferSize One (using only TCP) or three (using both TCP and UDP) buffers of this size are allocated. These
|
||||
* buffers are used to hold the bytes for a single object graph until it can be sent over the network or
|
||||
* deserialized.
|
||||
* <p>
|
||||
* The object buffers should be sized at least as large as the largest object that will be sent or received. */
|
||||
public Server (int writeBufferSize, int objectBufferSize) {
|
||||
this(writeBufferSize, objectBufferSize, new KryoSerialization());
|
||||
}
|
||||
|
||||
public Server (int writeBufferSize, int objectBufferSize, Serialization serialization) {
|
||||
this.writeBufferSize = writeBufferSize;
|
||||
this.objectBufferSize = objectBufferSize;
|
||||
|
||||
this.serialization = serialization;
|
||||
|
||||
try {
|
||||
selector = Selector.open();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException("Error opening selector.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Serialization getSerialization () {
|
||||
return serialization;
|
||||
}
|
||||
|
||||
public Kryo getKryo () {
|
||||
return ((KryoSerialization)serialization).getKryo();
|
||||
}
|
||||
|
||||
/** Opens a TCP only server.
|
||||
* @throws IOException if the server could not be opened. */
|
||||
public void bind (int tcpPort) throws IOException {
|
||||
bind(new InetSocketAddress(tcpPort), null);
|
||||
}
|
||||
|
||||
/** Opens a TCP and UDP server.
|
||||
* @throws IOException if the server could not be opened. */
|
||||
public void bind (int tcpPort, int udpPort) throws IOException {
|
||||
bind(new InetSocketAddress(tcpPort), new InetSocketAddress(udpPort));
|
||||
}
|
||||
|
||||
/** @param udpPort May be null. */
|
||||
public void bind (InetSocketAddress tcpPort, InetSocketAddress udpPort) throws IOException {
|
||||
close();
|
||||
synchronized (updateLock) {
|
||||
selector.wakeup();
|
||||
try {
|
||||
serverChannel = selector.provider().openServerSocketChannel();
|
||||
serverChannel.socket().bind(tcpPort);
|
||||
serverChannel.configureBlocking(false);
|
||||
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
|
||||
if (DEBUG) debug("kryonet", "Accepting connections on port: " + tcpPort + "/TCP");
|
||||
|
||||
if (udpPort != null) {
|
||||
udp = new UdpConnection(serialization, objectBufferSize);
|
||||
udp.bind(selector, udpPort);
|
||||
if (DEBUG) debug("kryonet", "Accepting connections on port: " + udpPort + "/UDP");
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
close();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
if (INFO) info("kryonet", "Server opened.");
|
||||
}
|
||||
|
||||
/** Accepts any new connections and reads or writes any pending data for the current connections.
|
||||
* @param timeout Wait for up to the specified milliseconds for a connection to be ready to process. May be zero to return
|
||||
* immediately if there are no connections to process. */
|
||||
public void update (int timeout) throws IOException {
|
||||
updateThread = Thread.currentThread();
|
||||
synchronized (updateLock) { // Blocks to avoid a select while the selector is used to bind the server connection.
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
int select = 0;
|
||||
if (timeout > 0) {
|
||||
select = selector.select(timeout);
|
||||
} else {
|
||||
select = selector.selectNow();
|
||||
}
|
||||
if (select == 0) {
|
||||
emptySelects++;
|
||||
if (emptySelects == 100) {
|
||||
emptySelects = 0;
|
||||
// NIO freaks and returns immediately with 0 sometimes, so try to keep from hogging the CPU.
|
||||
long elapsedTime = System.currentTimeMillis() - startTime;
|
||||
try {
|
||||
if (elapsedTime < 25) Thread.sleep(25 - elapsedTime);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
emptySelects = 0;
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
synchronized (keys) {
|
||||
UdpConnection udp = this.udp;
|
||||
outer:
|
||||
for (Iterator<SelectionKey> iter = keys.iterator(); iter.hasNext();) {
|
||||
SelectionKey selectionKey = iter.next();
|
||||
iter.remove();
|
||||
Connection fromConnection = (Connection)selectionKey.attachment();
|
||||
try {
|
||||
int ops = selectionKey.readyOps();
|
||||
|
||||
if (fromConnection != null) { // Must be a TCP read or write operation.
|
||||
if (udp != null && fromConnection.udpRemoteAddress == null) {
|
||||
fromConnection.close();
|
||||
continue;
|
||||
}
|
||||
if ((ops & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
|
||||
try {
|
||||
while (true) {
|
||||
Object object = fromConnection.tcp.readObject(fromConnection);
|
||||
if (object == null) break;
|
||||
if (DEBUG) {
|
||||
String objectString = object == null ? "null" : object.getClass().getSimpleName();
|
||||
if (!(object instanceof FrameworkMessage)) {
|
||||
debug("kryonet", fromConnection + " received TCP: " + objectString);
|
||||
} else if (TRACE) {
|
||||
trace("kryonet", fromConnection + " received TCP: " + objectString);
|
||||
}
|
||||
}
|
||||
fromConnection.notifyReceived(object);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
if (TRACE) {
|
||||
trace("kryonet", "Unable to read TCP from: " + fromConnection, ex);
|
||||
} else if (DEBUG) {
|
||||
debug("kryonet", fromConnection + " update: " + ex.getMessage());
|
||||
}
|
||||
fromConnection.close();
|
||||
} catch (KryoNetException ex) {
|
||||
if (ERROR) error("kryonet", "Error reading TCP from connection: " + fromConnection, ex);
|
||||
fromConnection.close();
|
||||
}
|
||||
}
|
||||
if ((ops & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE) {
|
||||
try {
|
||||
fromConnection.tcp.writeOperation();
|
||||
} catch (IOException ex) {
|
||||
if (TRACE) {
|
||||
trace("kryonet", "Unable to write TCP to connection: " + fromConnection, ex);
|
||||
} else if (DEBUG) {
|
||||
debug("kryonet", fromConnection + " update: " + ex.getMessage());
|
||||
}
|
||||
fromConnection.close();
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((ops & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
|
||||
ServerSocketChannel serverChannel = this.serverChannel;
|
||||
if (serverChannel == null) continue;
|
||||
try {
|
||||
SocketChannel socketChannel = serverChannel.accept();
|
||||
if (socketChannel != null) acceptOperation(socketChannel);
|
||||
} catch (IOException ex) {
|
||||
if (DEBUG) debug("kryonet", "Unable to accept new connection.", ex);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Must be a UDP read operation.
|
||||
if (udp == null) {
|
||||
selectionKey.channel().close();
|
||||
continue;
|
||||
}
|
||||
InetSocketAddress fromAddress;
|
||||
try {
|
||||
fromAddress = udp.readFromAddress();
|
||||
} catch (IOException ex) {
|
||||
if (WARN) warn("kryonet", "Error reading UDP data.", ex);
|
||||
continue;
|
||||
}
|
||||
if (fromAddress == null) continue;
|
||||
|
||||
Connection[] connections = this.connections;
|
||||
for (int i = 0, n = connections.length; i < n; i++) {
|
||||
Connection connection = connections[i];
|
||||
if (fromAddress.equals(connection.udpRemoteAddress)) {
|
||||
fromConnection = connection;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Object object;
|
||||
try {
|
||||
object = udp.readObject(fromConnection);
|
||||
} catch (KryoNetException ex) {
|
||||
if (WARN) {
|
||||
if (fromConnection != null) {
|
||||
if (ERROR) error("kryonet", "Error reading UDP from connection: " + fromConnection, ex);
|
||||
} else
|
||||
warn("kryonet", "Error reading UDP from unregistered address: " + fromAddress, ex);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (object instanceof FrameworkMessage) {
|
||||
if (object instanceof RegisterUDP) {
|
||||
// Store the fromAddress on the connection and reply over TCP with a RegisterUDP to indicate success.
|
||||
int fromConnectionID = ((RegisterUDP)object).connectionID;
|
||||
Connection connection = pendingConnections.remove(fromConnectionID);
|
||||
if (connection != null) {
|
||||
if (connection.udpRemoteAddress != null) continue outer;
|
||||
connection.udpRemoteAddress = fromAddress;
|
||||
addConnection(connection);
|
||||
connection.sendTCP(new RegisterUDP());
|
||||
if (DEBUG)
|
||||
debug("kryonet", "Port " + udp.datagramChannel.socket().getLocalPort() + "/UDP connected to: "
|
||||
+ fromAddress);
|
||||
connection.notifyConnected();
|
||||
continue;
|
||||
}
|
||||
if (DEBUG)
|
||||
debug("kryonet", "Ignoring incoming RegisterUDP with invalid connection ID: " + fromConnectionID);
|
||||
continue;
|
||||
}
|
||||
if (object instanceof DiscoverHost) {
|
||||
try {
|
||||
udp.datagramChannel.send(emptyBuffer, fromAddress);
|
||||
if (DEBUG) debug("kryonet", "Responded to host discovery from: " + fromAddress);
|
||||
} catch (IOException ex) {
|
||||
if (WARN) warn("kryonet", "Error replying to host discovery from: " + fromAddress, ex);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (fromConnection != null) {
|
||||
if (DEBUG) {
|
||||
String objectString = object == null ? "null" : object.getClass().getSimpleName();
|
||||
if (object instanceof FrameworkMessage) {
|
||||
if (TRACE) trace("kryonet", fromConnection + " received UDP: " + objectString);
|
||||
} else
|
||||
debug("kryonet", fromConnection + " received UDP: " + objectString);
|
||||
}
|
||||
fromConnection.notifyReceived(object);
|
||||
continue;
|
||||
}
|
||||
if (DEBUG) debug("kryonet", "Ignoring UDP from unregistered address: " + fromAddress);
|
||||
} catch (CancelledKeyException ex) {
|
||||
if (fromConnection != null)
|
||||
fromConnection.close();
|
||||
else
|
||||
selectionKey.channel().close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
long time = System.currentTimeMillis();
|
||||
Connection[] connections = this.connections;
|
||||
for (int i = 0, n = connections.length; i < n; i++) {
|
||||
Connection connection = connections[i];
|
||||
if (connection.tcp.isTimedOut(time)) {
|
||||
if (DEBUG) debug("kryonet", connection + " timed out.");
|
||||
connection.close();
|
||||
} else {
|
||||
if (connection.tcp.needsKeepAlive(time)) connection.sendTCP(FrameworkMessage.keepAlive);
|
||||
}
|
||||
if (connection.isIdle()) connection.notifyIdle();
|
||||
}
|
||||
}
|
||||
|
||||
public void run () {
|
||||
if (TRACE) trace("kryonet", "Server thread started.");
|
||||
shutdown = false;
|
||||
while (!shutdown) {
|
||||
try {
|
||||
update(250);
|
||||
} catch (IOException ex) {
|
||||
if (ERROR) error("kryonet", "Error updating server connections.", ex);
|
||||
close();
|
||||
}
|
||||
}
|
||||
if (TRACE) trace("kryonet", "Server thread stopped.");
|
||||
}
|
||||
|
||||
public void start () {
|
||||
new Thread(this, "Server").start();
|
||||
}
|
||||
|
||||
public void stop () {
|
||||
if (shutdown) return;
|
||||
close();
|
||||
if (TRACE) trace("kryonet", "Server thread stopping.");
|
||||
shutdown = true;
|
||||
}
|
||||
|
||||
private void acceptOperation (SocketChannel socketChannel) {
|
||||
Connection connection = newConnection();
|
||||
connection.initialize(serialization, writeBufferSize, objectBufferSize);
|
||||
connection.endPoint = this;
|
||||
UdpConnection udp = this.udp;
|
||||
if (udp != null) connection.udp = udp;
|
||||
try {
|
||||
SelectionKey selectionKey = connection.tcp.accept(selector, socketChannel);
|
||||
selectionKey.attach(connection);
|
||||
|
||||
int id = nextConnectionID++;
|
||||
if (nextConnectionID == -1) nextConnectionID = 1;
|
||||
connection.id = id;
|
||||
connection.setConnected(true);
|
||||
connection.addListener(dispatchListener);
|
||||
|
||||
if (udp == null)
|
||||
addConnection(connection);
|
||||
else
|
||||
pendingConnections.put(id, connection);
|
||||
|
||||
RegisterTCP registerConnection = new RegisterTCP();
|
||||
registerConnection.connectionID = id;
|
||||
connection.sendTCP(registerConnection);
|
||||
|
||||
if (udp == null) connection.notifyConnected();
|
||||
} catch (IOException ex) {
|
||||
connection.close();
|
||||
if (DEBUG) debug("kryonet", "Unable to accept TCP connection.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/** Allows the connections used by the server to be subclassed. This can be useful for storage per connection without an
|
||||
* additional lookup. */
|
||||
protected Connection newConnection () {
|
||||
return new Connection();
|
||||
}
|
||||
|
||||
private void addConnection (Connection connection) {
|
||||
Connection[] newConnections = new Connection[connections.length + 1];
|
||||
newConnections[0] = connection;
|
||||
System.arraycopy(connections, 0, newConnections, 1, connections.length);
|
||||
connections = newConnections;
|
||||
}
|
||||
|
||||
void removeConnection (Connection connection) {
|
||||
ArrayList<Connection> temp = new ArrayList(Arrays.asList(connections));
|
||||
temp.remove(connection);
|
||||
connections = temp.toArray(new Connection[temp.size()]);
|
||||
|
||||
pendingConnections.remove(connection.id);
|
||||
}
|
||||
|
||||
// BOZO - Provide mechanism for sending to multiple clients without serializing multiple times.
|
||||
|
||||
public void sendToAllTCP (Object object) {
|
||||
Connection[] connections = this.connections;
|
||||
for (int i = 0, n = connections.length; i < n; i++) {
|
||||
Connection connection = connections[i];
|
||||
connection.sendTCP(object);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendToAllExceptTCP (int connectionID, Object object) {
|
||||
Connection[] connections = this.connections;
|
||||
for (int i = 0, n = connections.length; i < n; i++) {
|
||||
Connection connection = connections[i];
|
||||
if (connection.id != connectionID) connection.sendTCP(object);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendToTCP (int connectionID, Object object) {
|
||||
Connection[] connections = this.connections;
|
||||
for (int i = 0, n = connections.length; i < n; i++) {
|
||||
Connection connection = connections[i];
|
||||
if (connection.id == connectionID) {
|
||||
connection.sendTCP(object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void sendToAllUDP (Object object) {
|
||||
Connection[] connections = this.connections;
|
||||
for (int i = 0, n = connections.length; i < n; i++) {
|
||||
Connection connection = connections[i];
|
||||
connection.sendUDP(object);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendToAllExceptUDP (int connectionID, Object object) {
|
||||
Connection[] connections = this.connections;
|
||||
for (int i = 0, n = connections.length; i < n; i++) {
|
||||
Connection connection = connections[i];
|
||||
if (connection.id != connectionID) connection.sendUDP(object);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendToUDP (int connectionID, Object object) {
|
||||
Connection[] connections = this.connections;
|
||||
for (int i = 0, n = connections.length; i < n; i++) {
|
||||
Connection connection = connections[i];
|
||||
if (connection.id == connectionID) {
|
||||
connection.sendUDP(object);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener (Listener listener) {
|
||||
if (listener == null) throw new IllegalArgumentException("listener cannot be null.");
|
||||
synchronized (listenerLock) {
|
||||
Listener[] listeners = this.listeners;
|
||||
int n = listeners.length;
|
||||
for (int i = 0; i < n; i++)
|
||||
if (listener == listeners[i]) return;
|
||||
Listener[] newListeners = new Listener[n + 1];
|
||||
newListeners[0] = listener;
|
||||
System.arraycopy(listeners, 0, newListeners, 1, n);
|
||||
this.listeners = newListeners;
|
||||
}
|
||||
if (TRACE) trace("kryonet", "Server listener added: " + listener.getClass().getName());
|
||||
}
|
||||
|
||||
public void removeListener (Listener listener) {
|
||||
if (listener == null) throw new IllegalArgumentException("listener cannot be null.");
|
||||
synchronized (listenerLock) {
|
||||
Listener[] listeners = this.listeners;
|
||||
int n = listeners.length;
|
||||
Listener[] newListeners = new Listener[n - 1];
|
||||
for (int i = 0, ii = 0; i < n; i++) {
|
||||
Listener copyListener = listeners[i];
|
||||
if (listener == copyListener) continue;
|
||||
if (ii == n - 1) return;
|
||||
newListeners[ii++] = copyListener;
|
||||
}
|
||||
this.listeners = newListeners;
|
||||
}
|
||||
if (TRACE) trace("kryonet", "Server listener removed: " + listener.getClass().getName());
|
||||
}
|
||||
|
||||
/** Closes all open connections and the server port(s). */
|
||||
public void close () {
|
||||
Connection[] connections = this.connections;
|
||||
if (INFO && connections.length > 0) info("kryonet", "Closing server connections...");
|
||||
for (int i = 0, n = connections.length; i < n; i++)
|
||||
connections[i].close();
|
||||
connections = new Connection[0];
|
||||
|
||||
ServerSocketChannel serverChannel = this.serverChannel;
|
||||
if (serverChannel != null) {
|
||||
try {
|
||||
serverChannel.close();
|
||||
if (INFO) info("kryonet", "Server closed.");
|
||||
} catch (IOException ex) {
|
||||
if (DEBUG) debug("kryonet", "Unable to close server.", ex);
|
||||
}
|
||||
this.serverChannel = null;
|
||||
}
|
||||
|
||||
UdpConnection udp = this.udp;
|
||||
if (udp != null) {
|
||||
udp.close();
|
||||
this.udp = null;
|
||||
}
|
||||
|
||||
// Select one last time to complete closing the socket.
|
||||
synchronized (updateLock) {
|
||||
selector.wakeup();
|
||||
try {
|
||||
selector.selectNow();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Thread getUpdateThread () {
|
||||
return updateThread;
|
||||
}
|
||||
|
||||
/** Returns the current connections. The array returned should not be modified. */
|
||||
public Connection[] getConnections () {
|
||||
return connections;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import static com.esotericsoftware.minlog.Log.*;
|
||||
|
||||
/** @author Nathan Sweet <misc@n4te.com> */
|
||||
class TcpConnection {
|
||||
static private final int IPTOS_LOWDELAY = 0x10;
|
||||
|
||||
SocketChannel socketChannel;
|
||||
int keepAliveMillis = 8000;
|
||||
final ByteBuffer readBuffer, writeBuffer;
|
||||
boolean bufferPositionFix;
|
||||
int timeoutMillis = 12000;
|
||||
float idleThreshold = 0.1f;
|
||||
|
||||
final Serialization serialization;
|
||||
private SelectionKey selectionKey;
|
||||
private long lastWriteTime, lastReadTime;
|
||||
private int currentObjectLength;
|
||||
private final Object writeLock = new Object();
|
||||
|
||||
public TcpConnection (Serialization serialization, int writeBufferSize, int objectBufferSize) {
|
||||
this.serialization = serialization;
|
||||
writeBuffer = ByteBuffer.allocate(writeBufferSize);
|
||||
readBuffer = ByteBuffer.allocate(objectBufferSize);
|
||||
readBuffer.flip();
|
||||
}
|
||||
|
||||
public SelectionKey accept (Selector selector, SocketChannel socketChannel) throws IOException {
|
||||
writeBuffer.clear();
|
||||
readBuffer.clear();
|
||||
readBuffer.flip();
|
||||
currentObjectLength = 0;
|
||||
try {
|
||||
this.socketChannel = socketChannel;
|
||||
socketChannel.configureBlocking(false);
|
||||
Socket socket = socketChannel.socket();
|
||||
socket.setTcpNoDelay(true);
|
||||
|
||||
selectionKey = socketChannel.register(selector, SelectionKey.OP_READ);
|
||||
|
||||
if (DEBUG) {
|
||||
debug("kryonet", "Port " + socketChannel.socket().getLocalPort() + "/TCP connected to: "
|
||||
+ socketChannel.socket().getRemoteSocketAddress());
|
||||
}
|
||||
|
||||
lastReadTime = lastWriteTime = System.currentTimeMillis();
|
||||
|
||||
return selectionKey;
|
||||
} catch (IOException ex) {
|
||||
close();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public void connect (Selector selector, SocketAddress remoteAddress, int timeout) throws IOException {
|
||||
close();
|
||||
writeBuffer.clear();
|
||||
readBuffer.clear();
|
||||
readBuffer.flip();
|
||||
currentObjectLength = 0;
|
||||
try {
|
||||
SocketChannel socketChannel = selector.provider().openSocketChannel();
|
||||
Socket socket = socketChannel.socket();
|
||||
socket.setTcpNoDelay(true);
|
||||
// socket.setTrafficClass(IPTOS_LOWDELAY);
|
||||
socket.connect(remoteAddress, timeout); // Connect using blocking mode for simplicity.
|
||||
socketChannel.configureBlocking(false);
|
||||
this.socketChannel = socketChannel;
|
||||
|
||||
selectionKey = socketChannel.register(selector, SelectionKey.OP_READ);
|
||||
selectionKey.attach(this);
|
||||
|
||||
if (DEBUG) {
|
||||
debug("kryonet", "Port " + socketChannel.socket().getLocalPort() + "/TCP connected to: "
|
||||
+ socketChannel.socket().getRemoteSocketAddress());
|
||||
}
|
||||
|
||||
lastReadTime = lastWriteTime = System.currentTimeMillis();
|
||||
} catch (IOException ex) {
|
||||
close();
|
||||
IOException ioEx = new IOException("Unable to connect to: " + remoteAddress);
|
||||
ioEx.initCause(ex);
|
||||
throw ioEx;
|
||||
}
|
||||
}
|
||||
|
||||
public Object readObject (Connection connection) throws IOException {
|
||||
SocketChannel socketChannel = this.socketChannel;
|
||||
if (socketChannel == null) throw new SocketException("Connection is closed.");
|
||||
|
||||
if (currentObjectLength == 0) {
|
||||
// Read the length of the next object from the socket.
|
||||
int lengthLength = serialization.getLengthLength();
|
||||
if (readBuffer.remaining() < lengthLength) {
|
||||
readBuffer.compact();
|
||||
int bytesRead = socketChannel.read(readBuffer);
|
||||
readBuffer.flip();
|
||||
if (bytesRead == -1) throw new SocketException("Connection is closed.");
|
||||
lastReadTime = System.currentTimeMillis();
|
||||
|
||||
if (readBuffer.remaining() < lengthLength) return null;
|
||||
}
|
||||
currentObjectLength = serialization.readLength(readBuffer);
|
||||
|
||||
if (currentObjectLength <= 0) throw new KryoNetException("Invalid object length: " + currentObjectLength);
|
||||
if (currentObjectLength > readBuffer.capacity())
|
||||
throw new KryoNetException("Unable to read object larger than read buffer: " + currentObjectLength);
|
||||
}
|
||||
|
||||
int length = currentObjectLength;
|
||||
if (readBuffer.remaining() < length) {
|
||||
// Fill the tcpInputStream.
|
||||
readBuffer.compact();
|
||||
int bytesRead = socketChannel.read(readBuffer);
|
||||
readBuffer.flip();
|
||||
if (bytesRead == -1) throw new SocketException("Connection is closed.");
|
||||
lastReadTime = System.currentTimeMillis();
|
||||
|
||||
if (readBuffer.remaining() < length) return null;
|
||||
}
|
||||
currentObjectLength = 0;
|
||||
|
||||
int startPosition = readBuffer.position();
|
||||
int oldLimit = readBuffer.limit();
|
||||
readBuffer.limit(startPosition + length);
|
||||
Object object;
|
||||
try {
|
||||
object = serialization.read(connection, readBuffer);
|
||||
} catch (Exception ex) {
|
||||
throw new KryoNetException("Error during deserialization.", ex);
|
||||
}
|
||||
|
||||
readBuffer.limit(oldLimit);
|
||||
if (readBuffer.position() - startPosition != length)
|
||||
throw new KryoNetException("Incorrect number of bytes (" + (startPosition + length - readBuffer.position())
|
||||
+ " remaining) used to deserialize object: " + object);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
public void writeOperation () throws IOException {
|
||||
synchronized (writeLock) {
|
||||
if (writeToSocket()) {
|
||||
// Write successful, clear OP_WRITE.
|
||||
selectionKey.interestOps(SelectionKey.OP_READ);
|
||||
}
|
||||
lastWriteTime = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean writeToSocket () throws IOException {
|
||||
SocketChannel socketChannel = this.socketChannel;
|
||||
if (socketChannel == null) throw new SocketException("Connection is closed.");
|
||||
|
||||
ByteBuffer buffer = writeBuffer;
|
||||
buffer.flip();
|
||||
while (buffer.hasRemaining()) {
|
||||
if (bufferPositionFix) {
|
||||
buffer.compact();
|
||||
buffer.flip();
|
||||
}
|
||||
if (socketChannel.write(buffer) == 0) break;
|
||||
}
|
||||
buffer.compact();
|
||||
|
||||
return buffer.position() == 0;
|
||||
}
|
||||
|
||||
/** This method is thread safe. */
|
||||
public int send (Connection connection, Object object) throws IOException {
|
||||
SocketChannel socketChannel = this.socketChannel;
|
||||
if (socketChannel == null) throw new SocketException("Connection is closed.");
|
||||
synchronized (writeLock) {
|
||||
// Leave room for length.
|
||||
int start = writeBuffer.position();
|
||||
int lengthLength = serialization.getLengthLength();
|
||||
writeBuffer.position(writeBuffer.position() + lengthLength);
|
||||
|
||||
// Write data.
|
||||
try {
|
||||
serialization.write(connection, writeBuffer, object);
|
||||
} catch (KryoNetException ex) {
|
||||
throw new KryoNetException("Error serializing object of type: " + object.getClass().getName(), ex);
|
||||
}
|
||||
int end = writeBuffer.position();
|
||||
|
||||
// Write data length.
|
||||
writeBuffer.position(start);
|
||||
serialization.writeLength(writeBuffer, end - lengthLength - start);
|
||||
writeBuffer.position(end);
|
||||
|
||||
// Write to socket if no data was queued.
|
||||
if (start == 0 && !writeToSocket()) {
|
||||
// A partial write, set OP_WRITE to be notified when more writing can occur.
|
||||
selectionKey.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
|
||||
} else {
|
||||
// Full write, wake up selector so idle event will be fired.
|
||||
selectionKey.selector().wakeup();
|
||||
}
|
||||
|
||||
if (DEBUG || TRACE) {
|
||||
float percentage = writeBuffer.position() / (float)writeBuffer.capacity();
|
||||
if (DEBUG && percentage > 0.75f)
|
||||
debug("kryonet", connection + " TCP write buffer is approaching capacity: " + percentage + "%");
|
||||
else if (TRACE && percentage > 0.25f)
|
||||
trace("kryonet", connection + " TCP write buffer utilization: " + percentage + "%");
|
||||
}
|
||||
|
||||
lastWriteTime = System.currentTimeMillis();
|
||||
return end - start;
|
||||
}
|
||||
}
|
||||
|
||||
public void close () {
|
||||
try {
|
||||
if (socketChannel != null) {
|
||||
socketChannel.close();
|
||||
socketChannel = null;
|
||||
if (selectionKey != null) selectionKey.selector().wakeup();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
if (DEBUG) debug("kryonet", "Unable to close TCP connection.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean needsKeepAlive (long time) {
|
||||
return socketChannel != null && keepAliveMillis > 0 && time - lastWriteTime > keepAliveMillis;
|
||||
}
|
||||
|
||||
public boolean isTimedOut (long time) {
|
||||
return socketChannel != null && timeoutMillis > 0 && time - lastReadTime > timeoutMillis;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.DatagramChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
|
||||
import static com.esotericsoftware.minlog.Log.*;
|
||||
|
||||
/** @author Nathan Sweet <misc@n4te.com> */
|
||||
class UdpConnection {
|
||||
InetSocketAddress connectedAddress;
|
||||
DatagramChannel datagramChannel;
|
||||
int keepAliveMillis = 19000;
|
||||
final ByteBuffer readBuffer, writeBuffer;
|
||||
private final Serialization serialization;
|
||||
private SelectionKey selectionKey;
|
||||
private final Object writeLock = new Object();
|
||||
private long lastCommunicationTime;
|
||||
|
||||
public UdpConnection (Serialization serialization, int bufferSize) {
|
||||
this.serialization = serialization;
|
||||
readBuffer = ByteBuffer.allocate(bufferSize);
|
||||
writeBuffer = ByteBuffer.allocateDirect(bufferSize);
|
||||
}
|
||||
|
||||
public void bind (Selector selector, InetSocketAddress localPort) throws IOException {
|
||||
close();
|
||||
readBuffer.clear();
|
||||
writeBuffer.clear();
|
||||
try {
|
||||
datagramChannel = selector.provider().openDatagramChannel();
|
||||
datagramChannel.socket().bind(localPort);
|
||||
datagramChannel.configureBlocking(false);
|
||||
selectionKey = datagramChannel.register(selector, SelectionKey.OP_READ);
|
||||
|
||||
lastCommunicationTime = System.currentTimeMillis();
|
||||
} catch (IOException ex) {
|
||||
close();
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
public void connect (Selector selector, InetSocketAddress remoteAddress) throws IOException {
|
||||
close();
|
||||
readBuffer.clear();
|
||||
writeBuffer.clear();
|
||||
try {
|
||||
datagramChannel = selector.provider().openDatagramChannel();
|
||||
datagramChannel.socket().bind(null);
|
||||
datagramChannel.socket().connect(remoteAddress);
|
||||
datagramChannel.configureBlocking(false);
|
||||
|
||||
selectionKey = datagramChannel.register(selector, SelectionKey.OP_READ);
|
||||
|
||||
lastCommunicationTime = System.currentTimeMillis();
|
||||
|
||||
connectedAddress = remoteAddress;
|
||||
} catch (IOException ex) {
|
||||
close();
|
||||
IOException ioEx = new IOException("Unable to connect to: " + remoteAddress);
|
||||
ioEx.initCause(ex);
|
||||
throw ioEx;
|
||||
}
|
||||
}
|
||||
|
||||
public InetSocketAddress readFromAddress () throws IOException {
|
||||
DatagramChannel datagramChannel = this.datagramChannel;
|
||||
if (datagramChannel == null) throw new SocketException("Connection is closed.");
|
||||
lastCommunicationTime = System.currentTimeMillis();
|
||||
return (InetSocketAddress)datagramChannel.receive(readBuffer);
|
||||
}
|
||||
|
||||
public Object readObject (Connection connection) {
|
||||
readBuffer.flip();
|
||||
try {
|
||||
try {
|
||||
Object object = serialization.read(connection, readBuffer);
|
||||
if (readBuffer.hasRemaining())
|
||||
throw new KryoNetException("Incorrect number of bytes (" + readBuffer.remaining()
|
||||
+ " remaining) used to deserialize object: " + object);
|
||||
return object;
|
||||
} catch (Exception ex) {
|
||||
throw new KryoNetException("Error during deserialization.", ex);
|
||||
}
|
||||
} finally {
|
||||
readBuffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/** This method is thread safe. */
|
||||
public int send (Connection connection, Object object, SocketAddress address) throws IOException {
|
||||
DatagramChannel datagramChannel = this.datagramChannel;
|
||||
if (datagramChannel == null) throw new SocketException("Connection is closed.");
|
||||
synchronized (writeLock) {
|
||||
try {
|
||||
try {
|
||||
serialization.write(connection, writeBuffer, object);
|
||||
} catch (Exception ex) {
|
||||
throw new KryoNetException("Error serializing object of type: " + object.getClass().getName(), ex);
|
||||
}
|
||||
writeBuffer.flip();
|
||||
int length = writeBuffer.limit();
|
||||
datagramChannel.send(writeBuffer, address);
|
||||
|
||||
lastCommunicationTime = System.currentTimeMillis();
|
||||
|
||||
boolean wasFullWrite = !writeBuffer.hasRemaining();
|
||||
return wasFullWrite ? length : -1;
|
||||
} finally {
|
||||
writeBuffer.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close () {
|
||||
connectedAddress = null;
|
||||
try {
|
||||
if (datagramChannel != null) {
|
||||
datagramChannel.close();
|
||||
datagramChannel = null;
|
||||
if (selectionKey != null) selectionKey.selector().wakeup();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
if (DEBUG) debug("kryonet", "Unable to close UDP connection.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean needsKeepAlive (long time) {
|
||||
return connectedAddress != null && keepAliveMillis > 0 && time - lastCommunicationTime > keepAliveMillis;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,624 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.rmi;
|
||||
|
||||
import static com.esotericsoftware.minlog.Log.*;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.KryoException;
|
||||
import com.esotericsoftware.kryo.KryoSerializable;
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
import com.esotericsoftware.kryo.serializers.FieldSerializer;
|
||||
import com.esotericsoftware.kryo.util.IntMap;
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.EndPoint;
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/** Allows methods on objects to be invoked remotely over TCP. Objects are {@link #register(int, Object) registered} with an ID.
|
||||
* The remote end of connections that have been {@link #addConnection(Connection) added} are allowed to
|
||||
* {@link #getRemoteObject(Connection, int, Class) access} registered objects.
|
||||
* <p>
|
||||
* It costs at least 2 bytes more to use remote method invocation than just sending the parameters. If the method has a return
|
||||
* value which is not {@link RemoteObject#setNonBlocking(boolean) ignored}, an extra byte is written. If the type of a parameter is
|
||||
* not final (note primitives are final) then an extra byte is written for that parameter.
|
||||
* @author Nathan Sweet <misc@n4te.com> */
|
||||
public class ObjectSpace {
|
||||
static private final byte kReturnValMask = (byte)0x80; // 1000 0000
|
||||
static private final byte kReturnExMask = (byte)0x40; // 0100 0000
|
||||
|
||||
static private final Object instancesLock = new Object();
|
||||
static ObjectSpace[] instances = new ObjectSpace[0];
|
||||
static private final HashMap<Class, CachedMethod[]> methodCache = new HashMap();
|
||||
|
||||
final IntMap idToObject = new IntMap();
|
||||
Connection[] connections = {};
|
||||
final Object connectionsLock = new Object();
|
||||
Executor executor;
|
||||
|
||||
private final Listener invokeListener = new Listener() {
|
||||
public void received (final Connection connection, Object object) {
|
||||
if (!(object instanceof InvokeMethod)) return;
|
||||
if (connections != null) {
|
||||
int i = 0, n = connections.length;
|
||||
for (; i < n; i++)
|
||||
if (connection == connections[i]) break;
|
||||
if (i == n) return; // The InvokeMethod message is not for a connection in this ObjectSpace.
|
||||
}
|
||||
final InvokeMethod invokeMethod = (InvokeMethod)object;
|
||||
final Object target = idToObject.get(invokeMethod.objectID);
|
||||
if (target == null) {
|
||||
if (WARN) warn("kryonet", "Ignoring remote invocation request for unknown object ID: " + invokeMethod.objectID);
|
||||
return;
|
||||
}
|
||||
if (executor == null)
|
||||
invoke(connection, target, invokeMethod);
|
||||
else {
|
||||
executor.execute(new Runnable() {
|
||||
public void run () {
|
||||
invoke(connection, target, invokeMethod);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnected (Connection connection) {
|
||||
removeConnection(connection);
|
||||
}
|
||||
};
|
||||
|
||||
/** Creates an ObjectSpace with no connections. Connections must be {@link #addConnection(Connection) added} to allow the remote
|
||||
* end of the connections to access objects in this ObjectSpace. */
|
||||
public ObjectSpace () {
|
||||
synchronized (instancesLock) {
|
||||
ObjectSpace[] instances = ObjectSpace.instances;
|
||||
ObjectSpace[] newInstances = new ObjectSpace[instances.length + 1];
|
||||
newInstances[0] = this;
|
||||
System.arraycopy(instances, 0, newInstances, 1, instances.length);
|
||||
ObjectSpace.instances = newInstances;
|
||||
}
|
||||
}
|
||||
|
||||
/** Creates an ObjectSpace with the specified connection. More connections can be {@link #addConnection(Connection) added}. */
|
||||
public ObjectSpace (Connection connection) {
|
||||
this();
|
||||
addConnection(connection);
|
||||
}
|
||||
|
||||
/** Sets the executor used to invoke methods when an invocation is received from a remote endpoint. By default, no executor is
|
||||
* set and invocations occur on the network thread, which should not be blocked for long.
|
||||
* @param executor May be null. */
|
||||
public void setExecutor (Executor executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
/** Registers an object to allow the remote end of the ObjectSpace's connections to access it using the specified ID.
|
||||
* <p>
|
||||
* If a connection is added to multiple ObjectSpaces, the same object ID should not be registered in more than one of those
|
||||
* ObjectSpaces.
|
||||
* @see #getRemoteObject(Connection, int, Class...) */
|
||||
public void register (int objectID, Object object) {
|
||||
if (object == null) throw new IllegalArgumentException("object cannot be null.");
|
||||
idToObject.put(objectID, object);
|
||||
if (TRACE) trace("kryonet", "Object registered with ObjectSpace as " + objectID + ": " + object);
|
||||
}
|
||||
|
||||
/** Removes an object. The remote end of the ObjectSpace's connections will no longer be able to access it. */
|
||||
public void remove (int objectID) {
|
||||
Object object = idToObject.remove(objectID);
|
||||
if (TRACE) trace("kryonet", "Object " + objectID + " removed from ObjectSpace: " + object);
|
||||
}
|
||||
|
||||
/** Removes an object. The remote end of the ObjectSpace's connections will no longer be able to access it. */
|
||||
public void remove (Object object) {
|
||||
if (!idToObject.containsValue(object, true)) return;
|
||||
int objectID = idToObject.findKey(object, true, -1);
|
||||
idToObject.remove(objectID);
|
||||
if (TRACE) trace("kryonet", "Object " + objectID + " removed from ObjectSpace: " + object);
|
||||
}
|
||||
|
||||
/** Causes this ObjectSpace to stop listening to the connections for method invocation messages. */
|
||||
public void close () {
|
||||
Connection[] connections = this.connections;
|
||||
for (int i = 0; i < connections.length; i++)
|
||||
connections[i].removeListener(invokeListener);
|
||||
|
||||
synchronized (instancesLock) {
|
||||
ArrayList<Connection> temp = new ArrayList(Arrays.asList(instances));
|
||||
temp.remove(this);
|
||||
instances = temp.toArray(new ObjectSpace[temp.size()]);
|
||||
}
|
||||
|
||||
if (TRACE) trace("kryonet", "Closed ObjectSpace.");
|
||||
}
|
||||
|
||||
/** Allows the remote end of the specified connection to access objects registered in this ObjectSpace. */
|
||||
public void addConnection (Connection connection) {
|
||||
if (connection == null) throw new IllegalArgumentException("connection cannot be null.");
|
||||
|
||||
synchronized (connectionsLock) {
|
||||
Connection[] newConnections = new Connection[connections.length + 1];
|
||||
newConnections[0] = connection;
|
||||
System.arraycopy(connections, 0, newConnections, 1, connections.length);
|
||||
connections = newConnections;
|
||||
}
|
||||
|
||||
connection.addListener(invokeListener);
|
||||
|
||||
if (TRACE) trace("kryonet", "Added connection to ObjectSpace: " + connection);
|
||||
}
|
||||
|
||||
/** Removes the specified connection, it will no longer be able to access objects registered in this ObjectSpace. */
|
||||
public void removeConnection (Connection connection) {
|
||||
if (connection == null) throw new IllegalArgumentException("connection cannot be null.");
|
||||
|
||||
connection.removeListener(invokeListener);
|
||||
|
||||
synchronized (connectionsLock) {
|
||||
ArrayList<Connection> temp = new ArrayList(Arrays.asList(connections));
|
||||
temp.remove(connection);
|
||||
connections = temp.toArray(new Connection[temp.size()]);
|
||||
}
|
||||
|
||||
if (TRACE) trace("kryonet", "Removed connection from ObjectSpace: " + connection);
|
||||
}
|
||||
|
||||
/** Invokes the method on the object and, if necessary, sends the result back to the connection that made the invocation
|
||||
* request. This method is invoked on the update thread of the {@link EndPoint} for this ObjectSpace and unless an
|
||||
* {@link #setExecutor(Executor) executor} has been set.
|
||||
* @param connection The remote side of this connection requested the invocation. */
|
||||
protected void invoke (Connection connection, Object target, InvokeMethod invokeMethod) {
|
||||
if (DEBUG) {
|
||||
String argString = "";
|
||||
if (invokeMethod.args != null) {
|
||||
argString = Arrays.deepToString(invokeMethod.args);
|
||||
argString = argString.substring(1, argString.length() - 1);
|
||||
}
|
||||
debug("kryonet", connection + " received: " + target.getClass().getSimpleName() + "#" + invokeMethod.method.getName()
|
||||
+ "(" + argString + ")");
|
||||
}
|
||||
|
||||
byte responseID = invokeMethod.responseID;
|
||||
boolean transmitReturnVal = (responseID & kReturnValMask) == kReturnValMask;
|
||||
boolean transmitExceptions = (responseID & kReturnExMask) == kReturnExMask;
|
||||
|
||||
Object result = null;
|
||||
Method method = invokeMethod.method;
|
||||
try {
|
||||
result = method.invoke(target, invokeMethod.args);
|
||||
// Catch exceptions caused by the Method#invoke
|
||||
} catch (InvocationTargetException ex) {
|
||||
if (transmitExceptions)
|
||||
result = ex.getCause();
|
||||
else
|
||||
throw new RuntimeException("Error invoking method: " + method.getDeclaringClass().getName() + "." + method.getName(),
|
||||
ex);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException("Error invoking method: " + method.getDeclaringClass().getName() + "." + method.getName(), ex);
|
||||
}
|
||||
|
||||
if (responseID == 0) return;
|
||||
|
||||
InvokeMethodResult invokeMethodResult = new InvokeMethodResult();
|
||||
invokeMethodResult.objectID = invokeMethod.objectID;
|
||||
invokeMethodResult.responseID = responseID;
|
||||
|
||||
// Do not return non-primitives if transmitReturnVal is false
|
||||
if (!transmitReturnVal && !invokeMethod.method.getReturnType().isPrimitive()) {
|
||||
invokeMethodResult.result = null;
|
||||
} else {
|
||||
invokeMethodResult.result = result;
|
||||
}
|
||||
|
||||
int length = connection.sendTCP(invokeMethodResult);
|
||||
if (DEBUG) debug("kryonet", connection + " sent: " + result + " (" + length + ")");
|
||||
}
|
||||
|
||||
/** Identical to {@link #getRemoteObject(Connection, int, Class...)} except returns the object cast to the specified interface
|
||||
* type. The returned object still implements {@link RemoteObject}. */
|
||||
static public <T> T getRemoteObject (final Connection connection, int objectID, Class<T> iface) {
|
||||
return (T)getRemoteObject(connection, objectID, new Class[] {iface});
|
||||
}
|
||||
|
||||
/** Returns a proxy object that implements the specified interfaces. Methods invoked on the proxy object will be invoked
|
||||
* remotely on the object with the specified ID in the ObjectSpace for the specified connection. If the remote end of the
|
||||
* connection has not {@link #addConnection(Connection) added} the connection to the ObjectSpace, the remote method invocations
|
||||
* will be ignored.
|
||||
* <p>
|
||||
* Methods that return a value will throw {@link TimeoutException} if the response is not received with the
|
||||
* {@link RemoteObject#setResponseTimeout(int) response timeout}.
|
||||
* <p>
|
||||
* If {@link RemoteObject#setNonBlocking(boolean) non-blocking} is false (the default), then methods that return a value must
|
||||
* not be called from the update thread for the connection. An exception will be thrown if this occurs. Methods with a void
|
||||
* return value can be called on the update thread.
|
||||
* <p>
|
||||
* If a proxy returned from this method is part of an object graph sent over the network, the object graph on the receiving
|
||||
* side will have the proxy object replaced with the registered object.
|
||||
* @see RemoteObject */
|
||||
static public RemoteObject getRemoteObject (Connection connection, int objectID, Class... ifaces) {
|
||||
if (connection == null) throw new IllegalArgumentException("connection cannot be null.");
|
||||
if (ifaces == null) throw new IllegalArgumentException("ifaces cannot be null.");
|
||||
Class[] temp = new Class[ifaces.length + 1];
|
||||
temp[0] = RemoteObject.class;
|
||||
System.arraycopy(ifaces, 0, temp, 1, ifaces.length);
|
||||
return (RemoteObject)Proxy.newProxyInstance(ObjectSpace.class.getClassLoader(), temp, new RemoteInvocationHandler(
|
||||
connection, objectID));
|
||||
}
|
||||
|
||||
/** Handles network communication when methods are invoked on a proxy. */
|
||||
static private class RemoteInvocationHandler implements InvocationHandler {
|
||||
private final Connection connection;
|
||||
final int objectID;
|
||||
private int timeoutMillis = 3000;
|
||||
private boolean nonBlocking = false;
|
||||
private boolean transmitReturnValue = true;
|
||||
private boolean transmitExceptions = true;
|
||||
private Byte lastResponseID;
|
||||
private byte nextResponseNum = 1;
|
||||
private Listener responseListener;
|
||||
|
||||
final ReentrantLock lock = new ReentrantLock();
|
||||
final Condition responseCondition = lock.newCondition();
|
||||
final ConcurrentHashMap<Byte, InvokeMethodResult> responseTable = new ConcurrentHashMap();
|
||||
|
||||
public RemoteInvocationHandler (Connection connection, final int objectID) {
|
||||
super();
|
||||
this.connection = connection;
|
||||
this.objectID = objectID;
|
||||
|
||||
responseListener = new Listener() {
|
||||
public void received (Connection connection, Object object) {
|
||||
if (!(object instanceof InvokeMethodResult)) return;
|
||||
InvokeMethodResult invokeMethodResult = (InvokeMethodResult)object;
|
||||
if (invokeMethodResult.objectID != objectID) return;
|
||||
|
||||
responseTable.put(invokeMethodResult.responseID, invokeMethodResult);
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
responseCondition.signalAll();
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnected (Connection connection) {
|
||||
close();
|
||||
}
|
||||
};
|
||||
connection.addListener(responseListener);
|
||||
}
|
||||
|
||||
public Object invoke (Object proxy, Method method, Object[] args) throws Exception {
|
||||
if (method.getDeclaringClass() == RemoteObject.class) {
|
||||
String name = method.getName();
|
||||
if (name.equals("close")) {
|
||||
close();
|
||||
return null;
|
||||
} else if (name.equals("setResponseTimeout")) {
|
||||
timeoutMillis = (Integer)args[0];
|
||||
return null;
|
||||
} else if (name.equals("setNonBlocking")) {
|
||||
nonBlocking = (Boolean)args[0];
|
||||
return null;
|
||||
} else if (name.equals("setTransmitReturnValue")) {
|
||||
transmitReturnValue = (Boolean)args[0];
|
||||
return null;
|
||||
} else if (name.equals("setTransmitExceptions")) {
|
||||
transmitExceptions = (Boolean)args[0];
|
||||
return null;
|
||||
} else if (name.equals("waitForLastResponse")) {
|
||||
if (lastResponseID == null) throw new IllegalStateException("There is no last response to wait for.");
|
||||
return waitForResponse(lastResponseID);
|
||||
} else if (name.equals("getLastResponseID")) {
|
||||
if (lastResponseID == null) throw new IllegalStateException("There is no last response ID.");
|
||||
return lastResponseID;
|
||||
} else if (name.equals("waitForResponse")) {
|
||||
if (!transmitReturnValue && !transmitExceptions && nonBlocking)
|
||||
throw new IllegalStateException("This RemoteObject is currently set to ignore all responses.");
|
||||
return waitForResponse((Byte)args[0]);
|
||||
} else if (name.equals("getConnection")) {
|
||||
return connection;
|
||||
} else {
|
||||
// Should never happen, for debugging purposes only
|
||||
throw new RuntimeException("Invocation handler could not find RemoteObject method. Check ObjectSpace.java");
|
||||
}
|
||||
} else if (method.getDeclaringClass() == Object.class) {
|
||||
if (method.getName().equals("toString")) return "<proxy>";
|
||||
try {
|
||||
return method.invoke(proxy, args);
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
InvokeMethod invokeMethod = new InvokeMethod();
|
||||
invokeMethod.objectID = objectID;
|
||||
invokeMethod.method = method;
|
||||
invokeMethod.args = args;
|
||||
|
||||
// The only time a invocation doesn't need a response is if it's async
|
||||
// and no return values or exceptions are wanted back.
|
||||
boolean needsResponse = transmitReturnValue || transmitExceptions || !nonBlocking;
|
||||
if (needsResponse) {
|
||||
byte responseID;
|
||||
synchronized (this) {
|
||||
// Increment the response counter and put it into the first six bits of the responseID byte
|
||||
responseID = nextResponseNum++;
|
||||
if (nextResponseNum == 64) nextResponseNum = 1; // Keep number under 2^6, avoid 0 (see else statement below)
|
||||
}
|
||||
// Pack return value and exception info into the top two bits
|
||||
if (transmitReturnValue) responseID |= kReturnValMask;
|
||||
if (transmitExceptions) responseID |= kReturnExMask;
|
||||
invokeMethod.responseID = responseID;
|
||||
} else {
|
||||
invokeMethod.responseID = 0; // A response info of 0 means to not respond
|
||||
}
|
||||
int length = connection.sendTCP(invokeMethod);
|
||||
if (DEBUG) {
|
||||
String argString = "";
|
||||
if (args != null) {
|
||||
argString = Arrays.deepToString(args);
|
||||
argString = argString.substring(1, argString.length() - 1);
|
||||
}
|
||||
debug("kryonet", connection + " sent: " + method.getDeclaringClass().getSimpleName() + "#" + method.getName() + "("
|
||||
+ argString + ") (" + length + ")");
|
||||
}
|
||||
|
||||
if (invokeMethod.responseID != 0) lastResponseID = invokeMethod.responseID;
|
||||
if (nonBlocking) {
|
||||
Class returnType = method.getReturnType();
|
||||
if (returnType.isPrimitive()) {
|
||||
if (returnType == int.class) return 0;
|
||||
if (returnType == boolean.class) return Boolean.FALSE;
|
||||
if (returnType == float.class) return 0f;
|
||||
if (returnType == char.class) return (char)0;
|
||||
if (returnType == long.class) return 0l;
|
||||
if (returnType == short.class) return (short)0;
|
||||
if (returnType == byte.class) return (byte)0;
|
||||
if (returnType == double.class) return 0d;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Object result = waitForResponse(invokeMethod.responseID);
|
||||
if (result != null && result instanceof Exception)
|
||||
throw (Exception)result;
|
||||
else
|
||||
return result;
|
||||
} catch (TimeoutException ex) {
|
||||
throw new TimeoutException("Response timed out: " + method.getDeclaringClass().getName() + "." + method.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private Object waitForResponse (byte responseID) {
|
||||
if (connection.getEndPoint().getUpdateThread() == Thread.currentThread())
|
||||
throw new IllegalStateException("Cannot wait for an RMI response on the connection's update thread.");
|
||||
|
||||
long endTime = System.currentTimeMillis() + timeoutMillis;
|
||||
|
||||
while (true) {
|
||||
long remaining = endTime - System.currentTimeMillis();
|
||||
if (responseTable.containsKey(responseID)) {
|
||||
InvokeMethodResult invokeMethodResult = responseTable.get(responseID);
|
||||
responseTable.remove(responseID);
|
||||
lastResponseID = null;
|
||||
return invokeMethodResult.result;
|
||||
} else {
|
||||
if (remaining <= 0) throw new TimeoutException("Response timed out.");
|
||||
|
||||
lock.lock();
|
||||
try {
|
||||
responseCondition.await(remaining, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void close () {
|
||||
connection.removeListener(responseListener);
|
||||
}
|
||||
}
|
||||
|
||||
/** Internal message to invoke methods remotely. */
|
||||
static public class InvokeMethod implements FrameworkMessage, KryoSerializable {
|
||||
public int objectID;
|
||||
public Method method;
|
||||
public Object[] args;
|
||||
// The top two bytes of the ID indicate if the remote invocation should respond with return values and exceptions,
|
||||
// respectively. The rest is a six bit counter. This means up to 63 responses can be stored before undefined behavior
|
||||
// occurs due to possible duplicate IDs.
|
||||
public byte responseID;
|
||||
|
||||
public void write (Kryo kryo, Output output) {
|
||||
output.writeInt(objectID, true);
|
||||
|
||||
int methodClassID = kryo.getRegistration(method.getDeclaringClass()).getId();
|
||||
output.writeInt(methodClassID, true);
|
||||
|
||||
CachedMethod[] cachedMethods = getMethods(kryo, method.getDeclaringClass());
|
||||
CachedMethod cachedMethod = null;
|
||||
for (int i = 0, n = cachedMethods.length; i < n; i++) {
|
||||
cachedMethod = cachedMethods[i];
|
||||
if (cachedMethod.method.equals(method)) {
|
||||
output.writeByte(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0, n = cachedMethod.serializers.length; i < n; i++) {
|
||||
Serializer serializer = cachedMethod.serializers[i];
|
||||
if (serializer != null)
|
||||
kryo.writeObjectOrNull(output, args[i], serializer);
|
||||
else
|
||||
kryo.writeClassAndObject(output, args[i]);
|
||||
}
|
||||
|
||||
output.writeByte(responseID);
|
||||
}
|
||||
|
||||
public void read (Kryo kryo, Input input) {
|
||||
objectID = input.readInt(true);
|
||||
|
||||
int methodClassID = input.readInt(true);
|
||||
Class methodClass = kryo.getRegistration(methodClassID).getType();
|
||||
byte methodIndex = input.readByte();
|
||||
CachedMethod cachedMethod;
|
||||
try {
|
||||
cachedMethod = getMethods(kryo, methodClass)[methodIndex];
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
throw new KryoException("Invalid method index " + methodIndex + " for class: " + methodClass.getName());
|
||||
}
|
||||
method = cachedMethod.method;
|
||||
|
||||
args = new Object[cachedMethod.serializers.length];
|
||||
for (int i = 0, n = args.length; i < n; i++) {
|
||||
Serializer serializer = cachedMethod.serializers[i];
|
||||
if (serializer != null)
|
||||
args[i] = kryo.readObjectOrNull(input, method.getParameterTypes()[i], serializer);
|
||||
else
|
||||
args[i] = kryo.readClassAndObject(input);
|
||||
}
|
||||
|
||||
responseID = input.readByte();
|
||||
}
|
||||
}
|
||||
|
||||
/** Internal message to return the result of a remotely invoked method. */
|
||||
static public class InvokeMethodResult implements FrameworkMessage {
|
||||
public int objectID;
|
||||
public byte responseID;
|
||||
public Object result;
|
||||
}
|
||||
|
||||
static CachedMethod[] getMethods (Kryo kryo, Class type) {
|
||||
CachedMethod[] cachedMethods = methodCache.get(type);
|
||||
if (cachedMethods != null) return cachedMethods;
|
||||
|
||||
ArrayList<Method> allMethods = new ArrayList();
|
||||
Class nextClass = type;
|
||||
while (nextClass != null && nextClass != Object.class) {
|
||||
Collections.addAll(allMethods, nextClass.getDeclaredMethods());
|
||||
nextClass = nextClass.getSuperclass();
|
||||
}
|
||||
PriorityQueue<Method> methods = new PriorityQueue(Math.max(1, allMethods.size()), new Comparator<Method>() {
|
||||
public int compare (Method o1, Method o2) {
|
||||
// Methods are sorted so they can be represented as an index.
|
||||
int diff = o1.getName().compareTo(o2.getName());
|
||||
if (diff != 0) return diff;
|
||||
Class[] argTypes1 = o1.getParameterTypes();
|
||||
Class[] argTypes2 = o2.getParameterTypes();
|
||||
if (argTypes1.length > argTypes2.length) return 1;
|
||||
if (argTypes1.length < argTypes2.length) return -1;
|
||||
for (int i = 0; i < argTypes1.length; i++) {
|
||||
diff = argTypes1[i].getName().compareTo(argTypes2[i].getName());
|
||||
if (diff != 0) return diff;
|
||||
}
|
||||
throw new RuntimeException("Two methods with same signature!"); // Impossible.
|
||||
}
|
||||
});
|
||||
for (int i = 0, n = allMethods.size(); i < n; i++) {
|
||||
Method method = allMethods.get(i);
|
||||
int modifiers = method.getModifiers();
|
||||
if (Modifier.isStatic(modifiers)) continue;
|
||||
if (Modifier.isPrivate(modifiers)) continue;
|
||||
if (method.isSynthetic()) continue;
|
||||
methods.add(method);
|
||||
}
|
||||
|
||||
int n = methods.size();
|
||||
cachedMethods = new CachedMethod[n];
|
||||
for (int i = 0; i < n; i++) {
|
||||
CachedMethod cachedMethod = new CachedMethod();
|
||||
cachedMethod.method = methods.poll();
|
||||
|
||||
// Store the serializer for each final parameter.
|
||||
Class[] parameterTypes = cachedMethod.method.getParameterTypes();
|
||||
cachedMethod.serializers = new Serializer[parameterTypes.length];
|
||||
for (int ii = 0, nn = parameterTypes.length; ii < nn; ii++)
|
||||
if (kryo.isFinal(parameterTypes[ii])) cachedMethod.serializers[ii] = kryo.getSerializer(parameterTypes[ii]);
|
||||
|
||||
cachedMethods[i] = cachedMethod;
|
||||
}
|
||||
methodCache.put(type, cachedMethods);
|
||||
return cachedMethods;
|
||||
}
|
||||
|
||||
/** Returns the first object registered with the specified ID in any of the ObjectSpaces the specified connection belongs to. */
|
||||
static Object getRegisteredObject (Connection connection, int objectID) {
|
||||
ObjectSpace[] instances = ObjectSpace.instances;
|
||||
for (int i = 0, n = instances.length; i < n; i++) {
|
||||
ObjectSpace objectSpace = instances[i];
|
||||
// Check if the connection is in this ObjectSpace.
|
||||
Connection[] connections = objectSpace.connections;
|
||||
for (int j = 0; j < connections.length; j++) {
|
||||
if (connections[j] != connection) continue;
|
||||
// Find an object with the objectID.
|
||||
Object object = objectSpace.idToObject.get(objectID);
|
||||
if (object != null) return object;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Registers the classes needed to use ObjectSpaces. This should be called before any connections are opened.
|
||||
* @see Kryo#register(Class, Serializer) */
|
||||
static public void registerClasses (final Kryo kryo) {
|
||||
kryo.register(Object[].class);
|
||||
kryo.register(InvokeMethod.class);
|
||||
|
||||
FieldSerializer serializer = (FieldSerializer)kryo.register(InvokeMethodResult.class).getSerializer();
|
||||
serializer.getField("objectID").setClass(int.class, new Serializer<Integer>() {
|
||||
public void write (Kryo kryo, Output output, Integer object) {
|
||||
output.writeInt(object, true);
|
||||
}
|
||||
|
||||
public Integer read (Kryo kryo, Input input, Class<Integer> type) {
|
||||
return input.readInt(true);
|
||||
}
|
||||
});
|
||||
|
||||
kryo.register(InvocationHandler.class, new Serializer() {
|
||||
public void write (Kryo kryo, Output output, Object object) {
|
||||
RemoteInvocationHandler handler = (RemoteInvocationHandler)Proxy.getInvocationHandler(object);
|
||||
output.writeInt(handler.objectID, true);
|
||||
}
|
||||
|
||||
public Object read (Kryo kryo, Input input, Class type) {
|
||||
int objectID = input.readInt(true);
|
||||
Connection connection = (Connection)kryo.getContext().get("connection");
|
||||
Object object = getRegisteredObject(connection, objectID);
|
||||
if (WARN && object == null) warn("kryonet", "Unknown object ID " + objectID + " for connection: " + connection);
|
||||
return object;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static class CachedMethod {
|
||||
Method method;
|
||||
Serializer[] serializers;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.rmi;
|
||||
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
|
||||
/** Provides access to various settings on a remote object.
|
||||
* @see ObjectSpace#getRemoteObject(com.esotericsoftware.kryonet.Connection, int, Class...)
|
||||
* @author Nathan Sweet <misc@n4te.com> */
|
||||
public interface RemoteObject {
|
||||
/** Sets the milliseconds to wait for a method to return value. Default is 3000. */
|
||||
public void setResponseTimeout (int timeoutMillis);
|
||||
|
||||
/** Sets the blocking behavior when invoking a remote method. Default is false.
|
||||
* @param nonBlocking If false, the invoking thread will wait for the remote method to return or timeout (default). If true,
|
||||
* the invoking thread will not wait for a response. The method will return immediately and the return value should
|
||||
* be ignored. If they are being transmitted, the return value or any thrown exception can later be retrieved with
|
||||
* {@link #waitForLastResponse()} or {@link #waitForResponse(byte)}. The responses will be stored until retrieved, so
|
||||
* each method call should have a matching retrieve. */
|
||||
public void setNonBlocking (boolean nonBlocking);
|
||||
|
||||
/** Sets whether return values are sent back when invoking a remote method. Default is true.
|
||||
* @param transmit If true, then the return value for non-blocking method invocations can be retrieved with
|
||||
* {@link #waitForLastResponse()} or {@link #waitForResponse(byte)}. If false, then non-primitive return values for
|
||||
* remote method invocations are not sent by the remote side of the connection and the response can never be
|
||||
* retrieved. This can also be used to save bandwidth if you will not check the return value of a blocking remote
|
||||
* invocation. Note that an exception could still be returned by {@link #waitForLastResponse()} or
|
||||
* {@link #waitForResponse(byte)} if {@link #setTransmitExceptions(boolean)} is true. */
|
||||
public void setTransmitReturnValue (boolean transmit);
|
||||
|
||||
/** Sets whether exceptions are sent back when invoking a remote method. Default is true.
|
||||
* @param transmit If false, exceptions will be unhandled and rethrown as RuntimeExceptions inside the invoking thread. This is
|
||||
* the legacy behavior. If true, behavior is dependent on whether {@link #setNonBlocking(boolean)}. If non-blocking
|
||||
* is true, the exception will be serialized and sent back to the call site of the remotely invoked method, where it
|
||||
* will be re-thrown. If non-blocking is false, an exception will not be thrown in the calling thread but instead can
|
||||
* be retrieved with {@link #waitForLastResponse()} or {@link #waitForResponse(byte)}, similar to a return value. */
|
||||
public void setTransmitExceptions (boolean transmit);
|
||||
|
||||
/** Waits for the response to the last method invocation to be received or the response timeout to be reached. Must not be
|
||||
* called from the connection's update thread.
|
||||
* @see ObjectSpace#getRemoteObject(com.esotericsoftware.kryonet.Connection, int, Class...) */
|
||||
public Object waitForLastResponse ();
|
||||
|
||||
/** Gets the ID of response for the last method invocation. */
|
||||
public byte getLastResponseID ();
|
||||
|
||||
/** Waits for the specified method invocation response to be received or the response timeout to be reached. Must not be called
|
||||
* from the connection's update thread. Response IDs use a six bit identifier, with one identifier reserved for "no response".
|
||||
* This means that this method should be called to get the result for a non-blocking call before an additional 63 non-blocking
|
||||
* calls are made, or risk undefined behavior due to identical IDs.
|
||||
* @see ObjectSpace#getRemoteObject(com.esotericsoftware.kryonet.Connection, int, Class...) */
|
||||
public Object waitForResponse (byte responseID);
|
||||
|
||||
/** Causes this RemoteObject to stop listening to the connection for method invocation response messages. */
|
||||
public void close ();
|
||||
|
||||
/** Returns the local connection for this remote object. */
|
||||
public Connection getConnection ();
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.rmi;
|
||||
|
||||
/** Thrown when a method with a return value is invoked on a remote object and the response is not received with the
|
||||
* {@link RemoteObject#setResponseTimeout(int) response timeout}.
|
||||
* @see ObjectSpace#getRemoteObject(com.esotericsoftware.kryonet.Connection, int, Class...)
|
||||
* @author Nathan Sweet <misc@n4te.com> */
|
||||
public class TimeoutException extends RuntimeException {
|
||||
public TimeoutException () {
|
||||
super();
|
||||
}
|
||||
|
||||
public TimeoutException (String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public TimeoutException (String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TimeoutException (Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.esotericsoftware.kryonet.KryoNetException;
|
||||
|
||||
abstract public class InputStreamSender extends TcpIdleSender {
|
||||
private final InputStream input;
|
||||
private final byte[] chunk;
|
||||
|
||||
public InputStreamSender (InputStream input, int chunkSize) {
|
||||
this.input = input;
|
||||
chunk = new byte[chunkSize];
|
||||
}
|
||||
|
||||
protected final Object next () {
|
||||
try {
|
||||
int total = 0;
|
||||
while (total < chunk.length) {
|
||||
int count = input.read(chunk, total, chunk.length - total);
|
||||
if (count < 0) {
|
||||
if (total == 0) return null;
|
||||
byte[] partial = new byte[total];
|
||||
System.arraycopy(chunk, 0, partial, 0, total);
|
||||
return next(partial);
|
||||
}
|
||||
total += count;
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
throw new KryoNetException(ex);
|
||||
}
|
||||
return next(chunk);
|
||||
}
|
||||
|
||||
abstract protected Object next (byte[] chunk);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.util;
|
||||
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
|
||||
abstract public class TcpIdleSender extends Listener {
|
||||
boolean started;
|
||||
|
||||
public void idle (Connection connection) {
|
||||
if (!started) {
|
||||
started = true;
|
||||
start();
|
||||
}
|
||||
Object object = next();
|
||||
if (object == null)
|
||||
connection.removeListener(this);
|
||||
else
|
||||
connection.sendTCP(object);
|
||||
}
|
||||
|
||||
/** Called once, before the first send. Subclasses can override this method to send something so the receiving side expects
|
||||
* subsequent objects. */
|
||||
protected void start () {
|
||||
}
|
||||
|
||||
/** Returns the next object to send, or null if no more objects will be sent. */
|
||||
abstract protected Object next ();
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
|
||||
public class BufferTest extends KryoNetTestCase {
|
||||
AtomicInteger received = new AtomicInteger();
|
||||
AtomicInteger receivedBytes = new AtomicInteger();
|
||||
|
||||
public void testManyLargeMessages () throws IOException {
|
||||
final int messageCount = 1024;
|
||||
int objectBufferSize = 10250;
|
||||
int writeBufferSize = 10250 * messageCount;
|
||||
|
||||
Server server = new Server(writeBufferSize, objectBufferSize);
|
||||
startEndPoint(server);
|
||||
register(server.getKryo());
|
||||
server.bind(tcpPort);
|
||||
|
||||
server.addListener(new Listener() {
|
||||
AtomicInteger received = new AtomicInteger();
|
||||
AtomicInteger receivedBytes = new AtomicInteger();
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof LargeMessage) {
|
||||
System.out.println("Server sending message: " + received.get());
|
||||
connection.sendTCP(object);
|
||||
|
||||
receivedBytes.addAndGet(((LargeMessage)object).bytes.length);
|
||||
|
||||
int count = received.incrementAndGet();
|
||||
System.out.println("Server received " + count + " messages.");
|
||||
if (count == messageCount) {
|
||||
System.out.println("Server received all " + messageCount + " messages!");
|
||||
System.out.println("Server received and sent " + receivedBytes.get() + " bytes.");
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final Client client = new Client(writeBufferSize, objectBufferSize);
|
||||
startEndPoint(client);
|
||||
register(client.getKryo());
|
||||
client.connect(5000, host, tcpPort);
|
||||
|
||||
client.addListener(new Listener() {
|
||||
AtomicInteger received = new AtomicInteger();
|
||||
AtomicInteger receivedBytes = new AtomicInteger();
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof LargeMessage) {
|
||||
int count = received.incrementAndGet();
|
||||
System.out.println("Client received " + count + " messages.");
|
||||
if (count == messageCount) {
|
||||
System.out.println("Client received all " + messageCount + " messages!");
|
||||
System.out.println("Client received and sent " + receivedBytes.get() + " bytes.");
|
||||
stopEndPoints();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
byte[] b = new byte[1024 * 10];
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
System.out.println("Client sending: " + i);
|
||||
client.sendTCP(new LargeMessage(b));
|
||||
}
|
||||
System.out.println("Client has queued " + messageCount + " messages.");
|
||||
|
||||
waitForThreads(5000);
|
||||
}
|
||||
|
||||
private void register (Kryo kryo) {
|
||||
kryo.register(byte[].class);
|
||||
kryo.register(LargeMessage.class);
|
||||
}
|
||||
|
||||
public static class LargeMessage {
|
||||
public byte[] bytes;
|
||||
|
||||
public LargeMessage () {
|
||||
}
|
||||
|
||||
public LargeMessage (byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
|
||||
public class DiscoverHostTest extends KryoNetTestCase {
|
||||
public void testBroadcast () throws IOException {
|
||||
// This server exists solely to reply to Client#discoverHost.
|
||||
// It wouldn't be needed if the real server was using UDP.
|
||||
final Server broadcastServer = new Server();
|
||||
startEndPoint(broadcastServer);
|
||||
broadcastServer.bind(0, udpPort);
|
||||
|
||||
final Server server = new Server();
|
||||
startEndPoint(server);
|
||||
server.bind(54555);
|
||||
server.addListener(new Listener() {
|
||||
public void disconnected (Connection connection) {
|
||||
broadcastServer.stop();
|
||||
server.stop();
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
Client client = new Client();
|
||||
InetAddress host = client.discoverHost(udpPort, 2000);
|
||||
if (host == null) {
|
||||
stopEndPoints();
|
||||
fail("No servers found.");
|
||||
return;
|
||||
}
|
||||
|
||||
startEndPoint(client);
|
||||
client.connect(2000, host, tcpPort);
|
||||
client.stop();
|
||||
|
||||
waitForThreads();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import com.esotericsoftware.kryonet.util.InputStreamSender;
|
||||
|
||||
public class InputStreamSenderTest extends KryoNetTestCase {
|
||||
boolean success;
|
||||
|
||||
public void testStream () throws IOException {
|
||||
final int largeDataSize = 12345;
|
||||
|
||||
final Server server = new Server(16384, 8192);
|
||||
server.getKryo().setRegistrationRequired(false);
|
||||
startEndPoint(server);
|
||||
server.bind(tcpPort, udpPort);
|
||||
server.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream(largeDataSize);
|
||||
for (int i = 0; i < largeDataSize; i++)
|
||||
output.write(i);
|
||||
ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
|
||||
// Send data in 512 byte chunks.
|
||||
connection.addListener(new InputStreamSender(input, 512) {
|
||||
protected void start () {
|
||||
// Normally would send an object so the receiving side knows how to handle the chunks we are about to send.
|
||||
System.out.println("starting");
|
||||
}
|
||||
|
||||
protected Object next (byte[] bytes) {
|
||||
System.out.println("sending " + bytes.length);
|
||||
return bytes; // Normally would wrap the byte[] with an object so the receiving side knows how to handle it.
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
final Client client = new Client(16384, 8192);
|
||||
client.getKryo().setRegistrationRequired(false);
|
||||
startEndPoint(client);
|
||||
client.addListener(new Listener() {
|
||||
int total;
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof byte[]) {
|
||||
int length = ((byte[])object).length;
|
||||
System.out.println("received " + length);
|
||||
total += length;
|
||||
if (total == largeDataSize) {
|
||||
success = true;
|
||||
stopEndPoints();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.connect(5000, host, tcpPort, udpPort);
|
||||
|
||||
waitForThreads(5000);
|
||||
if (!success) fail();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import com.esotericsoftware.jsonbeans.JsonWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class JsonTest extends KryoNetTestCase {
|
||||
String fail;
|
||||
|
||||
public void testJson () throws IOException {
|
||||
fail = null;
|
||||
|
||||
final Data dataTCP = new Data();
|
||||
populateData(dataTCP, true);
|
||||
final Data dataUDP = new Data();
|
||||
populateData(dataUDP, false);
|
||||
|
||||
final Server server = new Server(16384, 8192, new JsonSerialization());
|
||||
startEndPoint(server);
|
||||
server.bind(tcpPort, udpPort);
|
||||
server.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
connection.sendTCP(dataTCP);
|
||||
connection.sendUDP(dataUDP); // Note UDP ping pong stops if a UDP packet is lost.
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof Data) {
|
||||
Data data = (Data)object;
|
||||
if (data.isTCP) {
|
||||
if (!data.equals(dataTCP)) {
|
||||
fail = "TCP data is not equal on server.";
|
||||
throw new RuntimeException("Fail!");
|
||||
}
|
||||
connection.sendTCP(data);
|
||||
} else {
|
||||
if (!data.equals(dataUDP)) {
|
||||
fail = "UDP data is not equal on server.";
|
||||
throw new RuntimeException("Fail!");
|
||||
}
|
||||
connection.sendUDP(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
final Client client = new Client(16384, 8192, new JsonSerialization());
|
||||
startEndPoint(client);
|
||||
client.addListener(new Listener() {
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof Data) {
|
||||
Data data = (Data)object;
|
||||
if (data.isTCP) {
|
||||
if (!data.equals(dataTCP)) {
|
||||
fail = "TCP data is not equal on client.";
|
||||
throw new RuntimeException("Fail!");
|
||||
}
|
||||
connection.sendTCP(data);
|
||||
} else {
|
||||
if (!data.equals(dataUDP)) {
|
||||
fail = "UDP data is not equal on client.";
|
||||
throw new RuntimeException("Fail!");
|
||||
}
|
||||
connection.sendUDP(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.connect(5000, host, tcpPort, udpPort);
|
||||
|
||||
waitForThreads(5000);
|
||||
|
||||
if (fail != null) fail(fail);
|
||||
}
|
||||
|
||||
private void populateData (Data data, boolean isTCP) {
|
||||
data.isTCP = isTCP;
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
for (int i = 0; i < 3000; i++)
|
||||
buffer.append('a');
|
||||
data.string = buffer.toString();
|
||||
|
||||
data.strings = new String[] {"abcdefghijklmnopqrstuvwxyz0123456789", "", null, "!@#$", "<22><><EFBFBD><EFBFBD><EFBFBD>"};
|
||||
data.ints = new int[] {-1234567, 1234567, -1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE};
|
||||
data.shorts = new short[] {-12345, 12345, -1, 0, 1, Short.MAX_VALUE, Short.MIN_VALUE};
|
||||
data.floats = new float[] {0, 1, -1, 123456, -123456, 0.1f, 0.2f, -0.3f, (float)Math.PI, Float.MAX_VALUE, Float.MIN_VALUE};
|
||||
data.bytes = new byte[] {-123, 123, -1, 0, 1, Byte.MAX_VALUE, Byte.MIN_VALUE};
|
||||
data.booleans = new boolean[] {true, false};
|
||||
data.Ints = new Integer[] {-1234567, 1234567, -1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE};
|
||||
data.Shorts = new Short[] {-12345, 12345, -1, 0, 1, Short.MAX_VALUE, Short.MIN_VALUE};
|
||||
data.Floats = new Float[] {0f, 1f, -1f, 123456f, -123456f, 0.1f, 0.2f, -0.3f, (float)Math.PI, Float.MAX_VALUE,
|
||||
Float.MIN_VALUE};
|
||||
data.Bytes = new Byte[] {-123, 123, -1, 0, 1, Byte.MAX_VALUE, Byte.MIN_VALUE};
|
||||
data.Booleans = new Boolean[] {true, false};
|
||||
}
|
||||
|
||||
static public class Data {
|
||||
public String string;
|
||||
public String[] strings;
|
||||
public int[] ints;
|
||||
public short[] shorts;
|
||||
public float[] floats;
|
||||
public byte[] bytes;
|
||||
public boolean[] booleans;
|
||||
public Integer[] Ints;
|
||||
public Short[] Shorts;
|
||||
public Float[] Floats;
|
||||
public Byte[] Bytes;
|
||||
public Boolean[] Booleans;
|
||||
public boolean isTCP;
|
||||
|
||||
public int hashCode () {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode(Booleans);
|
||||
result = prime * result + Arrays.hashCode(Bytes);
|
||||
result = prime * result + Arrays.hashCode(Floats);
|
||||
result = prime * result + Arrays.hashCode(Ints);
|
||||
result = prime * result + Arrays.hashCode(Shorts);
|
||||
result = prime * result + Arrays.hashCode(booleans);
|
||||
result = prime * result + Arrays.hashCode(bytes);
|
||||
result = prime * result + Arrays.hashCode(floats);
|
||||
result = prime * result + Arrays.hashCode(ints);
|
||||
result = prime * result + (isTCP ? 1231 : 1237);
|
||||
result = prime * result + Arrays.hashCode(shorts);
|
||||
result = prime * result + ((string == null) ? 0 : string.hashCode());
|
||||
result = prime * result + Arrays.hashCode(strings);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals (Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
Data other = (Data)obj;
|
||||
if (!Arrays.equals(Booleans, other.Booleans)) return false;
|
||||
if (!Arrays.equals(Bytes, other.Bytes)) return false;
|
||||
if (!Arrays.equals(Floats, other.Floats)) return false;
|
||||
if (!Arrays.equals(Ints, other.Ints)) return false;
|
||||
if (!Arrays.equals(Shorts, other.Shorts)) return false;
|
||||
if (!Arrays.equals(booleans, other.booleans)) return false;
|
||||
if (!Arrays.equals(bytes, other.bytes)) return false;
|
||||
if (!Arrays.equals(floats, other.floats)) return false;
|
||||
if (!Arrays.equals(ints, other.ints)) return false;
|
||||
if (isTCP != other.isTCP) return false;
|
||||
if (!Arrays.equals(shorts, other.shorts)) return false;
|
||||
if (string == null) {
|
||||
if (other.string != null) return false;
|
||||
} else if (!string.equals(other.string)) return false;
|
||||
if (!Arrays.equals(strings, other.strings)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString () {
|
||||
return "Data";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.esotericsoftware.minlog.Log;
|
||||
|
||||
abstract public class KryoNetTestCase extends TestCase {
|
||||
static public String host = "localhost";
|
||||
static public int tcpPort = 54555, udpPort = 54777;
|
||||
|
||||
private ArrayList<Thread> threads = new ArrayList();
|
||||
ArrayList<EndPoint> endPoints = new ArrayList();
|
||||
private Timer timer;
|
||||
boolean fail;
|
||||
|
||||
public KryoNetTestCase () {
|
||||
// Log.TRACE();
|
||||
// Log.DEBUG();
|
||||
}
|
||||
|
||||
protected void setUp () throws Exception {
|
||||
System.out.println("---- " + getClass().getSimpleName());
|
||||
timer = new Timer();
|
||||
}
|
||||
|
||||
protected void tearDown () throws Exception {
|
||||
timer.cancel();
|
||||
}
|
||||
|
||||
public void startEndPoint (EndPoint endPoint) {
|
||||
endPoints.add(endPoint);
|
||||
Thread thread = new Thread(endPoint, endPoint.getClass().getSimpleName());
|
||||
threads.add(thread);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void stopEndPoints () {
|
||||
stopEndPoints(0);
|
||||
}
|
||||
|
||||
public void stopEndPoints (int stopAfterMillis) {
|
||||
timer.schedule(new TimerTask() {
|
||||
public void run () {
|
||||
for (EndPoint endPoint : endPoints)
|
||||
endPoint.stop();
|
||||
endPoints.clear();
|
||||
}
|
||||
}, stopAfterMillis);
|
||||
}
|
||||
|
||||
public void waitForThreads (int stopAfterMillis) {
|
||||
if (stopAfterMillis > 10000) throw new IllegalArgumentException("stopAfterMillis must be < 10000");
|
||||
stopEndPoints(stopAfterMillis);
|
||||
waitForThreads();
|
||||
}
|
||||
|
||||
public void waitForThreads () {
|
||||
fail = false;
|
||||
TimerTask failTask = new TimerTask() {
|
||||
public void run () {
|
||||
stopEndPoints();
|
||||
fail = true;
|
||||
}
|
||||
};
|
||||
timer.schedule(failTask, 11000);
|
||||
while (true) {
|
||||
for (Iterator iter = threads.iterator(); iter.hasNext();) {
|
||||
Thread thread = (Thread)iter.next();
|
||||
if (!thread.isAlive()) iter.remove();
|
||||
}
|
||||
if (threads.isEmpty()) break;
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
failTask.cancel();
|
||||
if (fail) fail("Test did not complete in a timely manner.");
|
||||
// Give sockets a chance to close before starting the next test.
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
|
||||
public class MultipleServerTest extends KryoNetTestCase {
|
||||
AtomicInteger received = new AtomicInteger();
|
||||
|
||||
public void testMultipleThreads () throws IOException {
|
||||
final Server server1 = new Server(16384, 8192);
|
||||
server1.getKryo().register(String[].class);
|
||||
startEndPoint(server1);
|
||||
server1.bind(tcpPort, udpPort);
|
||||
server1.addListener(new Listener() {
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof String) {
|
||||
if (!object.equals("client1")) fail();
|
||||
if (received.incrementAndGet() == 2) stopEndPoints();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final Server server2 = new Server(16384, 8192);
|
||||
server2.getKryo().register(String[].class);
|
||||
startEndPoint(server2);
|
||||
server2.bind(tcpPort + 1, udpPort + 1);
|
||||
server2.addListener(new Listener() {
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof String) {
|
||||
if (!object.equals("client2")) fail();
|
||||
if (received.incrementAndGet() == 2) stopEndPoints();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
Client client1 = new Client(16384, 8192);
|
||||
client1.getKryo().register(String[].class);
|
||||
startEndPoint(client1);
|
||||
client1.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
connection.sendTCP("client1");
|
||||
}
|
||||
});
|
||||
client1.connect(5000, host, tcpPort, udpPort);
|
||||
|
||||
Client client2 = new Client(16384, 8192);
|
||||
client2.getKryo().register(String[].class);
|
||||
startEndPoint(client2);
|
||||
client2.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
connection.sendTCP("client2");
|
||||
}
|
||||
});
|
||||
client2.connect(5000, host, tcpPort + 1, udpPort + 1);
|
||||
|
||||
waitForThreads(5000);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
|
||||
public class MultipleThreadTest extends KryoNetTestCase {
|
||||
int receivedServer, receivedClient1, receivedClient2;
|
||||
|
||||
public void testMultipleThreads () throws IOException {
|
||||
receivedServer = 0;
|
||||
|
||||
final int messageCount = 10;
|
||||
final int threads = 5;
|
||||
final int sleepMillis = 50;
|
||||
final int clients = 3;
|
||||
|
||||
final Server server = new Server(16384, 8192);
|
||||
server.getKryo().register(String[].class);
|
||||
startEndPoint(server);
|
||||
server.bind(tcpPort, udpPort);
|
||||
server.addListener(new Listener() {
|
||||
public void received (Connection connection, Object object) {
|
||||
receivedServer++;
|
||||
if (receivedServer == messageCount * clients) stopEndPoints();
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
for (int i = 0; i < clients; i++) {
|
||||
Client client = new Client(16384, 8192);
|
||||
client.getKryo().register(String[].class);
|
||||
startEndPoint(client);
|
||||
client.addListener(new Listener() {
|
||||
int received;
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof String) {
|
||||
received++;
|
||||
if (received == messageCount * threads) {
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
connection.sendTCP("message" + i);
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
client.connect(5000, host, tcpPort, udpPort);
|
||||
}
|
||||
|
||||
for (int i = 0; i < threads; i++) {
|
||||
new Thread() {
|
||||
public void run () {
|
||||
Connection[] connections = server.getConnections();
|
||||
for (int i = 0; i < messageCount; i++) {
|
||||
for (int ii = 0, n = connections.length; ii < n; ii++)
|
||||
connections[ii].sendTCP("message" + i);
|
||||
try {
|
||||
Thread.sleep(sleepMillis);
|
||||
} catch (InterruptedException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
waitForThreads(5000);
|
||||
|
||||
assertEquals(messageCount * clients, receivedServer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
|
||||
public class PingPongTest extends KryoNetTestCase {
|
||||
String fail;
|
||||
|
||||
public void testPingPong () throws IOException {
|
||||
fail = null;
|
||||
|
||||
final Data dataTCP = new Data();
|
||||
populateData(dataTCP, true);
|
||||
final Data dataUDP = new Data();
|
||||
populateData(dataUDP, false);
|
||||
|
||||
final Server server = new Server(16384, 8192);
|
||||
register(server.getKryo());
|
||||
startEndPoint(server);
|
||||
server.bind(tcpPort, udpPort);
|
||||
server.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
connection.sendTCP(dataTCP);
|
||||
connection.sendUDP(dataUDP); // Note UDP ping pong stops if a UDP packet is lost.
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof Data) {
|
||||
Data data = (Data)object;
|
||||
if (data.isTCP) {
|
||||
if (!data.equals(dataTCP)) {
|
||||
fail = "TCP data is not equal on server.";
|
||||
throw new RuntimeException("Fail!");
|
||||
}
|
||||
connection.sendTCP(data);
|
||||
} else {
|
||||
if (!data.equals(dataUDP)) {
|
||||
fail = "UDP data is not equal on server.";
|
||||
throw new RuntimeException("Fail!");
|
||||
}
|
||||
connection.sendUDP(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
final Client client = new Client(16384, 8192);
|
||||
register(client.getKryo());
|
||||
startEndPoint(client);
|
||||
client.addListener(new Listener() {
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof Data) {
|
||||
Data data = (Data)object;
|
||||
if (data.isTCP) {
|
||||
if (!data.equals(dataTCP)) {
|
||||
fail = "TCP data is not equal on client.";
|
||||
throw new RuntimeException("Fail!");
|
||||
}
|
||||
connection.sendTCP(data);
|
||||
} else {
|
||||
if (!data.equals(dataUDP)) {
|
||||
fail = "UDP data is not equal on client.";
|
||||
throw new RuntimeException("Fail!");
|
||||
}
|
||||
connection.sendUDP(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.connect(5000, host, tcpPort, udpPort);
|
||||
|
||||
waitForThreads(5000);
|
||||
}
|
||||
|
||||
private void populateData (Data data, boolean isTCP) {
|
||||
data.isTCP = isTCP;
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
for (int i = 0; i < 3000; i++)
|
||||
buffer.append('a');
|
||||
data.string = buffer.toString();
|
||||
|
||||
data.strings = new String[] {"abcdefghijklmnopqrstuvwxyz0123456789", "", null, "!@#$", "<22><><EFBFBD><EFBFBD><EFBFBD>"};
|
||||
data.ints = new int[] {-1234567, 1234567, -1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE};
|
||||
data.shorts = new short[] {-12345, 12345, -1, 0, 1, Short.MAX_VALUE, Short.MIN_VALUE};
|
||||
data.floats = new float[] {0, -0, 1, -1, 123456, -123456, 0.1f, 0.2f, -0.3f, (float)Math.PI, Float.MAX_VALUE,
|
||||
Float.MIN_VALUE};
|
||||
data.doubles = new double[] {0, -0, 1, -1, 123456, -123456, 0.1d, 0.2d, -0.3d, Math.PI, Double.MAX_VALUE, Double.MIN_VALUE};
|
||||
data.longs = new long[] {0, -0, 1, -1, 123456, -123456, 99999999999l, -99999999999l, Long.MAX_VALUE, Long.MIN_VALUE};
|
||||
data.bytes = new byte[] {-123, 123, -1, 0, 1, Byte.MAX_VALUE, Byte.MIN_VALUE};
|
||||
data.chars = new char[] {32345, 12345, 0, 1, 63, Character.MAX_VALUE, Character.MIN_VALUE};
|
||||
data.booleans = new boolean[] {true, false};
|
||||
data.Ints = new Integer[] {-1234567, 1234567, -1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE};
|
||||
data.Shorts = new Short[] {-12345, 12345, -1, 0, 1, Short.MAX_VALUE, Short.MIN_VALUE};
|
||||
data.Floats = new Float[] {0f, -0f, 1f, -1f, 123456f, -123456f, 0.1f, 0.2f, -0.3f, (float)Math.PI, Float.MAX_VALUE,
|
||||
Float.MIN_VALUE};
|
||||
data.Doubles = new Double[] {0d, -0d, 1d, -1d, 123456d, -123456d, 0.1d, 0.2d, -0.3d, Math.PI, Double.MAX_VALUE,
|
||||
Double.MIN_VALUE};
|
||||
data.Longs = new Long[] {0l, -0l, 1l, -1l, 123456l, -123456l, 99999999999l, -99999999999l, Long.MAX_VALUE, Long.MIN_VALUE};
|
||||
data.Bytes = new Byte[] {-123, 123, -1, 0, 1, Byte.MAX_VALUE, Byte.MIN_VALUE};
|
||||
data.Chars = new Character[] {32345, 12345, 0, 1, 63, Character.MAX_VALUE, Character.MIN_VALUE};
|
||||
data.Booleans = new Boolean[] {true, false};
|
||||
}
|
||||
|
||||
private void register (Kryo kryo) {
|
||||
kryo.register(String[].class);
|
||||
kryo.register(int[].class);
|
||||
kryo.register(short[].class);
|
||||
kryo.register(float[].class);
|
||||
kryo.register(double[].class);
|
||||
kryo.register(long[].class);
|
||||
kryo.register(byte[].class);
|
||||
kryo.register(char[].class);
|
||||
kryo.register(boolean[].class);
|
||||
kryo.register(Integer[].class);
|
||||
kryo.register(Short[].class);
|
||||
kryo.register(Float[].class);
|
||||
kryo.register(Double[].class);
|
||||
kryo.register(Long[].class);
|
||||
kryo.register(Byte[].class);
|
||||
kryo.register(Character[].class);
|
||||
kryo.register(Boolean[].class);
|
||||
kryo.register(Data.class);
|
||||
}
|
||||
|
||||
static public class Data {
|
||||
public String string;
|
||||
public String[] strings;
|
||||
public int[] ints;
|
||||
public short[] shorts;
|
||||
public float[] floats;
|
||||
public double[] doubles;
|
||||
public long[] longs;
|
||||
public byte[] bytes;
|
||||
public char[] chars;
|
||||
public boolean[] booleans;
|
||||
public Integer[] Ints;
|
||||
public Short[] Shorts;
|
||||
public Float[] Floats;
|
||||
public Double[] Doubles;
|
||||
public Long[] Longs;
|
||||
public Byte[] Bytes;
|
||||
public Character[] Chars;
|
||||
public Boolean[] Booleans;
|
||||
public boolean isTCP;
|
||||
|
||||
public int hashCode () {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode(Booleans);
|
||||
result = prime * result + Arrays.hashCode(Bytes);
|
||||
result = prime * result + Arrays.hashCode(Chars);
|
||||
result = prime * result + Arrays.hashCode(Doubles);
|
||||
result = prime * result + Arrays.hashCode(Floats);
|
||||
result = prime * result + Arrays.hashCode(Ints);
|
||||
result = prime * result + Arrays.hashCode(Longs);
|
||||
result = prime * result + Arrays.hashCode(Shorts);
|
||||
result = prime * result + Arrays.hashCode(booleans);
|
||||
result = prime * result + Arrays.hashCode(bytes);
|
||||
result = prime * result + Arrays.hashCode(chars);
|
||||
result = prime * result + Arrays.hashCode(doubles);
|
||||
result = prime * result + Arrays.hashCode(floats);
|
||||
result = prime * result + Arrays.hashCode(ints);
|
||||
result = prime * result + (isTCP ? 1231 : 1237);
|
||||
result = prime * result + Arrays.hashCode(longs);
|
||||
result = prime * result + Arrays.hashCode(shorts);
|
||||
result = prime * result + ((string == null) ? 0 : string.hashCode());
|
||||
result = prime * result + Arrays.hashCode(strings);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals (Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
Data other = (Data)obj;
|
||||
if (!Arrays.equals(Booleans, other.Booleans)) return false;
|
||||
if (!Arrays.equals(Bytes, other.Bytes)) return false;
|
||||
if (!Arrays.equals(Chars, other.Chars)) return false;
|
||||
if (!Arrays.equals(Doubles, other.Doubles)) return false;
|
||||
if (!Arrays.equals(Floats, other.Floats)) return false;
|
||||
if (!Arrays.equals(Ints, other.Ints)) return false;
|
||||
if (!Arrays.equals(Longs, other.Longs)) return false;
|
||||
if (!Arrays.equals(Shorts, other.Shorts)) return false;
|
||||
if (!Arrays.equals(booleans, other.booleans)) return false;
|
||||
if (!Arrays.equals(bytes, other.bytes)) return false;
|
||||
if (!Arrays.equals(chars, other.chars)) return false;
|
||||
if (!Arrays.equals(doubles, other.doubles)) return false;
|
||||
if (!Arrays.equals(floats, other.floats)) return false;
|
||||
if (!Arrays.equals(ints, other.ints)) return false;
|
||||
if (isTCP != other.isTCP) return false;
|
||||
if (!Arrays.equals(longs, other.longs)) return false;
|
||||
if (!Arrays.equals(shorts, other.shorts)) return false;
|
||||
if (string == null) {
|
||||
if (other.string != null) return false;
|
||||
} else if (!string.equals(other.string)) return false;
|
||||
if (!Arrays.equals(strings, other.strings)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString () {
|
||||
return "Data";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.esotericsoftware.kryonet.FrameworkMessage.Ping;
|
||||
|
||||
public class PingTest extends KryoNetTestCase {
|
||||
public void testPing () throws IOException {
|
||||
final Server server = new Server();
|
||||
startEndPoint(server);
|
||||
server.bind(tcpPort);
|
||||
|
||||
// ----
|
||||
|
||||
final Client client = new Client();
|
||||
startEndPoint(client);
|
||||
client.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
client.updateReturnTripTime();
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof Ping) {
|
||||
Ping ping = (Ping)object;
|
||||
if (ping.isReply) System.out.println("Ping: " + connection.getReturnTripTime());
|
||||
client.updateReturnTripTime();
|
||||
}
|
||||
}
|
||||
});
|
||||
client.connect(5000, host, tcpPort);
|
||||
|
||||
waitForThreads(5000);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ReconnectTest extends KryoNetTestCase {
|
||||
public void testReconnect () throws IOException {
|
||||
final Timer timer = new Timer();
|
||||
|
||||
final Server server = new Server();
|
||||
startEndPoint(server);
|
||||
server.bind(tcpPort);
|
||||
server.addListener(new Listener() {
|
||||
public void connected (final Connection connection) {
|
||||
timer.schedule(new TimerTask() {
|
||||
public void run () {
|
||||
System.out.println("Disconnecting after 2 seconds.");
|
||||
connection.close();
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
final AtomicInteger reconnetCount = new AtomicInteger();
|
||||
final Client client = new Client();
|
||||
startEndPoint(client);
|
||||
client.addListener(new Listener() {
|
||||
public void disconnected (Connection connection) {
|
||||
if (reconnetCount.getAndIncrement() == 2) {
|
||||
stopEndPoints();
|
||||
return;
|
||||
}
|
||||
new Thread() {
|
||||
public void run () {
|
||||
try {
|
||||
System.out.println("Reconnecting: " + reconnetCount.get());
|
||||
client.reconnect();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
});
|
||||
client.connect(5000, host, tcpPort);
|
||||
|
||||
waitForThreads(10000);
|
||||
assertEquals(3, reconnetCount.getAndIncrement());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class ReuseTest extends KryoNetTestCase {
|
||||
public void testPingPong () throws IOException {
|
||||
final AtomicInteger stringCount = new AtomicInteger(0);
|
||||
|
||||
final Server server = new Server();
|
||||
startEndPoint(server);
|
||||
server.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
connection.sendTCP("TCP from server");
|
||||
connection.sendUDP("UDP from server");
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof String) {
|
||||
stringCount.incrementAndGet();
|
||||
System.out.println(object);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
final Client client = new Client();
|
||||
startEndPoint(client);
|
||||
client.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
connection.sendTCP("TCP from client");
|
||||
connection.sendUDP("UDP from client");
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof String) {
|
||||
stringCount.incrementAndGet();
|
||||
System.out.println(object);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
int count = 5;
|
||||
for (int i = 0; i < count; i++) {
|
||||
server.bind(tcpPort, udpPort);
|
||||
client.connect(5000, host, tcpPort, udpPort);
|
||||
try {
|
||||
Thread.sleep(250);
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
assertEquals(count * 2 * 2, stringCount.get());
|
||||
|
||||
stopEndPoints();
|
||||
waitForThreads(10000);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
|
||||
package com.esotericsoftware.kryonet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class UnregisteredClassTest extends KryoNetTestCase {
|
||||
public void testPingPong () throws IOException {
|
||||
final Data dataTCP = new Data();
|
||||
populateData(dataTCP, true);
|
||||
final Data dataUDP = new Data();
|
||||
populateData(dataUDP, false);
|
||||
|
||||
final Server server = new Server(16384, 8192);
|
||||
server.getKryo().setRegistrationRequired(false);
|
||||
startEndPoint(server);
|
||||
server.bind(tcpPort, udpPort);
|
||||
server.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
connection.sendTCP(dataTCP);
|
||||
connection.sendUDP(dataUDP); // Note UDP ping pong stops if a UDP packet is lost.
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof Data) {
|
||||
Data data = (Data)object;
|
||||
if (data.isTCP) {
|
||||
if (!data.equals(dataTCP)) throw new RuntimeException("Fail!");
|
||||
connection.sendTCP(data);
|
||||
} else {
|
||||
if (!data.equals(dataUDP)) throw new RuntimeException("Fail!");
|
||||
connection.sendUDP(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
final Client client = new Client(16384, 8192);
|
||||
client.getKryo().setRegistrationRequired(false);
|
||||
startEndPoint(client);
|
||||
client.addListener(new Listener() {
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof Data) {
|
||||
Data data = (Data)object;
|
||||
if (data.isTCP) {
|
||||
if (!data.equals(dataTCP)) throw new RuntimeException("Fail!");
|
||||
connection.sendTCP(data);
|
||||
} else {
|
||||
if (!data.equals(dataUDP)) throw new RuntimeException("Fail!");
|
||||
connection.sendUDP(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
client.connect(5000, host, tcpPort, udpPort);
|
||||
|
||||
waitForThreads(5000);
|
||||
}
|
||||
|
||||
private void populateData (Data data, boolean isTCP) {
|
||||
data.isTCP = isTCP;
|
||||
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
for (int i = 0; i < 3000; i++)
|
||||
buffer.append('a');
|
||||
data.string = buffer.toString();
|
||||
|
||||
data.strings = new String[] {"abcdefghijklmnopqrstuvwxyz0123456789", "", null, "!@#$", "<22><><EFBFBD><EFBFBD><EFBFBD>"};
|
||||
data.ints = new int[] {-1234567, 1234567, -1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE};
|
||||
data.shorts = new short[] {-12345, 12345, -1, 0, 1, Short.MAX_VALUE, Short.MIN_VALUE};
|
||||
data.floats = new float[] {0, -0, 1, -1, 123456, -123456, 0.1f, 0.2f, -0.3f, (float)Math.PI, Float.MAX_VALUE,
|
||||
Float.MIN_VALUE};
|
||||
data.doubles = new double[] {0, -0, 1, -1, 123456, -123456, 0.1d, 0.2d, -0.3d, Math.PI, Double.MAX_VALUE, Double.MIN_VALUE};
|
||||
data.longs = new long[] {0, -0, 1, -1, 123456, -123456, 99999999999l, -99999999999l, Long.MAX_VALUE, Long.MIN_VALUE};
|
||||
data.bytes = new byte[] {-123, 123, -1, 0, 1, Byte.MAX_VALUE, Byte.MIN_VALUE};
|
||||
data.chars = new char[] {32345, 12345, 0, 1, 63, Character.MAX_VALUE, Character.MIN_VALUE};
|
||||
data.booleans = new boolean[] {true, false};
|
||||
data.Ints = new Integer[] {-1234567, 1234567, -1, 0, 1, Integer.MAX_VALUE, Integer.MIN_VALUE};
|
||||
data.Shorts = new Short[] {-12345, 12345, -1, 0, 1, Short.MAX_VALUE, Short.MIN_VALUE};
|
||||
data.Floats = new Float[] {0f, -0f, 1f, -1f, 123456f, -123456f, 0.1f, 0.2f, -0.3f, (float)Math.PI, Float.MAX_VALUE,
|
||||
Float.MIN_VALUE};
|
||||
data.Doubles = new Double[] {0d, -0d, 1d, -1d, 123456d, -123456d, 0.1d, 0.2d, -0.3d, Math.PI, Double.MAX_VALUE,
|
||||
Double.MIN_VALUE};
|
||||
data.Longs = new Long[] {0l, -0l, 1l, -1l, 123456l, -123456l, 99999999999l, -99999999999l, Long.MAX_VALUE, Long.MIN_VALUE};
|
||||
data.Bytes = new Byte[] {-123, 123, -1, 0, 1, Byte.MAX_VALUE, Byte.MIN_VALUE};
|
||||
data.Chars = new Character[] {32345, 12345, 0, 1, 63, Character.MAX_VALUE, Character.MIN_VALUE};
|
||||
data.Booleans = new Boolean[] {true, false};
|
||||
}
|
||||
|
||||
static public class Data {
|
||||
public String string;
|
||||
public String[] strings;
|
||||
public int[] ints;
|
||||
public short[] shorts;
|
||||
public float[] floats;
|
||||
public double[] doubles;
|
||||
public long[] longs;
|
||||
public byte[] bytes;
|
||||
public char[] chars;
|
||||
public boolean[] booleans;
|
||||
public Integer[] Ints;
|
||||
public Short[] Shorts;
|
||||
public Float[] Floats;
|
||||
public Double[] Doubles;
|
||||
public Long[] Longs;
|
||||
public Byte[] Bytes;
|
||||
public Character[] Chars;
|
||||
public Boolean[] Booleans;
|
||||
public boolean isTCP;
|
||||
|
||||
public int hashCode () {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode(Booleans);
|
||||
result = prime * result + Arrays.hashCode(Bytes);
|
||||
result = prime * result + Arrays.hashCode(Chars);
|
||||
result = prime * result + Arrays.hashCode(Doubles);
|
||||
result = prime * result + Arrays.hashCode(Floats);
|
||||
result = prime * result + Arrays.hashCode(Ints);
|
||||
result = prime * result + Arrays.hashCode(Longs);
|
||||
result = prime * result + Arrays.hashCode(Shorts);
|
||||
result = prime * result + Arrays.hashCode(booleans);
|
||||
result = prime * result + Arrays.hashCode(bytes);
|
||||
result = prime * result + Arrays.hashCode(chars);
|
||||
result = prime * result + Arrays.hashCode(doubles);
|
||||
result = prime * result + Arrays.hashCode(floats);
|
||||
result = prime * result + Arrays.hashCode(ints);
|
||||
result = prime * result + (isTCP ? 1231 : 1237);
|
||||
result = prime * result + Arrays.hashCode(longs);
|
||||
result = prime * result + Arrays.hashCode(shorts);
|
||||
result = prime * result + ((string == null) ? 0 : string.hashCode());
|
||||
result = prime * result + Arrays.hashCode(strings);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals (Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (getClass() != obj.getClass()) return false;
|
||||
Data other = (Data)obj;
|
||||
if (!Arrays.equals(Booleans, other.Booleans)) return false;
|
||||
if (!Arrays.equals(Bytes, other.Bytes)) return false;
|
||||
if (!Arrays.equals(Chars, other.Chars)) return false;
|
||||
if (!Arrays.equals(Doubles, other.Doubles)) return false;
|
||||
if (!Arrays.equals(Floats, other.Floats)) return false;
|
||||
if (!Arrays.equals(Ints, other.Ints)) return false;
|
||||
if (!Arrays.equals(Longs, other.Longs)) return false;
|
||||
if (!Arrays.equals(Shorts, other.Shorts)) return false;
|
||||
if (!Arrays.equals(booleans, other.booleans)) return false;
|
||||
if (!Arrays.equals(bytes, other.bytes)) return false;
|
||||
if (!Arrays.equals(chars, other.chars)) return false;
|
||||
if (!Arrays.equals(doubles, other.doubles)) return false;
|
||||
if (!Arrays.equals(floats, other.floats)) return false;
|
||||
if (!Arrays.equals(ints, other.ints)) return false;
|
||||
if (isTCP != other.isTCP) return false;
|
||||
if (!Arrays.equals(longs, other.longs)) return false;
|
||||
if (!Arrays.equals(shorts, other.shorts)) return false;
|
||||
if (string == null) {
|
||||
if (other.string != null) return false;
|
||||
} else if (!string.equals(other.string)) return false;
|
||||
if (!Arrays.equals(strings, other.strings)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString () {
|
||||
return "Data";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.compress;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.serializers.CollectionSerializer;
|
||||
import com.esotericsoftware.kryo.serializers.DeflateSerializer;
|
||||
import com.esotericsoftware.kryo.serializers.FieldSerializer;
|
||||
import com.esotericsoftware.kryonet.Client;
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.KryoNetTestCase;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
import com.esotericsoftware.kryonet.Server;
|
||||
|
||||
public class DeflateTest extends KryoNetTestCase {
|
||||
public void testDeflate () throws IOException {
|
||||
final Server server = new Server();
|
||||
register(server.getKryo());
|
||||
|
||||
final SomeData data = new SomeData();
|
||||
data.text = "some text here aaaaaaaaaabbbbbbbbbbbcccccccccc";
|
||||
data.stuff = new short[] {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
||||
final ArrayList a = new ArrayList();
|
||||
a.add(12);
|
||||
a.add(null);
|
||||
a.add(34);
|
||||
|
||||
startEndPoint(server);
|
||||
server.bind(tcpPort, udpPort);
|
||||
server.addListener(new Listener() {
|
||||
public void connected (Connection connection) {
|
||||
server.sendToAllTCP(data);
|
||||
connection.sendTCP(data);
|
||||
connection.sendTCP(a);
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
final Client client = new Client();
|
||||
register(client.getKryo());
|
||||
startEndPoint(client);
|
||||
client.addListener(new Listener() {
|
||||
public void received (Connection connection, Object object) {
|
||||
if (object instanceof SomeData) {
|
||||
SomeData data = (SomeData)object;
|
||||
System.out.println(data.stuff[3]);
|
||||
} else if (object instanceof ArrayList) {
|
||||
stopEndPoints();
|
||||
}
|
||||
}
|
||||
});
|
||||
client.connect(5000, host, tcpPort, udpPort);
|
||||
|
||||
waitForThreads();
|
||||
}
|
||||
|
||||
static public void register (Kryo kryo) {
|
||||
kryo.register(short[].class);
|
||||
kryo.register(SomeData.class, new DeflateSerializer(new FieldSerializer(kryo, SomeData.class)));
|
||||
kryo.register(ArrayList.class, new CollectionSerializer());
|
||||
}
|
||||
|
||||
static public class SomeData {
|
||||
public String text;
|
||||
public short[] stuff;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,205 @@
|
|||
|
||||
package com.esotericsoftware.kryonet.rmi;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryonet.Client;
|
||||
import com.esotericsoftware.kryonet.Connection;
|
||||
import com.esotericsoftware.kryonet.KryoNetTestCase;
|
||||
import com.esotericsoftware.kryonet.Listener;
|
||||
import com.esotericsoftware.kryonet.Server;
|
||||
|
||||
public class RmiTest extends KryoNetTestCase {
|
||||
public void testRMI () throws IOException {
|
||||
Server server = new Server();
|
||||
register(server.getKryo());
|
||||
startEndPoint(server);
|
||||
server.bind(tcpPort);
|
||||
|
||||
final ObjectSpace serverObjectSpace = new ObjectSpace();
|
||||
final TestObjectImpl serverTestObject = new TestObjectImpl(4321);
|
||||
serverObjectSpace.register((short)42, serverTestObject);
|
||||
|
||||
server.addListener(new Listener() {
|
||||
public void connected (final Connection connection) {
|
||||
serverObjectSpace.addConnection(connection);
|
||||
runTest(connection, 12, 1234);
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (!(object instanceof MessageWithTestObject)) return;
|
||||
MessageWithTestObject m = (MessageWithTestObject)object;
|
||||
System.out.println(serverTestObject.value);
|
||||
System.out.println(((TestObjectImpl)m.testObject).value);
|
||||
assertEquals(4321f, m.testObject.other());
|
||||
stopEndPoints(2000);
|
||||
}
|
||||
});
|
||||
|
||||
// ----
|
||||
|
||||
Client client = new Client();
|
||||
register(client.getKryo());
|
||||
|
||||
ObjectSpace clientObjectSpace = new ObjectSpace(client);
|
||||
final TestObjectImpl clientTestObject = new TestObjectImpl(1234);
|
||||
clientObjectSpace.register((short)12, clientTestObject);
|
||||
|
||||
startEndPoint(client);
|
||||
client.addListener(new Listener() {
|
||||
public void connected (final Connection connection) {
|
||||
RmiTest.runTest(connection, 42, 4321);
|
||||
}
|
||||
|
||||
public void received (Connection connection, Object object) {
|
||||
if (!(object instanceof MessageWithTestObject)) return;
|
||||
MessageWithTestObject m = (MessageWithTestObject)object;
|
||||
System.out.println(clientTestObject.value);
|
||||
System.out.println(((TestObjectImpl)m.testObject).value);
|
||||
assertEquals(1234f, m.testObject.other());
|
||||
stopEndPoints(2000);
|
||||
}
|
||||
});
|
||||
client.connect(5000, host, tcpPort);
|
||||
|
||||
waitForThreads();
|
||||
}
|
||||
|
||||
static public void runTest (final Connection connection, final int id, final float other) {
|
||||
new Thread() {
|
||||
public void run () {
|
||||
TestObject test = ObjectSpace.getRemoteObject(connection, id, TestObject.class);
|
||||
RemoteObject remoteObject = (RemoteObject)test;
|
||||
// Default behavior. RMI is transparent, method calls behave like normal
|
||||
// (return values and exceptions are returned, call is synchronous)
|
||||
test.moo();
|
||||
test.moo("Cow");
|
||||
assertEquals(other, test.other());
|
||||
|
||||
// Test that RMI correctly waits for the remotely invoked method to exit
|
||||
remoteObject.setResponseTimeout(5000);
|
||||
test.moo("You should see this two seconds before...", 2000);
|
||||
System.out.println("...This");
|
||||
remoteObject.setResponseTimeout(1000);
|
||||
|
||||
// Try exception handling
|
||||
boolean caught = false;
|
||||
try {
|
||||
test.asplode();
|
||||
} catch(UnsupportedOperationException ex) {
|
||||
caught = true;
|
||||
}
|
||||
assertTrue(caught);
|
||||
|
||||
// Return values are ignored, but exceptions are still dealt with properly
|
||||
|
||||
remoteObject.setTransmitReturnValue(false);
|
||||
test.moo("Baa");
|
||||
test.other();
|
||||
caught = false;
|
||||
try {
|
||||
test.asplode();
|
||||
} catch(UnsupportedOperationException ex) {
|
||||
caught = true;
|
||||
}
|
||||
assertTrue(caught);
|
||||
|
||||
// Non-blocking call that ignores the return value
|
||||
remoteObject.setNonBlocking(true);
|
||||
remoteObject.setTransmitReturnValue(false);
|
||||
test.moo("Meow");
|
||||
assertEquals(0f, test.other());
|
||||
|
||||
// Non-blocking call that returns the return value
|
||||
remoteObject.setTransmitReturnValue(true);
|
||||
test.moo("Foo");
|
||||
|
||||
assertEquals(0f, test.other());
|
||||
assertEquals(other, remoteObject.waitForLastResponse());
|
||||
|
||||
assertEquals(0f, test.other());
|
||||
byte responseID = remoteObject.getLastResponseID();
|
||||
assertEquals(other, remoteObject.waitForResponse(responseID));
|
||||
|
||||
// Non-blocking call that errors out
|
||||
remoteObject.setTransmitReturnValue(false);
|
||||
test.asplode();
|
||||
assertEquals(remoteObject.waitForLastResponse().getClass(), UnsupportedOperationException.class);
|
||||
|
||||
// Call will time out if non-blocking isn't working properly
|
||||
remoteObject.setTransmitExceptions(false);
|
||||
test.moo("Mooooooooo", 3000);
|
||||
|
||||
// Test sending a reference to a remote object.
|
||||
MessageWithTestObject m = new MessageWithTestObject();
|
||||
m.number = 678;
|
||||
m.text = "sometext";
|
||||
m.testObject = ObjectSpace.getRemoteObject(connection, (short)id, TestObject.class);
|
||||
connection.sendTCP(m);
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
static public void register (Kryo kryo) {
|
||||
kryo.register(TestObject.class);
|
||||
kryo.register(MessageWithTestObject.class);
|
||||
kryo.register(StackTraceElement.class);
|
||||
kryo.register(StackTraceElement[].class);
|
||||
kryo.register(UnsupportedOperationException.class);
|
||||
ObjectSpace.registerClasses(kryo);
|
||||
}
|
||||
|
||||
static public interface TestObject {
|
||||
public void asplode();
|
||||
|
||||
public void moo ();
|
||||
|
||||
public void moo (String value);
|
||||
|
||||
public void moo (String value, long delay);
|
||||
|
||||
public float other ();
|
||||
}
|
||||
|
||||
static public class TestObjectImpl implements TestObject {
|
||||
public long value = System.currentTimeMillis();
|
||||
private final float other;
|
||||
|
||||
public TestObjectImpl (int other) {
|
||||
this.other = other;
|
||||
}
|
||||
|
||||
public void asplode() {
|
||||
throw new UnsupportedOperationException("Why would I do that?");
|
||||
}
|
||||
|
||||
public void moo () {
|
||||
System.out.println("Moo!");
|
||||
}
|
||||
|
||||
public void moo (String value) {
|
||||
System.out.println("Moo: " + value);
|
||||
}
|
||||
|
||||
public void moo (String value, long delay) {
|
||||
System.out.println("Moo: " + value);
|
||||
try {
|
||||
Thread.sleep(delay);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public float other () {
|
||||
return other;
|
||||
}
|
||||
}
|
||||
|
||||
static public class MessageWithTestObject {
|
||||
public int number;
|
||||
public String text;
|
||||
public TestObject testObject;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:47 CET 2013 -->
|
||||
<title>All Classes</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="bar">All Classes</h1>
|
||||
<div class="indexContainer">
|
||||
<ul>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/AsmCacheFields.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">AsmCacheFields</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/BeanSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">BeanSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/BlowfishSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">BlowfishSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/ByteBufferInput.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">ByteBufferInput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/ByteBufferInputStream.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">ByteBufferInputStream</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/ByteBufferOutput.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">ByteBufferOutput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/ByteBufferOutputStream.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">ByteBufferOutputStream</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo" target="classFrame"><i>ClassResolver</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Client.html" title="class in com.esotericsoftware.kryonet" target="classFrame">Client</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/CollectionSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">CollectionSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/CompatibleFieldSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">CompatibleFieldSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Connection.html" title="class in com.esotericsoftware.kryonet" target="classFrame">Connection</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.BooleanArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers.BooleanArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.ByteArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers.ByteArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.CharArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers.CharArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.DoubleArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers.DoubleArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.FloatArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers.FloatArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.IntArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers.IntArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.LongArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers.LongArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.ObjectArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers.ObjectArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.ShortArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers.ShortArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.StringArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultArraySerializers.StringArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/DefaultClassResolver.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">DefaultClassResolver</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/DefaultSerializer.html" title="annotation in com.esotericsoftware.kryo" target="classFrame">DefaultSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.BigDecimalSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.BigDecimalSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.BigIntegerSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.BigIntegerSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.BooleanSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.BooleanSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.ByteSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.ByteSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CalendarSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.CalendarSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CharSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.CharSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.ClassSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.ClassSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsEmptyListSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.CollectionsEmptyListSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsEmptyMapSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.CollectionsEmptyMapSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsEmptySetSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.CollectionsEmptySetSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsSingletonListSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.CollectionsSingletonListSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsSingletonMapSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.CollectionsSingletonMapSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsSingletonSetSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.CollectionsSingletonSetSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CurrencySerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.CurrencySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.DateSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.DateSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.DoubleSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.DoubleSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.EnumSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.EnumSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.EnumSetSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.EnumSetSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.FloatSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.FloatSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.IntSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.IntSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.KryoSerializableSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.KryoSerializableSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.LongSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.LongSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.ShortSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.ShortSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.StringBufferSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.StringBufferSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.StringBuilderSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.StringBuilderSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.StringSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.StringSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.TimeZoneSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.TimeZoneSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.TreeMapSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.TreeMapSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.TreeSetSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.TreeSetSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.VoidSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DefaultSerializers.VoidSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/DefaultStreamFactory.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">DefaultStreamFactory</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DeflateSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">DeflateSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/EndPoint.html" title="interface in com.esotericsoftware.kryonet" target="classFrame"><i>EndPoint</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/FastestStreamFactory.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">FastestStreamFactory</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/FastInput.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">FastInput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/FastOutput.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">FastOutput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/FieldSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">FieldSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/FieldSerializer.CachedField.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">FieldSerializer.CachedField</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/FieldSerializer.CachedFieldFactory.html" title="interface in com.esotericsoftware.kryo.serializers" target="classFrame"><i>FieldSerializer.CachedFieldFactory</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/FieldSerializer.Optional.html" title="annotation in com.esotericsoftware.kryo.serializers" target="classFrame">FieldSerializer.Optional</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.html" title="interface in com.esotericsoftware.kryonet" target="classFrame"><i>FrameworkMessage</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.DiscoverHost.html" title="class in com.esotericsoftware.kryonet" target="classFrame">FrameworkMessage.DiscoverHost</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.KeepAlive.html" title="class in com.esotericsoftware.kryonet" target="classFrame">FrameworkMessage.KeepAlive</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.Ping.html" title="class in com.esotericsoftware.kryonet" target="classFrame">FrameworkMessage.Ping</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.RegisterTCP.html" title="class in com.esotericsoftware.kryonet" target="classFrame">FrameworkMessage.RegisterTCP</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.RegisterUDP.html" title="class in com.esotericsoftware.kryonet" target="classFrame">FrameworkMessage.RegisterUDP</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/Generics.html" title="class in com.esotericsoftware.kryo" target="classFrame">Generics</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityMap.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">IdentityMap</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityMap.Entries.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">IdentityMap.Entries</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityMap.Entry.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">IdentityMap.Entry</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityMap.Keys.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">IdentityMap.Keys</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityMap.Values.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">IdentityMap.Values</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityObjectIntMap.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">IdentityObjectIntMap</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">Input</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/InputChunked.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">InputChunked</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/util/InputStreamSender.html" title="class in com.esotericsoftware.kryonet.util" target="classFrame">InputStreamSender</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IntArray.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">IntArray</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IntMap.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">IntMap</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/JavaSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">JavaSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/JsonSerialization.html" title="class in com.esotericsoftware.kryonet" target="classFrame">JsonSerialization</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo" target="classFrame">Kryo</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/KryoCopyable.html" title="interface in com.esotericsoftware.kryo" target="classFrame"><i>KryoCopyable</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/KryoException.html" title="class in com.esotericsoftware.kryo" target="classFrame">KryoException</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/KryoNetException.html" title="class in com.esotericsoftware.kryonet" target="classFrame">KryoNetException</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/KryoSerializable.html" title="interface in com.esotericsoftware.kryo" target="classFrame"><i>KryoSerializable</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/KryoSerialization.html" title="class in com.esotericsoftware.kryonet" target="classFrame">KryoSerialization</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Listener.html" title="class in com.esotericsoftware.kryonet" target="classFrame">Listener</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Listener.LagListener.html" title="class in com.esotericsoftware.kryonet" target="classFrame">Listener.LagListener</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Listener.QueuedListener.html" title="class in com.esotericsoftware.kryonet" target="classFrame">Listener.QueuedListener</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Listener.ReflectionListener.html" title="class in com.esotericsoftware.kryonet" target="classFrame">Listener.ReflectionListener</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Listener.ThreadedListener.html" title="class in com.esotericsoftware.kryonet" target="classFrame">Listener.ThreadedListener</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ListReferenceResolver.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">ListReferenceResolver</a></li>
|
||||
<li><a href="com/esotericsoftware/minlog/Log.html" title="class in com.esotericsoftware.minlog" target="classFrame">Log</a></li>
|
||||
<li><a href="com/esotericsoftware/minlog/Log.Logger.html" title="class in com.esotericsoftware.minlog" target="classFrame">Log.Logger</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/MapReferenceResolver.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">MapReferenceResolver</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/MapSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">MapSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/NotNull.html" title="annotation in com.esotericsoftware.kryo" target="classFrame">NotNull</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ObjectMap.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">ObjectMap</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ObjectMap.Entries.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">ObjectMap.Entries</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ObjectMap.Entry.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">ObjectMap.Entry</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ObjectMap.Keys.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">ObjectMap.Keys</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ObjectMap.Values.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">ObjectMap.Values</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/rmi/ObjectSpace.html" title="class in com.esotericsoftware.kryonet.rmi" target="classFrame">ObjectSpace</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/rmi/ObjectSpace.InvokeMethod.html" title="class in com.esotericsoftware.kryonet.rmi" target="classFrame">ObjectSpace.InvokeMethod</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/rmi/ObjectSpace.InvokeMethodResult.html" title="class in com.esotericsoftware.kryonet.rmi" target="classFrame">ObjectSpace.InvokeMethodResult</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">Output</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/OutputChunked.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">OutputChunked</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/factories/PseudoSerializerFactory.html" title="class in com.esotericsoftware.kryo.factories" target="classFrame">PseudoSerializerFactory</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/ReferenceResolver.html" title="interface in com.esotericsoftware.kryo" target="classFrame"><i>ReferenceResolver</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/factories/ReflectionSerializerFactory.html" title="class in com.esotericsoftware.kryo.factories" target="classFrame">ReflectionSerializerFactory</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo" target="classFrame">Registration</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/rmi/RemoteObject.html" title="interface in com.esotericsoftware.kryonet.rmi" target="classFrame"><i>RemoteObject</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Serialization.html" title="interface in com.esotericsoftware.kryonet" target="classFrame"><i>Serialization</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo" target="classFrame">Serializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/factories/SerializerFactory.html" title="interface in com.esotericsoftware.kryo.factories" target="classFrame"><i>SerializerFactory</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Server.html" title="class in com.esotericsoftware.kryonet" target="classFrame">Server</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/StreamFactory.html" title="interface in com.esotericsoftware.kryo" target="classFrame"><i>StreamFactory</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/TaggedFieldSerializer.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">TaggedFieldSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/TaggedFieldSerializer.Tag.html" title="annotation in com.esotericsoftware.kryo.serializers" target="classFrame">TaggedFieldSerializer.Tag</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/util/TcpIdleSender.html" title="class in com.esotericsoftware.kryonet.util" target="classFrame">TcpIdleSender</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/rmi/TimeoutException.html" title="class in com.esotericsoftware.kryonet.rmi" target="classFrame">TimeoutException</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/UnsafeCacheFields.html" title="class in com.esotericsoftware.kryo.serializers" target="classFrame">UnsafeCacheFields</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/UnsafeInput.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">UnsafeInput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/UnsafeMemoryInput.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">UnsafeMemoryInput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/UnsafeMemoryOutput.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">UnsafeMemoryOutput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/UnsafeOutput.html" title="class in com.esotericsoftware.kryo.io" target="classFrame">UnsafeOutput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/UnsafeUtil.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">UnsafeUtil</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/Util.html" title="class in com.esotericsoftware.kryo.util" target="classFrame">Util</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,151 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:47 CET 2013 -->
|
||||
<title>All Classes</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<h1 class="bar">All Classes</h1>
|
||||
<div class="indexContainer">
|
||||
<ul>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/AsmCacheFields.html" title="class in com.esotericsoftware.kryo.serializers">AsmCacheFields</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/BeanSerializer.html" title="class in com.esotericsoftware.kryo.serializers">BeanSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/BlowfishSerializer.html" title="class in com.esotericsoftware.kryo.serializers">BlowfishSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/ByteBufferInput.html" title="class in com.esotericsoftware.kryo.io">ByteBufferInput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/ByteBufferInputStream.html" title="class in com.esotericsoftware.kryo.io">ByteBufferInputStream</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/ByteBufferOutput.html" title="class in com.esotericsoftware.kryo.io">ByteBufferOutput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/ByteBufferOutputStream.html" title="class in com.esotericsoftware.kryo.io">ByteBufferOutputStream</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo"><i>ClassResolver</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Client.html" title="class in com.esotericsoftware.kryonet">Client</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/CollectionSerializer.html" title="class in com.esotericsoftware.kryo.serializers">CollectionSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/CompatibleFieldSerializer.html" title="class in com.esotericsoftware.kryo.serializers">CompatibleFieldSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Connection.html" title="class in com.esotericsoftware.kryonet">Connection</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.BooleanArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers.BooleanArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.ByteArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers.ByteArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.CharArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers.CharArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.DoubleArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers.DoubleArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.FloatArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers.FloatArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.IntArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers.IntArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.LongArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers.LongArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.ObjectArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers.ObjectArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.ShortArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers.ShortArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultArraySerializers.StringArraySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultArraySerializers.StringArraySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/DefaultClassResolver.html" title="class in com.esotericsoftware.kryo.util">DefaultClassResolver</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/DefaultSerializer.html" title="annotation in com.esotericsoftware.kryo">DefaultSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.BigDecimalSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.BigDecimalSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.BigIntegerSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.BigIntegerSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.BooleanSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.BooleanSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.ByteSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.ByteSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CalendarSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.CalendarSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CharSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.CharSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.ClassSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.ClassSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsEmptyListSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.CollectionsEmptyListSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsEmptyMapSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.CollectionsEmptyMapSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsEmptySetSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.CollectionsEmptySetSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsSingletonListSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.CollectionsSingletonListSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsSingletonMapSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.CollectionsSingletonMapSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CollectionsSingletonSetSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.CollectionsSingletonSetSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.CurrencySerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.CurrencySerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.DateSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.DateSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.DoubleSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.DoubleSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.EnumSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.EnumSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.EnumSetSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.EnumSetSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.FloatSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.FloatSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.IntSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.IntSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.KryoSerializableSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.KryoSerializableSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.LongSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.LongSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.ShortSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.ShortSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.StringBufferSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.StringBufferSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.StringBuilderSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.StringBuilderSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.StringSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.StringSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.TimeZoneSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.TimeZoneSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.TreeMapSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.TreeMapSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.TreeSetSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.TreeSetSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DefaultSerializers.VoidSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DefaultSerializers.VoidSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/DefaultStreamFactory.html" title="class in com.esotericsoftware.kryo.util">DefaultStreamFactory</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/DeflateSerializer.html" title="class in com.esotericsoftware.kryo.serializers">DeflateSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/EndPoint.html" title="interface in com.esotericsoftware.kryonet"><i>EndPoint</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/FastestStreamFactory.html" title="class in com.esotericsoftware.kryo.util">FastestStreamFactory</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/FastInput.html" title="class in com.esotericsoftware.kryo.io">FastInput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/FastOutput.html" title="class in com.esotericsoftware.kryo.io">FastOutput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/FieldSerializer.html" title="class in com.esotericsoftware.kryo.serializers">FieldSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/FieldSerializer.CachedField.html" title="class in com.esotericsoftware.kryo.serializers">FieldSerializer.CachedField</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/FieldSerializer.CachedFieldFactory.html" title="interface in com.esotericsoftware.kryo.serializers"><i>FieldSerializer.CachedFieldFactory</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/FieldSerializer.Optional.html" title="annotation in com.esotericsoftware.kryo.serializers">FieldSerializer.Optional</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.html" title="interface in com.esotericsoftware.kryonet"><i>FrameworkMessage</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.DiscoverHost.html" title="class in com.esotericsoftware.kryonet">FrameworkMessage.DiscoverHost</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.KeepAlive.html" title="class in com.esotericsoftware.kryonet">FrameworkMessage.KeepAlive</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.Ping.html" title="class in com.esotericsoftware.kryonet">FrameworkMessage.Ping</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.RegisterTCP.html" title="class in com.esotericsoftware.kryonet">FrameworkMessage.RegisterTCP</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/FrameworkMessage.RegisterUDP.html" title="class in com.esotericsoftware.kryonet">FrameworkMessage.RegisterUDP</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/Generics.html" title="class in com.esotericsoftware.kryo">Generics</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityMap.html" title="class in com.esotericsoftware.kryo.util">IdentityMap</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityMap.Entries.html" title="class in com.esotericsoftware.kryo.util">IdentityMap.Entries</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityMap.Entry.html" title="class in com.esotericsoftware.kryo.util">IdentityMap.Entry</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityMap.Keys.html" title="class in com.esotericsoftware.kryo.util">IdentityMap.Keys</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityMap.Values.html" title="class in com.esotericsoftware.kryo.util">IdentityMap.Values</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IdentityObjectIntMap.html" title="class in com.esotericsoftware.kryo.util">IdentityObjectIntMap</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/InputChunked.html" title="class in com.esotericsoftware.kryo.io">InputChunked</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/util/InputStreamSender.html" title="class in com.esotericsoftware.kryonet.util">InputStreamSender</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IntArray.html" title="class in com.esotericsoftware.kryo.util">IntArray</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/IntMap.html" title="class in com.esotericsoftware.kryo.util">IntMap</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/JavaSerializer.html" title="class in com.esotericsoftware.kryo.serializers">JavaSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/JsonSerialization.html" title="class in com.esotericsoftware.kryonet">JsonSerialization</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/KryoCopyable.html" title="interface in com.esotericsoftware.kryo"><i>KryoCopyable</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/KryoException.html" title="class in com.esotericsoftware.kryo">KryoException</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/KryoNetException.html" title="class in com.esotericsoftware.kryonet">KryoNetException</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/KryoSerializable.html" title="interface in com.esotericsoftware.kryo"><i>KryoSerializable</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/KryoSerialization.html" title="class in com.esotericsoftware.kryonet">KryoSerialization</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Listener.html" title="class in com.esotericsoftware.kryonet">Listener</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Listener.LagListener.html" title="class in com.esotericsoftware.kryonet">Listener.LagListener</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Listener.QueuedListener.html" title="class in com.esotericsoftware.kryonet">Listener.QueuedListener</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Listener.ReflectionListener.html" title="class in com.esotericsoftware.kryonet">Listener.ReflectionListener</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Listener.ThreadedListener.html" title="class in com.esotericsoftware.kryonet">Listener.ThreadedListener</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ListReferenceResolver.html" title="class in com.esotericsoftware.kryo.util">ListReferenceResolver</a></li>
|
||||
<li><a href="com/esotericsoftware/minlog/Log.html" title="class in com.esotericsoftware.minlog">Log</a></li>
|
||||
<li><a href="com/esotericsoftware/minlog/Log.Logger.html" title="class in com.esotericsoftware.minlog">Log.Logger</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/MapReferenceResolver.html" title="class in com.esotericsoftware.kryo.util">MapReferenceResolver</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/MapSerializer.html" title="class in com.esotericsoftware.kryo.serializers">MapSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/NotNull.html" title="annotation in com.esotericsoftware.kryo">NotNull</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ObjectMap.html" title="class in com.esotericsoftware.kryo.util">ObjectMap</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ObjectMap.Entries.html" title="class in com.esotericsoftware.kryo.util">ObjectMap.Entries</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ObjectMap.Entry.html" title="class in com.esotericsoftware.kryo.util">ObjectMap.Entry</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ObjectMap.Keys.html" title="class in com.esotericsoftware.kryo.util">ObjectMap.Keys</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/ObjectMap.Values.html" title="class in com.esotericsoftware.kryo.util">ObjectMap.Values</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/rmi/ObjectSpace.html" title="class in com.esotericsoftware.kryonet.rmi">ObjectSpace</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/rmi/ObjectSpace.InvokeMethod.html" title="class in com.esotericsoftware.kryonet.rmi">ObjectSpace.InvokeMethod</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/rmi/ObjectSpace.InvokeMethodResult.html" title="class in com.esotericsoftware.kryonet.rmi">ObjectSpace.InvokeMethodResult</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/OutputChunked.html" title="class in com.esotericsoftware.kryo.io">OutputChunked</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/factories/PseudoSerializerFactory.html" title="class in com.esotericsoftware.kryo.factories">PseudoSerializerFactory</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/ReferenceResolver.html" title="interface in com.esotericsoftware.kryo"><i>ReferenceResolver</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/factories/ReflectionSerializerFactory.html" title="class in com.esotericsoftware.kryo.factories">ReflectionSerializerFactory</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/rmi/RemoteObject.html" title="interface in com.esotericsoftware.kryonet.rmi"><i>RemoteObject</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Serialization.html" title="interface in com.esotericsoftware.kryonet"><i>Serialization</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo">Serializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/factories/SerializerFactory.html" title="interface in com.esotericsoftware.kryo.factories"><i>SerializerFactory</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/Server.html" title="class in com.esotericsoftware.kryonet">Server</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/StreamFactory.html" title="interface in com.esotericsoftware.kryo"><i>StreamFactory</i></a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/TaggedFieldSerializer.html" title="class in com.esotericsoftware.kryo.serializers">TaggedFieldSerializer</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/TaggedFieldSerializer.Tag.html" title="annotation in com.esotericsoftware.kryo.serializers">TaggedFieldSerializer.Tag</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/util/TcpIdleSender.html" title="class in com.esotericsoftware.kryonet.util">TcpIdleSender</a></li>
|
||||
<li><a href="com/esotericsoftware/kryonet/rmi/TimeoutException.html" title="class in com.esotericsoftware.kryonet.rmi">TimeoutException</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/serializers/UnsafeCacheFields.html" title="class in com.esotericsoftware.kryo.serializers">UnsafeCacheFields</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/UnsafeInput.html" title="class in com.esotericsoftware.kryo.io">UnsafeInput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/UnsafeMemoryInput.html" title="class in com.esotericsoftware.kryo.io">UnsafeMemoryInput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/UnsafeMemoryOutput.html" title="class in com.esotericsoftware.kryo.io">UnsafeMemoryOutput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/io/UnsafeOutput.html" title="class in com.esotericsoftware.kryo.io">UnsafeOutput</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/UnsafeUtil.html" title="class in com.esotericsoftware.kryo.util">UnsafeUtil</a></li>
|
||||
<li><a href="com/esotericsoftware/kryo/util/Util.html" title="class in com.esotericsoftware.kryo.util">Util</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,334 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:45 CET 2013 -->
|
||||
<title>ClassResolver</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="ClassResolver";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/ClassResolver.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li>Prev Class</li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/DefaultSerializer.html" title="annotation in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/ClassResolver.html" target="_top">Frames</a></li>
|
||||
<li><a href="ClassResolver.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<!-- ======== START OF CLASS DATA ======== -->
|
||||
<div class="header">
|
||||
<div class="subTitle">com.esotericsoftware.kryo</div>
|
||||
<h2 title="Interface ClassResolver" class="title">Interface ClassResolver</h2>
|
||||
</div>
|
||||
<div class="contentContainer">
|
||||
<div class="description">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<dl>
|
||||
<dt>All Known Implementing Classes:</dt>
|
||||
<dd><a href="../../../com/esotericsoftware/kryo/util/DefaultClassResolver.html" title="class in com.esotericsoftware.kryo.util">DefaultClassResolver</a></dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<br>
|
||||
<pre>public interface <span class="strong">ClassResolver</span></pre>
|
||||
<div class="block">Handles class registration, writing class identifiers to bytes, and reading class identifiers from bytes.</div>
|
||||
<dl><dt><span class="strong">Author:</span></dt>
|
||||
<dd>Nathan Sweet <misc@n4te.com></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ========== METHOD SUMMARY =========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
|
||||
<caption><span>Methods</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Method and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ClassResolver.html#getRegistration(java.lang.Class)">getRegistration</a></strong>(java.lang.Class type)</code>
|
||||
<div class="block">Returns the registration for the specified class, or null if the class is not registered.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ClassResolver.html#getRegistration(int)">getRegistration</a></strong>(int classID)</code>
|
||||
<div class="block">Returns the registration for the specified ID, or null if no class is registered with that ID.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ClassResolver.html#readClass(com.esotericsoftware.kryo.io.Input)">readClass</a></strong>(<a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a> input)</code>
|
||||
<div class="block">Reads a class and returns its registration.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ClassResolver.html#register(com.esotericsoftware.kryo.Registration)">register</a></strong>(<a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a> registration)</code>
|
||||
<div class="block">Stores the specified registration.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ClassResolver.html#registerImplicit(java.lang.Class)">registerImplicit</a></strong>(java.lang.Class type)</code>
|
||||
<div class="block">Called when an unregistered type is encountered and <a href="../../../com/esotericsoftware/kryo/Kryo.html#setRegistrationRequired(boolean)"><code>Kryo.setRegistrationRequired(boolean)</code></a> is false.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ClassResolver.html#reset()">reset</a></strong>()</code>
|
||||
<div class="block">Called by <a href="../../../com/esotericsoftware/kryo/Kryo.html#reset()"><code>Kryo.reset()</code></a>.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ClassResolver.html#setKryo(com.esotericsoftware.kryo.Kryo)">setKryo</a></strong>(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo)</code>
|
||||
<div class="block">Sets the Kryo instance that this ClassResolver will be used for.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ClassResolver.html#writeClass(com.esotericsoftware.kryo.io.Output, java.lang.Class)">writeClass</a></strong>(<a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> output,
|
||||
java.lang.Class type)</code>
|
||||
<div class="block">Writes a class and returns its registration.</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="details">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ============ METHOD DETAIL ========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Detail</h3>
|
||||
<a name="setKryo(com.esotericsoftware.kryo.Kryo)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>setKryo</h4>
|
||||
<pre>void setKryo(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo)</pre>
|
||||
<div class="block">Sets the Kryo instance that this ClassResolver will be used for. This is called automatically by Kryo.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="register(com.esotericsoftware.kryo.Registration)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>register</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a> register(<a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a> registration)</pre>
|
||||
<div class="block">Stores the specified registration.</div>
|
||||
<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../com/esotericsoftware/kryo/Kryo.html#register(com.esotericsoftware.kryo.Registration)"><code>Kryo.register(Registration)</code></a></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="registerImplicit(java.lang.Class)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>registerImplicit</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a> registerImplicit(java.lang.Class type)</pre>
|
||||
<div class="block">Called when an unregistered type is encountered and <a href="../../../com/esotericsoftware/kryo/Kryo.html#setRegistrationRequired(boolean)"><code>Kryo.setRegistrationRequired(boolean)</code></a> is false.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getRegistration(java.lang.Class)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getRegistration</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a> getRegistration(java.lang.Class type)</pre>
|
||||
<div class="block">Returns the registration for the specified class, or null if the class is not registered.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getRegistration(int)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getRegistration</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a> getRegistration(int classID)</pre>
|
||||
<div class="block">Returns the registration for the specified ID, or null if no class is registered with that ID.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="writeClass(com.esotericsoftware.kryo.io.Output, java.lang.Class)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>writeClass</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a> writeClass(<a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> output,
|
||||
java.lang.Class type)</pre>
|
||||
<div class="block">Writes a class and returns its registration.</div>
|
||||
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>type</code> - May be null.</dd>
|
||||
<dt><span class="strong">Returns:</span></dt><dd>Will be null if type is null.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="readClass(com.esotericsoftware.kryo.io.Input)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>readClass</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo">Registration</a> readClass(<a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a> input)</pre>
|
||||
<div class="block">Reads a class and returns its registration.</div>
|
||||
<dl><dt><span class="strong">Returns:</span></dt><dd>May be null.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="reset()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>reset</h4>
|
||||
<pre>void reset()</pre>
|
||||
<div class="block">Called by <a href="../../../com/esotericsoftware/kryo/Kryo.html#reset()"><code>Kryo.reset()</code></a>.</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/ClassResolver.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li>Prev Class</li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/DefaultSerializer.html" title="annotation in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/ClassResolver.html" target="_top">Frames</a></li>
|
||||
<li><a href="ClassResolver.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,205 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:45 CET 2013 -->
|
||||
<title>DefaultSerializer</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="DefaultSerializer";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/DefaultSerializer.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Generics.html" title="class in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/DefaultSerializer.html" target="_top">Frames</a></li>
|
||||
<li><a href="DefaultSerializer.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li><a href="#annotation_type_required_element_summary">Required</a> | </li>
|
||||
<li>Optional</li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li><a href="#annotation_type_element_detail">Element</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<!-- ======== START OF CLASS DATA ======== -->
|
||||
<div class="header">
|
||||
<div class="subTitle">com.esotericsoftware.kryo</div>
|
||||
<h2 title="Annotation Type DefaultSerializer" class="title">Annotation Type DefaultSerializer</h2>
|
||||
</div>
|
||||
<div class="contentContainer">
|
||||
<div class="description">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<hr>
|
||||
<br>
|
||||
<pre>@Retention(value=RUNTIME)
|
||||
@Target(value=TYPE)
|
||||
public @interface <span class="strong">DefaultSerializer</span></pre>
|
||||
<div class="block">Sets the default serializer to use for the annotated class. The specified Serializer class must have a constructor taking a
|
||||
Kryo instance and a class, a Kryo instance, a class, or no arguments.</div>
|
||||
<dl><dt><span class="strong">Author:</span></dt>
|
||||
<dd>Nathan Sweet <misc@n4te.com></dd>
|
||||
<dt><span class="strong">See Also:</span></dt><dd><a href="../../../com/esotericsoftware/kryo/Kryo.html#register(java.lang.Class)"><code>Kryo.register(Class)</code></a></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- =========== ANNOTATION TYPE REQUIRED MEMBER SUMMARY =========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="annotation_type_required_element_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Required Element Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Required Element Summary table, listing required elements, and an explanation">
|
||||
<caption><span>Required Elements</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Required Element and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>java.lang.Class<? extends <a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo">Serializer</a>></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/DefaultSerializer.html#value()">value</a></strong></code> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="details">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ============ ANNOTATION TYPE MEMBER DETAIL =========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="annotation_type_element_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Element Detail</h3>
|
||||
<a name="value()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>value</h4>
|
||||
<pre>public abstract java.lang.Class<? extends <a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo">Serializer</a>> value</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/DefaultSerializer.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Generics.html" title="class in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/DefaultSerializer.html" target="_top">Frames</a></li>
|
||||
<li><a href="DefaultSerializer.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li><a href="#annotation_type_required_element_summary">Required</a> | </li>
|
||||
<li>Optional</li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li><a href="#annotation_type_element_detail">Element</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,354 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:45 CET 2013 -->
|
||||
<title>Generics</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="Generics";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/Generics.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/DefaultSerializer.html" title="annotation in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/Generics.html" target="_top">Frames</a></li>
|
||||
<li><a href="Generics.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_summary">Constr</a> | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_detail">Constr</a> | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<!-- ======== START OF CLASS DATA ======== -->
|
||||
<div class="header">
|
||||
<div class="subTitle">com.esotericsoftware.kryo</div>
|
||||
<h2 title="Class Generics" class="title">Class Generics</h2>
|
||||
</div>
|
||||
<div class="contentContainer">
|
||||
<ul class="inheritance">
|
||||
<li>java.lang.Object</li>
|
||||
<li>
|
||||
<ul class="inheritance">
|
||||
<li>com.esotericsoftware.kryo.Generics</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="description">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<hr>
|
||||
<br>
|
||||
<pre>public class <span class="strong">Generics</span>
|
||||
extends java.lang.Object</pre>
|
||||
<div class="block">Helper class to map type name variables to concrete classes that are used during instantiation</div>
|
||||
<dl><dt><span class="strong">Author:</span></dt>
|
||||
<dd>Roman Levenstein <romixlev@gmail.com></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ======== CONSTRUCTOR SUMMARY ======== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="constructor_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Constructor Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
|
||||
<caption><span>Constructors</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colOne" scope="col">Constructor and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colOne"><code><strong><a href="../../../com/esotericsoftware/kryo/Generics.html#Generics()">Generics</a></strong>()</code> </td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colOne"><code><strong><a href="../../../com/esotericsoftware/kryo/Generics.html#Generics(com.esotericsoftware.kryo.Generics)">Generics</a></strong>(<a href="../../../com/esotericsoftware/kryo/Generics.html" title="class in com.esotericsoftware.kryo">Generics</a> parentScope)</code> </td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colOne"><code><strong><a href="../../../com/esotericsoftware/kryo/Generics.html#Generics(java.util.Map)">Generics</a></strong>(java.util.Map<java.lang.String,java.lang.Class> mappings)</code> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- ========== METHOD SUMMARY =========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
|
||||
<caption><span>Methods</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Method and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Generics.html#add(java.lang.String, java.lang.Class)">add</a></strong>(java.lang.String typeVar,
|
||||
java.lang.Class clazz)</code> </td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>java.lang.Class</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Generics.html#getConcreteClass(java.lang.String)">getConcreteClass</a></strong>(java.lang.String typeVar)</code> </td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/Generics.html" title="class in com.esotericsoftware.kryo">Generics</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Generics.html#getParentScope()">getParentScope</a></strong>()</code> </td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Generics.html#resetParentScope()">resetParentScope</a></strong>()</code> </td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Generics.html#setParentScope(com.esotericsoftware.kryo.Generics)">setParentScope</a></strong>(<a href="../../../com/esotericsoftware/kryo/Generics.html" title="class in com.esotericsoftware.kryo">Generics</a> scope)</code> </td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>java.lang.String</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Generics.html#toString()">toString</a></strong>()</code> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="methods_inherited_from_class_java.lang.Object">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Methods inherited from class java.lang.Object</h3>
|
||||
<code>equals, getClass, hashCode, notify, notifyAll, wait, wait, wait</code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="details">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ========= CONSTRUCTOR DETAIL ======== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="constructor_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Constructor Detail</h3>
|
||||
<a name="Generics()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>Generics</h4>
|
||||
<pre>public Generics()</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="Generics(java.util.Map)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>Generics</h4>
|
||||
<pre>public Generics(java.util.Map<java.lang.String,java.lang.Class> mappings)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="Generics(com.esotericsoftware.kryo.Generics)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>Generics</h4>
|
||||
<pre>public Generics(<a href="../../../com/esotericsoftware/kryo/Generics.html" title="class in com.esotericsoftware.kryo">Generics</a> parentScope)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- ============ METHOD DETAIL ========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Detail</h3>
|
||||
<a name="add(java.lang.String, java.lang.Class)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>add</h4>
|
||||
<pre>public void add(java.lang.String typeVar,
|
||||
java.lang.Class clazz)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getConcreteClass(java.lang.String)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getConcreteClass</h4>
|
||||
<pre>public java.lang.Class getConcreteClass(java.lang.String typeVar)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="setParentScope(com.esotericsoftware.kryo.Generics)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>setParentScope</h4>
|
||||
<pre>public void setParentScope(<a href="../../../com/esotericsoftware/kryo/Generics.html" title="class in com.esotericsoftware.kryo">Generics</a> scope)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getParentScope()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getParentScope</h4>
|
||||
<pre>public <a href="../../../com/esotericsoftware/kryo/Generics.html" title="class in com.esotericsoftware.kryo">Generics</a> getParentScope()</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="toString()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>toString</h4>
|
||||
<pre>public java.lang.String toString()</pre>
|
||||
<dl>
|
||||
<dt><strong>Overrides:</strong></dt>
|
||||
<dd><code>toString</code> in class <code>java.lang.Object</code></dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="resetParentScope()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>resetParentScope</h4>
|
||||
<pre>public void resetParentScope()</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/Generics.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/DefaultSerializer.html" title="annotation in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/Generics.html" target="_top">Frames</a></li>
|
||||
<li><a href="Generics.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_summary">Constr</a> | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_detail">Constr</a> | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,216 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:45 CET 2013 -->
|
||||
<title>KryoCopyable</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="KryoCopyable";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/KryoCopyable.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/KryoException.html" title="class in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/KryoCopyable.html" target="_top">Frames</a></li>
|
||||
<li><a href="KryoCopyable.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<!-- ======== START OF CLASS DATA ======== -->
|
||||
<div class="header">
|
||||
<div class="subTitle">com.esotericsoftware.kryo</div>
|
||||
<h2 title="Interface KryoCopyable" class="title">Interface KryoCopyable<T></h2>
|
||||
</div>
|
||||
<div class="contentContainer">
|
||||
<div class="description">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<hr>
|
||||
<br>
|
||||
<pre>public interface <span class="strong">KryoCopyable<T></span></pre>
|
||||
<div class="block">Allows implementing classes to perform their own copying. Hand written copying can be more efficient in some cases.
|
||||
<p>
|
||||
This method is used instead of the registered serializer <a href="../../../com/esotericsoftware/kryo/Serializer.html#copy(com.esotericsoftware.kryo.Kryo, T)"><code>Serializer.copy(Kryo, Object)</code></a> method.</div>
|
||||
<dl><dt><span class="strong">Author:</span></dt>
|
||||
<dd>Nathan Sweet <misc@n4te.com></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ========== METHOD SUMMARY =========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
|
||||
<caption><span>Methods</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Method and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/KryoCopyable.html" title="type parameter in KryoCopyable">T</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/KryoCopyable.html#copy(com.esotericsoftware.kryo.Kryo)">copy</a></strong>(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo)</code>
|
||||
<div class="block">Returns a copy that has the same values as this object.</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="details">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ============ METHOD DETAIL ========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Detail</h3>
|
||||
<a name="copy(com.esotericsoftware.kryo.Kryo)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>copy</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/KryoCopyable.html" title="type parameter in KryoCopyable">T</a> copy(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo)</pre>
|
||||
<div class="block">Returns a copy that has the same values as this object. Before Kryo can be used to copy child objects,
|
||||
<a href="../../../com/esotericsoftware/kryo/Kryo.html#reference(java.lang.Object)"><code>Kryo.reference(Object)</code></a> must be called with the copy to ensure it can be referenced by the child objects.</div>
|
||||
<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../com/esotericsoftware/kryo/Serializer.html#copy(com.esotericsoftware.kryo.Kryo, T)"><code>Serializer.copy(Kryo, Object)</code></a></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/KryoCopyable.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/KryoException.html" title="class in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/KryoCopyable.html" target="_top">Frames</a></li>
|
||||
<li><a href="KryoCopyable.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,345 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:45 CET 2013 -->
|
||||
<title>KryoException</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="KryoException";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/KryoException.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/KryoCopyable.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/KryoSerializable.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/KryoException.html" target="_top">Frames</a></li>
|
||||
<li><a href="KryoException.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_summary">Constr</a> | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_detail">Constr</a> | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<!-- ======== START OF CLASS DATA ======== -->
|
||||
<div class="header">
|
||||
<div class="subTitle">com.esotericsoftware.kryo</div>
|
||||
<h2 title="Class KryoException" class="title">Class KryoException</h2>
|
||||
</div>
|
||||
<div class="contentContainer">
|
||||
<ul class="inheritance">
|
||||
<li>java.lang.Object</li>
|
||||
<li>
|
||||
<ul class="inheritance">
|
||||
<li>java.lang.Throwable</li>
|
||||
<li>
|
||||
<ul class="inheritance">
|
||||
<li>java.lang.Exception</li>
|
||||
<li>
|
||||
<ul class="inheritance">
|
||||
<li>java.lang.RuntimeException</li>
|
||||
<li>
|
||||
<ul class="inheritance">
|
||||
<li>com.esotericsoftware.kryo.KryoException</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="description">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<dl>
|
||||
<dt>All Implemented Interfaces:</dt>
|
||||
<dd>java.io.Serializable</dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<br>
|
||||
<pre>public class <span class="strong">KryoException</span>
|
||||
extends java.lang.RuntimeException</pre>
|
||||
<div class="block">General Kryo RuntimeException.</div>
|
||||
<dl><dt><span class="strong">Author:</span></dt>
|
||||
<dd>Nathan Sweet <misc@n4te.com></dd>
|
||||
<dt><span class="strong">See Also:</span></dt><dd><a href="../../../serialized-form.html#com.esotericsoftware.kryo.KryoException">Serialized Form</a></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ======== CONSTRUCTOR SUMMARY ======== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="constructor_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Constructor Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
|
||||
<caption><span>Constructors</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colOne" scope="col">Constructor and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colOne"><code><strong><a href="../../../com/esotericsoftware/kryo/KryoException.html#KryoException()">KryoException</a></strong>()</code> </td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colOne"><code><strong><a href="../../../com/esotericsoftware/kryo/KryoException.html#KryoException(java.lang.String)">KryoException</a></strong>(java.lang.String message)</code> </td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colOne"><code><strong><a href="../../../com/esotericsoftware/kryo/KryoException.html#KryoException(java.lang.String, java.lang.Throwable)">KryoException</a></strong>(java.lang.String message,
|
||||
java.lang.Throwable cause)</code> </td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colOne"><code><strong><a href="../../../com/esotericsoftware/kryo/KryoException.html#KryoException(java.lang.Throwable)">KryoException</a></strong>(java.lang.Throwable cause)</code> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- ========== METHOD SUMMARY =========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
|
||||
<caption><span>Methods</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Method and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/KryoException.html#addTrace(java.lang.String)">addTrace</a></strong>(java.lang.String info)</code>
|
||||
<div class="block">Adds information to the exception message about where in the the object graph serialization failure occurred.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>java.lang.String</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/KryoException.html#getMessage()">getMessage</a></strong>()</code> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="methods_inherited_from_class_java.lang.Throwable">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Methods inherited from class java.lang.Throwable</h3>
|
||||
<code>addSuppressed, fillInStackTrace, getCause, getLocalizedMessage, getStackTrace, getSuppressed, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toString</code></li>
|
||||
</ul>
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="methods_inherited_from_class_java.lang.Object">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Methods inherited from class java.lang.Object</h3>
|
||||
<code>equals, getClass, hashCode, notify, notifyAll, wait, wait, wait</code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="details">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ========= CONSTRUCTOR DETAIL ======== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="constructor_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Constructor Detail</h3>
|
||||
<a name="KryoException()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>KryoException</h4>
|
||||
<pre>public KryoException()</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="KryoException(java.lang.String, java.lang.Throwable)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>KryoException</h4>
|
||||
<pre>public KryoException(java.lang.String message,
|
||||
java.lang.Throwable cause)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="KryoException(java.lang.String)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>KryoException</h4>
|
||||
<pre>public KryoException(java.lang.String message)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="KryoException(java.lang.Throwable)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>KryoException</h4>
|
||||
<pre>public KryoException(java.lang.Throwable cause)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- ============ METHOD DETAIL ========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Detail</h3>
|
||||
<a name="getMessage()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getMessage</h4>
|
||||
<pre>public java.lang.String getMessage()</pre>
|
||||
<dl>
|
||||
<dt><strong>Overrides:</strong></dt>
|
||||
<dd><code>getMessage</code> in class <code>java.lang.Throwable</code></dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="addTrace(java.lang.String)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>addTrace</h4>
|
||||
<pre>public void addTrace(java.lang.String info)</pre>
|
||||
<div class="block">Adds information to the exception message about where in the the object graph serialization failure occurred.
|
||||
<a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo"><code>Serializers</code></a> can catch <a href="../../../com/esotericsoftware/kryo/KryoException.html" title="class in com.esotericsoftware.kryo"><code>KryoException</code></a>, add trace information, and rethrow the exception.</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/KryoException.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/KryoCopyable.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/KryoSerializable.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/KryoException.html" target="_top">Frames</a></li>
|
||||
<li><a href="KryoException.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_summary">Constr</a> | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_detail">Constr</a> | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,233 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:45 CET 2013 -->
|
||||
<title>KryoSerializable</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="KryoSerializable";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/KryoSerializable.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/KryoException.html" title="class in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/NotNull.html" title="annotation in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/KryoSerializable.html" target="_top">Frames</a></li>
|
||||
<li><a href="KryoSerializable.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<!-- ======== START OF CLASS DATA ======== -->
|
||||
<div class="header">
|
||||
<div class="subTitle">com.esotericsoftware.kryo</div>
|
||||
<h2 title="Interface KryoSerializable" class="title">Interface KryoSerializable</h2>
|
||||
</div>
|
||||
<div class="contentContainer">
|
||||
<div class="description">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<dl>
|
||||
<dt>All Known Implementing Classes:</dt>
|
||||
<dd><a href="../../../com/esotericsoftware/kryonet/rmi/ObjectSpace.InvokeMethod.html" title="class in com.esotericsoftware.kryonet.rmi">ObjectSpace.InvokeMethod</a></dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<br>
|
||||
<pre>public interface <span class="strong">KryoSerializable</span></pre>
|
||||
<div class="block">Allows implementing classes to perform their own serialization. Hand written serialization can be more efficient in some cases.
|
||||
<p>
|
||||
The default serializer for KryoSerializable is <a href="../../../com/esotericsoftware/kryo/serializers/DefaultSerializers.KryoSerializableSerializer.html" title="class in com.esotericsoftware.kryo.serializers"><code>DefaultSerializers.KryoSerializableSerializer</code></a>, which uses <a href="../../../com/esotericsoftware/kryo/Kryo.html#newInstance(java.lang.Class)"><code>Kryo.newInstance(Class)</code></a>
|
||||
to construct the class.</div>
|
||||
<dl><dt><span class="strong">Author:</span></dt>
|
||||
<dd>Nathan Sweet <misc@n4te.com></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ========== METHOD SUMMARY =========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
|
||||
<caption><span>Methods</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Method and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/KryoSerializable.html#read(com.esotericsoftware.kryo.Kryo, com.esotericsoftware.kryo.io.Input)">read</a></strong>(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo,
|
||||
<a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a> input)</code> </td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/KryoSerializable.html#write(com.esotericsoftware.kryo.Kryo, com.esotericsoftware.kryo.io.Output)">write</a></strong>(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo,
|
||||
<a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> output)</code> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="details">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ============ METHOD DETAIL ========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Detail</h3>
|
||||
<a name="write(com.esotericsoftware.kryo.Kryo, com.esotericsoftware.kryo.io.Output)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>write</h4>
|
||||
<pre>void write(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo,
|
||||
<a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> output)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="read(com.esotericsoftware.kryo.Kryo, com.esotericsoftware.kryo.io.Input)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>read</h4>
|
||||
<pre>void read(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo,
|
||||
<a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a> input)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/KryoSerializable.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/KryoException.html" title="class in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/NotNull.html" title="annotation in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/KryoSerializable.html" target="_top">Frames</a></li>
|
||||
<li><a href="KryoSerializable.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,156 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:45 CET 2013 -->
|
||||
<title>NotNull</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="NotNull";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/NotNull.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/KryoSerializable.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/NotNull.html" target="_top">Frames</a></li>
|
||||
<li><a href="NotNull.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Required | </li>
|
||||
<li>Optional</li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Element</li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<!-- ======== START OF CLASS DATA ======== -->
|
||||
<div class="header">
|
||||
<div class="subTitle">com.esotericsoftware.kryo</div>
|
||||
<h2 title="Annotation Type NotNull" class="title">Annotation Type NotNull</h2>
|
||||
</div>
|
||||
<div class="contentContainer">
|
||||
<div class="description">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<hr>
|
||||
<br>
|
||||
<pre>@Retention(value=RUNTIME)
|
||||
@Target(value=FIELD)
|
||||
public @interface <span class="strong">NotNull</span></pre>
|
||||
<div class="block">Indicates a field can never be null when it is being serialized and deserialized. Some serializers use this to save space. Eg,
|
||||
<a href="../../../com/esotericsoftware/kryo/serializers/FieldSerializer.html" title="class in com.esotericsoftware.kryo.serializers"><code>FieldSerializer</code></a> may save 1 byte per field.</div>
|
||||
<dl><dt><span class="strong">Author:</span></dt>
|
||||
<dd>Nathan Sweet <misc@n4te.com></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/NotNull.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/KryoSerializable.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/NotNull.html" target="_top">Frames</a></li>
|
||||
<li><a href="NotNull.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Required | </li>
|
||||
<li>Optional</li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Element</li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,339 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:45 CET 2013 -->
|
||||
<title>ReferenceResolver</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="ReferenceResolver";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/ReferenceResolver.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/NotNull.html" title="annotation in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/ReferenceResolver.html" target="_top">Frames</a></li>
|
||||
<li><a href="ReferenceResolver.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<!-- ======== START OF CLASS DATA ======== -->
|
||||
<div class="header">
|
||||
<div class="subTitle">com.esotericsoftware.kryo</div>
|
||||
<h2 title="Interface ReferenceResolver" class="title">Interface ReferenceResolver</h2>
|
||||
</div>
|
||||
<div class="contentContainer">
|
||||
<div class="description">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<dl>
|
||||
<dt>All Known Implementing Classes:</dt>
|
||||
<dd><a href="../../../com/esotericsoftware/kryo/util/ListReferenceResolver.html" title="class in com.esotericsoftware.kryo.util">ListReferenceResolver</a>, <a href="../../../com/esotericsoftware/kryo/util/MapReferenceResolver.html" title="class in com.esotericsoftware.kryo.util">MapReferenceResolver</a></dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<br>
|
||||
<pre>public interface <span class="strong">ReferenceResolver</span></pre>
|
||||
<div class="block">When references are enabled, this tracks objects that have already been read or written, provides an ID for objects that are
|
||||
written, and looks up by ID objects that have been read.</div>
|
||||
<dl><dt><span class="strong">Author:</span></dt>
|
||||
<dd>Nathan Sweet <misc@n4te.com></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ========== METHOD SUMMARY =========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
|
||||
<caption><span>Methods</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Method and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>int</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html#addWrittenObject(java.lang.Object)">addWrittenObject</a></strong>(java.lang.Object object)</code>
|
||||
<div class="block">Returns a new ID for an object that is being written for the first time.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>java.lang.Object</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html#getReadObject(java.lang.Class, int)">getReadObject</a></strong>(java.lang.Class type,
|
||||
int id)</code>
|
||||
<div class="block">Returns the object for the specified ID.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>int</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html#getWrittenId(java.lang.Object)">getWrittenId</a></strong>(java.lang.Object object)</code>
|
||||
<div class="block">Returns an ID for the object if it has been written previously, otherwise returns -1.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>int</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html#nextReadId(java.lang.Class)">nextReadId</a></strong>(java.lang.Class type)</code>
|
||||
<div class="block">Reserves the ID for the next object that will be read.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html#reset()">reset</a></strong>()</code>
|
||||
<div class="block">Called by <a href="../../../com/esotericsoftware/kryo/Kryo.html#reset()"><code>Kryo.reset()</code></a>.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html#setKryo(com.esotericsoftware.kryo.Kryo)">setKryo</a></strong>(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo)</code>
|
||||
<div class="block">Sets the Kryo instance that this ClassResolver will be used for.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html#setReadObject(int, java.lang.Object)">setReadObject</a></strong>(int id,
|
||||
java.lang.Object object)</code>
|
||||
<div class="block">Sets the ID for an object that has been read.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>boolean</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html#useReferences(java.lang.Class)">useReferences</a></strong>(java.lang.Class type)</code>
|
||||
<div class="block">Returns true if references will be written for the specified type.</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="details">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ============ METHOD DETAIL ========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Detail</h3>
|
||||
<a name="setKryo(com.esotericsoftware.kryo.Kryo)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>setKryo</h4>
|
||||
<pre>void setKryo(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo)</pre>
|
||||
<div class="block">Sets the Kryo instance that this ClassResolver will be used for. This is called automatically by Kryo.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getWrittenId(java.lang.Object)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getWrittenId</h4>
|
||||
<pre>int getWrittenId(java.lang.Object object)</pre>
|
||||
<div class="block">Returns an ID for the object if it has been written previously, otherwise returns -1.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="addWrittenObject(java.lang.Object)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>addWrittenObject</h4>
|
||||
<pre>int addWrittenObject(java.lang.Object object)</pre>
|
||||
<div class="block">Returns a new ID for an object that is being written for the first time.</div>
|
||||
<dl><dt><span class="strong">Returns:</span></dt><dd>The ID, which is stored more efficiently if it is positive and must not be -1 or -2.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="nextReadId(java.lang.Class)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>nextReadId</h4>
|
||||
<pre>int nextReadId(java.lang.Class type)</pre>
|
||||
<div class="block">Reserves the ID for the next object that will be read. This is called only the first time an object is encountered.</div>
|
||||
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>type</code> - The type of object that will be read.</dd>
|
||||
<dt><span class="strong">Returns:</span></dt><dd>The ID, which is stored more efficiently if it is positive and must not be -1 or -2.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="setReadObject(int, java.lang.Object)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>setReadObject</h4>
|
||||
<pre>void setReadObject(int id,
|
||||
java.lang.Object object)</pre>
|
||||
<div class="block">Sets the ID for an object that has been read.</div>
|
||||
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>id</code> - The ID from <a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html#nextReadId(java.lang.Class)"><code>nextReadId(Class)</code></a>.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getReadObject(java.lang.Class, int)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getReadObject</h4>
|
||||
<pre>java.lang.Object getReadObject(java.lang.Class type,
|
||||
int id)</pre>
|
||||
<div class="block">Returns the object for the specified ID. The ID and object are guaranteed to have been previously passed in a call to
|
||||
<a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html#setReadObject(int, java.lang.Object)"><code>setReadObject(int, Object)</code></a>.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="reset()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>reset</h4>
|
||||
<pre>void reset()</pre>
|
||||
<div class="block">Called by <a href="../../../com/esotericsoftware/kryo/Kryo.html#reset()"><code>Kryo.reset()</code></a>.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="useReferences(java.lang.Class)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>useReferences</h4>
|
||||
<pre>boolean useReferences(java.lang.Class type)</pre>
|
||||
<div class="block">Returns true if references will be written for the specified type.</div>
|
||||
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>type</code> - Will never be a primitive type, but may be a primitive type wrapper.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/ReferenceResolver.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/NotNull.html" title="annotation in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Registration.html" title="class in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/ReferenceResolver.html" target="_top">Frames</a></li>
|
||||
<li><a href="ReferenceResolver.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,353 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:45 CET 2013 -->
|
||||
<title>Registration</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="Registration";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/Registration.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/Registration.html" target="_top">Frames</a></li>
|
||||
<li><a href="Registration.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_summary">Constr</a> | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_detail">Constr</a> | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<!-- ======== START OF CLASS DATA ======== -->
|
||||
<div class="header">
|
||||
<div class="subTitle">com.esotericsoftware.kryo</div>
|
||||
<h2 title="Class Registration" class="title">Class Registration</h2>
|
||||
</div>
|
||||
<div class="contentContainer">
|
||||
<ul class="inheritance">
|
||||
<li>java.lang.Object</li>
|
||||
<li>
|
||||
<ul class="inheritance">
|
||||
<li>com.esotericsoftware.kryo.Registration</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="description">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<hr>
|
||||
<br>
|
||||
<pre>public class <span class="strong">Registration</span>
|
||||
extends java.lang.Object</pre>
|
||||
<div class="block">Describes the <a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo"><code>Serializer</code></a> and class ID to use for a class.</div>
|
||||
<dl><dt><span class="strong">Author:</span></dt>
|
||||
<dd>Nathan Sweet <misc@n4te.com></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ======== CONSTRUCTOR SUMMARY ======== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="constructor_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Constructor Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
|
||||
<caption><span>Constructors</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colOne" scope="col">Constructor and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colOne"><code><strong><a href="../../../com/esotericsoftware/kryo/Registration.html#Registration(java.lang.Class, com.esotericsoftware.kryo.Serializer, int)">Registration</a></strong>(java.lang.Class type,
|
||||
<a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo">Serializer</a> serializer,
|
||||
int id)</code> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- ========== METHOD SUMMARY =========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
|
||||
<caption><span>Methods</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Method and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>int</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Registration.html#getId()">getId</a></strong>()</code>
|
||||
<div class="block">Returns the registered class ID.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>org.objenesis.instantiator.ObjectInstantiator</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Registration.html#getInstantiator()">getInstantiator</a></strong>()</code> </td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo">Serializer</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Registration.html#getSerializer()">getSerializer</a></strong>()</code> </td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>java.lang.Class</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Registration.html#getType()">getType</a></strong>()</code> </td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Registration.html#setInstantiator(org.objenesis.instantiator.ObjectInstantiator)">setInstantiator</a></strong>(org.objenesis.instantiator.ObjectInstantiator instantiator)</code>
|
||||
<div class="block">Sets the instantiator that will create a new instance of the type in <a href="../../../com/esotericsoftware/kryo/Kryo.html#newInstance(java.lang.Class)"><code>Kryo.newInstance(Class)</code></a>.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Registration.html#setSerializer(com.esotericsoftware.kryo.Serializer)">setSerializer</a></strong>(<a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo">Serializer</a> serializer)</code> </td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>java.lang.String</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/Registration.html#toString()">toString</a></strong>()</code> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="methods_inherited_from_class_java.lang.Object">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Methods inherited from class java.lang.Object</h3>
|
||||
<code>equals, getClass, hashCode, notify, notifyAll, wait, wait, wait</code></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="details">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ========= CONSTRUCTOR DETAIL ======== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="constructor_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Constructor Detail</h3>
|
||||
<a name="Registration(java.lang.Class, com.esotericsoftware.kryo.Serializer, int)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>Registration</h4>
|
||||
<pre>public Registration(java.lang.Class type,
|
||||
<a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo">Serializer</a> serializer,
|
||||
int id)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- ============ METHOD DETAIL ========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Detail</h3>
|
||||
<a name="getType()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getType</h4>
|
||||
<pre>public java.lang.Class getType()</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getId()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getId</h4>
|
||||
<pre>public int getId()</pre>
|
||||
<div class="block">Returns the registered class ID.</div>
|
||||
<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../com/esotericsoftware/kryo/Kryo.html#register(java.lang.Class)"><code>Kryo.register(Class)</code></a></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getSerializer()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getSerializer</h4>
|
||||
<pre>public <a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo">Serializer</a> getSerializer()</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="setSerializer(com.esotericsoftware.kryo.Serializer)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>setSerializer</h4>
|
||||
<pre>public void setSerializer(<a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo">Serializer</a> serializer)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getInstantiator()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getInstantiator</h4>
|
||||
<pre>public org.objenesis.instantiator.ObjectInstantiator getInstantiator()</pre>
|
||||
<dl><dt><span class="strong">Returns:</span></dt><dd>May be null if not yet set.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="setInstantiator(org.objenesis.instantiator.ObjectInstantiator)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>setInstantiator</h4>
|
||||
<pre>public void setInstantiator(org.objenesis.instantiator.ObjectInstantiator instantiator)</pre>
|
||||
<div class="block">Sets the instantiator that will create a new instance of the type in <a href="../../../com/esotericsoftware/kryo/Kryo.html#newInstance(java.lang.Class)"><code>Kryo.newInstance(Class)</code></a>.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="toString()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>toString</h4>
|
||||
<pre>public java.lang.String toString()</pre>
|
||||
<dl>
|
||||
<dt><strong>Overrides:</strong></dt>
|
||||
<dd><code>toString</code> in class <code>java.lang.Object</code></dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/Registration.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/ReferenceResolver.html" title="interface in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo"><span class="strong">Next Class</span></a></li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/Registration.html" target="_top">Frames</a></li>
|
||||
<li><a href="Registration.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_summary">Constr</a> | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li><a href="#constructor_detail">Constr</a> | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,441 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:45 CET 2013 -->
|
||||
<title>StreamFactory</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="StreamFactory";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/StreamFactory.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li>Next Class</li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/StreamFactory.html" target="_top">Frames</a></li>
|
||||
<li><a href="StreamFactory.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<!-- ======== START OF CLASS DATA ======== -->
|
||||
<div class="header">
|
||||
<div class="subTitle">com.esotericsoftware.kryo</div>
|
||||
<h2 title="Interface StreamFactory" class="title">Interface StreamFactory</h2>
|
||||
</div>
|
||||
<div class="contentContainer">
|
||||
<div class="description">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<dl>
|
||||
<dt>All Known Implementing Classes:</dt>
|
||||
<dd><a href="../../../com/esotericsoftware/kryo/util/DefaultStreamFactory.html" title="class in com.esotericsoftware.kryo.util">DefaultStreamFactory</a>, <a href="../../../com/esotericsoftware/kryo/util/FastestStreamFactory.html" title="class in com.esotericsoftware.kryo.util">FastestStreamFactory</a></dd>
|
||||
</dl>
|
||||
<hr>
|
||||
<br>
|
||||
<pre>public interface <span class="strong">StreamFactory</span></pre>
|
||||
<div class="block">Provides input and output streams based on system settings.</div>
|
||||
<dl><dt><span class="strong">Author:</span></dt>
|
||||
<dd>Roman Levenstein <romixlev@gmail.com></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="summary">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ========== METHOD SUMMARY =========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_summary">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Summary</h3>
|
||||
<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
|
||||
<caption><span>Methods</span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Method and Description</th>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getInput()">getInput</a></strong>()</code>
|
||||
<div class="block">Creates an uninitialized Input.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getInput(byte[])">getInput</a></strong>(byte[] buffer)</code>
|
||||
<div class="block">Creates a new Input for reading from a byte array.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getInput(byte[], int, int)">getInput</a></strong>(byte[] buffer,
|
||||
int offset,
|
||||
int count)</code>
|
||||
<div class="block">Creates a new Input for reading from a byte array.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getInput(java.io.InputStream)">getInput</a></strong>(java.io.InputStream inputStream)</code>
|
||||
<div class="block">Creates a new Input for reading from an InputStream with a buffer size of 4096.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getInput(java.io.InputStream, int)">getInput</a></strong>(java.io.InputStream inputStream,
|
||||
int bufferSize)</code>
|
||||
<div class="block">Creates a new Input for reading from an InputStream.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getInput(int)">getInput</a></strong>(int bufferSize)</code>
|
||||
<div class="block">Creates a new Input for reading from a byte array.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getOutput()">getOutput</a></strong>()</code>
|
||||
<div class="block">Creates an uninitialized Output.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getOutput(byte[])">getOutput</a></strong>(byte[] buffer)</code>
|
||||
<div class="block">Creates a new Output for writing to a byte array.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getOutput(byte[], int)">getOutput</a></strong>(byte[] buffer,
|
||||
int maxBufferSize)</code>
|
||||
<div class="block">Creates a new Output for writing to a byte array.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getOutput(int)">getOutput</a></strong>(int bufferSize)</code>
|
||||
<div class="block">Creates a new Output for writing to a byte array.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getOutput(int, int)">getOutput</a></strong>(int bufferSize,
|
||||
int maxBufferSize)</code>
|
||||
<div class="block">Creates a new Output for writing to a byte array.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getOutput(java.io.OutputStream)">getOutput</a></strong>(java.io.OutputStream outputStream)</code>
|
||||
<div class="block">Creates a new Output for writing to an OutputStream.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a></code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#getOutput(java.io.OutputStream, int)">getOutput</a></strong>(java.io.OutputStream outputStream,
|
||||
int bufferSize)</code>
|
||||
<div class="block">Creates a new Output for writing to an OutputStream.</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><code>void</code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../com/esotericsoftware/kryo/StreamFactory.html#setKryo(com.esotericsoftware.kryo.Kryo)">setKryo</a></strong>(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo)</code> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="details">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<!-- ============ METHOD DETAIL ========== -->
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="method_detail">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Method Detail</h3>
|
||||
<a name="getInput()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getInput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a> getInput()</pre>
|
||||
<div class="block">Creates an uninitialized Input.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getInput(int)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getInput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a> getInput(int bufferSize)</pre>
|
||||
<div class="block">Creates a new Input for reading from a byte array.</div>
|
||||
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>bufferSize</code> - The size of the buffer. An exception is thrown if more bytes than this are read.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getInput(byte[])">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getInput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a> getInput(byte[] buffer)</pre>
|
||||
<div class="block">Creates a new Input for reading from a byte array.</div>
|
||||
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>buffer</code> - An exception is thrown if more bytes than this are read.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getInput(byte[], int, int)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getInput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a> getInput(byte[] buffer,
|
||||
int offset,
|
||||
int count)</pre>
|
||||
<div class="block">Creates a new Input for reading from a byte array.</div>
|
||||
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>buffer</code> - An exception is thrown if more bytes than this are read.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getInput(java.io.InputStream)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getInput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a> getInput(java.io.InputStream inputStream)</pre>
|
||||
<div class="block">Creates a new Input for reading from an InputStream with a buffer size of 4096.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getInput(java.io.InputStream, int)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getInput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Input.html" title="class in com.esotericsoftware.kryo.io">Input</a> getInput(java.io.InputStream inputStream,
|
||||
int bufferSize)</pre>
|
||||
<div class="block">Creates a new Input for reading from an InputStream.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getOutput()">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getOutput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> getOutput()</pre>
|
||||
<div class="block">Creates an uninitialized Output. <a href="../../../com/esotericsoftware/kryo/io/Output.html#setBuffer(byte[], int)"><code>Output.setBuffer(byte[], int)</code></a> must be called before the Output is used.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getOutput(int)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getOutput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> getOutput(int bufferSize)</pre>
|
||||
<div class="block">Creates a new Output for writing to a byte array.</div>
|
||||
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>bufferSize</code> - The initial and maximum size of the buffer. An exception is thrown if this size is exceeded.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getOutput(int, int)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getOutput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> getOutput(int bufferSize,
|
||||
int maxBufferSize)</pre>
|
||||
<div class="block">Creates a new Output for writing to a byte array.</div>
|
||||
<dl><dt><span class="strong">Parameters:</span></dt><dd><code>bufferSize</code> - The initial size of the buffer.</dd><dd><code>maxBufferSize</code> - The buffer is doubled as needed until it exceeds maxBufferSize and an exception is thrown. Can be -1
|
||||
for no maximum.</dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getOutput(byte[])">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getOutput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> getOutput(byte[] buffer)</pre>
|
||||
<div class="block">Creates a new Output for writing to a byte array.</div>
|
||||
<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../com/esotericsoftware/kryo/io/Output.html#setBuffer(byte[])"><code>Output.setBuffer(byte[])</code></a></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getOutput(byte[], int)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getOutput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> getOutput(byte[] buffer,
|
||||
int maxBufferSize)</pre>
|
||||
<div class="block">Creates a new Output for writing to a byte array.</div>
|
||||
<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../com/esotericsoftware/kryo/io/Output.html#setBuffer(byte[], int)"><code>Output.setBuffer(byte[], int)</code></a></dd></dl>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getOutput(java.io.OutputStream)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getOutput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> getOutput(java.io.OutputStream outputStream)</pre>
|
||||
<div class="block">Creates a new Output for writing to an OutputStream. A buffer size of 4096 is used.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="getOutput(java.io.OutputStream, int)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<h4>getOutput</h4>
|
||||
<pre><a href="../../../com/esotericsoftware/kryo/io/Output.html" title="class in com.esotericsoftware.kryo.io">Output</a> getOutput(java.io.OutputStream outputStream,
|
||||
int bufferSize)</pre>
|
||||
<div class="block">Creates a new Output for writing to an OutputStream.</div>
|
||||
</li>
|
||||
</ul>
|
||||
<a name="setKryo(com.esotericsoftware.kryo.Kryo)">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="blockListLast">
|
||||
<li class="blockList">
|
||||
<h4>setKryo</h4>
|
||||
<pre>void setKryo(<a href="../../../com/esotericsoftware/kryo/Kryo.html" title="class in com.esotericsoftware.kryo">Kryo</a> kryo)</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- ========= END OF CLASS DATA ========= -->
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="package-summary.html">Package</a></li>
|
||||
<li class="navBarCell1Rev">Class</li>
|
||||
<li><a href="class-use/StreamFactory.html">Use</a></li>
|
||||
<li><a href="package-tree.html">Tree</a></li>
|
||||
<li><a href="../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li><a href="../../../com/esotericsoftware/kryo/Serializer.html" title="class in com.esotericsoftware.kryo"><span class="strong">Prev Class</span></a></li>
|
||||
<li>Next Class</li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../index.html?com/esotericsoftware/kryo/StreamFactory.html" target="_top">Frames</a></li>
|
||||
<li><a href="StreamFactory.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="subNavList">
|
||||
<li>Summary: </li>
|
||||
<li>Nested | </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_summary">Method</a></li>
|
||||
</ul>
|
||||
<ul class="subNavList">
|
||||
<li>Detail: </li>
|
||||
<li>Field | </li>
|
||||
<li>Constr | </li>
|
||||
<li><a href="#method_detail">Method</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,196 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<!-- NewPage -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Generated by javadoc (version 1.7.0_45) on Tue Nov 12 20:31:47 CET 2013 -->
|
||||
<title>Uses of Interface com.esotericsoftware.kryo.ClassResolver</title>
|
||||
<meta name="date" content="2013-11-12">
|
||||
<link rel="stylesheet" type="text/css" href="../../../../stylesheet.css" title="Style">
|
||||
</head>
|
||||
<body>
|
||||
<script type="text/javascript"><!--
|
||||
if (location.href.indexOf('is-external=true') == -1) {
|
||||
parent.document.title="Uses of Interface com.esotericsoftware.kryo.ClassResolver";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<noscript>
|
||||
<div>JavaScript is disabled on your browser.</div>
|
||||
</noscript>
|
||||
<!-- ========= START OF TOP NAVBAR ======= -->
|
||||
<div class="topNav"><a name="navbar_top">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_top" title="Skip navigation links"></a><a name="navbar_top_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="../package-summary.html">Package</a></li>
|
||||
<li><a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">Class</a></li>
|
||||
<li class="navBarCell1Rev">Use</li>
|
||||
<li><a href="../../../../overview-tree.html">Tree</a></li>
|
||||
<li><a href="../../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li>Prev</li>
|
||||
<li>Next</li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../../index.html?com/esotericsoftware/kryo/class-use/ClassResolver.html" target="_top">Frames</a></li>
|
||||
<li><a href="ClassResolver.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_top">
|
||||
<li><a href="../../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_top");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<a name="skip-navbar_top">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ========= END OF TOP NAVBAR ========= -->
|
||||
<div class="header">
|
||||
<h2 title="Uses of Interface com.esotericsoftware.kryo.ClassResolver" class="title">Uses of Interface<br>com.esotericsoftware.kryo.ClassResolver</h2>
|
||||
</div>
|
||||
<div class="classUseContainer">
|
||||
<ul class="blockList">
|
||||
<li class="blockList">
|
||||
<table border="0" cellpadding="3" cellspacing="0" summary="Use table, listing packages, and an explanation">
|
||||
<caption><span>Packages that use <a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">ClassResolver</a></span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Package</th>
|
||||
<th class="colLast" scope="col">Description</th>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><a href="#com.esotericsoftware.kryo">com.esotericsoftware.kryo</a></td>
|
||||
<td class="colLast"> </td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colFirst"><a href="#com.esotericsoftware.kryo.util">com.esotericsoftware.kryo.util</a></td>
|
||||
<td class="colLast"> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</li>
|
||||
<li class="blockList">
|
||||
<ul class="blockList">
|
||||
<li class="blockList"><a name="com.esotericsoftware.kryo">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Uses of <a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">ClassResolver</a> in <a href="../../../../com/esotericsoftware/kryo/package-summary.html">com.esotericsoftware.kryo</a></h3>
|
||||
<table border="0" cellpadding="3" cellspacing="0" summary="Use table, listing methods, and an explanation">
|
||||
<caption><span>Methods in <a href="../../../../com/esotericsoftware/kryo/package-summary.html">com.esotericsoftware.kryo</a> that return <a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">ClassResolver</a></span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Method and Description</th>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code><a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">ClassResolver</a></code></td>
|
||||
<td class="colLast"><span class="strong">Kryo.</span><code><strong><a href="../../../../com/esotericsoftware/kryo/Kryo.html#getClassResolver()">getClassResolver</a></strong>()</code> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<table border="0" cellpadding="3" cellspacing="0" summary="Use table, listing constructors, and an explanation">
|
||||
<caption><span>Constructors in <a href="../../../../com/esotericsoftware/kryo/package-summary.html">com.esotericsoftware.kryo</a> with parameters of type <a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">ClassResolver</a></span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colOne" scope="col">Constructor and Description</th>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr class="altColor">
|
||||
<td class="colLast"><code><strong><a href="../../../../com/esotericsoftware/kryo/Kryo.html#Kryo(com.esotericsoftware.kryo.ClassResolver, com.esotericsoftware.kryo.ReferenceResolver)">Kryo</a></strong>(<a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">ClassResolver</a> classResolver,
|
||||
<a href="../../../../com/esotericsoftware/kryo/ReferenceResolver.html" title="interface in com.esotericsoftware.kryo">ReferenceResolver</a> referenceResolver)</code> </td>
|
||||
</tr>
|
||||
<tr class="rowColor">
|
||||
<td class="colLast"><code><strong><a href="../../../../com/esotericsoftware/kryo/Kryo.html#Kryo(com.esotericsoftware.kryo.ClassResolver, com.esotericsoftware.kryo.ReferenceResolver, com.esotericsoftware.kryo.StreamFactory)">Kryo</a></strong>(<a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">ClassResolver</a> classResolver,
|
||||
<a href="../../../../com/esotericsoftware/kryo/ReferenceResolver.html" title="interface in com.esotericsoftware.kryo">ReferenceResolver</a> referenceResolver,
|
||||
<a href="../../../../com/esotericsoftware/kryo/StreamFactory.html" title="interface in com.esotericsoftware.kryo">StreamFactory</a> streamFactory)</code> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</li>
|
||||
<li class="blockList"><a name="com.esotericsoftware.kryo.util">
|
||||
<!-- -->
|
||||
</a>
|
||||
<h3>Uses of <a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">ClassResolver</a> in <a href="../../../../com/esotericsoftware/kryo/util/package-summary.html">com.esotericsoftware.kryo.util</a></h3>
|
||||
<table border="0" cellpadding="3" cellspacing="0" summary="Use table, listing classes, and an explanation">
|
||||
<caption><span>Classes in <a href="../../../../com/esotericsoftware/kryo/util/package-summary.html">com.esotericsoftware.kryo.util</a> that implement <a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">ClassResolver</a></span><span class="tabEnd"> </span></caption>
|
||||
<tr>
|
||||
<th class="colFirst" scope="col">Modifier and Type</th>
|
||||
<th class="colLast" scope="col">Class and Description</th>
|
||||
</tr>
|
||||
<tbody>
|
||||
<tr class="altColor">
|
||||
<td class="colFirst"><code>class </code></td>
|
||||
<td class="colLast"><code><strong><a href="../../../../com/esotericsoftware/kryo/util/DefaultClassResolver.html" title="class in com.esotericsoftware.kryo.util">DefaultClassResolver</a></strong></code>
|
||||
<div class="block">Resolves classes by ID or by fully qualified class name.</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
||||
<div class="bottomNav"><a name="navbar_bottom">
|
||||
<!-- -->
|
||||
</a><a href="#skip-navbar_bottom" title="Skip navigation links"></a><a name="navbar_bottom_firstrow">
|
||||
<!-- -->
|
||||
</a>
|
||||
<ul class="navList" title="Navigation">
|
||||
<li><a href="../../../../overview-summary.html">Overview</a></li>
|
||||
<li><a href="../package-summary.html">Package</a></li>
|
||||
<li><a href="../../../../com/esotericsoftware/kryo/ClassResolver.html" title="interface in com.esotericsoftware.kryo">Class</a></li>
|
||||
<li class="navBarCell1Rev">Use</li>
|
||||
<li><a href="../../../../overview-tree.html">Tree</a></li>
|
||||
<li><a href="../../../../deprecated-list.html">Deprecated</a></li>
|
||||
<li><a href="../../../../index-files/index-1.html">Index</a></li>
|
||||
<li><a href="../../../../help-doc.html">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="subNav">
|
||||
<ul class="navList">
|
||||
<li>Prev</li>
|
||||
<li>Next</li>
|
||||
</ul>
|
||||
<ul class="navList">
|
||||
<li><a href="../../../../index.html?com/esotericsoftware/kryo/class-use/ClassResolver.html" target="_top">Frames</a></li>
|
||||
<li><a href="ClassResolver.html" target="_top">No Frames</a></li>
|
||||
</ul>
|
||||
<ul class="navList" id="allclasses_navbar_bottom">
|
||||
<li><a href="../../../../allclasses-noframe.html">All Classes</a></li>
|
||||
</ul>
|
||||
<div>
|
||||
<script type="text/javascript"><!--
|
||||
allClassesLink = document.getElementById("allclasses_navbar_bottom");
|
||||
if(window==top) {
|
||||
allClassesLink.style.display = "block";
|
||||
}
|
||||
else {
|
||||
allClassesLink.style.display = "none";
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
</div>
|
||||
<a name="skip-navbar_bottom">
|
||||
<!-- -->
|
||||
</a></div>
|
||||
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue