fix networking issues
This commit is contained in:
parent
c641512886
commit
ab5abb019f
@ -362,12 +362,6 @@ public class LoadingThread extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void initClientTerrainManager(){
|
static void initClientTerrainManager(){
|
||||||
while(!Globals.clientConnection.getClientProtocol().hasReceivedWorld()){
|
|
||||||
try {
|
|
||||||
TimeUnit.MILLISECONDS.sleep(5);
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Globals.clientTerrainManager = new ClientTerrainManager(Globals.clientWorldData);
|
Globals.clientTerrainManager = new ClientTerrainManager(Globals.clientWorldData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,6 +387,14 @@ public class LoadingThread extends Thread {
|
|||||||
Globals.spawnPoint.set((float)startX,(float)Globals.commonWorldData.getElevationAtPoint(new Vector3d(startX,0,startZ)),(float)startZ);
|
Globals.spawnPoint.set((float)startX,(float)Globals.commonWorldData.getElevationAtPoint(new Vector3d(startX,0,startZ)),(float)startZ);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
//basically wait for the client to receive the world metadata
|
||||||
|
while(!Globals.clientConnection.getClientProtocol().hasReceivedWorld()){
|
||||||
|
try {
|
||||||
|
TimeUnit.MILLISECONDS.sleep(5);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//then create common world data
|
||||||
Globals.commonWorldData = new CommonWorldData(Globals.clientWorldData, Globals.clientTerrainManager);
|
Globals.commonWorldData = new CommonWorldData(Globals.clientWorldData, Globals.clientTerrainManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,16 +436,16 @@ public class LoadingThread extends Thread {
|
|||||||
|
|
||||||
|
|
||||||
static void initDrawCellManager(){
|
static void initDrawCellManager(){
|
||||||
|
//if it hasn't already been initialized, create draw cell manager
|
||||||
if(Globals.drawCellManager == null){
|
if(Globals.drawCellManager == null){
|
||||||
Globals.drawCellManager = new DrawCellManager(
|
Globals.drawCellManager = new DrawCellManager(
|
||||||
Globals.commonWorldData,
|
Globals.commonWorldData,
|
||||||
Globals.clientTerrainManager,
|
Globals.clientTerrainManager,
|
||||||
Globals.clientPlayerData.getWorldPositionX(),
|
Globals.clientPlayerData.getWorldPositionX(),
|
||||||
Globals.clientPlayerData.getWorldPositionY()
|
Globals.clientPlayerData.getWorldPositionY()
|
||||||
// Globals.terrainManager.getDynamicInterpolationRatio(),
|
|
||||||
// Globals.terrainManager.getRandomDampener()
|
|
||||||
);
|
);
|
||||||
} else {
|
}
|
||||||
|
if(Globals.RUN_CLIENT == true) {
|
||||||
//set our draw cell manager to actually generate drawable chunks
|
//set our draw cell manager to actually generate drawable chunks
|
||||||
Globals.drawCellManager.setGenerateDrawables(true);
|
Globals.drawCellManager.setGenerateDrawables(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package electrosphere.menu;
|
package electrosphere.menu;
|
||||||
|
|
||||||
|
import electrosphere.auth.AuthenticationManager;
|
||||||
import electrosphere.controls.ControlHandler.ControlsState;
|
import electrosphere.controls.ControlHandler.ControlsState;
|
||||||
import electrosphere.engine.LoadingThread;
|
import electrosphere.engine.LoadingThread;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
@ -353,16 +354,38 @@ public class MenuGenerators {
|
|||||||
portInput.setText(NetUtils.getPort() + "");
|
portInput.setText(NetUtils.getPort() + "");
|
||||||
rVal.addChild(portInput);
|
rVal.addChild(portInput);
|
||||||
|
|
||||||
|
//label (address)
|
||||||
|
Label usernameLabel = new Label(100,screenTop + 350,1.0f);
|
||||||
|
usernameLabel.setText("Username");
|
||||||
|
rVal.addChild(usernameLabel);
|
||||||
|
|
||||||
|
//text entry (address)
|
||||||
|
TextInput usernameInput = new TextInput(100,screenTop + 425,1.0f);
|
||||||
|
usernameInput.setText("");
|
||||||
|
rVal.addChild(usernameInput);
|
||||||
|
|
||||||
|
//label (port)
|
||||||
|
Label passwordLabel = new Label(100,screenTop + 500,1.0f);
|
||||||
|
passwordLabel.setText("Password");
|
||||||
|
rVal.addChild(passwordLabel);
|
||||||
|
|
||||||
|
//text entry (port)
|
||||||
|
TextInput passwordInput = new TextInput(100,screenTop + 575,1.0f);
|
||||||
|
passwordInput.setText("");
|
||||||
|
rVal.addChild(passwordInput);
|
||||||
|
|
||||||
//button (connect)
|
//button (connect)
|
||||||
Button connectButton = new Button();
|
Button connectButton = new Button();
|
||||||
Label connectLabel = new Label(100,screenTop + 350,1.0f);
|
Label connectLabel = new Label(100,screenTop + 650,1.0f);
|
||||||
connectLabel.setText("Connect");
|
connectLabel.setText("Connect");
|
||||||
connectButton.addChild(connectLabel);
|
connectButton.addChild(connectLabel);
|
||||||
rVal.addChild(connectButton);
|
rVal.addChild(connectButton);
|
||||||
connectButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
|
connectButton.setOnClick(new ClickableElement.ClickEventCallback(){public boolean execute(ClickEvent event){
|
||||||
NetUtils.setAddress(addressInput.getText());
|
NetUtils.setAddress(addressInput.getText());
|
||||||
NetUtils.setPort(Integer.parseInt(portInput.getText()));
|
NetUtils.setPort(Integer.parseInt(portInput.getText()));
|
||||||
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_MAIN_GAME);
|
Globals.clientUsername = usernameInput.getText();
|
||||||
|
Globals.clientPassword = AuthenticationManager.getHashedString(passwordInput.getText());
|
||||||
|
LoadingThread clientThread = new LoadingThread(LoadingThread.LOAD_CHARACTER_SERVER);
|
||||||
Globals.loadingThreadsList.add(clientThread);
|
Globals.loadingThreadsList.add(clientThread);
|
||||||
Globals.RUN_CLIENT = true;
|
Globals.RUN_CLIENT = true;
|
||||||
Globals.RUN_SERVER = false;
|
Globals.RUN_SERVER = false;
|
||||||
@ -372,7 +395,7 @@ public class MenuGenerators {
|
|||||||
|
|
||||||
//button (back)
|
//button (back)
|
||||||
Button backButton = new Button();
|
Button backButton = new Button();
|
||||||
Label backLabel = new Label(100,screenTop + 425,1.0f);
|
Label backLabel = new Label(100,screenTop + 725,1.0f);
|
||||||
backLabel.setText("Back");
|
backLabel.setText("Back");
|
||||||
backButton.addChild(backLabel);
|
backButton.addChild(backLabel);
|
||||||
rVal.addChild(backButton);
|
rVal.addChild(backButton);
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import electrosphere.net.client.protocol.ClientProtocol;
|
|||||||
import electrosphere.net.parser.net.message.EntityMessage;
|
import electrosphere.net.parser.net.message.EntityMessage;
|
||||||
import electrosphere.net.parser.net.message.NetworkMessage;
|
import electrosphere.net.parser.net.message.NetworkMessage;
|
||||||
import electrosphere.net.parser.net.message.PlayerMessage;
|
import electrosphere.net.parser.net.message.PlayerMessage;
|
||||||
|
import electrosphere.net.parser.net.message.ServerMessage;
|
||||||
import electrosphere.net.parser.net.raw.NetworkParser;
|
import electrosphere.net.parser.net.raw.NetworkParser;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -48,6 +49,11 @@ public class ClientNetworking implements Runnable{
|
|||||||
|
|
||||||
static final int MAX_CONNECTION_ATTEMPTS = 10;
|
static final int MAX_CONNECTION_ATTEMPTS = 10;
|
||||||
|
|
||||||
|
static final long SEND_PING_THRESHOLD = 3000;
|
||||||
|
static final long PING_DISCONNECT_THRESHOLD = 20000;
|
||||||
|
long lastPingTime = 0;
|
||||||
|
long lastPongTime = 0;
|
||||||
|
|
||||||
public ClientNetworking(String address, int port){
|
public ClientNetworking(String address, int port){
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
@ -112,6 +118,30 @@ public class ClientNetworking implements Runnable{
|
|||||||
parser.readMessagesIn();
|
parser.readMessagesIn();
|
||||||
//outgoing messages
|
//outgoing messages
|
||||||
parser.pushMessagesOut();
|
parser.pushMessagesOut();
|
||||||
|
//ping logic
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
//basically if we haven't sent a ping in a while, send one
|
||||||
|
if(currentTime - lastPingTime > SEND_PING_THRESHOLD){
|
||||||
|
queueOutgoingMessage(ServerMessage.constructPingMessage());
|
||||||
|
lastPingTime = currentTime;
|
||||||
|
if(lastPongTime == 0){
|
||||||
|
lastPongTime = lastPingTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(lastPingTime - lastPongTime > PING_DISCONNECT_THRESHOLD){
|
||||||
|
//disconnected from the server
|
||||||
|
LoggerInterface.loggerNetworking.WARNING("Disconnected from server");
|
||||||
|
//close socket
|
||||||
|
if(socket.isConnected()){
|
||||||
|
try {
|
||||||
|
socket.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LoggerInterface.loggerNetworking.ERROR("Error closing socket", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TODO: kick us back to the main menu
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -137,4 +167,8 @@ public class ClientNetworking implements Runnable{
|
|||||||
return clientProtocol;
|
return clientProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void markReceivedPongMessage(){
|
||||||
|
lastPongTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,10 @@ public class EntityProtocol {
|
|||||||
EntityUtils.setEntityID(newlySpawnedEntity, message.getentityID());
|
EntityUtils.setEntityID(newlySpawnedEntity, message.getentityID());
|
||||||
break;
|
break;
|
||||||
case DESTROY:
|
case DESTROY:
|
||||||
|
//only obey if we're not also the server
|
||||||
|
if(!Globals.RUN_SERVER){
|
||||||
|
Globals.entityManager.deregisterEntity(Globals.entityManager.getEntityFromId(message.getentityID()));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MOVE:
|
case MOVE:
|
||||||
//literally just adding this to scope so I can use `` Entity target; `` again
|
//literally just adding this to scope so I can use `` Entity target; `` again
|
||||||
@ -84,6 +88,12 @@ public class EntityProtocol {
|
|||||||
case ATTACKUPDATE:
|
case ATTACKUPDATE:
|
||||||
CreatureUtils.attachEntityMessageToAttackTree(Globals.entityManager.getEntityFromId(message.getentityID()),message);
|
CreatureUtils.attachEntityMessageToAttackTree(Globals.entityManager.getEntityFromId(message.getentityID()),message);
|
||||||
break;
|
break;
|
||||||
|
case KILL:
|
||||||
|
break;
|
||||||
|
case SETPOSITION:
|
||||||
|
break;
|
||||||
|
case SETFACING:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,8 @@ public class ServerProtocol {
|
|||||||
Globals.clientConnection.queueOutgoingMessage(ServerMessage.constructPongMessage());
|
Globals.clientConnection.queueOutgoingMessage(ServerMessage.constructPongMessage());
|
||||||
break;
|
break;
|
||||||
case PONG:
|
case PONG:
|
||||||
//silently drop
|
//let the networking loop know we received a pong message
|
||||||
|
Globals.clientConnection.markReceivedPongMessage();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ import electrosphere.net.parser.net.message.NetworkMessage;
|
|||||||
import electrosphere.net.parser.net.message.PlayerMessage;
|
import electrosphere.net.parser.net.message.PlayerMessage;
|
||||||
import electrosphere.net.parser.net.message.ServerMessage;
|
import electrosphere.net.parser.net.message.ServerMessage;
|
||||||
import electrosphere.net.parser.net.raw.NetworkParser;
|
import electrosphere.net.parser.net.raw.NetworkParser;
|
||||||
|
import electrosphere.net.server.player.Player;
|
||||||
import electrosphere.net.server.protocol.ServerProtocol;
|
import electrosphere.net.server.protocol.ServerProtocol;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -35,6 +36,8 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
import org.joml.Vector3d;
|
||||||
import org.joml.Vector3f;
|
import org.joml.Vector3f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,6 +62,15 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
|
|
||||||
ServerProtocol serverProtocol;
|
ServerProtocol serverProtocol;
|
||||||
|
|
||||||
|
//thresholds for determining when to send pings and when a client has disconnected
|
||||||
|
static final long SEND_PING_THRESHOLD = 3000;
|
||||||
|
static final long PING_DISCONNECT_THRESHOLD = 20000;
|
||||||
|
//used to keep track of ping/pong messages with client
|
||||||
|
long lastPingTime = 0;
|
||||||
|
long lastPongTime = 0;
|
||||||
|
//flag to disconnect due to pipe break
|
||||||
|
boolean socketException = false;
|
||||||
|
|
||||||
public ServerConnectionHandler(Socket socket) {
|
public ServerConnectionHandler(Socket socket) {
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
playerID = getNewPlayerID();
|
playerID = getNewPlayerID();
|
||||||
@ -104,21 +116,59 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
while(Main.isRunning()){
|
while(Main.isRunning()){
|
||||||
//attempt poll incoming messages
|
//parse messages both incoming and outgoing
|
||||||
networkParser.readMessagesIn();
|
|
||||||
//ponder incoming messages
|
|
||||||
while(networkParser.hasIncomingMessaage()){
|
|
||||||
NetworkMessage message = networkParser.popIncomingMessage();
|
|
||||||
serverProtocol.handleMessage(message);
|
|
||||||
}
|
|
||||||
//push outgoing message
|
|
||||||
networkParser.pushMessagesOut();
|
|
||||||
try {
|
try {
|
||||||
//sleep
|
parseMessages();
|
||||||
TimeUnit.MILLISECONDS.sleep(1);
|
} catch (SocketException e) {
|
||||||
} catch (InterruptedException ex) {
|
//if we get a SocketException broken pipe (basically the client dc'd without telling us)
|
||||||
ex.printStackTrace();
|
//set flag to disconnect client
|
||||||
|
//TODO: fix, this doesn't actually catch the socket exception which is exceedingly obnoxious
|
||||||
|
socketException = true;
|
||||||
|
LoggerInterface.loggerNetworking.DEBUG(e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
|
//ping logic
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
//basically if we haven't sent a ping in a while, send one
|
||||||
|
if(currentTime - lastPingTime > SEND_PING_THRESHOLD){
|
||||||
|
addMessagetoOutgoingQueue(ServerMessage.constructPingMessage());
|
||||||
|
lastPingTime = currentTime;
|
||||||
|
if(lastPongTime == 0){
|
||||||
|
lastPongTime = lastPingTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//check if we meet disconnection criteria
|
||||||
|
//has it been too long since the last ping?
|
||||||
|
//have we had a socket exception?
|
||||||
|
if(lastPingTime - lastPongTime > PING_DISCONNECT_THRESHOLD || this.socketException == true){
|
||||||
|
//disconnected from the server
|
||||||
|
LoggerInterface.loggerNetworking.WARNING("Client disconnected");
|
||||||
|
//run disconnect routine
|
||||||
|
disconnect();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Had to wrap the message parsing block in a function to throw a SocketException
|
||||||
|
* without my linter freaking out
|
||||||
|
* @throws SocketException
|
||||||
|
*/
|
||||||
|
void parseMessages() throws SocketException {
|
||||||
|
//attempt poll incoming messages
|
||||||
|
networkParser.readMessagesIn();
|
||||||
|
//ponder incoming messages
|
||||||
|
while(networkParser.hasIncomingMessaage()){
|
||||||
|
NetworkMessage message = networkParser.popIncomingMessage();
|
||||||
|
serverProtocol.handleMessage(message);
|
||||||
|
}
|
||||||
|
//push outgoing message
|
||||||
|
networkParser.pushMessagesOut();
|
||||||
|
try {
|
||||||
|
//sleep
|
||||||
|
TimeUnit.MILLISECONDS.sleep(1);
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,8 +215,6 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
networkParser.addOutgoingMessage(message);
|
networkParser.addOutgoingMessage(message);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SPAWNCREATURE:
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
networkParser.addOutgoingMessage(message);
|
networkParser.addOutgoingMessage(message);
|
||||||
break;
|
break;
|
||||||
@ -186,4 +234,31 @@ public class ServerConnectionHandler implements Runnable {
|
|||||||
return this.currentCreatureTemplate;
|
return this.currentCreatureTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void markReceivedPongMessage(){
|
||||||
|
lastPongTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Routine to run when the client disconnects
|
||||||
|
*/
|
||||||
|
void disconnect(){
|
||||||
|
//close socket
|
||||||
|
if(socket.isConnected()){
|
||||||
|
try {
|
||||||
|
socket.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
LoggerInterface.loggerNetworking.ERROR("Error closing socket", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//figure out what player we are
|
||||||
|
Player playerObject = Globals.playerManager.getPlayerFromId(getPlayerId());
|
||||||
|
//get player entity & position
|
||||||
|
Entity playerEntity = playerObject.getPlayerEntity();
|
||||||
|
Vector3d position = EntityUtils.getPosition(playerEntity);
|
||||||
|
//deregister entity
|
||||||
|
Globals.entityManager.deregisterEntity(playerObject.getPlayerEntity());
|
||||||
|
//tell all clients to destroy the entity
|
||||||
|
Globals.dataCellManager.getDataCellAtPoint(position).broadcastNetworkMessage(EntityMessage.constructDestroyMessage(playerEntity.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ public class AuthProtocol {
|
|||||||
connectionHandler.addMessagetoOutgoingQueue(AuthMessage.constructAuthSuccessMessage());
|
connectionHandler.addMessagetoOutgoingQueue(AuthMessage.constructAuthSuccessMessage());
|
||||||
Player newPlayer = new Player(connectionHandler);
|
Player newPlayer = new Player(connectionHandler);
|
||||||
Globals.playerManager.registerPlayer(newPlayer);
|
Globals.playerManager.registerPlayer(newPlayer);
|
||||||
if(connectionHandler.getIPAddress().contains("127.0.0.1")){
|
if(connectionHandler.getIPAddress().contains("127.0.0.1") && Globals.RUN_CLIENT == true){
|
||||||
Globals.clientPlayer = newPlayer;
|
Globals.clientPlayer = newPlayer;
|
||||||
}
|
}
|
||||||
connectionHandler.addMessagetoOutgoingQueue(PlayerMessage.constructSet_IDMessage(connectionHandler.getPlayerId()));
|
connectionHandler.addMessagetoOutgoingQueue(PlayerMessage.constructSet_IDMessage(connectionHandler.getPlayerId()));
|
||||||
|
|||||||
@ -29,7 +29,6 @@ import electrosphere.net.server.player.Player;
|
|||||||
public class ServerProtocol {
|
public class ServerProtocol {
|
||||||
|
|
||||||
ServerConnectionHandler connectionHandler;
|
ServerConnectionHandler connectionHandler;
|
||||||
int playerCharacterID;
|
|
||||||
|
|
||||||
public ServerProtocol(ServerConnectionHandler connectionHandler){
|
public ServerProtocol(ServerConnectionHandler connectionHandler){
|
||||||
this.connectionHandler = connectionHandler;
|
this.connectionHandler = connectionHandler;
|
||||||
@ -70,7 +69,7 @@ public class ServerProtocol {
|
|||||||
connectionHandler.addMessagetoOutgoingQueue(ServerMessage.constructPongMessage());
|
connectionHandler.addMessagetoOutgoingQueue(ServerMessage.constructPongMessage());
|
||||||
break;
|
break;
|
||||||
case PONG:
|
case PONG:
|
||||||
//silently drop
|
connectionHandler.markReceivedPongMessage();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user