mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-06 08:40:03 +00:00
Fix login queue.
This commit is contained in:
@@ -7,9 +7,9 @@ import com.google.common.base.Preconditions;
|
|||||||
/**
|
/**
|
||||||
* A {@link MobRepository} is a repository of {@link Mob}s that are currently active in the game world.
|
* A {@link MobRepository} is a repository of {@link Mob}s that are currently active in the game world.
|
||||||
*
|
*
|
||||||
|
* @param <T> The type of Mob.
|
||||||
* @author Graham
|
* @author Graham
|
||||||
* @author Ryley
|
* @author Ryley
|
||||||
* @param <T> The type of Mob.
|
|
||||||
*/
|
*/
|
||||||
public final class MobRepository<T extends Mob> implements Iterable<T> {
|
public final class MobRepository<T extends Mob> implements Iterable<T> {
|
||||||
|
|
||||||
@@ -95,10 +95,10 @@ public final class MobRepository<T extends Mob> implements Iterable<T> {
|
|||||||
* Adds a Mob to the repository.
|
* Adds a Mob to the repository.
|
||||||
*
|
*
|
||||||
* @param mob The Mob to add.
|
* @param mob The Mob to add.
|
||||||
* @return {@code true} if the Mob was added, {@code false} if the size has reached the capacity of this repository.
|
* @return {@code true} if the Mob was added, {@code false} if this MobRepository is at maximum capacity.
|
||||||
*/
|
*/
|
||||||
public boolean add(T mob) {
|
public boolean add(T mob) {
|
||||||
if (size == capacity()) {
|
if (full()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +126,15 @@ public final class MobRepository<T extends Mob> implements Iterable<T> {
|
|||||||
return mobs.length;
|
return mobs.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not this MobRepository has reached its maxmimum capacity.
|
||||||
|
*
|
||||||
|
* @return {@code true} iff this MobRepository is full.
|
||||||
|
*/
|
||||||
|
public boolean full() {
|
||||||
|
return size == mobs.length;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the Mob at the given index.
|
* Gets the Mob at the given index.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -447,25 +447,6 @@ public final class Player extends Mob {
|
|||||||
public PrivilegeLevel getPrivilegeLevel() {
|
public PrivilegeLevel getPrivilegeLevel() {
|
||||||
return privilegeLevel;
|
return privilegeLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Determines the {@link RegistrationStatus} for this player. This method
|
|
||||||
* can remain lock-free since writes to the player {@link MobRepository} are
|
|
||||||
* only happening on the game thread.
|
|
||||||
*
|
|
||||||
* @return The status.
|
|
||||||
*/
|
|
||||||
public RegistrationStatus getRegistrationStatus() {
|
|
||||||
MobRepository<Player> repository = world.getPlayerRepository();
|
|
||||||
|
|
||||||
if (world.isPlayerOnline(getUsername())) {
|
|
||||||
return RegistrationStatus.ALREADY_ONLINE;
|
|
||||||
} else if (repository.capacity() == repository.size()) {
|
|
||||||
return RegistrationStatus.WORLD_FULL;
|
|
||||||
}
|
|
||||||
return RegistrationStatus.OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the player's run energy.
|
* Gets the player's run energy.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ import org.apollo.game.model.area.Region;
|
|||||||
import org.apollo.game.model.entity.MobRepository;
|
import org.apollo.game.model.entity.MobRepository;
|
||||||
import org.apollo.game.model.entity.Player;
|
import org.apollo.game.model.entity.Player;
|
||||||
import org.apollo.game.session.GameSession;
|
import org.apollo.game.session.GameSession;
|
||||||
|
import org.apollo.game.session.LoginSession;
|
||||||
import org.apollo.game.sync.ClientSynchronizer;
|
import org.apollo.game.sync.ClientSynchronizer;
|
||||||
|
import org.apollo.net.codec.login.LoginConstants;
|
||||||
import org.apollo.util.ThreadUtil;
|
import org.apollo.util.ThreadUtil;
|
||||||
import org.apollo.util.xml.XmlNode;
|
import org.apollo.util.xml.XmlNode;
|
||||||
import org.apollo.util.xml.XmlParser;
|
import org.apollo.util.xml.XmlParser;
|
||||||
@@ -32,6 +34,34 @@ import org.xml.sax.SAXException;
|
|||||||
*/
|
*/
|
||||||
public final class GameService extends Service {
|
public final class GameService extends Service {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility class wrapping a {@link Player} and their corresponding {@link LoginSession}.
|
||||||
|
*/
|
||||||
|
private static final class LoginPlayerRequest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Player.
|
||||||
|
*/
|
||||||
|
private final Player player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The LoginSession.
|
||||||
|
*/
|
||||||
|
private final LoginSession session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the LoginPlayerRequest.
|
||||||
|
*
|
||||||
|
* @param player The {@link Player} logging in.
|
||||||
|
* @param session The {@link LoginSession} of the Player.
|
||||||
|
*/
|
||||||
|
public LoginPlayerRequest(Player player, LoginSession session) {
|
||||||
|
this.player = player;
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount of players to deregister per cycle. This is to ensure the saving threads don't get swamped with
|
* The amount of players to deregister per cycle. This is to ensure the saving threads don't get swamped with
|
||||||
* requests and slow everything down.
|
* requests and slow everything down.
|
||||||
@@ -54,12 +84,12 @@ public final class GameService extends Service {
|
|||||||
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(ThreadUtil.create("GameService"));
|
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(ThreadUtil.create("GameService"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A queue of players to add.
|
* The Queue of LoginPlayers to add.
|
||||||
*/
|
*/
|
||||||
private final Queue<Player> newPlayers = new ConcurrentLinkedQueue<>();
|
private final Queue<LoginPlayerRequest> newPlayers = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A queue of players to remove.
|
* The Queue of Players to remove.
|
||||||
*/
|
*/
|
||||||
private final Queue<Player> oldPlayers = new ConcurrentLinkedQueue<>();
|
private final Queue<Player> oldPlayers = new ConcurrentLinkedQueue<>();
|
||||||
|
|
||||||
@@ -138,13 +168,13 @@ public final class GameService extends Service {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a player. Returns immediately. The player is registered at the
|
* Registers a {@link Player} at the end of the next cycle.
|
||||||
* start of the next cycle.
|
|
||||||
*
|
*
|
||||||
* @param player The player.
|
* @param player The Player to register.
|
||||||
|
* @param session the {@link LoginSession} of the Player.
|
||||||
*/
|
*/
|
||||||
public void registerPlayer(Player player) {
|
public void registerPlayer(Player player, LoginSession session) {
|
||||||
newPlayers.add(player);
|
newPlayers.add(new LoginPlayerRequest(player, session));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,11 +207,20 @@ public final class GameService extends Service {
|
|||||||
*/
|
*/
|
||||||
private void finalizeRegistrations() {
|
private void finalizeRegistrations() {
|
||||||
for (int count = 0; count < REGISTRATIONS_PER_CYCLE; count++) {
|
for (int count = 0; count < REGISTRATIONS_PER_CYCLE; count++) {
|
||||||
Player player = newPlayers.poll();
|
LoginPlayerRequest request = newPlayers.poll();
|
||||||
if (player == null) {
|
if (request == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Player player = request.player;
|
||||||
|
if (world.isPlayerOnline(player.getUsername())) {
|
||||||
|
request.session.sendLoginFailure(LoginConstants.STATUS_ACCOUNT_ONLINE);
|
||||||
|
} else if (world.getPlayerRepository().full()) {
|
||||||
|
request.session.sendLoginFailure(LoginConstants.STATUS_SERVER_FULL);
|
||||||
|
} else {
|
||||||
|
request.session.sendLoginSuccess(player);
|
||||||
|
}
|
||||||
|
|
||||||
finalizePlayerRegistration(player);
|
finalizePlayerRegistration(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,10 +31,15 @@ import org.apollo.util.security.IsaacRandomPair;
|
|||||||
public final class LoginSession extends Session {
|
public final class LoginSession extends Session {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The server context.
|
* The ServerContext.
|
||||||
*/
|
*/
|
||||||
private final ServerContext context;
|
private final ServerContext context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The LoginRequest for this LoginSession.
|
||||||
|
*/
|
||||||
|
private LoginRequest request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a login session for the specified channel.
|
* Creates a login session for the specified channel.
|
||||||
*
|
*
|
||||||
@@ -58,52 +63,14 @@ public final class LoginSession extends Session {
|
|||||||
* @param response The response.
|
* @param response The response.
|
||||||
*/
|
*/
|
||||||
public void handlePlayerLoaderResponse(LoginRequest request, PlayerLoaderResponse response) {
|
public void handlePlayerLoaderResponse(LoginRequest request, PlayerLoaderResponse response) {
|
||||||
|
this.request = request;
|
||||||
GameService service = context.getGameService();
|
GameService service = context.getGameService();
|
||||||
Channel channel = getChannel();
|
|
||||||
|
|
||||||
Optional<Player> optional = response.getPlayer();
|
Optional<Player> optional = response.getPlayer();
|
||||||
int status = response.getStatus(), rights = 0;
|
|
||||||
boolean flagged = false;
|
|
||||||
|
|
||||||
if (optional.isPresent()) {
|
if (optional.isPresent()) {
|
||||||
Player player = optional.get();
|
service.registerPlayer(optional.get(), this);
|
||||||
rights = player.getPrivilegeLevel().toInteger();
|
|
||||||
|
|
||||||
RegistrationStatus registration = player.getRegistrationStatus();
|
|
||||||
|
|
||||||
if (registration != RegistrationStatus.OK) {
|
|
||||||
optional = Optional.empty();
|
|
||||||
rights = 0;
|
|
||||||
|
|
||||||
status = registration == RegistrationStatus.ALREADY_ONLINE ? LoginConstants.STATUS_ACCOUNT_ONLINE
|
|
||||||
: LoginConstants.STATUS_SERVER_FULL;
|
|
||||||
} else {
|
|
||||||
GameSession session = new GameSession(channel, context, player, request.isReconnecting());
|
|
||||||
channel.attr(ApolloHandler.SESSION_KEY).set(session);
|
|
||||||
player.setSession(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChannelFuture future = channel.write(new LoginResponse(status, rights, flagged));
|
|
||||||
|
|
||||||
destroy();
|
|
||||||
|
|
||||||
if (optional.isPresent()) {
|
|
||||||
IsaacRandomPair randomPair = request.getRandomPair();
|
|
||||||
Release release = context.getRelease();
|
|
||||||
|
|
||||||
channel.pipeline().addFirst("messageEncoder", new GameMessageEncoder(release));
|
|
||||||
channel.pipeline().addBefore("messageEncoder", "gameEncoder", new GamePacketEncoder(randomPair.getEncodingRandom()));
|
|
||||||
|
|
||||||
channel.pipeline().addBefore("handler", "gameDecoder",
|
|
||||||
new GamePacketDecoder(randomPair.getDecodingRandom(), context.getRelease()));
|
|
||||||
channel.pipeline().addAfter("gameDecoder", "messageDecoder", new GameMessageDecoder(release));
|
|
||||||
|
|
||||||
channel.pipeline().remove("loginDecoder");
|
|
||||||
channel.pipeline().remove("loginEncoder");
|
|
||||||
service.registerPlayer(optional.get());
|
|
||||||
} else {
|
} else {
|
||||||
future.addListener(ChannelFutureListener.CLOSE);
|
sendLoginFailure(response.getStatus());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +81,46 @@ public final class LoginSession extends Session {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a failed {@link LoginResponse} to the client.
|
||||||
|
*
|
||||||
|
* @param status The failure status.
|
||||||
|
*/
|
||||||
|
public void sendLoginFailure(int status) {
|
||||||
|
boolean flagged = false;
|
||||||
|
LoginResponse response = new LoginResponse(status, 0, flagged);
|
||||||
|
channel.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a succesfull {@link LoginResponse} to the client.
|
||||||
|
*
|
||||||
|
* @param player The {@link Player} that successfully logged in.
|
||||||
|
*/
|
||||||
|
public void sendLoginSuccess(Player player) {
|
||||||
|
IsaacRandomPair randomPair = request.getRandomPair();
|
||||||
|
boolean flagged = false;
|
||||||
|
|
||||||
|
GameSession session = new GameSession(channel, context, player, request.isReconnecting());
|
||||||
|
channel.attr(ApolloHandler.SESSION_KEY).set(session);
|
||||||
|
player.setSession(session);
|
||||||
|
|
||||||
|
int rights = player.getPrivilegeLevel().toInteger();
|
||||||
|
channel.writeAndFlush(new LoginResponse(LoginConstants.STATUS_OK, rights, flagged));
|
||||||
|
|
||||||
|
Release release = context.getRelease();
|
||||||
|
|
||||||
|
channel.pipeline().addFirst("messageEncoder", new GameMessageEncoder(release));
|
||||||
|
channel.pipeline().addBefore("messageEncoder", "gameEncoder", new GamePacketEncoder(randomPair.getEncodingRandom()));
|
||||||
|
|
||||||
|
channel.pipeline().addBefore("handler", "gameDecoder",
|
||||||
|
new GamePacketDecoder(randomPair.getDecodingRandom(), context.getRelease()));
|
||||||
|
channel.pipeline().addAfter("gameDecoder", "messageDecoder", new GameMessageDecoder(release));
|
||||||
|
|
||||||
|
channel.pipeline().remove("loginDecoder");
|
||||||
|
channel.pipeline().remove("loginEncoder");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a login request.
|
* Handles a login request.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -213,8 +213,6 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
|||||||
private void writeResponseCode(ChannelHandlerContext ctx, int response) {
|
private void writeResponseCode(ChannelHandlerContext ctx, int response) {
|
||||||
ByteBuf buffer = ctx.alloc().buffer(Byte.BYTES);
|
ByteBuf buffer = ctx.alloc().buffer(Byte.BYTES);
|
||||||
buffer.writeByte(response);
|
buffer.writeByte(response);
|
||||||
System.out.println("Sending response: " + response);
|
|
||||||
|
|
||||||
ctx.writeAndFlush(buffer).addListener(ChannelFutureListener.CLOSE);
|
ctx.writeAndFlush(buffer).addListener(ChannelFutureListener.CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user