diff --git a/README.md b/README.md
index 46147d6b..208f7ba2 100644
--- a/README.md
+++ b/README.md
@@ -19,4 +19,22 @@ Apollo is now ready, and can be started using `gradle run`. You may wish to chan
### Contributing
-Please see [contributing to Apollo](#CONTRIBUTING.md).
+Please see [contributing to Apollo](CONTRIBUTING.md).
+
+### Acknowledgements
+
+We'd like to thank the list of service providers/development tool vendors below for offering their products to the Apollo project free of charge.
+
+---
+
+#### [](https://www.yourkit.com/java/profiler/index.jsp)
+
+YourKit supports open source projects with its full-featured Java Profiler.
+YourKit, LLC is the creator of YourKit Java Profiler
+and YourKit .NET Profiler,
+innovative and intelligent tools for profiling Java and .NET applications.
+
+#### [Travis CI](https://travis-ci.org)
+
+Travis CI is a Continuous Integration platform that allows for setup of automated testing with minimal configuration.
+
diff --git a/data/plugins/skill/magic/magic.rb b/data/plugins/skill/magic/magic.rb
index 43bedb89..71ddcfb4 100644
--- a/data/plugins/skill/magic/magic.rb
+++ b/data/plugins/skill/magic/magic.rb
@@ -61,7 +61,7 @@ class SpellAction < Action
def check_skill
required = @spell.level
- if required > mob.skill_set.skill(Skill::MAGIC).current_level
+ if required > mob.skill_set.getSkill(Skill::MAGIC).current_level
mob.send_message("You need a Magic level of at least #{required} to cast this spell.")
return false
end
diff --git a/net/src/main/java/org/apollo/net/codec/login/LoginDecoder.java b/net/src/main/java/org/apollo/net/codec/login/LoginDecoder.java
index 394d70d5..b59cc70e 100644
--- a/net/src/main/java/org/apollo/net/codec/login/LoginDecoder.java
+++ b/net/src/main/java/org/apollo/net/codec/login/LoginDecoder.java
@@ -9,6 +9,7 @@ import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.security.SecureRandom;
import java.util.List;
+import java.util.logging.Logger;
import org.apollo.cache.FileSystemConstants;
import org.apollo.net.NetworkConstants;
@@ -27,6 +28,11 @@ import com.google.common.net.InetAddresses;
*/
public final class LoginDecoder extends StatefulFrameDecoder {
+ /**
+ * The logger for this class.
+ */
+ private static final Logger logger = Logger.getLogger(LoginDecoder.class.getName());
+
/**
* The secure random number generator.
*/
@@ -110,6 +116,7 @@ public final class LoginDecoder extends StatefulFrameDecoder
int type = buffer.readUnsignedByte();
if (type != LoginConstants.TYPE_STANDARD && type != LoginConstants.TYPE_RECONNECTION) {
+ logger.fine("Failed to decode login header.");
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
return;
}
@@ -137,6 +144,7 @@ public final class LoginDecoder extends StatefulFrameDecoder
int memoryStatus = payload.readUnsignedByte();
if (memoryStatus != 0 && memoryStatus != 1) {
+ logger.fine("Login memoryStatus (" + memoryStatus + ") not in expected range of [0, 1].");
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
return;
}
@@ -150,6 +158,7 @@ public final class LoginDecoder extends StatefulFrameDecoder
int length = payload.readUnsignedByte();
if (length != loginLength - 41) {
+ logger.fine("Login packet unexpected length (" + length + ")");
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
return;
}
@@ -162,6 +171,7 @@ public final class LoginDecoder extends StatefulFrameDecoder
int id = secure.readUnsignedByte();
if (id != 10) {
+ logger.fine("Unable to read id from secure payload.");
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
return;
}
@@ -169,6 +179,7 @@ public final class LoginDecoder extends StatefulFrameDecoder
long clientSeed = secure.readLong();
long reportedSeed = secure.readLong();
if (reportedSeed != serverSeed) {
+ logger.fine("Reported seed differed from server seed.");
writeResponseCode(ctx, LoginConstants.STATUS_LOGIN_SERVER_REJECTED_SESSION);
return;
}
@@ -180,6 +191,7 @@ public final class LoginDecoder extends StatefulFrameDecoder
String hostAddress = InetAddresses.toAddrString(socketAddress.getAddress());
if (password.length() < 6 || password.length() > 20 || username.isEmpty() || username.length() > 12) {
+ logger.fine("Username ('" + username + "') or password did not pass validation.");
writeResponseCode(ctx, LoginConstants.STATUS_INVALID_CREDENTIALS);
return;
}
diff --git a/util/build.gradle b/util/build.gradle
index c28c6c4a..6f0a0d96 100644
--- a/util/build.gradle
+++ b/util/build.gradle
@@ -10,4 +10,14 @@ dependencies {
implementation group: 'org.bouncycastle', name: 'bcprov-jdk15on', version: bouncycastleVersion
testImplementation group: 'junit', name: 'junit', version: junitVersion
-}
\ No newline at end of file
+}
+
+task(genRsa, dependsOn: classes, type: JavaExec) {
+ def utilSubproject = project(':util')
+ def utilClasspath = utilSubproject.sourceSets.main.runtimeClasspath
+
+ main = 'org.apollo.util.tools.RsaKeyGenerator'
+ classpath = utilClasspath
+ jvmArgs = ['-Xmx1024M']
+ workingDir = project.rootDir
+}