251 lines
11 KiB
Java
251 lines
11 KiB
Java
package electrosphere.net.server;
|
|
|
|
import electrosphere.entity.types.creature.CreatureUtils;
|
|
import electrosphere.entity.Entity;
|
|
import electrosphere.entity.EntityUtils;
|
|
import electrosphere.entity.types.item.ItemUtils;
|
|
import electrosphere.entity.types.attach.AttachUtils;
|
|
import electrosphere.entity.types.collision.CollisionObjUtils;
|
|
import electrosphere.logger.LoggerInterface;
|
|
import electrosphere.main.Globals;
|
|
import electrosphere.main.Main;
|
|
import electrosphere.net.NetUtils;
|
|
import electrosphere.net.parser.net.message.EntityMessage;
|
|
import electrosphere.net.parser.net.message.NetworkMessage;
|
|
import electrosphere.net.parser.net.message.PlayerMessage;
|
|
import electrosphere.net.parser.net.message.StatusMessage;
|
|
import electrosphere.net.parser.net.message.WorldMessage;
|
|
import electrosphere.net.parser.net.raw.NetworkParser;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.math.BigInteger;
|
|
import java.net.Socket;
|
|
import java.net.SocketException;
|
|
import java.nio.ByteBuffer;
|
|
import java.security.spec.RSAKeyGenParameterSpec;
|
|
import java.util.Properties;
|
|
import java.util.Random;
|
|
import java.util.concurrent.CopyOnWriteArrayList;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
import org.apache.commons.crypto.stream.CryptoInputStream;
|
|
import org.apache.commons.crypto.stream.CryptoOutputStream;
|
|
import org.joml.Vector3f;
|
|
|
|
/**
|
|
*
|
|
* @author satellite
|
|
*/
|
|
public class ServerConnectionHandler implements Runnable {
|
|
|
|
static int playerIdIncrementer = 0;
|
|
|
|
Socket socket;
|
|
// CryptoInputStream inputStream;
|
|
// CryptoOutputStream outputStream;
|
|
InputStream inputStream;
|
|
OutputStream outputStream;
|
|
boolean initialized;
|
|
NetworkParser networkParser;
|
|
int playerID;
|
|
int playerCharacterID;
|
|
|
|
ServerProtocol serverProtocol;
|
|
|
|
public ServerConnectionHandler(Socket socket) {
|
|
this.socket = socket;
|
|
playerID = getPlayerID();
|
|
LoggerInterface.loggerNetworking.INFO("Player ID: " + playerID);
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
LoggerInterface.loggerNetworking.INFO("ServerConnectionHandler start");
|
|
initialized = false;
|
|
try {
|
|
socket.setSoTimeout(100);
|
|
} catch (SocketException ex) {
|
|
ex.printStackTrace();
|
|
}
|
|
// final SecretKeySpec key = new SecretKeySpec(("1234567890123456").getBytes(),"AES");
|
|
// final Properties properties = new Properties();
|
|
// final RSAKeyGenParameterSpec spec = new RSAKeyGenParameterSpec(4096, BigInteger.probablePrime(4000, new Random()));
|
|
// try {
|
|
// inputStream = new CryptoInputStream("AES/ECB/PKCS5Padding",properties,socket.getInputStream(),key,spec);
|
|
// } catch (IOException ex) {
|
|
// ex.printStackTrace();
|
|
// System.exit(1);
|
|
// }
|
|
// try {
|
|
// outputStream = new CryptoOutputStream("AES/ECB/PKCS5Padding",properties,socket.getOutputStream(),key,spec);
|
|
// } catch (IOException ex) {
|
|
// ex.printStackTrace();
|
|
// System.exit(1);
|
|
// }
|
|
try {
|
|
inputStream = socket.getInputStream();
|
|
outputStream = socket.getOutputStream();
|
|
networkParser = new NetworkParser(inputStream,outputStream);
|
|
serverProtocol = new ServerProtocol(this);
|
|
} catch (IOException ex) {
|
|
ex.printStackTrace();
|
|
System.exit(1);
|
|
}
|
|
Player newPlayerObject = new Player(this);
|
|
Globals.playerManager.addPlayer(newPlayerObject);
|
|
//spawn player in world
|
|
Entity newPlayerCharacter = CreatureUtils.spawnBasicCreature("Human");
|
|
playerCharacterID = newPlayerCharacter.getId();
|
|
CollisionObjUtils.positionCharacter(newPlayerCharacter, new Vector3f(Globals.spawnPoint.x,Globals.spawnPoint.y,Globals.spawnPoint.z));
|
|
//attach player object to player character
|
|
newPlayerObject.setPlayerEntity(newPlayerCharacter);
|
|
newPlayerObject.setWorldX(Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.x));
|
|
newPlayerObject.setWorldY(Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.z));
|
|
Globals.dataCellManager.addPlayer(newPlayerObject);
|
|
Globals.dataCellManager.movePlayer(newPlayerObject, Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.x), Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.z));
|
|
//spawn player sword
|
|
Entity sword = ItemUtils.spawnBasicItem("Katana");
|
|
AttachUtils.attachEntityToEntityAtBone(newPlayerCharacter, sword, "Bone.031");
|
|
//set controller id
|
|
CreatureUtils.setControllerPlayerId(newPlayerCharacter, playerID);
|
|
if(Globals.RUN_SERVER && Main.playerId == -1){
|
|
Globals.playerCharacter = newPlayerCharacter;
|
|
Globals.serverPlayer = newPlayerObject;
|
|
}
|
|
//world metadata
|
|
networkParser.addOutgoingMessage(
|
|
WorldMessage.constructMetadataMessage(
|
|
Globals.serverWorldData.getWorldSizeDiscrete(),
|
|
Globals.serverWorldData.getDynamicInterpolationRatio(),
|
|
Globals.serverWorldData.getRandomDampener(),
|
|
(int)Globals.serverWorldData.getWorldBoundMin().x,
|
|
(int)Globals.serverWorldData.getWorldBoundMin().z,
|
|
(int)Globals.serverWorldData.getWorldBoundMax().x,
|
|
(int)Globals.serverWorldData.getWorldBoundMax().z
|
|
)
|
|
);
|
|
//set client initial discrete position
|
|
networkParser.addOutgoingMessage(
|
|
PlayerMessage.constructSetInitialDiscretePositionMessage(
|
|
Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.x),
|
|
Globals.serverWorldData.convertRealToChunkSpace(Globals.spawnPoint.z)
|
|
)
|
|
);
|
|
//send spawn point
|
|
networkParser.addOutgoingMessage(
|
|
WorldMessage.constructSpawnPositionMessage(Globals.spawnPoint.x, Globals.spawnPoint.z)
|
|
);
|
|
//tell them what player stats they are
|
|
networkParser.addOutgoingMessage(PlayerMessage.constructSet_IDMessage(playerID));
|
|
//figure out what chunk they're in
|
|
|
|
//queue messages for that chunk
|
|
if(Globals.RUN_SERVER && Main.playerId == -1){
|
|
|
|
} else {
|
|
for(Entity currentEntity : Globals.entityManager.getMoveable()){
|
|
networkParser.addOutgoingMessage(
|
|
EntityMessage.constructCreateMessage(
|
|
currentEntity.getId(),
|
|
0, //0 for creatures
|
|
CreatureUtils.getType(currentEntity),
|
|
EntityUtils.getPosition(currentEntity).x,
|
|
EntityUtils.getPosition(currentEntity).y,
|
|
EntityUtils.getPosition(currentEntity).z
|
|
)
|
|
);
|
|
if(CreatureUtils.isCreature(currentEntity)){
|
|
if(CreatureUtils.hasControllerPlayerId(currentEntity)){
|
|
LoggerInterface.loggerNetworking.INFO("Sending controller packets");
|
|
networkParser.addOutgoingMessage(NetUtils.createSetCreatureControllerIdEntityMessage(currentEntity));
|
|
}
|
|
}
|
|
}
|
|
for(Entity currentEntity : Globals.entityManager.getItemEntities()){
|
|
networkParser.addOutgoingMessage(
|
|
EntityMessage.constructCreateMessage(
|
|
currentEntity.getId(),
|
|
1, //1 for items
|
|
ItemUtils.getType(currentEntity),
|
|
EntityUtils.getPosition(currentEntity).x,
|
|
EntityUtils.getPosition(currentEntity).y,
|
|
EntityUtils.getPosition(currentEntity).z
|
|
)
|
|
);
|
|
if(AttachUtils.isAttached(currentEntity)){
|
|
networkParser.addOutgoingMessage(
|
|
EntityMessage.constructattachEntityToEntityMessage(
|
|
currentEntity.getId(),
|
|
AttachUtils.getTargetBone(currentEntity),
|
|
AttachUtils.getParent(currentEntity).getId()
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
//let client know it's ready
|
|
networkParser.addOutgoingMessage(StatusMessage.constructReadyMessage(1));
|
|
|
|
initialized = true;
|
|
while(Main.isRunning()){
|
|
//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();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int getPlayerID(){
|
|
playerIdIncrementer++;
|
|
return playerIdIncrementer;
|
|
}
|
|
|
|
public void addMessagetoOutgoingQueue(NetworkMessage message){
|
|
switch(message.getType()){
|
|
case ENTITY_MESSAGE:
|
|
switch(((EntityMessage)message).getMessageSubtype()){
|
|
case MOVEUPDATE:
|
|
if(((EntityMessage)message).getentityID()==playerCharacterID){
|
|
//basically don't send the message if this is the player's character and it's a move update
|
|
} else {
|
|
networkParser.addOutgoingMessage(message);
|
|
}
|
|
break;
|
|
case ATTACKUPDATE:
|
|
if(((EntityMessage)message).getentityID()==playerCharacterID){
|
|
//basically don't send the message if this is the player's character and it's a move update
|
|
} else {
|
|
networkParser.addOutgoingMessage(message);
|
|
}
|
|
break;
|
|
default:
|
|
networkParser.addOutgoingMessage(message);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
networkParser.addOutgoingMessage(message);
|
|
break;
|
|
}
|
|
}
|
|
}
|