# . com.sun.sgs.app.name=RockPaperScissors # , AppListener com.sun.sgs.app.listener=hello.reddwarf.server.Server # , com.sun.sgs.app.root=data
void initialize(Properties props)
is called when the server is first started. It fills the internal database with the initial values ​​necessary for the operation. An important feature: if the server is stopped (or killed) and then restarted, this method will not be called, since The internal database is stored between server launches and allows you to continue working from the moment you stop.ClientSessionListener loggedIn(ClientSession session)
is called after successful authentication and must return an object that represents the player. In our example, this will be Player. package hello.reddwarf.server; import java.io.Serializable; import com.sun.sgs.app.*; import com.sun.sgs.app.util.ScalableHashMap; import java.util.Properties; /** * . , * . */ public class Server implements AppListener, Serializable, ManagedObject { public ManagedReference<ScalableHashMap<String, Player>> onlinePlayersRef; @Override public void initialize(Properties props) { // ScalableHashMap<String, Player> onlinePlayers = new ScalableHashMap<String, Player>(); onlinePlayersRef = AppContext.getDataManager().createReference(onlinePlayers); } @Override public ClientSessionListener loggedIn(ClientSession session) { String name = session.getName(); // . , Player player = loadOrRegister(name); // . - , // - player.setSession(session); // , player.connected(); // - onlinePlayersRef.get().put(player.name, player); return player; } }
private Player loadOrRegister(String name) { try { return (Player) AppContext.getDataManager().getBindingForUpdate("player." + name); } catch (NameNotBoundException e) { // - // , Player player = new Player(name, this); AppContext.getDataManager().setBinding("player." + name, player); return player; } }
package hello.reddwarf.server; import java.nio.ByteBuffer; public class Messages { public static ByteBuffer encodeString(String s) { return ByteBuffer.wrap(s.getBytes()); } public static String decodeString(ByteBuffer message) { byte[] bytes = new byte[message.remaining()]; message.get(bytes); return new String(bytes); } }
package hello.reddwarf.server; import com.sun.sgs.app.*; import com.sun.sgs.app.util.ScalableHashMap; import java.io.Serializable; import java.nio.ByteBuffer; import java.util.*; public class Player implements Serializable, ManagedObject, ClientSessionListener { private final static Random random = new Random(); public final String name; private int score; // , private ManagedReference<ClientSession> sessionRef; // - private ManagedReference<Server> serverRef; // . - null private ManagedReference<Battle> battleRef; public Player(String name, Server server) { this.name = name; serverRef = AppContext.getDataManager().createReference(server); score = 0; } @Override public void receivedMessage(ByteBuffer byteBuffer) { // String message = Messages.decodeString(byteBuffer); if (message.equals("PLAY")) { play(); } else if (message.equals("ROCK")) { answer(Weapon.ROCK); } else if (message.equals("PAPER")) { answer(Weapon.PAPER); } else if (message.equals("SCISSORS")) { answer(Weapon.SCISSORS); } } @Override public void disconnected(boolean b) { serverRef.get().disconnect(this); } private void answer(Weapon weapon) { if (battleRef != null) { battleRef.getForUpdate().answer(this, weapon); } } private void play() { logger.info("Choosing enemy for "+name); // Player target = getRandomPlayer(); if (target != null && target.battleRef == null) { Battle battle = new Battle(this, target); this.sessionRef.get().send(Messages.encodeString("BATTLE " + target.name)); target.sessionRef.get().send(Messages.encodeString("BATTLE " + this.name)); target.battleRef = AppContext.getDataManager().createReference(battle); this.battleRef = target.battleRef; battle.start(); } else { this.sessionRef.get().send(Messages.encodeString("ERROR")); } } /** * ( ) * , null * @return null, */ private Player getRandomPlayer() { ScalableHashMap<String,Player> onlineMap = serverRef.get().onlinePlayersRef.get(); Set<String> namesSet = new HashSet<String>(onlineMap.keySet()); namesSet.remove(name); if (namesSet.isEmpty()) { return null; } else { ArrayList<String> namesList = new ArrayList<String>(namesSet); String randomName = namesList.get(random.nextInt(namesList.size())); return onlineMap.get(randomName); } } public void connected() { // , sessionRef.get().send(Messages.encodeString("SCORE " + score)); } /** * , */ public void battleResult(Battle.Result result) { switch (result) { case DRAW: score+=1; sessionRef.get().send(Messages.encodeString("DRAW")); break; case WON: score+=2; sessionRef.get().send(Messages.encodeString("WON")); break; case LOST: sessionRef.get().send(Messages.encodeString("LOST")); break; } sessionRef.get().send(Messages.encodeString("SCORE " + score)); battleRef = null; } public void setSession(ClientSession session) { sessionRef = AppContext.getDataManager().createReference(session); } }
package hello.reddwarf.server; public enum Weapon { ROCK, PAPER, SCISSORS; boolean beats(Weapon other) { return other != null && this != other && this.ordinal() == (other.ordinal() + 1) % values().length; } }
package hello.reddwarf.server; import com.sun.sgs.app.AppContext; import com.sun.sgs.app.ManagedObject; import com.sun.sgs.app.ManagedReference; import com.sun.sgs.app.Task; import java.io.Serializable; import java.util.concurrent.atomic.AtomicInteger; public class Battle implements ManagedObject, Serializable { // 5 private static final long BATTLE_TIME_MS = 5000; enum Result { DRAW, WON, LOST } private boolean active; private ManagedReference<Player> starterPlayerRef; private ManagedReference<Player> invitedPlayerRef; private Weapon starterWeapon = null; private Weapon invitedWeapon = null; public Battle(Player starterPlayer, Player invitedPlayer) { starterPlayerRef = AppContext.getDataManager().createReference(starterPlayer); invitedPlayerRef = AppContext.getDataManager().createReference(invitedPlayer); active = false; } /** * . * , BATTLE_TIME_MS . */ public void start(){ active = true; AppContext.getTaskManager().scheduleTask(new BattleTimeout(this), BATTLE_TIME_MS); } /** * . * , . * @param player - * @param weapon - */ public void answer(Player player, Weapon weapon){ if (active) { if (player.name.equals(starterPlayerRef.get().name)) { starterWeapon = weapon; } else { invitedWeapon = weapon; } } } /** * . * . */ private void finish() { active = false; Player starterPlayer = starterPlayerRef.getForUpdate(); Player invitedPlayer = invitedPlayerRef.getForUpdate(); if (starterWeapon != null && starterWeapon.beats(invitedWeapon)) { starterPlayer.battleResult(Result.WON); invitedPlayer.battleResult(Result.LOST); } else if (invitedWeapon != null && invitedWeapon.beats(starterWeapon)) { invitedPlayer.battleResult(Result.WON); starterPlayer.battleResult(Result.LOST); } else { starterPlayer.battleResult(Result.DRAW); invitedPlayer.battleResult(Result.DRAW); } AppContext.getDataManager().removeObject(this); } /** * , . */ private static class BattleTimeout implements Serializable, Task { private ManagedReference<Battle> battleRef; public BattleTimeout(Battle battle) { battleRef = AppContext.getDataManager().createReference(battle); } @Override public void run() throws Exception { battleRef.getForUpdate().finish(); } } }
java -jar bin/sgs-boot.jar
02, 2012 9:45:19 PM com.sun.sgs.impl.kernel.Kernel <init> INFO: The Kernel is ready, version: 0.10.2.1 02, 2012 9:45:19 PM com.sun.sgs.impl.service.data.store.DataStoreImpl <init> INFO: Creating database directory : C:\sgs-server-dist-0.10.2.1\data\dsdb 02, 2012 9:45:19 PM com.sun.sgs.impl.service.watchdog.WatchdogServerImpl registerNode INFO: node:com.sun.sgs.impl.service.watchdog.NodeImpl[1,health:GREEN,backup:(none)]@black registered 02, 2012 9:45:19 PM hello.reddwarf.server.Server initialize INFO: Starting new Rock-Paper-Scissors Server. Initialized database. 02, 2012 9:45:19 PM com.sun.sgs.impl.kernel.Kernel startApplication INFO: RockPaperScissors: application is ready
Source: https://habr.com/ru/post/134812/
All Articles