Renderer/src/main/java/electrosphere/net/server/ServerConnectionHandler.java
2021-11-07 17:41:26 -05:00

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;
}
}
}