mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-03 08:39:11 +00:00
Merge branch 'master' of bitbucket.org:Major-/apollo.
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
java_import 'org.apollo.game.model.entity.Player'
|
||||
|
||||
on :login do |event, player|
|
||||
show_action(player, TRADE_ACTION)
|
||||
show_action(player, FOLLOW_ACTION)
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
require 'java'
|
||||
|
||||
java_import 'org.apollo.game.message.impl.SetPlayerActionMessage'
|
||||
java_import 'org.apollo.game.model.entity.Player'
|
||||
|
||||
class PlayerAction
|
||||
attr_reader :slot, :primary, :name
|
||||
|
||||
def initialize(slot, primary, name)
|
||||
index = [ :first, :second, :third, :fourth, :fifth ].find_index(slot)
|
||||
raise "Unsupport action slot #{slot}." if index.nil?
|
||||
|
||||
@slot = index
|
||||
@primary = primary
|
||||
@name = name
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
ATTACK_ACTION = PlayerAction.new(:third, true, 'Attack')
|
||||
CHALLENGE_ACTION = PlayerAction.new(:third, true, 'Challenge')
|
||||
TRADE_ACTION = PlayerAction.new(:fourth, true, 'Trade with')
|
||||
FOLLOW_ACTION = PlayerAction.new(:fifth, true, 'Follow')
|
||||
|
||||
# Shows multiple context menu action for the specified player
|
||||
def show_actions(player, *actions)
|
||||
raise 'Must specify at least one action to show' if actions.nil?
|
||||
|
||||
actions.each do |action|
|
||||
player.add_action(action)
|
||||
player.send(SetPlayerActionMessage.new(action.name, action.slot, action.primary))
|
||||
end
|
||||
end
|
||||
|
||||
# Shows a single context menu action for the specified player
|
||||
def show_action(player, action)
|
||||
show_actions(player, action)
|
||||
end
|
||||
|
||||
# Hides a context menu action for the specified player
|
||||
def hide_action(player, action)
|
||||
show_action(player, PlayerAction.new('null', action.slot, action.primary))
|
||||
end
|
||||
|
||||
class Player
|
||||
|
||||
def actions
|
||||
@actions ||= {}
|
||||
end
|
||||
|
||||
def add_action(action)
|
||||
actions[action.slot] = action.name
|
||||
end
|
||||
|
||||
def has_action(action)
|
||||
return actions[action.slot] == action.name
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0"?>
|
||||
<plugin>
|
||||
<id>player-action</id>
|
||||
<version>1</version>
|
||||
<name>Player actions</name>
|
||||
<description>Manages player right click actions</description>
|
||||
<authors>
|
||||
<author>Ryley</author>
|
||||
</authors>
|
||||
<scripts>
|
||||
<script>player-action.rb</script>
|
||||
<script>login.rb</script>
|
||||
</scripts>
|
||||
<dependencies />
|
||||
</plugin>
|
||||
@@ -4,7 +4,6 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import net.burtleburtle.bob.rand.IsaacRandom;
|
||||
@@ -61,7 +60,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, GameDecoderState state) throws IOException {
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, GameDecoderState state) {
|
||||
switch (state) {
|
||||
case GAME_OPCODE:
|
||||
decodeOpcode(in, out);
|
||||
@@ -96,9 +95,8 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
* @param out The {@link List} of objects to be passed along the pipeline.
|
||||
* @throws IOException If a received opcode or packet type is illegal.
|
||||
*/
|
||||
private void decodeOpcode(ByteBuf buffer, List<Object> out) throws IOException {
|
||||
private void decodeOpcode(ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.isReadable()) {
|
||||
int encryptedOpcode = buffer.readUnsignedByte();
|
||||
opcode = encryptedOpcode - random.nextInt() & 0xFF;
|
||||
@@ -121,7 +119,7 @@ public final class GamePacketDecoder extends StatefulFrameDecoder<GameDecoderSta
|
||||
setState(GameDecoderState.GAME_LENGTH);
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Illegal packet type: " + type + ".");
|
||||
throw new IllegalStateException("Illegal packet type: " + type + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,9 @@ package org.apollo.net.codec.login;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.List;
|
||||
@@ -28,7 +28,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
/**
|
||||
* The secure random number generator.
|
||||
*/
|
||||
private static final SecureRandom random = new SecureRandom();
|
||||
private static final SecureRandom RANDOM = new SecureRandom();
|
||||
|
||||
/**
|
||||
* The login packet length.
|
||||
@@ -54,11 +54,11 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
* Creates the login decoder with the default initial state.
|
||||
*/
|
||||
public LoginDecoder() {
|
||||
super(LoginDecoderState.LOGIN_HANDSHAKE, true);
|
||||
super(LoginDecoderState.LOGIN_HANDSHAKE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, LoginDecoderState state) throws Exception {
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, LoginDecoderState state) {
|
||||
switch (state) {
|
||||
case LOGIN_HANDSHAKE:
|
||||
decodeHandshake(ctx, in, out);
|
||||
@@ -70,7 +70,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
decodePayload(ctx, in, out);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Invalid login decoder state.");
|
||||
throw new IllegalStateException("Invalid login decoder state: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
private void decodeHandshake(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.isReadable()) {
|
||||
usernameHash = buffer.readUnsignedByte();
|
||||
serverSeed = random.nextLong();
|
||||
serverSeed = RANDOM.nextLong();
|
||||
|
||||
ByteBuf response = ctx.alloc().buffer(17);
|
||||
response.writeByte(LoginConstants.STATUS_EXCHANGE_DATA);
|
||||
@@ -102,14 +102,14 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
* @param ctx The channel handler context.
|
||||
* @param buffer The buffer.
|
||||
* @param out The {@link List} of objects to pass forward through the pipeline.
|
||||
* @throws IOException If the login type sent by the client is invalid.
|
||||
*/
|
||||
private void decodeHeader(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws IOException {
|
||||
private void decodeHeader(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.readableBytes() >= 2) {
|
||||
int loginType = buffer.readUnsignedByte();
|
||||
|
||||
if (loginType != LoginConstants.TYPE_STANDARD && loginType != LoginConstants.TYPE_RECONNECTION) {
|
||||
throw new IOException("Invalid login type.");
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
reconnecting = loginType == LoginConstants.TYPE_RECONNECTION;
|
||||
@@ -125,9 +125,8 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
* @param ctx The channel handler context.
|
||||
* @param buffer The buffer.
|
||||
* @param out The {@link List} of objects to pass forward through the pipeline.
|
||||
* @throws Exception If an error occurs.
|
||||
*/
|
||||
private void decodePayload(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
|
||||
private void decodePayload(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) {
|
||||
if (buffer.readableBytes() >= loginLength) {
|
||||
ByteBuf payload = buffer.readBytes(loginLength);
|
||||
int clientVersion = 255 - payload.readUnsignedByte();
|
||||
@@ -136,7 +135,8 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
|
||||
int lowMemoryFlag = payload.readUnsignedByte();
|
||||
if (lowMemoryFlag != 0 && lowMemoryFlag != 1) {
|
||||
throw new Exception("Invalid value for low memory flag.");
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean lowMemory = lowMemoryFlag == 1;
|
||||
@@ -148,7 +148,8 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
|
||||
int securePayloadLength = payload.readUnsignedByte();
|
||||
if (securePayloadLength != loginLength - 41) {
|
||||
throw new Exception("Secure payload length mismatch.");
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuf securePayload = payload.readBytes(securePayloadLength);
|
||||
@@ -160,13 +161,15 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
|
||||
int secureId = securePayload.readUnsignedByte();
|
||||
if (secureId != 10) {
|
||||
throw new Exception("Invalid secure payload id.");
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
long clientSeed = securePayload.readLong();
|
||||
long reportedServerSeed = securePayload.readLong();
|
||||
if (reportedServerSeed != serverSeed) {
|
||||
throw new Exception("Server seed mismatch.");
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
|
||||
return;
|
||||
}
|
||||
|
||||
int uid = securePayload.readInt();
|
||||
@@ -174,10 +177,9 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
String username = BufferUtil.readString(securePayload);
|
||||
String password = BufferUtil.readString(securePayload);
|
||||
|
||||
if (password.length() < 6 || password.length() > 20) {
|
||||
throw new Exception("Invalid password.");
|
||||
} else if (username.isEmpty() || username.length() > 12) {
|
||||
throw new Exception("Invalid username.");
|
||||
if (password.length() < 6 || password.length() > 20 || username.isEmpty() || username.length() > 12) {
|
||||
writeResponseCode(ctx, LoginConstants.STATUS_INVALID_CREDENTIALS);
|
||||
return;
|
||||
}
|
||||
|
||||
int[] seed = new int[4];
|
||||
@@ -196,14 +198,23 @@ public final class LoginDecoder extends StatefulFrameDecoder<LoginDecoderState>
|
||||
PlayerCredentials credentials = new PlayerCredentials(username, password, usernameHash, uid);
|
||||
IsaacRandomPair randomPair = new IsaacRandomPair(encodingRandom, decodingRandom);
|
||||
|
||||
LoginRequest request = new LoginRequest(credentials, randomPair, reconnecting, lowMemory, releaseNumber, archiveCrcs,
|
||||
clientVersion);
|
||||
LoginRequest request = new LoginRequest(credentials, randomPair, reconnecting, lowMemory, releaseNumber, archiveCrcs, clientVersion);
|
||||
|
||||
out.add(request);
|
||||
if (buffer.isReadable()) {
|
||||
out.add(buffer.readBytes(buffer.readableBytes()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a response code to the client and closes the current channel.
|
||||
*
|
||||
* @param ctx The context of the channel handler.
|
||||
* @param responseCode The response code to write.
|
||||
*/
|
||||
private void writeResponseCode(ChannelHandlerContext ctx, int responseCode) {
|
||||
ByteBuf buffer = ctx.alloc().buffer(1);
|
||||
buffer.writeByte(responseCode);
|
||||
|
||||
ctx.writeAndFlush(buffer).addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public interface ResourceProvider {
|
||||
public boolean accept(String path) throws IOException;
|
||||
|
||||
/**
|
||||
* The resource data, as a {@link ByteBuffer}, wrapped in an {@link Optional}.
|
||||
* Gets the resource data, as a {@link ByteBuffer}, wrapped in an {@link Optional}.
|
||||
*
|
||||
* @param path The path to the resource.
|
||||
* @return A {@code ByteBuffer} representation of a resource if it exists otherwise {@link Optional#empty()} is
|
||||
|
||||
@@ -5,8 +5,7 @@ import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A stateful implementation of a {@link ByteToMessageDecoder} which may be extended and used by other classes. The
|
||||
@@ -17,7 +16,7 @@ import com.google.common.base.Preconditions;
|
||||
* The current state is supplied as a parameter in the {@link StatefulFrameDecoder#decode} and
|
||||
* {@link StatefulFrameDecoder#decodeLast} methods.
|
||||
*
|
||||
* This class is not thread safe: it is recommended that the state is only set in the decode methods overriden.
|
||||
* This class is not thread safe: it is recommended that the state is only set in the decode methods overridden.
|
||||
*
|
||||
* @author Graham
|
||||
* @param <T> The state enumeration.
|
||||
@@ -36,17 +35,6 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends ByteToMess
|
||||
* @throws NullPointerException If the state is {@code null}.
|
||||
*/
|
||||
public StatefulFrameDecoder(T state) {
|
||||
this(state, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the stateful frame decoder with the specified initial state and unwrap flag.
|
||||
*
|
||||
* @param state The initial state.
|
||||
* @param unwrap The unwrap flag.
|
||||
* @throws NullPointerException If the state is {@code null}.
|
||||
*/
|
||||
public StatefulFrameDecoder(T state, boolean unwrap) {
|
||||
setState(state);
|
||||
}
|
||||
|
||||
@@ -66,24 +54,6 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends ByteToMess
|
||||
*/
|
||||
protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, T state) throws Exception;
|
||||
|
||||
@Override
|
||||
protected final void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
|
||||
decodeLast(ctx, in, out, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes remaining data before the channel is closed into a frame. You may override this method, but it is not
|
||||
* required. If you do not, remaining data will be discarded!
|
||||
*
|
||||
* @param ctx The current context of this handler.
|
||||
* @param in The cumulative buffer, which may contain zero or more bytes.
|
||||
* @param out The {@link List} of objects to pass forward through the pipeline.
|
||||
* @param state The current state. The state may be changed by calling {@link #setState}.
|
||||
*/
|
||||
protected void decodeLast(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, T state) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new state.
|
||||
*
|
||||
@@ -91,8 +61,7 @@ public abstract class StatefulFrameDecoder<T extends Enum<T>> extends ByteToMess
|
||||
* @throws NullPointerException If the state is {@code null}.
|
||||
*/
|
||||
public final void setState(T state) {
|
||||
Preconditions.checkNotNull(state, "State cannot be null.");
|
||||
this.state = state;
|
||||
this.state = Objects.requireNonNull(state, "State cannot be null.");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user