package ch.fusun.baron.server.rmi;
import java.io.IOException;
import java.util.List;
import ch.fusun.baron.core.command.GameCommand;
import ch.fusun.baron.core.initialization.GameInitializationUtil;
import ch.fusun.baron.core.initialization.GameInitializer;
import ch.fusun.baron.core.injection.Configure;
import ch.fusun.baron.core.injection.Inject;
import ch.fusun.baron.core.injection.ReInjector;
import ch.fusun.baron.core.rmi.KryoUtil;
import ch.fusun.baron.core.rmi.User;
import ch.fusun.baron.core.service.UserService;
import ch.fusun.baron.data.DataRegistry;
import ch.fusun.baron.data.DataUpdate;
import ch.fusun.baron.turn.TurnRegistry;
import ch.fusun.baron.turn.TurnService;
import ch.fusun.baron.turn.TurnTask;
import com.esotericsoftware.kryonet.Connection;
import com.esotericsoftware.kryonet.Listener;
import com.esotericsoftware.kryonet.Server;
/**
* This is the server class. It handles all incoming commands and triggers
* turns.
*/
public class GameServerImpl implements GameServer {
@Configure(value = "4000")
private int DELAY;
private transient GameStateService gameStateService;
@Inject
private transient GameInitializationUtil initializationUtil;
@Inject
private transient DataRegistry dataRegistry;
private transient UserService userService;
private transient TurnService turnService;
/**
* The Kryonet server
*/
private transient Server server;
/**
* The Game server constructor
*/
public GameServerImpl() {
// ReInjector.getInstance().reInject(this);
}
/**
* @param userService
* The user service
*/
@Inject
public void setUserService(UserService userService) {
this.userService = userService;
userService.addDataListener(this);
}
/**
* @param turnService
* The turn service
*/
@Inject
public void setTurnService(TurnService turnService) {
this.turnService = turnService;
this.turnService.addDataListenerIfNotAlready(this);
if (gameStateService == null) {
gameStateService = ReInjector.getInstance().getInstanceForClass(
GameStateService.class);
}
if (ServerPhase.GAME.equals(gameStateService.current())) {
turnService.start(DELAY);
}
}
/**
* SDZ We need a @Before(class)...
*
* @param gameStateService
* sets the gameStateService
*/
@Inject
public void setGameStateService(GameStateService gameStateService) {
this.gameStateService = gameStateService;
}
@Override
public void userLoggedIn(User user) {
// Do nothing
}
private void fullUpdateUser(Connection connection) {
synchronized (dataRegistry) {
List<DataUpdate> fullUpdate = dataRegistry.getFullUpdate();
for (DataUpdate update : fullUpdate) {
server.getConnections();
connection.sendTCP(update);
}
}
}
@Override
public void startup() {
server = new Server();
for (Class<?> clazz : KryoUtil.getInstance()
.getClassesForRegistration()) {
server.getKryo().register(clazz);
}
server.start();
try {
server.bind(54555, 54555);
} catch (IOException e) {
e.printStackTrace();
}
server.addListener(new Listener() {
@Override
public synchronized void received(Connection connection,
Object object) {
System.out.println(object);
if (object instanceof GameCommand) {
synchronized (GameServerImpl.this) {
tryExecuteCommand(object);
}
}
}
private void tryExecuteCommand(Object object) {
try {
GameCommand command = (GameCommand) object;
ReInjector.getInstance().reInject(command);
if (command.isAllowed()) {
command.execute();
updateUsers();
} else {
System.err.println(command + " not allowed"); //$NON-NLS-1$
}
} catch (Exception e) {
System.err.println("Error occured while executing " //$NON-NLS-1$
+ object + e.getMessage());
}
}
@Override
public void connected(Connection connection) {
fullUpdateUser(connection);
}
@Override
public void disconnected(Connection connection) {
userService.logout(connection.getID());
}
});
gameStateService.transitionTo(ServerPhase.LOBBY);
}
@Override
public void startGame() {
if (gameStateService.current().startGameAllowed()) {
synchronized (GameServerImpl.this) {
gameStateService.transitionTo(ServerPhase.GAMESTARTUP);
initializeGame();
updateUsers();
turnService.start(DELAY);
gameStateService.transitionTo(ServerPhase.GAME);
}
}
}
private void initializeGame() {
List<GameInitializer> initializers = initializationUtil
.getInitializers();
for (GameInitializer initializer : initializers) {
initializer.initialize();
}
}
/**
* Updates all the users with the data on the server
*/
private void updateUsers() {
synchronized (dataRegistry) {
List<DataUpdate> updates = dataRegistry.getUpdates();
if (!updates.isEmpty()) {
for (Connection client : server.getConnections()) {
for (DataUpdate update : updates) {
client.sendTCP(update);
}
}
}
dataRegistry.clearUpdates();
}
}
@Override
public void onTurn() {
synchronized (GameServerImpl.this) {
for (TurnTask turnTask : TurnRegistry.getInstance().getTurnTasks()) {
turnTask.execute();
}
System.out.println("turn"); //$NON-NLS-1$
updateUsers();
}
}
@Override
public void saveState(String path) {
dataRegistry.persist(path);
}
@Override
public void loadState(String path) {
dataRegistry.load(path);
}
@Override
public void dataChanged(DataUpdate update) {
// Do nothing
}
@Override
public void userLoggedOut(User user) {
// Do nothing
}
@Override
public void userCreated(User user) {
// Do nothing
}
}