/* * IDK Game Server by Steve Winfield * https://github.com/WinfieldSteve */ package org.stevewinfield.suja.idk.network.sessions; import org.apache.log4j.Logger; import org.jboss.netty.channel.Channel; import org.magicwerk.brownies.collections.GapList; import org.stevewinfield.suja.idk.Bootloader; import org.stevewinfield.suja.idk.IDK; import org.stevewinfield.suja.idk.communication.MessageWriter; import org.stevewinfield.suja.idk.communication.QueuedMessageWriter; import org.stevewinfield.suja.idk.communication.global.writers.GenericErrorWriter; import org.stevewinfield.suja.idk.communication.miscellaneous.writers.ModeratorNotificationWriter; import org.stevewinfield.suja.idk.communication.miscellaneous.writers.MultiNotificationWriter; import org.stevewinfield.suja.idk.communication.miscellaneous.writers.StaffNotificationWriter; import org.stevewinfield.suja.idk.communication.player.writers.PlayerInfoUpdateWriter; import org.stevewinfield.suja.idk.communication.room.writers.*; import org.stevewinfield.suja.idk.game.event.session.SessionAuthenticatedEvent; import org.stevewinfield.suja.idk.game.friendstream.FriendStream; import org.stevewinfield.suja.idk.game.messenger.Messenger; import org.stevewinfield.suja.idk.game.messenger.MessengerBuddy; import org.stevewinfield.suja.idk.game.miscellaneous.NotifyType; import org.stevewinfield.suja.idk.game.players.PlayerAchievement; import org.stevewinfield.suja.idk.game.players.PlayerInstance; import org.stevewinfield.suja.idk.game.rooms.RoomAccessType; import org.stevewinfield.suja.idk.game.rooms.RoomInstance; import org.stevewinfield.suja.idk.game.rooms.RoomPlayer; import org.stevewinfield.suja.idk.game.rooms.RoomType; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Map.Entry; public class Session { private static final Logger logger = Logger.getLogger(Session.class); // getters public int getId() { return id; } public Channel getChannel() { return channel; } public boolean isAuthenticated() { return authenticated; } public int getRoomRequestId() { return roomRequestId; } public PlayerInstance getPlayerInstance() { return playerInstance; } public Messenger getPlayerMessenger() { return playerMessenger; } public int getRoomId() { return roomId; } public FriendStream getFriendStream() { return friendStream; } public boolean isLoadingRoom() { return roomId > 0 && !roomJoined; } public boolean isInRoom() { return roomId > 0 && roomJoined && roomPlayer != null; } public boolean roomLoadingChecksPassed() { return loadingsCheckPassed; } /** * @return RoomPlayer if player is in room, otherwise null */ public RoomPlayer getRoomPlayer() { return roomPlayer; } public int getTargetTeleporter() { return targetTeleporter; } public int getTargetTeleporterRoom() { return targetTeleporterRoom; } public boolean isTeleporting() { return targetTeleporter > 0; } public Session(final int id, final Channel channel) { this.id = id; this.channel = channel; this.authenticated = false; } public void prepareRoom(final RoomInstance room, final String password) { prepareRoom(room, password, false); } public void setTargetTeleporterId(final int id) { this.targetTeleporter = id; } public void prepareRoom(final RoomInstance room, final String password, final boolean bypassAuth) { if (this.isInRoom()) { final RoomInstance oldRoom = Bootloader.getGame().getRoomManager().loadRoomInstance(this.getRoomId()); oldRoom.removePlayerFromRoom(this, false, false); } this.clearLoading(); final QueuedMessageWriter queue = new QueuedMessageWriter(); if (room.getInformation().getTotalPlayers() >= room.getInformation().getMaxPlayers() && !playerInstance.hasRight("enter_full_rooms")) { queue.push(new RoomJoinErrorWriter(1)); queue.push(new RoomKickedWriter()); this.writeMessage(queue); return; } this.roomId = room.getInformation().getId(); this.roomJoined = false; this.loadingsCheckPassed = bypassAuth || room.getInformation().getOwnerId() == playerInstance.getInformation().getId() || playerInstance.hasRight("enter_locked_rooms"); if (!this.loadingsCheckPassed) { if (room.getInformation().getAccessType() == RoomAccessType.PASSWORD && !room.getInformation().getPassword().equals(password)) { queue.push(new GenericErrorWriter(-100002)); queue.push(new RoomKickedWriter()); this.writeMessage(queue); return; } else if (room.getInformation().getAccessType() == RoomAccessType.BELL) { final MessageWriter target = new RoomDoorbellWriter(this.getPlayerInstance().getInformation().getPlayerName()); int rightCount = 0; for (final RoomPlayer player : room.getRoomPlayers().values()) { if (player.getSession() != null && room.hasRights(player.getSession())) { player.getSession().writeMessage(target); rightCount++; } } queue.push(rightCount > 0 ? new RoomDoorbellWriter() : new RoomDoorbellNoResponseWriter()); if (rightCount > 0) { this.roomRequestId = room.getInformation().getId(); } this.writeMessage(queue); return; } this.loadingsCheckPassed = true; } this.enterRoom(room); } public void enterRoom(final RoomInstance room) { if (!this.loadingsCheckPassed || this.roomJoined || this.roomId != room.getInformation().getId()) { return; } final QueuedMessageWriter queue = new QueuedMessageWriter(); queue.push(new RoomOpenFlatWriter()); queue.push(new RoomUrlWriter("http://www.twitter.com/WinfieldSteve")); queue.push(new RoomEntryModelWriter(room.getInformation().getModelName(), room.getInformation().getId())); if (room.getInformation().getRoomType() == RoomType.PRIVATE) { for (final Entry<String, String> decoration : room.getInformation().getDecorations().entrySet()) { if (!decoration.getValue().equals("0.0")) { queue.push(new RoomDecorationWriter(decoration)); } } if (room.hasRights(this, true)) { queue.push(new RoomRightsWriter()); queue.push(new RoomOwnerRightsWriter()); } else if (room.hasRights(this)) { queue.push(new RoomRightsWriter()); } queue.push(new RoomRatingInfoWriter( this.playerInstance.getInformation().getId() == room.getInformation().getOwnerId() || room.getVotes().contains(playerInstance.getInformation().getId()) ? room.getInformation().getScore() : -1 ) ); } this.writeMessage(queue); } public void sendInformationUpdate() { if (!this.authenticated) { return; } this.writeMessage( new PlayerInfoUpdateWriter( -1, this.playerInstance.getInformation().getAvatar(), this.playerInstance.getInformation().getGender(), this.playerInstance.getInformation().getMission(), this.playerInstance.getInformation().getScore() ) ); if (this.isInRoom()) { this.roomPlayer.getRoom().writeMessage( new PlayerInfoUpdateWriter( this.roomPlayer.getVirtualId(), this.playerInstance.getInformation().getAvatar(), this.playerInstance.getInformation().getGender(), this.playerInstance.getInformation().getMission(), this.playerInstance.getInformation().getScore() ), null ); } } public boolean tryAuthenticate(final String token) { try { final PreparedStatement statement = Bootloader.getStorage().queryParams("SELECT * FROM players WHERE auth_token = ? LIMIT 1"); statement.setString(1, token); final ResultSet row = statement.executeQuery(); if (row.next()) { final Session checkSession = Bootloader.getSessionManager().getAuthenticatedSession(row.getInt("id")); if (checkSession != null) { checkSession.disconnect(); } final int timestamp = (int) Bootloader.getTimestamp(); this.playerInstance = new PlayerInstance(); this.playerInstance.load(row); Bootloader.getStorage().executeQuery("UPDATE players SET last_login_timestamp=" + timestamp + " WHERE id=" + row.getInt("id")); this.playerInstance.getInformation().setLastLoginTimestamp(timestamp); Bootloader.getSessionManager().makeAuthenticatedSession(this.playerInstance.getInformation().getId(), this); this.playerMessenger = new Messenger(this, this.playerInstance.getInformation()); this.friendStream = new FriendStream(); final GapList<Integer> friends = new GapList<>(); for (final Integer id : playerMessenger.getBuddies().keySet()) { friends.add(id); } this.friendStream.load(this.playerInstance.getInformation().getId(), friends); this.authenticated = true; Bootloader.getGame().getEventManager().callEvent(new SessionAuthenticatedEvent(this)); return true; } } catch (final SQLException exception) { logger.error("SQL Exception", exception); } return false; } public void disconnect() { if (!this.getChannel().isConnected()) { return; } this.getChannel().disconnect(); } public void sendNotification(final NotifyType notifyType, final String message, final String url) { switch (notifyType) { case MOD_ALERT: this.writeMessage(new ModeratorNotificationWriter(message, url)); return; case STAFF_ALERT: this.writeMessage(new StaffNotificationWriter(message, url)); return; case MULTI_ALERT: this.writeMessage(new MultiNotificationWriter(message)); break; } } public void sendNotification(final NotifyType notifyType, final String message) { this.sendNotification(notifyType, message, ""); } public void writeMessage(final MessageWriter writer) { if (!this.getChannel().isConnected()) { return; } if (IDK.DEBUG) { logger.debug("SND #" + writer.getId() + " " + writer.getDebugString().replace((char) 13, ' ').replace((char) 10, ' ')); } this.getChannel().write(writer); } public void setTargetTeleporterRoom(final int id) { this.targetTeleporterRoom = id; } public void writeMessage(final QueuedMessageWriter writer) { if (!this.getChannel().isConnected()) { return; } if (IDK.DEBUG) { logger.debug("SND #QUEUE " + writer.getDebugString().replace((char) 13, ' ').replace((char) 10, ' ')); } this.getChannel().write(writer); } public void clearLoading() { this.roomId = 0; this.roomJoined = false; this.loadingsCheckPassed = false; } public void setLoadingRoomId(final int roomId) { this.roomId = roomId; } public void setRoomPlayer(final RoomPlayer player) { this.roomPlayer = player; } public void setLoadingChecksPassed(final boolean passed) { this.loadingsCheckPassed = passed; } public void setRoomJoined(final boolean joined) { this.roomJoined = joined; } public void dispose() { try { if (this.isAuthenticated()) { StringBuilder insertAchievementQuery = new StringBuilder(); StringBuilder updateAchievementQuery = new StringBuilder(); for (final PlayerAchievement achievement : this.playerInstance.getAchievements().values()) { if (achievement.toInsert()) { insertAchievementQuery.append(", (").append(playerInstance.getInformation().getId()).append(", ").append(achievement.getAchievementId()).append(", ").append(achievement.getLevel()).append(", ").append(achievement.getProgress()).append(")"); } else if (achievement.toUpdate()) { updateAchievementQuery.append(", (").append(achievement.getId()).append(", ").append(playerInstance.getInformation().getId()).append(", ").append(achievement.getAchievementId()).append(", ").append(achievement.getLevel()).append(", ").append(achievement.getProgress()).append(")"); } } if (insertAchievementQuery.length() > 0) { Bootloader.getStorage().executeQuery("INSERT INTO player_achievements (player_id, achievement_id, level, progress) VALUES " + insertAchievementQuery.toString().substring(2)); } if (updateAchievementQuery.length() > 0) { Bootloader.getStorage().executeQuery("REPLACE INTO player_achievements (id, player_id, achievement_id, level, progress) VALUES " + updateAchievementQuery.toString().substring(2)); } this.playerInstance.getInventory().save(this.playerInstance.getInformation().getId()); if (this.isInRoom()) { final RoomInstance oldRoom = Bootloader.getGame().getRoomManager().loadRoomInstance(this.getRoomId()); oldRoom.removePlayerFromRoom(this, false, false); } for (final MessengerBuddy buddy : this.getPlayerMessenger().getOnlineBuddies().values()) { buddy.getSession().getPlayerMessenger().onStatusChanged(this.getPlayerInstance().getInformation().getId(), false); } } this.finalize(); } catch (final Throwable e) { logger.error("", e); } } // fields private final int id; private final Channel channel; private PlayerInstance playerInstance; private Messenger playerMessenger; private FriendStream friendStream; private RoomPlayer roomPlayer; private boolean authenticated; private boolean loadingsCheckPassed; private boolean roomJoined; private int roomId; private int roomRequestId; private int targetTeleporter; private int targetTeleporterRoom; }