mirror of
https://github.com/2006-Scape/2006Scape.git
synced 2026-07-03 00:31:51 +00:00
Network cleanup (#552)
* Replaced packetType/Size with packet * Replace Instream with Packet Read data directly from packet to ease future network upgrade * Update Packet.java Removed unused methods to ease netty migration and network rewrite. * Moved packet sizes. * Removed unused stream methods * Added readhex method for buttons * preparing to replace mina * Packet->GamePacket for refactoring * Netty 3.6.6 * formatting * formatting * Apollo core * Update net.xml Added variables for 2006scape * Netty 4 migration. Jagcached replaced with Apollo Core * Porting network into apollo * WIP Packet Changes Do not merge. This is broken. * Packet read methods converted to netty buffer * Replacing game network and login with apollo * Netty 4 * Cleanup * Same port for update and game server. * Cleanup login for integration with apollo * Login works. fixing packets * Running on apollo netcode. * Server runs * Update apollo-core.jar * Disable encoder. write outstream directly to channel. * Update RS2ProtocolDecoder.java Added apollo decoder * Add constant * Synchronization not needed * Update apollo-core.jar * Better performance. * Commit pre PR * Update apollo-core.jar * Fixup Port Binding Based On World * Apollo files * Additional Commit --------- Co-authored-by: Dark98 <darkaidz98@gmail.com>
This commit is contained in:
@@ -30,6 +30,13 @@ public class ClientSettings {
|
|||||||
*/
|
*/
|
||||||
public static int SERVER_WORLD = 1;
|
public static int SERVER_WORLD = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If false, the server will run the on demand server on every world. If true it will
|
||||||
|
* only connect to the server on world 1.
|
||||||
|
*/
|
||||||
|
public static boolean SINGLE_ONDEMAND = true;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enables/Disables FileServer CRC Checking For Cache Updates
|
* Enables/Disables FileServer CRC Checking For Cache Updates
|
||||||
* FileServer Must Be Running Before Starting The Client If This Is True
|
* FileServer Must Be Running Before Starting The Client If This Is True
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ public final class OnDemandFetcher extends OnDemandFetcherParent implements Runn
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
openSocketTime = l;
|
openSocketTime = l;
|
||||||
socket = clientInstance.openSocket(43596 + Game.portOff);
|
socket = clientInstance.openSocket((ClientSettings.SINGLE_ONDEMAND || ClientSettings.SERVER_WORLD == 1) ? 43594 : 43596 + ClientSettings.SERVER_WORLD + Game.portOff);
|
||||||
inputStream = socket.getInputStream();
|
inputStream = socket.getInputStream();
|
||||||
outputStream = socket.getOutputStream();
|
outputStream = socket.getOutputStream();
|
||||||
outputStream.write(15);
|
outputStream.write(15);
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<net>
|
||||||
|
<rsa>
|
||||||
|
<modulus>91553247461173033466542043374346300088148707506479543786501537350363031301992107112953015516557748875487935404852620239974482067336878286174236183516364787082711186740254168914127361643305190640280157664988536979163450791820893999053469529344247707567448479470137716627440246788713008490213212272520901741443</modulus>
|
||||||
|
<private-exponent>33280025241734061313051117678670856264399753710527826596057587687835856000539511539311834363046145710983857746766009612538140077973762171163294453513440619295457626227183742315140865830778841533445402605660729039310637444146319289077374748018792349647460850308384280105990607337322160553135806205784213241305</private-exponent>
|
||||||
|
</rsa>
|
||||||
|
|
||||||
|
<ports>
|
||||||
|
<http>8080</http>
|
||||||
|
<service>43594</service>
|
||||||
|
<jaggrab>43595</jaggrab>
|
||||||
|
</ports>
|
||||||
|
</net>
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-compress</artifactId>
|
<artifactId>commons-compress</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.21</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
|
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -70,12 +70,6 @@
|
|||||||
<artifactId>logging-interceptor</artifactId>
|
<artifactId>logging-interceptor</artifactId>
|
||||||
<version>4.3.1</version>
|
<version>4.3.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.mina/mina-core -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.mina</groupId>
|
|
||||||
<artifactId>mina-core</artifactId>
|
|
||||||
<version>1.1.7</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
|
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
@@ -86,7 +80,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.netty</groupId>
|
<groupId>io.netty</groupId>
|
||||||
<artifactId>netty-all</artifactId>
|
<artifactId>netty-all</artifactId>
|
||||||
<version>4.1.44.Final</version>
|
<version>4.0.34.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/com.neovisionaries/nv-websocket-client -->
|
<!-- https://mvnrepository.com/artifact/com.neovisionaries/nv-websocket-client -->
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -161,16 +155,11 @@
|
|||||||
<scope>system</scope>
|
<scope>system</scope>
|
||||||
<systemPath>${project.basedir}/libs/everythingrs-api.jar</systemPath>
|
<systemPath>${project.basedir}/libs/everythingrs-api.jar</systemPath>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.collections</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
<artifactId>google-collections</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>1.0</version>
|
<version>19.0</version>
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.netty</groupId>
|
|
||||||
<artifactId>netty</artifactId>
|
|
||||||
<version>3.6.6.Final</version>
|
|
||||||
<scope>compile</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
import org.apollo.jagcached.FileServer;
|
||||||
|
|
||||||
import com.rs2.game.bots.BotHandler;
|
import com.rs2.game.bots.BotHandler;
|
||||||
import org.apache.mina.common.IoAcceptor;
|
import com.google.common.base.Stopwatch;
|
||||||
import org.apache.mina.transport.socket.nio.SocketAcceptor;
|
|
||||||
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;
|
|
||||||
import com.rs2.event.CycleEventHandler;
|
import com.rs2.event.CycleEventHandler;
|
||||||
import com.rs2.game.content.minigames.FightCaves;
|
import com.rs2.game.content.minigames.FightCaves;
|
||||||
import com.rs2.game.content.minigames.FightPits;
|
import com.rs2.game.content.minigames.FightPits;
|
||||||
@@ -37,8 +37,6 @@ import com.rs2.integrations.PlayersOnlineWebsite;
|
|||||||
import com.rs2.integrations.RegisteredAccsWebsite;
|
import com.rs2.integrations.RegisteredAccsWebsite;
|
||||||
import com.rs2.integrations.discord.DiscordActivity;
|
import com.rs2.integrations.discord.DiscordActivity;
|
||||||
import com.rs2.integrations.discord.JavaCord;
|
import com.rs2.integrations.discord.JavaCord;
|
||||||
import com.rs2.net.ConnectionHandler;
|
|
||||||
import com.rs2.net.ConnectionThrottleFilter;
|
|
||||||
import com.rs2.tick.Scheduler;
|
import com.rs2.tick.Scheduler;
|
||||||
import com.rs2.tick.Tick;
|
import com.rs2.tick.Tick;
|
||||||
import com.rs2.util.HostBlacklist;
|
import com.rs2.util.HostBlacklist;
|
||||||
@@ -48,7 +46,9 @@ import com.rs2.world.ObjectHandler;
|
|||||||
import com.rs2.world.ObjectManager;
|
import com.rs2.world.ObjectManager;
|
||||||
import com.rs2.world.clip.ObjectDefinition;
|
import com.rs2.world.clip.ObjectDefinition;
|
||||||
import com.rs2.world.clip.RegionFactory;
|
import com.rs2.world.clip.RegionFactory;
|
||||||
import org.apollo.jagcached.FileServer;
|
|
||||||
|
import io.netty.util.ResourceLeakDetector;
|
||||||
|
import io.netty.util.ResourceLeakDetector.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Server.java
|
* Server.java
|
||||||
@@ -111,13 +111,9 @@ public class GameEngine {
|
|||||||
public static boolean sleeping;
|
public static boolean sleeping;
|
||||||
public static boolean updateServer = false;
|
public static boolean updateServer = false;
|
||||||
public static long lastMassSave = System.currentTimeMillis();
|
public static long lastMassSave = System.currentTimeMillis();
|
||||||
private static IoAcceptor acceptor;
|
|
||||||
private static ConnectionHandler connectionHandler;
|
|
||||||
private static ConnectionThrottleFilter throttleFilter;
|
|
||||||
public static boolean shutdownServer = false;
|
public static boolean shutdownServer = false;
|
||||||
public static int garbageCollectDelay = 40;
|
public static int garbageCollectDelay = 40;
|
||||||
public static boolean shutdownClientHandler;
|
public static boolean shutdownClientHandler;
|
||||||
private static int serverlistenerPort;
|
|
||||||
public static ItemHandler itemHandler = new ItemHandler();
|
public static ItemHandler itemHandler = new ItemHandler();
|
||||||
public static PlayerHandler playerHandler = new PlayerHandler();
|
public static PlayerHandler playerHandler = new PlayerHandler();
|
||||||
public static NpcHandler npcHandler = new NpcHandler();
|
public static NpcHandler npcHandler = new NpcHandler();
|
||||||
@@ -152,7 +148,6 @@ public class GameEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serverlistenerPort = (GameConstants.WORLD == 1) ? 43594 : 43596 + GameConstants.WORLD;
|
|
||||||
|
|
||||||
System.out.println("Starting game engine..");
|
System.out.println("Starting game engine..");
|
||||||
if (GameConstants.SERVER_DEBUG) {
|
if (GameConstants.SERVER_DEBUG) {
|
||||||
@@ -177,18 +172,6 @@ public class GameEngine {
|
|||||||
*/
|
*/
|
||||||
System.out.println("Launching " + GameConstants.SERVER_NAME + " World: " + GameConstants.WORLD + "...");
|
System.out.println("Launching " + GameConstants.SERVER_NAME + " World: " + GameConstants.WORLD + "...");
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts The File Server If Enabled In GameConstants
|
|
||||||
*/
|
|
||||||
if (GameConstants.FILE_SERVER) {
|
|
||||||
FileServer fs = new FileServer();
|
|
||||||
try {
|
|
||||||
fs.start();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start Integration Services
|
* Start Integration Services
|
||||||
**/
|
**/
|
||||||
@@ -198,17 +181,15 @@ public class GameEngine {
|
|||||||
/**
|
/**
|
||||||
* Accepting Connections
|
* Accepting Connections
|
||||||
*/
|
*/
|
||||||
acceptor = new SocketAcceptor();
|
//TODO debug ResourceLeakDetector.setLevel(Level.PARANOID);
|
||||||
connectionHandler = new ConnectionHandler();
|
ResourceLeakDetector.setLevel(Level.DISABLED);
|
||||||
|
FileServer fs = new FileServer();
|
||||||
SocketAcceptorConfig sac = new SocketAcceptorConfig();
|
try {
|
||||||
sac.getSessionConfig().setTcpNoDelay(false);
|
fs.start();
|
||||||
sac.setReuseAddress(true);
|
} catch (Exception e) {
|
||||||
sac.setBacklog(100);
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
throttleFilter = new ConnectionThrottleFilter(GameConstants.CONNECTION_DELAY);
|
}
|
||||||
sac.getFilterChain().addFirst("throttleFilter", throttleFilter);
|
|
||||||
acceptor.bind(new InetSocketAddress(serverlistenerPort), connectionHandler, sac);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialise Handlers
|
* Initialise Handlers
|
||||||
@@ -232,7 +213,7 @@ public class GameEngine {
|
|||||||
/**
|
/**
|
||||||
* Server Successfully Loaded
|
* Server Successfully Loaded
|
||||||
*/
|
*/
|
||||||
System.out.println("Server listening on port " + serverlistenerPort);
|
System.out.println("World Server listening on " + fs.service.toString());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main Server Tick
|
* Main Server Tick
|
||||||
@@ -245,6 +226,7 @@ public class GameEngine {
|
|||||||
*/
|
*/
|
||||||
scheduler.scheduleAtFixedRate(new Runnable() {
|
scheduler.scheduleAtFixedRate(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
//TODO debug Stopwatch stopwatch = Stopwatch.createStarted();
|
||||||
/**
|
/**
|
||||||
* Main Server Tick
|
* Main Server Tick
|
||||||
*/
|
*/
|
||||||
@@ -298,6 +280,7 @@ public class GameEngine {
|
|||||||
}
|
}
|
||||||
scheduler.shutdown(); // Kills the tickloop thread if Exception is thrown.
|
scheduler.shutdown(); // Kills the tickloop thread if Exception is thrown.
|
||||||
}
|
}
|
||||||
|
//TODO debug System.out.println("Cycle took " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms.");
|
||||||
}
|
}
|
||||||
}, 0, GameConstants.CYCLE_TIME, TimeUnit.MILLISECONDS);
|
}, 0, GameConstants.CYCLE_TIME, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
@@ -316,9 +299,6 @@ public class GameEngine {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
acceptor = null;
|
|
||||||
connectionHandler = null;
|
|
||||||
sac = null;
|
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,23 @@ import static com.rs2.game.players.PlayerSave.loadPlayerInfo;
|
|||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import com.rs2.GameConstants;
|
||||||
import com.rs2.GameEngine;
|
import com.rs2.GameEngine;
|
||||||
import com.rs2.game.items.ItemAssistant;
|
import com.rs2.game.items.ItemAssistant;
|
||||||
import com.rs2.game.players.Client;
|
import com.rs2.game.players.Client;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
|
import com.rs2.util.Stream;
|
||||||
|
|
||||||
public class Bot {
|
public class Bot {
|
||||||
|
|
||||||
private Client botClient;
|
private Client botClient;
|
||||||
static Timer timer = new Timer();
|
static Timer timer = new Timer();
|
||||||
|
private Stream inStream;
|
||||||
|
|
||||||
public Bot(String username, Integer x, Integer y, Integer z) {
|
public Bot(String username, Integer x, Integer y, Integer z) {
|
||||||
botClient = new Client(null);
|
botClient = new Client(null);
|
||||||
|
inStream = new Stream(new byte[GameConstants.BUFFER_SIZE]);
|
||||||
|
inStream.currentOffset = 0;
|
||||||
botClient.playerName = username;
|
botClient.playerName = username;
|
||||||
botClient.playerName2 = botClient.playerName;
|
botClient.playerName2 = botClient.playerName;
|
||||||
botClient.properName = Character.toUpperCase(username.charAt(1)) + username.substring(2);
|
botClient.properName = Character.toUpperCase(username.charAt(1)) + username.substring(2);
|
||||||
@@ -78,10 +82,10 @@ public class Bot {
|
|||||||
// Normal chat from here down:
|
// Normal chat from here down:
|
||||||
botClient.setChatTextColor(Misc.random(11));
|
botClient.setChatTextColor(Misc.random(11));
|
||||||
botClient.setChatTextEffects(Misc.random(5));
|
botClient.setChatTextEffects(Misc.random(5));
|
||||||
Misc.textPack(botClient.inStream, _message);
|
Misc.textPack(inStream, _message);
|
||||||
botClient.setChatTextSize((byte) botClient.inStream.currentOffset);
|
botClient.setChatTextSize((byte) inStream.currentOffset);
|
||||||
botClient.setChatText(botClient.inStream.buffer);
|
botClient.setChatText(inStream.buffer);
|
||||||
botClient.inStream.currentOffset = 0;
|
inStream.currentOffset = 0;
|
||||||
botClient.setChatTextUpdateRequired(true);
|
botClient.setChatTextUpdateRequired(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.rs2.game.dialogues;
|
package com.rs2.game.dialogues;
|
||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,7 +11,7 @@ import com.rs2.net.packets.PacketType;
|
|||||||
public class Dialogue implements PacketType {
|
public class Dialogue implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player c, int packetType, int packetSize) {
|
public void processPacket(Player c, Packet packet) {
|
||||||
if (c.nextChat > 0) {
|
if (c.nextChat > 0) {
|
||||||
c.getDialogueHandler().sendDialogues(c.nextChat, c.talkingNpc);
|
c.getDialogueHandler().sendDialogues(c.nextChat, c.talkingNpc);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,30 +1,32 @@
|
|||||||
package com.rs2.game.players;
|
package com.rs2.game.players;
|
||||||
|
|
||||||
import org.apache.mina.common.IoSession;
|
import org.apollo.game.session.GameSession;
|
||||||
|
|
||||||
import com.rs2.GameConstants;
|
import com.rs2.GameConstants;
|
||||||
import com.rs2.util.Stream;
|
import com.rs2.util.Stream;
|
||||||
|
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
|
||||||
public class Client extends Player {
|
public class Client extends Player {
|
||||||
|
|
||||||
public Client(IoSession s, int _playerId) {
|
public Client(GameSession s, int _playerId) {
|
||||||
super(_playerId);
|
super(_playerId);
|
||||||
session = s;
|
session = s;
|
||||||
outStream = new Stream(new byte[GameConstants.BUFFER_SIZE]);
|
outStream = new Stream(new byte[GameConstants.BUFFER_SIZE]);
|
||||||
outStream.currentOffset = 0;
|
outStream.currentOffset = 0;
|
||||||
inStream = new Stream(new byte[GameConstants.BUFFER_SIZE]);
|
|
||||||
inStream.currentOffset = 0;
|
|
||||||
buffer = new byte[GameConstants.BUFFER_SIZE];
|
buffer = new byte[GameConstants.BUFFER_SIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
//bots
|
//bots
|
||||||
public Client(IoSession s) {
|
public Client(GameSession s) {
|
||||||
super(-1);
|
super(-1);
|
||||||
isBot = true;
|
isBot = true;
|
||||||
session = null;
|
session = null;
|
||||||
inStream = new Stream(new byte[GameConstants.BUFFER_SIZE]);
|
|
||||||
inStream.currentOffset = 0;
|
|
||||||
buffer = new byte[GameConstants.BUFFER_SIZE];
|
buffer = new byte[GameConstants.BUFFER_SIZE];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSession(GameSession session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,21 +51,26 @@ import com.rs2.game.npcs.NpcHandler;
|
|||||||
import com.rs2.game.npcs.impl.Pets;
|
import com.rs2.game.npcs.impl.Pets;
|
||||||
import com.rs2.game.objects.ObjectsActions;
|
import com.rs2.game.objects.ObjectsActions;
|
||||||
import com.rs2.game.shops.ShopAssistant;
|
import com.rs2.game.shops.ShopAssistant;
|
||||||
import com.rs2.net.HostList;
|
|
||||||
import com.rs2.net.Packet;
|
import com.rs2.net.Packet;
|
||||||
|
import com.rs2.net.Packet.Type;
|
||||||
import com.rs2.net.PacketSender;
|
import com.rs2.net.PacketSender;
|
||||||
import com.rs2.net.StaticPacketBuilder;
|
|
||||||
import com.rs2.net.packets.PacketHandler;
|
import com.rs2.net.packets.PacketHandler;
|
||||||
import com.rs2.net.packets.impl.ChallengePlayer;
|
import com.rs2.net.packets.impl.ChallengePlayer;
|
||||||
import com.rs2.plugin.PluginService;
|
import com.rs2.plugin.PluginService;
|
||||||
import com.rs2.util.ISAACRandomGen;
|
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
import com.rs2.util.Stream;
|
import com.rs2.util.Stream;
|
||||||
import com.rs2.world.Boundary;
|
import com.rs2.world.Boundary;
|
||||||
import com.rs2.world.ObjectManager;
|
import com.rs2.world.ObjectManager;
|
||||||
import org.apache.mina.common.IoSession;
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
|
||||||
|
import org.apollo.game.session.GameSession;
|
||||||
|
import org.apollo.util.security.IsaacRandom;
|
||||||
|
|
||||||
public abstract class Player {
|
public abstract class Player {
|
||||||
|
|
||||||
@@ -85,8 +90,8 @@ public abstract class Player {
|
|||||||
private SpecialPlantOne specialPlantOne = new SpecialPlantOne(this);
|
private SpecialPlantOne specialPlantOne = new SpecialPlantOne(this);
|
||||||
private SpecialPlantTwo specialPlantTwo = new SpecialPlantTwo(this);
|
private SpecialPlantTwo specialPlantTwo = new SpecialPlantTwo(this);
|
||||||
private ToolLeprechaun toolLeprechaun = new ToolLeprechaun(this);
|
private ToolLeprechaun toolLeprechaun = new ToolLeprechaun(this);
|
||||||
public Stream inStream = null, outStream = null;
|
public Stream outStream = null;
|
||||||
public IoSession session;
|
public GameSession session;
|
||||||
private final ItemAssistant itemAssistant = new ItemAssistant(this);
|
private final ItemAssistant itemAssistant = new ItemAssistant(this);
|
||||||
private final ShopAssistant shopAssistant = new ShopAssistant(this);
|
private final ShopAssistant shopAssistant = new ShopAssistant(this);
|
||||||
private final MageTrainingArena mageArena = new MageTrainingArena(this);
|
private final MageTrainingArena mageArena = new MageTrainingArena(this);
|
||||||
@@ -96,7 +101,7 @@ public abstract class Player {
|
|||||||
private final CombatAssistant combatAssistant = new CombatAssistant(this);
|
private final CombatAssistant combatAssistant = new CombatAssistant(this);
|
||||||
private final ObjectsActions actionHandler = new ObjectsActions(this);
|
private final ObjectsActions actionHandler = new ObjectsActions(this);
|
||||||
private final NpcActions npcs = new NpcActions(this);
|
private final NpcActions npcs = new NpcActions(this);
|
||||||
private final Queue<Packet> queuedPackets = new LinkedList<Packet>();
|
private final BlockingQueue<Packet> queuedPackets = new ArrayBlockingQueue<Packet>(25);
|
||||||
private final Potions potions = new Potions(this);
|
private final Potions potions = new Potions(this);
|
||||||
private final PotionMixing potionMixing = new PotionMixing(this);
|
private final PotionMixing potionMixing = new PotionMixing(this);
|
||||||
private final EmoteHandler emoteHandler = new EmoteHandler(this);
|
private final EmoteHandler emoteHandler = new EmoteHandler(this);
|
||||||
@@ -356,18 +361,6 @@ public abstract class Player {
|
|||||||
return bankPin;
|
return bankPin;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Stream getInStream() {
|
|
||||||
return inStream;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized int getPacketType() {
|
|
||||||
return packetType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized int getPacketSize() {
|
|
||||||
return packetSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized Stream getOutStream() {
|
public synchronized Stream getOutStream() {
|
||||||
return outStream;
|
return outStream;
|
||||||
}
|
}
|
||||||
@@ -412,7 +405,7 @@ public abstract class Player {
|
|||||||
return npcs;
|
return npcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IoSession getSession() {
|
public GameSession getSession() {
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,17 +527,21 @@ public abstract class Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void flushOutStream() {
|
public void flushOutStream() {
|
||||||
if (disconnected || outStream == null || outStream.currentOffset == 0) {
|
if (!session.isActive() || disconnected || outStream == null || outStream.currentOffset == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
synchronized (this) {
|
|
||||||
StaticPacketBuilder out = new StaticPacketBuilder().setBare(true);
|
|
||||||
byte[] temp = new byte[outStream.currentOffset];
|
byte[] temp = new byte[outStream.currentOffset];
|
||||||
System.arraycopy(outStream.buffer, 0, temp, 0, temp.length);
|
System.arraycopy(outStream.buffer, 0, temp, 0, temp.length);
|
||||||
out.addBytes(temp);
|
|
||||||
session.write(out.toPacket());
|
// Packet packet = new Packet(-1, Type.FIXED, Unpooled.wrappedBuffer(temp));
|
||||||
|
// session.write(packet);
|
||||||
|
session.write(Unpooled.buffer().writeBytes(temp));
|
||||||
outStream.currentOffset = 0;
|
outStream.currentOffset = 0;
|
||||||
}
|
|
||||||
|
|
||||||
|
// ByteBuf buffer = Unpooled.buffer();
|
||||||
|
// buffer.writeBytes(temp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendClan(String name, String message, String clan, int rights) {
|
public void sendClan(String name, String message, String clan, int rights) {
|
||||||
@@ -558,34 +555,6 @@ public abstract class Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int PACKET_SIZES[] = { 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, // 0
|
|
||||||
0, 0, 0, 0, 8, 0, 6, 2, 2, 0, // 10
|
|
||||||
0, 2, 0, 6, 0, 12, 0, 0, 0, 0, // 20
|
|
||||||
0, 0, 0, 0, 0, 8, 4, 0, 0, 2, // 30
|
|
||||||
2, 6, 0, 6, 0, -1, 0, 0, 0, 0, // 40
|
|
||||||
0, 0, 0, 12, 0, 0, 0, 8, 8, 12, // 50
|
|
||||||
8, 8, 0, 0, 0, 0, 0, 0, 0, 0, // 60
|
|
||||||
6, 0, 2, 2, 8, 6, 0, -1, 0, 6, // 70
|
|
||||||
0, 0, 0, 0, 0, 1, 4, 6, 0, 0, // 80
|
|
||||||
0, 0, 0, 0, 0, 3, 0, 0, -1, 0, // 90
|
|
||||||
0, 13, 0, -1, 0, 0, 0, 0, 0, 0,// 100
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 6, 0, 0, // 110
|
|
||||||
1, 0, 6, 0, 0, 0, -1, 0, 2, 6, // 120
|
|
||||||
0, 4, 6, 8, 0, 6, 0, 0, 0, 2, // 130
|
|
||||||
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, // 140
|
|
||||||
0, 0, 1, 2, 0, 2, 6, 0, 0, 0, // 150
|
|
||||||
0, 0, 0, 0, -1, -1, 0, 0, 0, 0,// 160
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170
|
|
||||||
0, 8, 0, 3, 0, 2, 0, 0, 8, 1, // 180
|
|
||||||
0, 0, 12, 0, 0, 0, 0, 0, 0, 0, // 190
|
|
||||||
2, 0, 0, 0, 0, 0, 0, 0, 4, 0, // 200
|
|
||||||
4, 0, 0, 0, 7, 8, 0, 0, 10, 0, // 210
|
|
||||||
0, 0, 0, 0, 0, 0, -1, 0, 6, 0, // 220
|
|
||||||
1, 0, 0, 0, 6, 0, 6, 8, 1, 0, // 230
|
|
||||||
0, 4, 0, 0, 0, 0, -1, 0, -1, 4,// 240
|
|
||||||
0, 0, 6, 6, 0, 0, 0 // 250
|
|
||||||
};
|
|
||||||
|
|
||||||
public void destruct() {
|
public void destruct() {
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
return;
|
return;
|
||||||
@@ -636,12 +605,11 @@ public abstract class Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Misc.println("[DEREGISTERED]: " + playerName + "");
|
Misc.println("[DEREGISTERED]: " + playerName + "");
|
||||||
HostList.getHostList().remove(session);
|
// HostList.getHostList().remove(session);
|
||||||
CycleEventHandler.getSingleton().stopEvents(this);
|
CycleEventHandler.getSingleton().stopEvents(this);
|
||||||
disconnected = true;
|
disconnected = true;
|
||||||
session.close();
|
session.close();
|
||||||
session = null;
|
session = null;
|
||||||
inStream = null;
|
|
||||||
outStream = null;
|
outStream = null;
|
||||||
isActive = false;
|
isActive = false;
|
||||||
buffer = null;
|
buffer = null;
|
||||||
@@ -787,7 +755,6 @@ public abstract class Player {
|
|||||||
return eventProvider;
|
return eventProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int packetSize = 0, packetType = -1;
|
|
||||||
public boolean wildernessWarning;
|
public boolean wildernessWarning;
|
||||||
public int axeAnimation = -1;
|
public int axeAnimation = -1;
|
||||||
|
|
||||||
@@ -1099,42 +1066,18 @@ public abstract class Player {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void queueMessage(Packet arg1) {
|
public void queueMessage(Packet arg1) {
|
||||||
queuedPackets.add(arg1);
|
if (queuedPackets.size() < 25) {
|
||||||
|
queuedPackets.add(arg1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean processQueuedPackets() {
|
public void processQueuedPackets() {
|
||||||
Packet p = null;
|
while (!queuedPackets.isEmpty()) {
|
||||||
synchronized (queuedPackets) {
|
Packet p = queuedPackets.poll();
|
||||||
p = queuedPackets.poll();
|
if (p.getOpcode() > 0) {
|
||||||
}
|
PacketHandler.processPacket(this, p);
|
||||||
if (p == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
inStream.currentOffset = 0;
|
|
||||||
packetType = p.getId();
|
|
||||||
packetSize = p.getLength();
|
|
||||||
inStream.buffer = p.getData();
|
|
||||||
if (packetType > 0) {
|
|
||||||
PacketHandler.processPacket(this, packetType, packetSize);
|
|
||||||
}
|
|
||||||
timeOutCounter = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized boolean processPacket(Packet p) {
|
|
||||||
synchronized (this) {
|
|
||||||
if (p == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
inStream.currentOffset = 0;
|
|
||||||
packetType = p.getId();
|
|
||||||
packetSize = p.getLength();
|
|
||||||
inStream.buffer = p.getData();
|
|
||||||
if (packetType > 0) {
|
|
||||||
PacketHandler.processPacket(this, packetType, packetSize);
|
|
||||||
}
|
}
|
||||||
timeOutCounter = 0;
|
timeOutCounter = 0;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3140,11 +3083,11 @@ public abstract class Player {
|
|||||||
return newWalkCmdIsRunning;
|
return newWalkCmdIsRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setInStreamDecryption(ISAACRandomGen inStreamDecryption) {
|
public void setInStreamDecryption(IsaacRandom inStreamDecryption) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setOutStreamDecryption(ISAACRandomGen outStreamDecryption) {
|
public void setOutStreamDecryption(IsaacRandom outStreamDecryption) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,6 @@ public class PlayerHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void process() {
|
public void process() {
|
||||||
// synchronized (PlayerHandler.players) {
|
|
||||||
updatePlayerNames();
|
updatePlayerNames();
|
||||||
if (kickAllPlayers) {
|
if (kickAllPlayers) {
|
||||||
for (int i = 0; i < PlayerHandler.players.length; i++) {
|
for (int i = 0; i < PlayerHandler.players.length; i++) {
|
||||||
@@ -182,9 +181,7 @@ public class PlayerHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
while (players[i].processQueuedPackets()) {
|
players[i].processQueuedPackets();
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
players[i].process();
|
players[i].process();
|
||||||
players[i].postProcessing();
|
players[i].postProcessing();
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.rs2.net;
|
|
||||||
|
|
||||||
import org.apache.mina.filter.codec.ProtocolCodecFactory;
|
|
||||||
import org.apache.mina.filter.codec.ProtocolDecoder;
|
|
||||||
import org.apache.mina.filter.codec.ProtocolEncoder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides access to the encoders and decoders for the 508 protocol.
|
|
||||||
*
|
|
||||||
* @author Graham
|
|
||||||
*/
|
|
||||||
public class CodecFactory implements ProtocolCodecFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The encoder.
|
|
||||||
*/
|
|
||||||
private final ProtocolEncoder encoder = new RS2ProtocolEncoder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The decoder.
|
|
||||||
*/
|
|
||||||
private final ProtocolDecoder decoder = new RS2LoginProtocolDecoder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
/**
|
|
||||||
* Get the encoder.
|
|
||||||
*/
|
|
||||||
public ProtocolEncoder getEncoder() throws Exception {
|
|
||||||
return encoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
/**
|
|
||||||
* Get the decoder.
|
|
||||||
*/
|
|
||||||
public ProtocolDecoder getDecoder() throws Exception {
|
|
||||||
return decoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,63 +1,76 @@
|
|||||||
package com.rs2.net;
|
package com.rs2.net;
|
||||||
|
|
||||||
import org.apache.mina.common.IdleStatus;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
import org.apache.mina.common.IoHandler;
|
|
||||||
import org.apache.mina.common.IoSession;
|
|
||||||
import org.apache.mina.filter.codec.ProtocolCodecFilter;
|
|
||||||
|
|
||||||
import com.rs2.game.players.Client;
|
|
||||||
|
|
||||||
public class ConnectionHandler implements IoHandler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(IoSession arg0, Throwable arg1)
|
|
||||||
throws Exception {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void messageReceived(IoSession arg0, Object arg1) throws Exception {
|
|
||||||
if (arg0.getAttachment() != null) {
|
|
||||||
Client plr = (Client) arg0.getAttachment();
|
|
||||||
plr.queueMessage((Packet) arg1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void messageSent(IoSession arg0, Object arg1) throws Exception {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sessionClosed(IoSession arg0) throws Exception {
|
|
||||||
if (arg0.getAttachment() != null) {
|
|
||||||
Client plr = (Client) arg0.getAttachment();
|
|
||||||
plr.disconnected = true;
|
|
||||||
}
|
|
||||||
HostList.getHostList().remove(arg0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sessionCreated(IoSession arg0) throws Exception {
|
|
||||||
if (!HostList.getHostList().add(arg0)) {
|
|
||||||
arg0.close();
|
|
||||||
} else {
|
|
||||||
arg0.setAttribute("inList", Boolean.TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception {
|
|
||||||
arg0.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sessionOpened(IoSession arg0) throws Exception {
|
|
||||||
arg0.setIdleTime(IdleStatus.BOTH_IDLE, 60);
|
|
||||||
arg0.getFilterChain().addLast("protocolFilter",
|
|
||||||
new ProtocolCodecFilter(new CodecFactory()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Old class that was used with netty 4 impl. This is no longer needed but will be a reference for re-adding the HostList stuff into the ApolloHandler.
|
||||||
|
* @author Advocatus
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ConnectionHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
|
//// public static final AttributeKey<Session> SESSION_KEY = AttributeKey.valueOf("session");
|
||||||
|
//
|
||||||
|
// private Session session = null;
|
||||||
|
//
|
||||||
|
//// @Override
|
||||||
|
//// public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
||||||
|
//// if (session == null) {
|
||||||
|
//// session = new Session(ctx.getChannel());
|
||||||
|
//// if (!HostList.getHostList().add(session)) {
|
||||||
|
//// ctx.getChannel().close();
|
||||||
|
//// } else {
|
||||||
|
//// session.setInList(true);
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void channelInactive(ChannelHandlerContext ctx) {
|
||||||
|
// if (session != null) {
|
||||||
|
// // HostList.getHostList().remove(session);
|
||||||
|
// Client client = session.getClient();
|
||||||
|
// if (client != null) {
|
||||||
|
// client.disconnected = true;
|
||||||
|
// }
|
||||||
|
// session = null;
|
||||||
|
// }
|
||||||
|
// Channel channel = ctx.channel();
|
||||||
|
// channel.close();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void exceptionCaught(ChannelHandlerContext ctx, Throwable e) {
|
||||||
|
// if (!e.getMessage().contains("An existing connection was forcibly closed by the remote host")) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// // logger.log(Level.WARNING, "Exception occured for channel: " + ctx.channel() + ", closing...", e);
|
||||||
|
// }
|
||||||
|
// ctx.channel().close();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
|
||||||
|
//// System.out.println(message.getClass());
|
||||||
|
// if (session == null) {
|
||||||
|
// session = new Session(ctx.channel());
|
||||||
|
//// if (!HostList.getHostList().add(session)) {
|
||||||
|
//// ctx.channel().close();
|
||||||
|
//// } else {
|
||||||
|
//// session.setInList(true);
|
||||||
|
//// }
|
||||||
|
// }
|
||||||
|
// if (message instanceof Client) {
|
||||||
|
// session.setClient((Client) message);
|
||||||
|
// } else if (message instanceof Packet) {
|
||||||
|
// if (session.getClient() != null) {
|
||||||
|
// session.getClient().queueMessage((Packet) message);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void channelReadComplete(ChannelHandlerContext ctx) {
|
||||||
|
// ctx.flush();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,132 +0,0 @@
|
|||||||
package com.rs2.net;
|
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.apache.mina.common.IoFilter;
|
|
||||||
import org.apache.mina.common.IoFilterAdapter;
|
|
||||||
import org.apache.mina.common.IoSession;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link IoFilter} which blocks connections from connecting at a rate faster
|
|
||||||
* than the specified interval.
|
|
||||||
*
|
|
||||||
* @author The Apache MINA Project (dev@mina.apache.org)
|
|
||||||
* @version $Rev$, $Date$
|
|
||||||
*/
|
|
||||||
public class ConnectionThrottleFilter extends IoFilterAdapter {
|
|
||||||
|
|
||||||
private long allowedInterval;
|
|
||||||
private final Map<InetAddress, Long> clients;
|
|
||||||
private final Map<InetAddress, Integer> counts;
|
|
||||||
private final Set<InetAddress> connectedAddresses;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor that takes in a specified wait time.
|
|
||||||
*
|
|
||||||
* @param allowedInterval
|
|
||||||
* The number of milliseconds a client is allowed to wait before
|
|
||||||
* making another successful connection
|
|
||||||
*/
|
|
||||||
public ConnectionThrottleFilter(long allowedInterval) {
|
|
||||||
this.allowedInterval = allowedInterval;
|
|
||||||
clients = Collections.synchronizedMap(new HashMap<InetAddress, Long>());
|
|
||||||
counts = Collections
|
|
||||||
.synchronizedMap(new HashMap<InetAddress, Integer>());
|
|
||||||
connectedAddresses = new HashSet<InetAddress>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the interval between connections from a client. This value is
|
|
||||||
* measured in milliseconds.
|
|
||||||
*
|
|
||||||
* @param allowedInterval
|
|
||||||
* The number of milliseconds a client is allowed to wait before
|
|
||||||
* making another successful connection
|
|
||||||
*/
|
|
||||||
public void setAllowedInterval(long allowedInterval) {
|
|
||||||
this.allowedInterval = allowedInterval;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delayClient(IoSession session, int delay) {
|
|
||||||
long d = System.currentTimeMillis() - delay;
|
|
||||||
clients.put(getAddress(session), d);
|
|
||||||
}
|
|
||||||
|
|
||||||
private InetAddress getAddress(IoSession io) {
|
|
||||||
return ((InetSocketAddress) io.getRemoteAddress()).getAddress();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Method responsible for deciding if a connection is OK to continue
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* The new session that will be verified
|
|
||||||
* @return True if the session meets the criteria, otherwise false
|
|
||||||
*/
|
|
||||||
public boolean isConnectionOk(IoSession session) {
|
|
||||||
InetAddress addr = getAddress(session);
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
if (clients.containsKey(addr)) {
|
|
||||||
long lastConnTime = clients.get(addr);
|
|
||||||
|
|
||||||
if (now - lastConnTime < allowedInterval) {
|
|
||||||
int c = 0;
|
|
||||||
if (!counts.containsKey(addr)) {
|
|
||||||
counts.put(addr, 0);
|
|
||||||
} else {
|
|
||||||
c = counts.get(addr) + 1;
|
|
||||||
}
|
|
||||||
if (c >= 350) {
|
|
||||||
|
|
||||||
c = 0;
|
|
||||||
}
|
|
||||||
counts.put(addr, c);
|
|
||||||
// Logger.err("["+host+"] Session dropped (delay="+(now-lastConnTime)+"ms)");
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
clients.put(addr, now);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
clients.put(addr, now);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void closedSession(IoSession io) {
|
|
||||||
connectedAddresses.remove(getAddress(io));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void acceptedLogin(IoSession io) {
|
|
||||||
connectedAddresses.add(getAddress(io));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isConnected(IoSession io) {
|
|
||||||
return connectedAddresses.contains(getAddress(io));
|
|
||||||
}
|
|
||||||
|
|
||||||
public int[] getSizes() {
|
|
||||||
return new int[] { clients.size(), counts.size(),
|
|
||||||
connectedAddresses.size() };
|
|
||||||
}
|
|
||||||
|
|
||||||
public void connectionOk(IoSession io) {
|
|
||||||
counts.remove(getAddress(io));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sessionCreated(NextFilter nextFilter, IoSession session)
|
|
||||||
throws Exception {
|
|
||||||
if (!isConnectionOk(session)) {
|
|
||||||
session.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nextFilter.sessionCreated(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package com.rs2.net;
|
|
||||||
|
|
||||||
import org.apache.mina.filter.codec.ProtocolCodecFactory;
|
|
||||||
import org.apache.mina.filter.codec.ProtocolDecoder;
|
|
||||||
import org.apache.mina.filter.codec.ProtocolEncoder;
|
|
||||||
|
|
||||||
import com.rs2.util.ISAACRandomGen;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides access to the encoders and decoders for the 508 protocol.
|
|
||||||
*
|
|
||||||
* @author Graham
|
|
||||||
*/
|
|
||||||
public class GameCodecFactory implements ProtocolCodecFactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The encoder.
|
|
||||||
*/
|
|
||||||
private final ProtocolEncoder encoder = new RS2ProtocolEncoder();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The decoder.
|
|
||||||
*/
|
|
||||||
private final ProtocolDecoder decoder;
|
|
||||||
|
|
||||||
public GameCodecFactory(ISAACRandomGen inC) {
|
|
||||||
decoder = new RS2ProtocolDecoder(inC);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
/**
|
|
||||||
* Get the encoder.
|
|
||||||
*/
|
|
||||||
public ProtocolEncoder getEncoder() throws Exception {
|
|
||||||
return encoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
/**
|
|
||||||
* Get the decoder.
|
|
||||||
*/
|
|
||||||
public ProtocolDecoder getDecoder() throws Exception {
|
|
||||||
return decoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.rs2.net;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enumeration with the different states the {@link GamePacketDecoder} can be in.
|
||||||
|
*
|
||||||
|
* @author Graham
|
||||||
|
*/
|
||||||
|
public enum GameDecoderState {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The game length state waits for the packet length. Once it has been received, it sets the state to the payload
|
||||||
|
* state.
|
||||||
|
*/
|
||||||
|
GAME_LENGTH,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The game opcode state waits for an encrypted opcode. It decrypts it, and will either set the next state to the
|
||||||
|
* length (if the packet is variably- sized) or the payload (if it is not variably-sized) state.
|
||||||
|
*/
|
||||||
|
GAME_OPCODE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The payload state will wait for the whole packet to be received. Then, it will pass a {@link GamePacket} object
|
||||||
|
* to Netty and reset the state back to the game opcode state, ready for the next packet.
|
||||||
|
*/
|
||||||
|
GAME_PAYLOAD;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,57 +1,90 @@
|
|||||||
package com.rs2.net;
|
package com.rs2.net;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.mina.common.IoSession;
|
|
||||||
|
|
||||||
import com.rs2.Connection;
|
import com.rs2.Connection;
|
||||||
import com.rs2.GameConstants;
|
import com.rs2.GameConstants;
|
||||||
|
|
||||||
public class HostList {
|
public class HostList {
|
||||||
|
//
|
||||||
private static HostList list = new HostList();
|
// private final Map<InetAddress, Long> clients;
|
||||||
|
//
|
||||||
public static HostList getHostList() {
|
// private HostList() {
|
||||||
return list;
|
// clients = Collections.synchronizedMap(new HashMap<InetAddress, Long>());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
private final Map<String, Integer> connections = new HashMap<String, Integer>();
|
// private static HostList list = new HostList();
|
||||||
|
//
|
||||||
public synchronized boolean add(IoSession session) {
|
// public static HostList getHostList() {
|
||||||
String addr = ((InetSocketAddress) session.getRemoteAddress())
|
// return list;
|
||||||
.getAddress().getHostAddress();
|
// }
|
||||||
Integer amt = connections.get(addr);
|
//
|
||||||
if (amt == null) {
|
// private final Map<String, Integer> connections = new HashMap<String, Integer>();
|
||||||
amt = 1;
|
//
|
||||||
} else {
|
// public synchronized boolean add(Session session) {
|
||||||
amt += 1;
|
// if(!isConnectionOk(session)) {
|
||||||
}
|
// return false;
|
||||||
if (amt > GameConstants.IPS_ALLOWED || Connection.isIpBanned(addr)) {
|
// }
|
||||||
return false;
|
// String addr = ((InetSocketAddress) session.getChannel().remoteAddress()).getAddress().getHostAddress();
|
||||||
} else {
|
// Integer amt = connections.get(addr);
|
||||||
connections.put(addr, amt);
|
// if (amt == null) {
|
||||||
return true;
|
// amt = 1;
|
||||||
}
|
// } else {
|
||||||
}
|
// amt += 1;
|
||||||
|
// }
|
||||||
public synchronized void remove(IoSession session) {
|
// if (amt > GameConstants.IPS_ALLOWED || Connection.isIpBanned(addr)) {
|
||||||
if (session.getAttribute("inList") != Boolean.TRUE) {
|
// return false;
|
||||||
return;
|
// } else {
|
||||||
}
|
// connections.put(addr, amt);
|
||||||
String addr = ((InetSocketAddress) session.getRemoteAddress())
|
// return true;
|
||||||
.getAddress().getHostAddress();
|
// }
|
||||||
Integer amt = connections.get(addr);
|
// }
|
||||||
if (amt == null) {
|
//
|
||||||
return;
|
// public synchronized void remove(Session session) {
|
||||||
}
|
// if (!session.isInList()) {
|
||||||
amt -= 1;
|
// return;
|
||||||
if (amt <= 0) {
|
// }
|
||||||
connections.remove(addr);
|
// String addr = ((InetSocketAddress) session.getChannel().remoteAddress())
|
||||||
} else {
|
// .getAddress().getHostAddress();
|
||||||
connections.put(addr, amt);
|
// Integer amt = connections.get(addr);
|
||||||
}
|
// if (amt == null) {
|
||||||
}
|
// return;
|
||||||
|
// }
|
||||||
|
// amt -= 1;
|
||||||
|
// if (amt <= 0) {
|
||||||
|
// connections.remove(addr);
|
||||||
|
// } else {
|
||||||
|
// connections.put(addr, amt);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private InetAddress getAddress(Session io) {
|
||||||
|
// return ((InetSocketAddress) io.getChannel().remoteAddress()).getAddress();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /**
|
||||||
|
// * Method responsible for deciding if a connection is OK to continue
|
||||||
|
// *
|
||||||
|
// * @param session
|
||||||
|
// * The new session that will be verified
|
||||||
|
// * @return True if the session meets the criteria, otherwise false
|
||||||
|
// */
|
||||||
|
// private boolean isConnectionOk(Session session) {
|
||||||
|
// InetAddress addr = getAddress(session);
|
||||||
|
// long now = System.currentTimeMillis();
|
||||||
|
// if (clients.containsKey(addr)) {
|
||||||
|
// long lastConnTime = clients.get(addr);
|
||||||
|
//
|
||||||
|
// if (now - lastConnTime < GameConstants.CONNECTION_DELAY) {
|
||||||
|
// System.out.println("["+addr+"] Session dropped (delay="+(now-lastConnTime)+"ms)");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// clients.put(addr, now);
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,304 +1,472 @@
|
|||||||
package com.rs2.net;
|
package com.rs2.net;
|
||||||
|
|
||||||
import org.apache.mina.common.IoSession;
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immutable packet object.
|
* Represents a single packet.
|
||||||
|
*
|
||||||
|
* @author Graham Edgecombe
|
||||||
*
|
*
|
||||||
* @author Graham
|
|
||||||
*/
|
*/
|
||||||
public final class Packet {
|
public class Packet {
|
||||||
|
|
||||||
public static enum Size {
|
|
||||||
Fixed, VariableByte, VariableShort
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The associated IO session
|
* The type of packet.
|
||||||
*/
|
*
|
||||||
private final IoSession session;
|
* @author Graham Edgecombe
|
||||||
/**
|
|
||||||
* The ID of the packet
|
|
||||||
*/
|
|
||||||
private final int pID;
|
|
||||||
/**
|
|
||||||
* The length of the payload
|
|
||||||
*/
|
|
||||||
private final int pLength;
|
|
||||||
/**
|
|
||||||
* The payload
|
|
||||||
*/
|
|
||||||
private final byte[] pData;
|
|
||||||
/**
|
|
||||||
* The current index into the payload buffer for reading
|
|
||||||
*/
|
|
||||||
private int caret = 0;
|
|
||||||
/**
|
|
||||||
* Whether this packet is without the standard packet header
|
|
||||||
*/
|
|
||||||
private final boolean bare;
|
|
||||||
private Size size = Size.Fixed;
|
|
||||||
|
|
||||||
public Packet(IoSession session, int pID, byte[] pData, boolean bare, Size s) {
|
|
||||||
this.session = session;
|
|
||||||
this.pID = pID;
|
|
||||||
this.pData = pData;
|
|
||||||
pLength = pData.length;
|
|
||||||
this.bare = bare;
|
|
||||||
size = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new packet with the specified parameters.
|
|
||||||
*
|
*
|
||||||
* @param session
|
|
||||||
* The session to associate with the packet
|
|
||||||
* @param pID
|
|
||||||
* The ID of the packet
|
|
||||||
* @param pData
|
|
||||||
* The payload of the packet
|
|
||||||
* @param bare
|
|
||||||
* Whether this packet is bare, which means that it does not
|
|
||||||
* include the standard packet header
|
|
||||||
*/
|
*/
|
||||||
public Packet(IoSession session, int pID, byte[] pData, boolean bare) {
|
public enum Type {
|
||||||
this(session, pID, pData, bare, Size.Fixed);
|
|
||||||
|
/**
|
||||||
|
* A fixed size packet where the size never changes.
|
||||||
|
*/
|
||||||
|
FIXED,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variable packet where the size is described by a byte.
|
||||||
|
*/
|
||||||
|
VARIABLE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variable packet where the size is described by a word.
|
||||||
|
*/
|
||||||
|
VARIABLE_SHORT;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new packet with the specified parameters. The packet is
|
* The opcode.
|
||||||
* considered not to be a bare packet.
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* The session to associate with the packet
|
|
||||||
* @param pID
|
|
||||||
* The ID of the packet
|
|
||||||
* @param pData
|
|
||||||
* The payload the packet
|
|
||||||
*/
|
*/
|
||||||
public Packet(IoSession session, int pID, byte[] pData) {
|
private final int opcode;
|
||||||
this(session, pID, pData, false);
|
|
||||||
|
/**
|
||||||
|
* The type.
|
||||||
|
*/
|
||||||
|
private final Type type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The payload.
|
||||||
|
*/
|
||||||
|
private final ByteBuf payload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a packet.
|
||||||
|
*
|
||||||
|
* @param opcode The opcode.
|
||||||
|
* @param type The type.
|
||||||
|
* @param payload The payload.
|
||||||
|
*/
|
||||||
|
public Packet(final int opcode, final Type type, final ByteBuf payload) {
|
||||||
|
this.opcode = opcode;
|
||||||
|
this.type = type;
|
||||||
|
this.payload = payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the IO session associated with the packet, if any.
|
* Checks if this packet is raw. A raw packet does not have the usual headers
|
||||||
|
* such as opcode or size.
|
||||||
*
|
*
|
||||||
* @return The <code>IoSession</code> object, or <code>null</code> if none.
|
* @return <code>true</code> if so, <code>false</code> if not.
|
||||||
*/
|
*/
|
||||||
public IoSession getSession() {
|
public boolean isRaw() {
|
||||||
return session;
|
return opcode == -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this packet is considered to be a bare packet, which means that
|
* Gets the opcode.
|
||||||
* it does not include the standard packet header (ID and length values).
|
|
||||||
*
|
*
|
||||||
* @return Whether this packet is a bare packet
|
* @return The opcode.
|
||||||
*/
|
*/
|
||||||
public boolean isBare() {
|
public int getOpcode() {
|
||||||
return bare;
|
return opcode;
|
||||||
}
|
|
||||||
|
|
||||||
public Size getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the packet ID.
|
* Gets the type.
|
||||||
*
|
*
|
||||||
* @return The packet ID
|
* @return The type.
|
||||||
*/
|
*/
|
||||||
public int getId() {
|
public Type getType() {
|
||||||
return pID;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the length of the payload of this packet.
|
* Gets the payload.
|
||||||
*
|
*
|
||||||
* @return The length of the packet's payload
|
* @return The payload.
|
||||||
|
*/
|
||||||
|
public ByteBuf getPayload() {
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the length.
|
||||||
|
*
|
||||||
|
* @return The length.
|
||||||
*/
|
*/
|
||||||
public int getLength() {
|
public int getLength() {
|
||||||
return pLength;
|
return payload.capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the entire payload data of this packet.
|
* Reads a single byte.
|
||||||
*
|
*
|
||||||
* @return The payload <code>byte</code> array
|
* @return A single byte.
|
||||||
*/
|
*/
|
||||||
public byte[] getData() {
|
public byte get() {
|
||||||
return pData;
|
return payload.readByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the remaining payload data of this packet.
|
* Reads several bytes.
|
||||||
*
|
*
|
||||||
* @return The payload <code>byte</code> array
|
* @param b The target array.
|
||||||
*/
|
*/
|
||||||
public byte[] getRemainingData() {
|
public void get(final byte[] b) {
|
||||||
byte[] data = new byte[pLength - caret];
|
payload.readBytes(b);
|
||||||
for (int i = 0; i < data.length; i++) {
|
|
||||||
data[i] = pData[i + caret];
|
|
||||||
}
|
|
||||||
caret += data.length;
|
|
||||||
return data;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the next <code>byte</code> from the payload.
|
* Reads a byte.
|
||||||
*
|
*
|
||||||
* @return A <code>byte</code>
|
* @return A single byte.
|
||||||
*/
|
*/
|
||||||
public byte readByte() {
|
public byte getByte() {
|
||||||
return pData[caret++];
|
return get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the next <code>short</code> from the payload.
|
* Reads an unsigned byte.
|
||||||
*
|
*
|
||||||
* @return A <code>short</code>
|
* @return An unsigned byte.
|
||||||
*/
|
*/
|
||||||
public short readShort() {
|
public int getUnsignedByte() {
|
||||||
return (short) ((short) ((pData[caret++] & 0xff) << 8) | (short) (pData[caret++] & 0xff));
|
return payload.readByte() & 0xff;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readLEShortA() {
|
/**
|
||||||
int i = (pData[caret++] - 128 & 0xff) + ((pData[caret++] & 0xff) << 8);
|
* Reads a short.
|
||||||
if (i > 32767) {
|
*
|
||||||
|
* @return A short.
|
||||||
|
*/
|
||||||
|
public short getShort() {
|
||||||
|
return payload.readShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads an unsigned short.
|
||||||
|
*
|
||||||
|
* @return An unsigned short.
|
||||||
|
*/
|
||||||
|
public int getUnsignedShort() {
|
||||||
|
int value = 0;
|
||||||
|
value |= (get() & 0xff) << 8;
|
||||||
|
value |= (get() & 0xff);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUnsignedShortA() {
|
||||||
|
int value = 0;
|
||||||
|
value |= (get() & 0xff) << 8;
|
||||||
|
value |= ((get() - 128) & 0xff);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads an integer.
|
||||||
|
*
|
||||||
|
* @return An integer.
|
||||||
|
*/
|
||||||
|
public int getInt() {
|
||||||
|
return payload.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a long.
|
||||||
|
*
|
||||||
|
* @return A long.
|
||||||
|
*/
|
||||||
|
public long getLong() {
|
||||||
|
return payload.readLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a type C byte.
|
||||||
|
*
|
||||||
|
* @return A type C byte.
|
||||||
|
*/
|
||||||
|
public byte getByteC() {
|
||||||
|
return (byte) (-get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a type S byte.
|
||||||
|
*
|
||||||
|
* @return A type S byte.
|
||||||
|
*/
|
||||||
|
public byte getByteS() {
|
||||||
|
return (byte) (128 - get());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a little-endian type A short.
|
||||||
|
*
|
||||||
|
* @return A little-endian type A short.
|
||||||
|
*/
|
||||||
|
public short getLEShortA() {
|
||||||
|
int i = (get() - 128 & 0xFF) | ((get() & 0xFF) << 8);
|
||||||
|
if (i > 32767)
|
||||||
i -= 0x10000;
|
i -= 0x10000;
|
||||||
}
|
return (short) i;
|
||||||
return i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readLEShort() {
|
/**
|
||||||
int i = (pData[caret++] & 0xff) + ((pData[caret++] & 0xff) << 8);
|
* Reads a little-endian short.
|
||||||
if (i > 32767) {
|
*
|
||||||
|
* @return A little-endian short.
|
||||||
|
*/
|
||||||
|
public short getLEShort() {
|
||||||
|
int i = (get() & 0xFF) | ((get() & 0xFF) << 8);
|
||||||
|
if (i > 32767)
|
||||||
i -= 0x10000;
|
i -= 0x10000;
|
||||||
|
return (short) i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a V1 integer.
|
||||||
|
*
|
||||||
|
* @return A V1 integer.
|
||||||
|
*/
|
||||||
|
public int getInt1() {
|
||||||
|
final byte b1 = get();
|
||||||
|
final byte b2 = get();
|
||||||
|
final byte b3 = get();
|
||||||
|
final byte b4 = get();
|
||||||
|
return ((b3 << 24) & 0xFF) | ((b4 << 16) & 0xFF) | ((b1 << 8) & 0xFF) | (b2 & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a V2 integer.
|
||||||
|
*
|
||||||
|
* @return A V2 integer.
|
||||||
|
*/
|
||||||
|
public int getInt2() {
|
||||||
|
final int b1 = get() & 0xFF;
|
||||||
|
final int b2 = get() & 0xFF;
|
||||||
|
final int b3 = get() & 0xFF;
|
||||||
|
final int b4 = get() & 0xFF;
|
||||||
|
return ((b2 << 24) & 0xFF) | ((b1 << 16) & 0xFF) | ((b4 << 8) & 0xFF) | (b3 & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a 3-byte integer.
|
||||||
|
*
|
||||||
|
* @return The 3-byte integer.
|
||||||
|
*/
|
||||||
|
public int getTriByte() {
|
||||||
|
return ((get() << 16) & 0xFF) | ((get() << 8) & 0xFF) | (get() & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a type A byte.
|
||||||
|
*
|
||||||
|
* @return A type A byte.
|
||||||
|
*/
|
||||||
|
public byte getByteA() {
|
||||||
|
return (byte) (get() - 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a RuneScape string.
|
||||||
|
*
|
||||||
|
* @return The string.
|
||||||
|
*/
|
||||||
|
public String getRS2String() {
|
||||||
|
byte temp;
|
||||||
|
StringBuilder b = new StringBuilder();
|
||||||
|
while ((temp = payload.readByte()) != 10) {
|
||||||
|
b.append((char) temp);
|
||||||
}
|
}
|
||||||
return i;
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the next <code>int</code> from the payload.
|
* Reads a type A short.
|
||||||
*
|
*
|
||||||
* @return An <code>int</code>
|
* @return A type A short.
|
||||||
*/
|
*/
|
||||||
public int readInt() {
|
public short getShortA() {
|
||||||
return (pData[caret++] & 0xff) << 24 | (pData[caret++] & 0xff) << 16
|
int i = ((get() & 0xFF) << 8) | (get() - 128 & 0xFF);
|
||||||
| (pData[caret++] & 0xff) << 8 | pData[caret++] & 0xff;
|
if (i > 32767)
|
||||||
}
|
i -= 0x10000;
|
||||||
|
return (short) i;
|
||||||
public int readLEInt() {
|
|
||||||
return pData[caret++] & 0xff | (pData[caret++] & 0xff) << 8
|
|
||||||
| (pData[caret++] & 0xff) << 16 | (pData[caret++] & 0xff) << 24;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the next <code>long</code> from the payload.
|
* Reads a series of bytes in reverse.
|
||||||
*
|
*
|
||||||
* @return A <code>long</code>
|
* @param is The target byte array.
|
||||||
|
* @param offset The offset.
|
||||||
|
* @param length The length.
|
||||||
*/
|
*/
|
||||||
public long readLong() {
|
public void getReverse(final byte[] is, final int offset, final int length) {
|
||||||
return (long) (pData[caret++] & 0xff) << 56
|
for (int i = (offset + length - 1); i >= offset; i--)
|
||||||
| (long) (pData[caret++] & 0xff) << 48
|
is[i] = get();
|
||||||
| (long) (pData[caret++] & 0xff) << 40
|
|
||||||
| (long) (pData[caret++] & 0xff) << 32
|
|
||||||
| (long) (pData[caret++] & 0xff) << 24
|
|
||||||
| (long) (pData[caret++] & 0xff) << 16
|
|
||||||
| (long) (pData[caret++] & 0xff) << 8 | pData[caret++] & 0xff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads the string which is formed by the unread portion of the payload.
|
* Reads a series of type A bytes in reverse.
|
||||||
*
|
*
|
||||||
* @return A <code>String</code>
|
* @param is The target byte array.
|
||||||
|
* @param offset The offset.
|
||||||
|
* @param length The length.
|
||||||
*/
|
*/
|
||||||
|
public void getReverseA(final byte[] is, final int offset, final int length) {
|
||||||
|
for (int i = (offset + length - 1); i >= offset; i--)
|
||||||
|
is[i] = getByteA();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a series of bytes.
|
||||||
|
*
|
||||||
|
* @param is The target byte array.
|
||||||
|
* @param offset The offset.
|
||||||
|
* @param length The length.
|
||||||
|
*/
|
||||||
|
public void get(final byte[] is, final int offset, final int length) {
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
is[offset + i] = get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a smart.
|
||||||
|
*
|
||||||
|
* @return The smart.
|
||||||
|
*/
|
||||||
|
public int getSmart() {
|
||||||
|
final int peek = payload.getByte(payload.readerIndex());
|
||||||
|
if (peek < 128)
|
||||||
|
return (get() & 0xFF);
|
||||||
|
else
|
||||||
|
return (getShort() & 0xFFFF) - 32768;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a signed smart.
|
||||||
|
*
|
||||||
|
* @return The signed smart.
|
||||||
|
*/
|
||||||
|
public int getSignedSmart() {
|
||||||
|
final int peek = payload.getByte(payload.readerIndex());
|
||||||
|
if (peek < 128)
|
||||||
|
return ((get() & 0xFF) - 64);
|
||||||
|
else
|
||||||
|
return ((getShort() & 0xFFFF) - 49152);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Legacy methods here */
|
||||||
|
|
||||||
|
public int readUnsignedByte() {
|
||||||
|
return get() & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte readSignedByte() {
|
||||||
|
return get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte readSignedByteC() {
|
||||||
|
return (byte) -get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readUnsignedByteS() {
|
||||||
|
return 128 - get() & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readHex() {
|
||||||
|
return ((get() & 0xFF) * 1000) + (get() & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readBytes(byte abyte0[], int length, int offset) {
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
abyte0[offset + i] = get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readBytes_reverseA(byte abyte0[], int length, int offset) {
|
||||||
|
for (int i = (offset + length - 1); i >= offset; i--)
|
||||||
|
abyte0[i] = getByteA();
|
||||||
|
}
|
||||||
|
|
||||||
public String readString() {
|
public String readString() {
|
||||||
return readString(pLength - caret);
|
byte temp;
|
||||||
}
|
StringBuilder b = new StringBuilder();
|
||||||
|
while ((temp = payload.readByte()) != 10) {
|
||||||
public String readRS2String() {
|
b.append((char) temp);
|
||||||
int start = caret;
|
|
||||||
while (pData[caret++] != 0) {
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
return new String(pData, start, caret - start - 1);
|
return b.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readBytes(byte[] buf, int off, int len) {
|
public int readDWord() {
|
||||||
for (int i = 0; i < len; i++) {
|
return ((readUnsignedByte()) << 24) + ((readUnsignedByte()) << 16) + ((readUnsignedByte()) << 8) + (readUnsignedByte());
|
||||||
buf[off + i] = pData[caret++];
|
}
|
||||||
|
|
||||||
|
public long readQWord() {
|
||||||
|
long l = readDWord() & 0xffffffffL;
|
||||||
|
long l1 = readDWord() & 0xffffffffL;
|
||||||
|
return (l << 32) + l1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long readQWord2() {
|
||||||
|
final long l = readDWord() & 0xffffffffL;
|
||||||
|
final long l1 = readDWord() & 0xffffffffL;
|
||||||
|
return (l << 32) + l1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readSignedWordA() {
|
||||||
|
int i = ((readUnsignedByte()) << 8) + (get() - 128 & 0xff);
|
||||||
|
if (i > 32767) {
|
||||||
|
i -= 0x10000;
|
||||||
}
|
}
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public int readUnsignedWordA() {
|
||||||
* Reads a string of the specified length from the payload.
|
return ((readUnsignedByte()) << 8) + (get() - 128 & 0xff);
|
||||||
*
|
|
||||||
* @param length
|
|
||||||
* The length of the string to be read
|
|
||||||
* @return A <code>String</code>
|
|
||||||
*/
|
|
||||||
public String readString(int length) {
|
|
||||||
String rv = new String(pData, caret, length);
|
|
||||||
caret += length;
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public int readUnsignedWord() {
|
||||||
* Skips the specified number of bytes in the payload.
|
return ((readUnsignedByte()) << 8) + (readUnsignedByte());
|
||||||
*
|
|
||||||
* @param x
|
|
||||||
* The number of bytes to be skipped
|
|
||||||
*/
|
|
||||||
public void skip(int x) {
|
|
||||||
caret += x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int remaining() {
|
public int readSignedWord() {
|
||||||
return pData.length - caret;
|
int i = ((readUnsignedByte()) << 8) + (readUnsignedByte());
|
||||||
}
|
if (i > 32767) {
|
||||||
|
i -= 0x10000;
|
||||||
/**
|
|
||||||
* Returns this packet in string form.
|
|
||||||
*
|
|
||||||
* @return A <code>String</code> representing this packet
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("[id=" + pID + ",len=" + pLength + ",data=0x");
|
|
||||||
for (int x = 0; x < pLength; x++) {
|
|
||||||
sb.append(byteToHex(pData[x], true));
|
|
||||||
}
|
}
|
||||||
sb.append("]");
|
return i;
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String byteToHex(byte b, boolean forceLeadingZero) {
|
public int readSignedWordBigEndian() {
|
||||||
StringBuilder out = new StringBuilder();
|
int i = (readUnsignedByte()) + ((readUnsignedByte()) << 8);
|
||||||
int ub = b & 0xff;
|
if (i > 32767) {
|
||||||
if (ub / 16 > 0 || forceLeadingZero) {
|
i -= 0x10000;
|
||||||
out.append(hex[ub / 16]);
|
|
||||||
}
|
}
|
||||||
out.append(hex[ub % 16]);
|
return i;
|
||||||
return out.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final char[] hex = "0123456789ABCDEF".toCharArray();
|
public int readSignedWordBigEndianA() {
|
||||||
|
int i = (get() - 128 & 0xff) + ((readUnsignedByte()) << 8);
|
||||||
public int readShortA() {
|
if (i > 32767) {
|
||||||
caret += 2;
|
i -= 0x10000;
|
||||||
return ((pData[caret - 2] & 0xFF) << 8)
|
}
|
||||||
+ (pData[caret - 1] - 128 & 0xFF);
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte readByteC() {
|
public int readUnsignedWordBigEndian() {
|
||||||
return (byte) -readByte();
|
return (readUnsignedByte()) + ((readUnsignedByte()) << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte readByteS() {
|
public int readUnsignedWordBigEndianA() {
|
||||||
return (byte) (128 - readByte());
|
return (get() - 128 & 0xff) + ((readUnsignedByte()) << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
package com.rs2.net;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a packet buffer.
|
|
||||||
*
|
|
||||||
* @author Ultimate1
|
|
||||||
* @author blakeman8192
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class PacketBuffer {
|
|
||||||
|
|
||||||
private int caret;
|
|
||||||
private byte[] buffer;
|
|
||||||
|
|
||||||
public PacketBuffer(int capcity) {
|
|
||||||
buffer = new byte[capcity];
|
|
||||||
caret = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBuffer(byte[] buffer) {
|
|
||||||
this.buffer = buffer;
|
|
||||||
caret = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketBuffer setOpcode(int opcode) {
|
|
||||||
return addByte(opcode);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketBuffer addByte(int i) {
|
|
||||||
buffer[caret++] = (byte) i;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getByte() {
|
|
||||||
return buffer[caret++] & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketBuffer addBoolean(boolean val) {
|
|
||||||
return addByte(val ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getBoolean() {
|
|
||||||
return getByte() == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketBuffer addShort(int i) {
|
|
||||||
return addByte(i >> 8).addByte(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getShort() {
|
|
||||||
return getByte() << 8 | getByte();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketBuffer addInt(int i) {
|
|
||||||
return addShort(i >> 16).addShort(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getInt() {
|
|
||||||
return getShort() << 16 | getShort();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketBuffer addLong(long i) {
|
|
||||||
return addInt((int) (i >> 32)).addInt((int) i);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getLong() {
|
|
||||||
return (long) getInt() << 32L | getInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
public PacketBuffer addString(String s) {
|
|
||||||
for (byte b : s.getBytes()) {
|
|
||||||
addByte(b);
|
|
||||||
}
|
|
||||||
return addByte('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getString() {
|
|
||||||
int c;
|
|
||||||
StringBuilder builder = new StringBuilder();
|
|
||||||
while ((c = getByte()) != '\n') {
|
|
||||||
builder.append((char) c);
|
|
||||||
}
|
|
||||||
return builder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBuffer() {
|
|
||||||
byte[] newBuffer = new byte[caret + 1];
|
|
||||||
newBuffer[0] = (byte) caret;
|
|
||||||
System.arraycopy(buffer, 0, newBuffer, 1, caret);
|
|
||||||
return newBuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLength() {
|
|
||||||
return buffer.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
caret = 0;
|
|
||||||
for (int i = 0; i < buffer.length; i++) {
|
|
||||||
buffer[i] = 0;
|
|
||||||
}
|
|
||||||
buffer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package com.rs2.net;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet builder interface
|
|
||||||
*
|
|
||||||
* @author Graham
|
|
||||||
*/
|
|
||||||
public interface PacketBuilder {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -336,7 +336,8 @@ public class PacketSender {
|
|||||||
player.getOutStream().writeWordA(id);
|
player.getOutStream().writeWordA(id);
|
||||||
player.getOutStream().endFrameVarSizeWord();
|
player.getOutStream().endFrameVarSizeWord();
|
||||||
player.flushOutStream();
|
player.flushOutStream();
|
||||||
}
|
}//send(new SetWidgetTextMessage(id, s));
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,305 +0,0 @@
|
|||||||
package com.rs2.net;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
|
|
||||||
import org.apache.mina.common.ByteBuffer;
|
|
||||||
import org.apache.mina.common.IoFuture;
|
|
||||||
import org.apache.mina.common.IoFutureListener;
|
|
||||||
import org.apache.mina.common.IoSession;
|
|
||||||
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
|
|
||||||
import org.apache.mina.filter.codec.ProtocolCodecFilter;
|
|
||||||
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
|
|
||||||
|
|
||||||
import com.rs2.Connection;
|
|
||||||
import com.rs2.GameConstants;
|
|
||||||
import com.rs2.GameEngine;
|
|
||||||
import com.rs2.game.players.Client;
|
|
||||||
import com.rs2.game.players.PlayerHandler;
|
|
||||||
import com.rs2.game.players.PlayerSave;
|
|
||||||
import com.rs2.util.HostBlacklist;
|
|
||||||
import com.rs2.util.ISAACRandomGen;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Login protocol decoder.
|
|
||||||
*
|
|
||||||
* @author Graham
|
|
||||||
* @author Ryan / Lmctruck30 <- login Protocol fixes
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class RS2LoginProtocolDecoder extends CumulativeProtocolDecoder {
|
|
||||||
|
|
||||||
private static final BigInteger RSA_MODULUS = new BigInteger("91553247461173033466542043374346300088148707506479543786501537350363031301992107112953015516557748875487935404852620239974482067336878286174236183516364787082711186740254168914127361643305190640280157664988536979163450791820893999053469529344247707567448479470137716627440246788713008490213212272520901741443");
|
|
||||||
private static final BigInteger RSA_EXPONENT = new BigInteger("33280025241734061313051117678670856264399753710527826596057587687835856000539511539311834363046145710983857746766009612538140077973762171163294453513440619295457626227183742315140865830778841533445402605660729039310637444146319289077374748018792349647460850308384280105990607337322160553135806205784213241305");
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses the data in the provided byte buffer and writes it to
|
|
||||||
* <code>out</code> as a <code>Packet</code>.
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* The IoSession the data was read from
|
|
||||||
* @param in
|
|
||||||
* The buffer
|
|
||||||
* @param out
|
|
||||||
* The decoder output stream to which to write the
|
|
||||||
* <code>Packet</code>
|
|
||||||
* @return Whether enough data was available to create a packet
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean doDecode(IoSession session, ByteBuffer in,
|
|
||||||
ProtocolDecoderOutput out) {
|
|
||||||
synchronized (session) {
|
|
||||||
Object loginStageObj = session.getAttribute("LOGIN_STAGE");
|
|
||||||
int loginStage = 0;
|
|
||||||
if (loginStageObj != null) {
|
|
||||||
loginStage = (Integer) loginStageObj;
|
|
||||||
}
|
|
||||||
// Logger.log("recv login packet, stage: "+loginStage);
|
|
||||||
switch (loginStage) {
|
|
||||||
case 0:
|
|
||||||
if (2 <= in.remaining()) {
|
|
||||||
int protocol = in.get() & 0xff;
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
int nameHash = in.get() & 0xff;
|
|
||||||
if (protocol == 14) {
|
|
||||||
long serverSessionKey = ((long) (java.lang.Math
|
|
||||||
.random() * 99999999D) << 32)
|
|
||||||
+ (long) (java.lang.Math.random() * 99999999D);
|
|
||||||
StaticPacketBuilder s1Response = new StaticPacketBuilder();
|
|
||||||
s1Response
|
|
||||||
.setBare(true)
|
|
||||||
.addBytes(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 })
|
|
||||||
.addByte((byte) 0).addLong(serverSessionKey);
|
|
||||||
session.setAttribute("SERVER_SESSION_KEY",
|
|
||||||
serverSessionKey);
|
|
||||||
session.write(s1Response.toPacket());
|
|
||||||
session.setAttribute("LOGIN_STAGE", 1);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
in.rewind();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
int loginType = -1,
|
|
||||||
loginPacketSize = -1,
|
|
||||||
loginEncryptPacketSize = -1;
|
|
||||||
if (2 <= in.remaining()) {
|
|
||||||
loginType = in.get() & 0xff; // should be 16 or 18
|
|
||||||
loginPacketSize = in.get() & 0xff;
|
|
||||||
loginEncryptPacketSize = loginPacketSize - (36 + 1 + 1 + 2);
|
|
||||||
if (loginPacketSize <= 0 || loginEncryptPacketSize <= 0) {
|
|
||||||
System.out.println("Zero or negative login size.");
|
|
||||||
session.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
in.rewind();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (loginPacketSize <= in.remaining()) {
|
|
||||||
int magic = in.get() & 0xff;
|
|
||||||
int version = in.getUnsignedShort();
|
|
||||||
if (magic != 255) {
|
|
||||||
// System.out.println("Wrong magic id.");
|
|
||||||
session.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (version != 1) {
|
|
||||||
// Dont Add Anything
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
int lowMem = in.get() & 0xff;
|
|
||||||
for (int i = 0; i < 9; i++) {
|
|
||||||
in.getInt();
|
|
||||||
}
|
|
||||||
loginEncryptPacketSize--;
|
|
||||||
if(loginEncryptPacketSize != (in.get() & 0xff)) {
|
|
||||||
System.out.println("Encrypted size mismatch.");
|
|
||||||
session.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
byte[] encryptionBytes = new byte[loginEncryptPacketSize];
|
|
||||||
in.get(encryptionBytes);
|
|
||||||
ByteBuffer rsaBuffer = ByteBuffer.wrap(new BigInteger(encryptionBytes).modPow(RSA_EXPONENT, RSA_MODULUS).toByteArray());
|
|
||||||
if((rsaBuffer.get() & 0xff) != 10) {
|
|
||||||
System.out.println("Encrypted id != 10.");
|
|
||||||
session.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
long clientSessionKey = rsaBuffer.getLong();
|
|
||||||
long serverSessionKey = rsaBuffer.getLong();
|
|
||||||
int uid = rsaBuffer.getInt();
|
|
||||||
if(uid != 314268572) {
|
|
||||||
session.close();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
String name = readRS2String(rsaBuffer);
|
|
||||||
String pass = readRS2String(rsaBuffer);
|
|
||||||
int sessionKey[] = new int[4];
|
|
||||||
sessionKey[0] = (int) (clientSessionKey >> 32);
|
|
||||||
sessionKey[1] = (int) clientSessionKey;
|
|
||||||
sessionKey[2] = (int) (serverSessionKey >> 32);
|
|
||||||
sessionKey[3] = (int) serverSessionKey;
|
|
||||||
ISAACRandomGen inC = new ISAACRandomGen(sessionKey);
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
sessionKey[i] += 50;
|
|
||||||
ISAACRandomGen outC = new ISAACRandomGen(sessionKey);
|
|
||||||
load(session, uid, name, pass, inC, outC, version);
|
|
||||||
session.getFilterChain().remove("protocolFilter");
|
|
||||||
session.getFilterChain().addLast("protocolFilter", new ProtocolCodecFilter(new GameCodecFactory(inC)));
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
in.rewind();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private synchronized void load(final IoSession session, final int uid,
|
|
||||||
String name, String pass, final ISAACRandomGen inC,
|
|
||||||
ISAACRandomGen outC, int version) {
|
|
||||||
session.setAttribute("opcode", -1);
|
|
||||||
session.setAttribute("size", -1);
|
|
||||||
int returnCode = 2;
|
|
||||||
|
|
||||||
name = name.trim();
|
|
||||||
name = name.toLowerCase();
|
|
||||||
// pass = pass.toLowerCase();
|
|
||||||
|
|
||||||
String hostName = ((InetSocketAddress) session.getRemoteAddress())
|
|
||||||
.getAddress().getHostName();
|
|
||||||
|
|
||||||
//if (version != 1) {
|
|
||||||
//returnCode = 31;
|
|
||||||
//d}
|
|
||||||
|
|
||||||
if (HostBlacklist.isBlocked(hostName)) {
|
|
||||||
returnCode = 11;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!name.matches("[A-Za-z0-9 ]+")) {
|
|
||||||
returnCode = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.length() > 12) {
|
|
||||||
returnCode = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pass.length() == 0) {
|
|
||||||
returnCode = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
Client cl = new Client(session, -1);
|
|
||||||
cl.playerName = name;
|
|
||||||
cl.playerName2 = cl.playerName;
|
|
||||||
cl.playerPass = pass;
|
|
||||||
|
|
||||||
cl.setInStreamDecryption(inC);
|
|
||||||
cl.setOutStreamDecryption(outC);
|
|
||||||
cl.outStream.packetEncryption = outC;
|
|
||||||
cl.saveCharacter = false;
|
|
||||||
char first = name.charAt(0);
|
|
||||||
cl.properName = Character.toUpperCase(first)
|
|
||||||
+ name.substring(1, name.length());
|
|
||||||
|
|
||||||
if (Connection.isNamedBanned(cl.playerName)) {
|
|
||||||
returnCode = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (PlayerHandler.isPlayerOn(name)) {
|
|
||||||
returnCode = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PlayerHandler.playerCount >= GameConstants.MAX_PLAYERS) {
|
|
||||||
returnCode = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GameEngine.updateServer) {
|
|
||||||
returnCode = 14;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (returnCode == 2) {
|
|
||||||
int load = PlayerSave.loadGame(cl, cl.playerName, cl.playerPass);
|
|
||||||
if (load == 0) {
|
|
||||||
cl.addStarter = true;
|
|
||||||
}
|
|
||||||
if (load == 3) {
|
|
||||||
returnCode = 3;
|
|
||||||
cl.saveFile = false;
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < cl.playerEquipment.length; i++) {
|
|
||||||
if (cl.playerEquipment[i] == 0) {
|
|
||||||
cl.playerEquipment[i] = -1;
|
|
||||||
cl.playerEquipmentN[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!GameEngine.playerHandler.newPlayerClient(cl)) {
|
|
||||||
returnCode = 7;
|
|
||||||
cl.saveFile = false;
|
|
||||||
} else {
|
|
||||||
cl.saveFile = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cl.packetType = -1;
|
|
||||||
cl.packetSize = 0;
|
|
||||||
|
|
||||||
StaticPacketBuilder bldr = new StaticPacketBuilder();
|
|
||||||
bldr.setBare(true);
|
|
||||||
bldr.addByte((byte) returnCode);
|
|
||||||
if (returnCode == 2) {
|
|
||||||
cl.saveCharacter = true;
|
|
||||||
if (cl.playerRights == 3) {
|
|
||||||
bldr.addByte((byte) 2);
|
|
||||||
} else {
|
|
||||||
bldr.addByte((byte) cl.playerRights);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bldr.addByte((byte) 0);
|
|
||||||
}
|
|
||||||
bldr.addByte((byte) 0);
|
|
||||||
cl.isActive = true;
|
|
||||||
Packet pkt = bldr.toPacket();
|
|
||||||
session.setAttachment(cl);
|
|
||||||
session.write(pkt).addListener(new IoFutureListener() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void operationComplete(IoFuture arg0) {
|
|
||||||
session.getFilterChain().remove("protocolFilter");
|
|
||||||
session.getFilterChain().addFirst("protocolFilter",
|
|
||||||
new ProtocolCodecFilter(new GameCodecFactory(inC)));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized String readRS2String(ByteBuffer in) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
byte b;
|
|
||||||
while ((b = in.get()) != 10) {
|
|
||||||
sb.append((char) b);
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Releases the buffer used by the given session.
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* The session for which to release the buffer
|
|
||||||
* @throws Exception
|
|
||||||
* if failed to dispose all resources
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void dispose(IoSession session) throws Exception {
|
|
||||||
super.dispose(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,145 +1,210 @@
|
|||||||
package com.rs2.net;
|
package com.rs2.net;
|
||||||
|
|
||||||
import org.apache.mina.common.ByteBuffer;
|
import io.netty.buffer.ByteBuf;
|
||||||
import org.apache.mina.common.IoSession;
|
import io.netty.buffer.Unpooled;
|
||||||
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
|
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||||
|
|
||||||
import com.rs2.game.players.Client;
|
import java.util.List;
|
||||||
import com.rs2.util.ISAACRandomGen;
|
|
||||||
|
|
||||||
public class RS2ProtocolDecoder extends CumulativeProtocolDecoder {
|
import org.apollo.util.StatefulFrameDecoder;
|
||||||
|
import org.apollo.util.security.IsaacRandom;
|
||||||
|
|
||||||
private final ISAACRandomGen isaac;
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.rs2.net.Packet.Type;
|
||||||
|
|
||||||
|
public class RS2ProtocolDecoder extends StatefulFrameDecoder<GameDecoderState> {
|
||||||
|
|
||||||
|
private int opcode = -1;
|
||||||
|
private int length = -1;
|
||||||
|
private final IsaacRandom random;
|
||||||
|
public static final int PACKET_SIZES[] = { 0, 0, 0, 1, -1, 0, 0, 0, 0, 0, // 0
|
||||||
|
0, 0, 0, 0, 8, 0, 6, 2, 2, 0, // 10
|
||||||
|
0, 2, 0, 6, 0, 12, 0, 0, 0, 0, // 20
|
||||||
|
0, 0, 0, 0, 0, 8, 4, 0, 0, 2, // 30
|
||||||
|
2, 6, 0, 6, 0, -1, 0, 0, 0, 0, // 40
|
||||||
|
0, 0, 0, 12, 0, 0, 0, 8, 8, 12, // 50
|
||||||
|
8, 8, 0, 0, 0, 0, 0, 0, 0, 0, // 60
|
||||||
|
6, 0, 2, 2, 8, 6, 0, -1, 0, 6, // 70
|
||||||
|
0, 0, 0, 0, 0, 1, 4, 6, 0, 0, // 80
|
||||||
|
0, 0, 0, 0, 0, 3, 0, 0, -1, 0, // 90
|
||||||
|
0, 13, 0, -1, 0, 0, 0, 0, 0, 0,// 100
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 6, 0, 0, // 110
|
||||||
|
1, 0, 6, 0, 0, 0, -1, 0, 2, 6, // 120
|
||||||
|
0, 4, 6, 8, 0, 6, 0, 0, 0, 2, // 130
|
||||||
|
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, // 140
|
||||||
|
0, 0, 1, 2, 0, 2, 6, 0, 0, 0, // 150
|
||||||
|
0, 0, 0, 0, -1, -1, 0, 0, 0, 0,// 160
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 170
|
||||||
|
0, 8, 0, 3, 0, 2, 0, 0, 8, 1, // 180
|
||||||
|
0, 0, 12, 0, 0, 0, 0, 0, 0, 0, // 190
|
||||||
|
2, 0, 0, 0, 0, 0, 0, 0, 4, 0, // 200
|
||||||
|
4, 0, 0, 0, 7, 8, 0, 0, 10, 0, // 210
|
||||||
|
0, 0, 0, 0, 0, 0, -1, 0, 6, 0, // 220
|
||||||
|
1, 0, 0, 0, 6, 0, 6, 8, 1, 0, // 230
|
||||||
|
0, 4, 0, 0, 0, 0, -1, 0, -1, 4,// 240
|
||||||
|
0, 0, 6, 6, 0, 0, 0 // 250
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To make sure only the CodecFactory can initialise us.
|
* To make sure only the CodecFactory can initialise us.
|
||||||
*/
|
*/
|
||||||
protected RS2ProtocolDecoder(ISAACRandomGen isaac) {
|
public RS2ProtocolDecoder(IsaacRandom isaac) {
|
||||||
this.isaac = isaac;
|
super(GameDecoderState.GAME_OPCODE);
|
||||||
|
this.random = isaac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Decodes a message.
|
||||||
|
// *
|
||||||
|
// * @param session
|
||||||
|
// * @param in
|
||||||
|
// * @param out
|
||||||
|
// * @return
|
||||||
|
// */
|
||||||
|
// @Override
|
||||||
|
// protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||||
|
// /*
|
||||||
|
// * If the opcode is not present.
|
||||||
|
// */
|
||||||
|
// if (opcode == -1) {
|
||||||
|
// /*
|
||||||
|
// * Check if it can be read.
|
||||||
|
// */
|
||||||
|
// if (in.readableBytes() >= 1) {
|
||||||
|
// /*
|
||||||
|
// * Read and decrypt the opcode.
|
||||||
|
// */
|
||||||
|
// opcode = in.readByte() & 0xFF;
|
||||||
|
// opcode = (opcode - random.nextInt()) & 0xFF;
|
||||||
|
// /*
|
||||||
|
// * Find the packet size.
|
||||||
|
// */
|
||||||
|
// length = PACKET_SIZES[opcode];
|
||||||
|
// } else {
|
||||||
|
// /*
|
||||||
|
// * We need to wait for more data.
|
||||||
|
// */
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /*
|
||||||
|
// * If the packet is variable-length.
|
||||||
|
// */
|
||||||
|
// if (length == -1) {
|
||||||
|
// /*
|
||||||
|
// * Check if the size can be read.
|
||||||
|
// */
|
||||||
|
// if (in.readableBytes() >= 1) {
|
||||||
|
// /*
|
||||||
|
// * Read the packet size and cache it.
|
||||||
|
// */
|
||||||
|
// length = in.readByte() & 0xFF;
|
||||||
|
// } else {
|
||||||
|
// /*
|
||||||
|
// * We need to wait for more data.
|
||||||
|
// */
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /*
|
||||||
|
// * If the packet payload (data) can be read.
|
||||||
|
// */
|
||||||
|
// if (in.readableBytes() >= length) {
|
||||||
|
// /*
|
||||||
|
// * Read it.
|
||||||
|
// */
|
||||||
|
// ByteBuf payload = in.readBytes(length);
|
||||||
|
// /*
|
||||||
|
// * Produce and write the packet object.
|
||||||
|
// */
|
||||||
|
// out.add(new Packet(opcode, Type.FIXED, payload));
|
||||||
|
// opcode = -1;
|
||||||
|
// length = -1;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// /*
|
||||||
|
// * We need to wait for more data.
|
||||||
|
// */
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
/**
|
|
||||||
* Decodes a message.
|
|
||||||
*
|
|
||||||
* @param session
|
|
||||||
* @param in
|
|
||||||
* @param out
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean doDecode(IoSession session, ByteBuffer in,
|
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, GameDecoderState state) {
|
||||||
ProtocolDecoderOutput out) throws Exception {
|
switch (state) {
|
||||||
synchronized (session) {
|
case GAME_OPCODE:
|
||||||
/*
|
decodeOpcode(in, out);
|
||||||
* Fetch the ISAAC cipher for this session.
|
break;
|
||||||
*/
|
case GAME_LENGTH:
|
||||||
// ISAACRandomGen inCipher = ((Player)
|
decodeLength(in);
|
||||||
// session.getAttribute("player")).getInStreamDecryption();
|
break;
|
||||||
|
case GAME_PAYLOAD:
|
||||||
/*
|
decodePayload(in, out);
|
||||||
* Fetch any cached opcodes and sizes, reset to -1 if not present.
|
break;
|
||||||
*/
|
default:
|
||||||
int opcode = (Integer) session.getAttribute("opcode");
|
throw new IllegalStateException("Invalid game decoder state.");
|
||||||
int size = (Integer) session.getAttribute("size");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the opcode is not present.
|
|
||||||
*/
|
|
||||||
if (opcode == -1) {
|
|
||||||
/*
|
|
||||||
* Check if it can be read.
|
|
||||||
*/
|
|
||||||
if (in.remaining() >= 1) {
|
|
||||||
/*
|
|
||||||
* Read and decrypt the opcode.
|
|
||||||
*/
|
|
||||||
opcode = in.get() & 0xFF;
|
|
||||||
opcode = opcode - isaac.getNextKey() & 0xFF;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find the packet size.
|
|
||||||
*/
|
|
||||||
size = Client.PACKET_SIZES[opcode];
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the cached opcode and size.
|
|
||||||
*/
|
|
||||||
session.setAttribute("opcode", opcode);
|
|
||||||
session.setAttribute("size", size);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* We need to wait for more data.
|
|
||||||
*/
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the packet is variable-length.
|
|
||||||
*/
|
|
||||||
if (size == -1) {
|
|
||||||
/*
|
|
||||||
* Check if the size can be read.
|
|
||||||
*/
|
|
||||||
if (in.remaining() >= 1) {
|
|
||||||
/*
|
|
||||||
* Read the packet size and cache it.
|
|
||||||
*/
|
|
||||||
size = in.get() & 0xFF;
|
|
||||||
session.setAttribute("size", size);
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* We need to wait for more data.
|
|
||||||
*/
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If the packet payload (data) can be read.
|
|
||||||
*/
|
|
||||||
if (in.remaining() >= size) {
|
|
||||||
/*
|
|
||||||
* Read it.
|
|
||||||
*/
|
|
||||||
byte[] data = new byte[size];
|
|
||||||
in.get(data);
|
|
||||||
ByteBuffer payload = ByteBuffer.allocate(data.length);
|
|
||||||
payload.put(data);
|
|
||||||
payload.flip();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Produce and write the packet object.
|
|
||||||
*/
|
|
||||||
out.write(new Packet(session, opcode, data));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Reset the cached opcode and sizes.
|
|
||||||
*/
|
|
||||||
session.setAttribute("opcode", -1);
|
|
||||||
session.setAttribute("size", -1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Indicate we are ready to read another packet.
|
|
||||||
*/
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We need to wait for more data.
|
|
||||||
*/
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
/**
|
/**
|
||||||
* Releases resources used by this decoder.
|
* Decodes the length state.
|
||||||
* @param session
|
*
|
||||||
|
* @param buffer The buffer.
|
||||||
*/
|
*/
|
||||||
public void dispose(IoSession session) throws Exception {
|
private void decodeLength(ByteBuf buffer) {
|
||||||
super.dispose(session);
|
if (buffer.isReadable()) {
|
||||||
|
length = buffer.readUnsignedByte();
|
||||||
|
if (length != 0) {
|
||||||
|
setState(GameDecoderState.GAME_PAYLOAD);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the opcode state.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer.
|
||||||
|
* @param out The {@link List} of objects to be passed along the pipeline.
|
||||||
|
*/
|
||||||
|
private void decodeOpcode(ByteBuf buffer, List<Object> out) {
|
||||||
|
if (buffer.isReadable()) {
|
||||||
|
int encryptedOpcode = buffer.readUnsignedByte();
|
||||||
|
opcode = encryptedOpcode - random.nextInt() & 0xFF;
|
||||||
|
|
||||||
|
int s = PACKET_SIZES[opcode];
|
||||||
|
|
||||||
|
switch (s) {
|
||||||
|
default:
|
||||||
|
length = s;
|
||||||
|
if (length == 0) {
|
||||||
|
setState(GameDecoderState.GAME_OPCODE);
|
||||||
|
out.add(new Packet(opcode, Type.FIXED, Unpooled.EMPTY_BUFFER));
|
||||||
|
} else {
|
||||||
|
setState(GameDecoderState.GAME_PAYLOAD);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case -1:
|
||||||
|
setState(GameDecoderState.GAME_LENGTH);
|
||||||
|
break;
|
||||||
|
// default:
|
||||||
|
// throw new IllegalStateException("Illegal packet type: " + type + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the payload state.
|
||||||
|
*
|
||||||
|
* @param buffer The buffer.
|
||||||
|
* @param out The {@link List} of objects to be passed along the pipeline.
|
||||||
|
*/
|
||||||
|
private void decodePayload(ByteBuf buffer, List<Object> out) {
|
||||||
|
if (buffer.readableBytes() >= length) {
|
||||||
|
ByteBuf payload = buffer.readBytes(length);
|
||||||
|
setState(GameDecoderState.GAME_OPCODE);
|
||||||
|
out.add(new Packet(opcode, Type.FIXED, payload));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,82 +1,26 @@
|
|||||||
package com.rs2.net;
|
//package com.rs2.net;
|
||||||
|
//
|
||||||
import org.apache.mina.common.ByteBuffer;
|
//import io.netty.buffer.ByteBuf;
|
||||||
import org.apache.mina.common.IoSession;
|
//import io.netty.channel.ChannelHandlerContext;
|
||||||
import org.apache.mina.filter.codec.ProtocolEncoder;
|
//import io.netty.handler.codec.MessageToByteEncoder;
|
||||||
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
|
//
|
||||||
|
//public class RS2ProtocolEncoder extends MessageToByteEncoder<Packet> {
|
||||||
public class RS2ProtocolEncoder implements ProtocolEncoder {
|
//
|
||||||
|
// /**
|
||||||
/**
|
// * Only CodecFactory can create us.
|
||||||
* Only CodecFactory can create us.
|
// */
|
||||||
*/
|
// public RS2ProtocolEncoder() {
|
||||||
protected RS2ProtocolEncoder() {
|
// }
|
||||||
}
|
//
|
||||||
|
// @Override
|
||||||
@Override
|
// /**
|
||||||
/**
|
// * Encodes a message.
|
||||||
* Encodes a message.
|
// * @param session
|
||||||
* @param session
|
// * @param message
|
||||||
* @param message
|
// * @param out
|
||||||
* @param out
|
// */
|
||||||
*/
|
// protected void encode(ChannelHandlerContext ctx, Packet msg, ByteBuf out) throws Exception {
|
||||||
public void encode(IoSession session, Object message,
|
// out.writeBytes(msg.getPayload());//return ((Packet) object).getPayload(); Do we need to go bldr->packet?
|
||||||
ProtocolEncoderOutput out) throws Exception {
|
// }
|
||||||
try {
|
//
|
||||||
synchronized (session) {
|
//}
|
||||||
Packet p = (Packet) message;
|
|
||||||
byte[] data = p.getData();
|
|
||||||
int dataLength = p.getLength();
|
|
||||||
ByteBuffer buffer;
|
|
||||||
if (!p.isBare()) {
|
|
||||||
buffer = ByteBuffer.allocate(dataLength + 3);
|
|
||||||
int id = p.getId();
|
|
||||||
buffer.put((byte) id);
|
|
||||||
if (p.getSize() != Packet.Size.Fixed) { // variable length
|
|
||||||
// Logger.log("variable length: id="+id+",dataLength="+dataLength);
|
|
||||||
if (p.getSize() == Packet.Size.VariableByte) {
|
|
||||||
if (dataLength > 255) {
|
|
||||||
// then we can represent
|
|
||||||
// with 8 bits!
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Tried to send packet length "
|
|
||||||
+ dataLength
|
|
||||||
+ " in 8 bits [pid="
|
|
||||||
+ p.getId() + "]");
|
|
||||||
}
|
|
||||||
buffer.put((byte) dataLength);
|
|
||||||
} else if (p.getSize() == Packet.Size.VariableShort) {
|
|
||||||
if (dataLength > 65535) {
|
|
||||||
// then we can represent
|
|
||||||
// with 16 bits!
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Tried to send packet length "
|
|
||||||
+ dataLength
|
|
||||||
+ " in 16 bits [pid="
|
|
||||||
+ p.getId() + "]");
|
|
||||||
}
|
|
||||||
buffer.put((byte) (dataLength >> 8));
|
|
||||||
buffer.put((byte) dataLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
buffer = ByteBuffer.allocate(dataLength);
|
|
||||||
}
|
|
||||||
buffer.put(data, 0, dataLength);
|
|
||||||
buffer.flip();
|
|
||||||
out.write(buffer);
|
|
||||||
}
|
|
||||||
} catch (Exception err) {
|
|
||||||
err.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
/**
|
|
||||||
* Releases resources used by this encoder.
|
|
||||||
* @param session
|
|
||||||
*/
|
|
||||||
public void dispose(IoSession session) throws Exception {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,385 +0,0 @@
|
|||||||
package com.rs2.net;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A mutable sequence of bytes used to construct the immutable
|
|
||||||
* <code>Packet</code> objects. By default, methods use big endian byte
|
|
||||||
* ordering.
|
|
||||||
*/
|
|
||||||
public class StaticPacketBuilder implements PacketBuilder {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default capacity
|
|
||||||
*/
|
|
||||||
private static final int DEFAULT_SIZE = 32;
|
|
||||||
/**
|
|
||||||
* The payload buffer
|
|
||||||
*/
|
|
||||||
private byte[] payload;
|
|
||||||
/**
|
|
||||||
* Current number of bytes used in the buffer
|
|
||||||
*/
|
|
||||||
private int curLength;
|
|
||||||
/**
|
|
||||||
* ID of the packet
|
|
||||||
*/
|
|
||||||
private int id;
|
|
||||||
/**
|
|
||||||
* Current index into the buffer by bits
|
|
||||||
*/
|
|
||||||
private int bitPosition = 0;
|
|
||||||
private Packet.Size size = Packet.Size.Fixed;
|
|
||||||
/**
|
|
||||||
* Whether this packet does not use the standard packet header
|
|
||||||
*/
|
|
||||||
private boolean bare = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bitmasks for <code>addBits()</code>
|
|
||||||
*/
|
|
||||||
private static int bitmasks[] = { 0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f,
|
|
||||||
0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff,
|
|
||||||
0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
|
|
||||||
0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff,
|
|
||||||
0x3fffffff, 0x7fffffff, -1 };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a packet builder with no data and an initial capacity of
|
|
||||||
* <code>DEFAULT_SIZE</code>.
|
|
||||||
*
|
|
||||||
* @see DEFAULT_SIZE
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder() {
|
|
||||||
this(DEFAULT_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getPayload() {
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a packet builder with no data and an initial capacity of
|
|
||||||
* <code>capacity</code>.
|
|
||||||
*
|
|
||||||
* @param capacity
|
|
||||||
* The initial capacity of the buffer
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder(int capacity) {
|
|
||||||
payload = new byte[capacity];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures that the buffer is at least <code>minimumBytes</code> bytes.
|
|
||||||
*
|
|
||||||
* @param minimumCapacity
|
|
||||||
* The size needed
|
|
||||||
*/
|
|
||||||
private void ensureCapacity(int minimumCapacity) {
|
|
||||||
if (minimumCapacity >= payload.length) {
|
|
||||||
expandCapacity(minimumCapacity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Expands the buffer to the specified size.
|
|
||||||
*
|
|
||||||
* @param minimumCapacity
|
|
||||||
* The minimum capacity to which to expand
|
|
||||||
* @see java.lang.AbstractStringBuilder#expandCapacity(int)
|
|
||||||
*/
|
|
||||||
private void expandCapacity(int minimumCapacity) {
|
|
||||||
int newCapacity = (payload.length + 1) * 2;
|
|
||||||
if (newCapacity < 0) {
|
|
||||||
newCapacity = Integer.MAX_VALUE;
|
|
||||||
} else if (minimumCapacity > newCapacity) {
|
|
||||||
newCapacity = minimumCapacity;
|
|
||||||
}
|
|
||||||
byte[] newPayload = new byte[newCapacity];
|
|
||||||
try {
|
|
||||||
while (curLength > payload.length) {
|
|
||||||
curLength--;
|
|
||||||
}
|
|
||||||
System.arraycopy(payload, 0, newPayload, 0, curLength);
|
|
||||||
} catch (Exception e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
payload = newPayload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets this packet as bare. A bare packet will contain only the payload
|
|
||||||
* data, rather than having the standard packet header prepended.
|
|
||||||
*
|
|
||||||
* @param bare
|
|
||||||
* Whether this packet is to be sent bare
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder setBare(boolean bare) {
|
|
||||||
this.bare = bare;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the ID for this packet.
|
|
||||||
*
|
|
||||||
* @param id
|
|
||||||
* The ID of the packet
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder setSize(Packet.Size s) {
|
|
||||||
size = s;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder initBitAccess() {
|
|
||||||
bitPosition = curLength * 8;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder finishBitAccess() {
|
|
||||||
curLength = (bitPosition + 7) / 8;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO needs a proper description.
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder addBits(int numBits, int value) {
|
|
||||||
int bytePos = bitPosition >> 3;
|
|
||||||
int bitOffset = 8 - (bitPosition & 7);
|
|
||||||
bitPosition += numBits;
|
|
||||||
curLength = (bitPosition + 7) / 8;
|
|
||||||
ensureCapacity(curLength);
|
|
||||||
for (; numBits > bitOffset; bitOffset = 8) {
|
|
||||||
payload[bytePos] &= ~bitmasks[bitOffset]; // mask out the desired
|
|
||||||
// area
|
|
||||||
payload[bytePos++] |= value >> numBits - bitOffset
|
|
||||||
& bitmasks[bitOffset];
|
|
||||||
|
|
||||||
numBits -= bitOffset;
|
|
||||||
}
|
|
||||||
if (numBits == bitOffset) {
|
|
||||||
payload[bytePos] &= ~bitmasks[bitOffset];
|
|
||||||
payload[bytePos] |= value & bitmasks[bitOffset];
|
|
||||||
} else {
|
|
||||||
payload[bytePos] &= ~(bitmasks[numBits] << bitOffset - numBits);
|
|
||||||
payload[bytePos] |= (value & bitmasks[numBits]) << bitOffset
|
|
||||||
- numBits;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the contents of <code>byte</code> array <code>data</code> to the
|
|
||||||
* packet. The size of this packet will grow by the length of the provided
|
|
||||||
* array.
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* The bytes to add to this packet
|
|
||||||
* @return A reference to this object
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder addBytes(byte[] data) {
|
|
||||||
return addBytes(data, 0, data.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds the contents of <code>byte</code> array <code>data</code>, starting
|
|
||||||
* at index <code>offset</code>. The size of this packet will grow by
|
|
||||||
* <code>len</code> bytes.
|
|
||||||
*
|
|
||||||
* @param data
|
|
||||||
* The bytes to add to this packet
|
|
||||||
* @param offset
|
|
||||||
* The index of the first byte to append
|
|
||||||
* @param len
|
|
||||||
* The number of bytes to append
|
|
||||||
* @return A reference to this object
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder addBytes(byte[] data, int offset, int len) {
|
|
||||||
int newLength = curLength + len;
|
|
||||||
ensureCapacity(newLength);
|
|
||||||
System.arraycopy(data, offset, payload, curLength, len);
|
|
||||||
curLength = newLength;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder addLEShortA(int i) {
|
|
||||||
ensureCapacity(curLength + 2);
|
|
||||||
addByte((byte) (i + 128), false);
|
|
||||||
addByte((byte) (i >> 8), false);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder addShortA(int i) {
|
|
||||||
ensureCapacity(curLength + 2);
|
|
||||||
addByte((byte) (i >> 8), false);
|
|
||||||
addByte((byte) (i + 128), false);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a <code>byte</code> to the data buffer. The size of this packet will
|
|
||||||
* grow by one byte.
|
|
||||||
*
|
|
||||||
* @param val
|
|
||||||
* The <code>byte</code> value to add
|
|
||||||
* @return A reference to this object
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder addByte(byte val) {
|
|
||||||
return addByte(val, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder addByteA(int i) {
|
|
||||||
return addByte((byte) (i + 128), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a <code>byte</code> to the data buffer. The size of this packet will
|
|
||||||
* grow by one byte.
|
|
||||||
*
|
|
||||||
* @param val
|
|
||||||
* The <code>byte</code> value to add
|
|
||||||
* @param checkCapacity
|
|
||||||
* Whether the buffer capacity should be checked
|
|
||||||
* @return A reference to this object
|
|
||||||
*/
|
|
||||||
private StaticPacketBuilder addByte(byte val, boolean checkCapacity) {
|
|
||||||
if (checkCapacity) {
|
|
||||||
ensureCapacity(curLength + 1);
|
|
||||||
}
|
|
||||||
payload[curLength++] = val;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a <code>short</code> to the data stream. The size of this packet
|
|
||||||
* will grow by two bytes.
|
|
||||||
*
|
|
||||||
* @param val
|
|
||||||
* The <code>short</code> value to add
|
|
||||||
* @return A reference to this object
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder addShort(int val) {
|
|
||||||
ensureCapacity(curLength + 2);
|
|
||||||
addByte((byte) (val >> 8), false);
|
|
||||||
addByte((byte) val, false);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder addLEShort(int val) {
|
|
||||||
ensureCapacity(curLength + 2);
|
|
||||||
addByte((byte) val, false);
|
|
||||||
addByte((byte) (val >> 8), false);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder setShort(int val, int offset) {
|
|
||||||
payload[offset++] = (byte) (val >> 8);
|
|
||||||
payload[offset++] = (byte) val;
|
|
||||||
if (curLength < offset + 2) {
|
|
||||||
curLength += 2;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a <code>int</code> to the data stream. The size of this packet will
|
|
||||||
* grow by four bytes.
|
|
||||||
*
|
|
||||||
* @param val
|
|
||||||
* The <code>int</code> value to add
|
|
||||||
* @return A reference to this object
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder addInt(int val) {
|
|
||||||
ensureCapacity(curLength + 4);
|
|
||||||
addByte((byte) (val >> 24), false);
|
|
||||||
addByte((byte) (val >> 16), false);
|
|
||||||
addByte((byte) (val >> 8), false);
|
|
||||||
addByte((byte) val, false);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder addInt1(int val) {
|
|
||||||
ensureCapacity(curLength + 4);
|
|
||||||
addByte((byte) (val >> 8), false);
|
|
||||||
addByte((byte) val, false);
|
|
||||||
addByte((byte) (val >> 24), false);
|
|
||||||
addByte((byte) (val >> 16), false);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder addInt2(int val) {
|
|
||||||
ensureCapacity(curLength + 4);
|
|
||||||
addByte((byte) (val >> 16), false);
|
|
||||||
addByte((byte) (val >> 24), false);
|
|
||||||
addByte((byte) val, false);
|
|
||||||
addByte((byte) (val >> 8), false);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder addLEInt(int val) {
|
|
||||||
ensureCapacity(curLength + 4);
|
|
||||||
addByte((byte) val, false);
|
|
||||||
addByte((byte) (val >> 8), false);
|
|
||||||
addByte((byte) (val >> 16), false);
|
|
||||||
addByte((byte) (val >> 24), false);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a <code>long</code> to the data stream. The size of this packet will
|
|
||||||
* grow by eight bytes.
|
|
||||||
*
|
|
||||||
* @param val
|
|
||||||
* The <code>long</code> value to add
|
|
||||||
* @return A reference to this object
|
|
||||||
*/
|
|
||||||
public StaticPacketBuilder addLong(long val) {
|
|
||||||
addInt((int) (val >> 32));
|
|
||||||
addInt((int) (val & -1L));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder addLELong(long val) {
|
|
||||||
addLEInt((int) (val & -1L));
|
|
||||||
addLEInt((int) (val >> 32));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public StaticPacketBuilder addString(String s) {
|
|
||||||
ensureCapacity(curLength + s.length() + 1);
|
|
||||||
s.getBytes(0, s.length(), payload, curLength);
|
|
||||||
curLength += s.length();
|
|
||||||
payload[curLength++] = 0;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLength() {
|
|
||||||
return curLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a <code>Packet</code> object for the data contained in this
|
|
||||||
* builder.
|
|
||||||
*
|
|
||||||
* @return A <code>Packet</code> object
|
|
||||||
*/
|
|
||||||
public Packet toPacket() {
|
|
||||||
byte[] data = new byte[curLength];
|
|
||||||
System.arraycopy(payload, 0, data, 0, curLength);
|
|
||||||
return new Packet(null, id, data, bare, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder addByteC(int val) {
|
|
||||||
addByte((byte) -val);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public StaticPacketBuilder addByteS(int val) {
|
|
||||||
addByte((byte) (128 - val));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,7 @@ package com.rs2.net.packets;
|
|||||||
import com.rs2.GameConstants;
|
import com.rs2.GameConstants;
|
||||||
import com.rs2.game.dialogues.Dialogue;
|
import com.rs2.game.dialogues.Dialogue;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.impl.AttackPlayer;
|
import com.rs2.net.packets.impl.AttackPlayer;
|
||||||
import com.rs2.net.packets.impl.Bank10;
|
import com.rs2.net.packets.impl.Bank10;
|
||||||
import com.rs2.net.packets.impl.Bank5;
|
import com.rs2.net.packets.impl.Bank5;
|
||||||
@@ -156,14 +157,16 @@ public class PacketHandler {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
public static void processPacket(Player player, int packetType, int packetSize) {
|
public static void processPacket(Player player, Packet packet) {
|
||||||
|
int packetType = packet.getOpcode();
|
||||||
|
int packetSize = packet.getLength();
|
||||||
PacketType p = packetId[packetType];
|
PacketType p = packetId[packetType];
|
||||||
if(p != null && packetType > 0 && packetType < 257 && packetType == player.packetType && packetSize == player.packetSize) {
|
if(p != null && packetType > 0 && packetType < 257) {
|
||||||
if (GameConstants.sendServerPackets && player.playerRights == 3) {
|
if (GameConstants.sendServerPackets && player.playerRights == 3) {
|
||||||
player.getPacketSender().sendMessage("PacketType: " + packetType + ". PacketSize: " + packetSize + ".");
|
player.getPacketSender().sendMessage("PacketType: " + packetType + ". PacketSize: " + packetSize + ".");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
p.processPacket(player, packetType, packetSize);
|
p.processPacket(player, packet);
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package com.rs2.net.packets;
|
package com.rs2.net.packets;
|
||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
|
|
||||||
public interface PacketType {
|
public interface PacketType {
|
||||||
|
|
||||||
public void processPacket(Player player, int packetType, int packetSize);
|
public void processPacket(Player player, Packet packet);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.rs2.game.content.combat.range.RangeData;
|
|||||||
import com.rs2.game.items.ItemAssistant;
|
import com.rs2.game.items.ItemAssistant;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
import com.rs2.game.players.PlayerHandler;
|
import com.rs2.game.players.PlayerHandler;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
public class AttackPlayer implements PacketType {
|
public class AttackPlayer implements PacketType {
|
||||||
@@ -15,23 +16,23 @@ public class AttackPlayer implements PacketType {
|
|||||||
public static final int ATTACK_PLAYER = 73, MAGE_PLAYER = 249;
|
public static final int ATTACK_PLAYER = 73, MAGE_PLAYER = 249;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
player.playerIndex = 0;
|
player.playerIndex = 0;
|
||||||
player.npcIndex = 0;
|
player.npcIndex = 0;
|
||||||
switch (packetType) {
|
switch (packet.getOpcode()) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attack player
|
* Attack player
|
||||||
**/
|
**/
|
||||||
case ATTACK_PLAYER:
|
case ATTACK_PLAYER:
|
||||||
player.playerIndex = player.getInStream().readSignedWordBigEndian();
|
player.playerIndex = packet.readSignedWordBigEndian();
|
||||||
if (PlayerHandler.players[player.playerIndex] == null) {
|
if (PlayerHandler.players[player.playerIndex] == null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.inDuelArena() && !player.duelingArena()) {
|
if (player.inDuelArena() && !player.duelingArena()) {
|
||||||
player.getChallengePlayer().processPacket(player, packetType, packetSize);
|
player.getChallengePlayer().processPacket(player, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.respawnTimer > 0) {
|
if (player.respawnTimer > 0) {
|
||||||
@@ -149,8 +150,8 @@ public class AttackPlayer implements PacketType {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.playerIndex = player.getInStream().readSignedWordA();
|
player.playerIndex = packet.readSignedWordA();
|
||||||
int castingSpellId = player.getInStream().readSignedWordBigEndian();
|
int castingSpellId = packet.readSignedWordBigEndian();
|
||||||
player.castingSpellId = castingSpellId;
|
player.castingSpellId = castingSpellId;
|
||||||
player.usingMagic = false;
|
player.usingMagic = false;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.rs2.GameConstants;
|
|||||||
import com.rs2.game.content.random.PartyRoom;
|
import com.rs2.game.content.random.PartyRoom;
|
||||||
import com.rs2.game.content.skills.crafting.JewelryMaking;
|
import com.rs2.game.content.skills.crafting.JewelryMaking;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.world.Boundary;
|
import com.rs2.world.Boundary;
|
||||||
|
|
||||||
@@ -13,10 +14,10 @@ import com.rs2.world.Boundary;
|
|||||||
public class Bank10 implements PacketType {
|
public class Bank10 implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int interfaceId = player.getInStream().readUnsignedWordBigEndian();
|
int interfaceId = packet.readUnsignedWordBigEndian();
|
||||||
int removeId = player.getInStream().readUnsignedWordA();
|
int removeId = packet.readUnsignedWordA();
|
||||||
int removeSlot = player.getInStream().readUnsignedWordA();
|
int removeSlot = packet.readUnsignedWordA();
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
switch (interfaceId) {
|
switch (interfaceId) {
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.rs2.GameConstants;
|
|||||||
import com.rs2.game.content.random.PartyRoom;
|
import com.rs2.game.content.random.PartyRoom;
|
||||||
import com.rs2.game.content.skills.crafting.JewelryMaking;
|
import com.rs2.game.content.skills.crafting.JewelryMaking;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.world.Boundary;
|
import com.rs2.world.Boundary;
|
||||||
|
|
||||||
@@ -13,10 +14,10 @@ import com.rs2.world.Boundary;
|
|||||||
public class Bank5 implements PacketType {
|
public class Bank5 implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int interfaceId = player.getInStream().readSignedWordBigEndianA();
|
int interfaceId = packet.readSignedWordBigEndianA();
|
||||||
int removeId = player.getInStream().readSignedWordBigEndianA();
|
int removeId = packet.readSignedWordBigEndianA();
|
||||||
int removeSlot = player.getInStream().readSignedWordBigEndian();
|
int removeSlot = packet.readSignedWordBigEndian();
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
switch (interfaceId) {
|
switch (interfaceId) {
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.rs2.game.content.random.PartyRoom;
|
|||||||
import com.rs2.game.items.GameItem;
|
import com.rs2.game.items.GameItem;
|
||||||
import com.rs2.game.items.ItemData;
|
import com.rs2.game.items.ItemData;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.world.Boundary;
|
import com.rs2.world.Boundary;
|
||||||
|
|
||||||
@@ -13,10 +14,10 @@ import com.rs2.world.Boundary;
|
|||||||
public class BankAll implements PacketType {
|
public class BankAll implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int removeSlot = player.getInStream().readUnsignedWordA();
|
int removeSlot = packet.readUnsignedWordA();
|
||||||
int interfaceId = player.getInStream().readUnsignedWord();
|
int interfaceId = packet.readUnsignedWord();
|
||||||
int removeId = player.getInStream().readUnsignedWordA();
|
int removeId = packet.readUnsignedWordA();
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
switch (interfaceId) {
|
switch (interfaceId) {
|
||||||
case 2274:
|
case 2274:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.rs2.net.packets.impl;
|
package com.rs2.net.packets.impl;
|
||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -13,19 +14,19 @@ public class BankX1 implements PacketType {
|
|||||||
public int XremoveSlot, XinterfaceID, XremoveID, Xamount;
|
public int XremoveSlot, XinterfaceID, XremoveID, Xamount;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
if (packetType == 135) {
|
if (packet.getOpcode() == 135) {
|
||||||
player.xRemoveSlot = player.getInStream().readSignedWordBigEndian();
|
player.xRemoveSlot = packet.readSignedWordBigEndian();
|
||||||
player.xInterfaceId = player.getInStream().readUnsignedWordA();
|
player.xInterfaceId = packet.readUnsignedWordA();
|
||||||
player.xRemoveId = player.getInStream().readSignedWordBigEndian();
|
player.xRemoveId = packet.readSignedWordBigEndian();
|
||||||
} else {
|
} else {
|
||||||
if (player.xInterfaceId == 7423) {
|
if (player.xInterfaceId == 7423) {
|
||||||
player.getItemAssistant().bankItem(player.xRemoveId, player.xRemoveSlot, Xamount);// Depo 1
|
player.getItemAssistant().bankItem(player.xRemoveId, player.xRemoveSlot, Xamount);// Depo 1
|
||||||
player.getItemAssistant().resetItems(7423);
|
player.getItemAssistant().resetItems(7423);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (packetType == PART1) {
|
if (packet.getOpcode() == PART1) {
|
||||||
synchronized (player) {
|
synchronized (player) {
|
||||||
player.getOutStream().createFrame(27);
|
player.getOutStream().createFrame(27);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.rs2.net.packets.impl;
|
|||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
import com.rs2.game.players.PlayerHandler;
|
import com.rs2.game.players.PlayerHandler;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,10 +11,10 @@ import com.rs2.net.packets.PacketType;
|
|||||||
public class ChallengePlayer implements PacketType {
|
public class ChallengePlayer implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
switch (packetType) {
|
switch (packet.getOpcode()) {
|
||||||
case 128:
|
case 128:
|
||||||
int answerPlayer = player.getInStream().readUnsignedWord();
|
int answerPlayer = packet.readUnsignedWord();
|
||||||
if(PlayerHandler.players[answerPlayer] == null || answerPlayer == player.playerId)
|
if(PlayerHandler.players[answerPlayer] == null || answerPlayer == player.playerId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.rs2.net.packets.impl;
|
package com.rs2.net.packets.impl;
|
||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,8 +36,8 @@ public class ChangeAppearance implements PacketType {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(final Player player, final int packetType, final int packetSize) {
|
public void processPacket(final Player player, Packet packet) {
|
||||||
final int gender = player.getInStream().readSignedByte();
|
final int gender = packet.readSignedByte();
|
||||||
|
|
||||||
if (gender != 0 && gender != 1) {
|
if (gender != 0 && gender != 1) {
|
||||||
return;
|
return;
|
||||||
@@ -44,7 +45,7 @@ public class ChangeAppearance implements PacketType {
|
|||||||
|
|
||||||
final int[] apperances = new int[MALE_VALUES.length]; // appearance values check
|
final int[] apperances = new int[MALE_VALUES.length]; // appearance values check
|
||||||
for (int i = 0; i < apperances.length; i++) {
|
for (int i = 0; i < apperances.length; i++) {
|
||||||
int value = player.getInStream().readSignedByte();
|
int value = packet.readSignedByte();
|
||||||
if (value < (gender == 0 ? MALE_VALUES[i][0] : FEMALE_VALUES[i][0])
|
if (value < (gender == 0 ? MALE_VALUES[i][0] : FEMALE_VALUES[i][0])
|
||||||
|| value > (gender == 0 ? MALE_VALUES[i][1]
|
|| value > (gender == 0 ? MALE_VALUES[i][1]
|
||||||
: FEMALE_VALUES[i][1])) {
|
: FEMALE_VALUES[i][1])) {
|
||||||
@@ -55,7 +56,7 @@ public class ChangeAppearance implements PacketType {
|
|||||||
|
|
||||||
final int[] colors = new int[ALLOWED_COLORS.length]; // color value check
|
final int[] colors = new int[ALLOWED_COLORS.length]; // color value check
|
||||||
for (int i = 0; i < colors.length; i++) {
|
for (int i = 0; i < colors.length; i++) {
|
||||||
int value = player.getInStream().readSignedByte();
|
int value = packet.readSignedByte();
|
||||||
if (value < ALLOWED_COLORS[i][0] || value > ALLOWED_COLORS[i][1]) {
|
if (value < ALLOWED_COLORS[i][0] || value > ALLOWED_COLORS[i][1]) {
|
||||||
value = ALLOWED_COLORS[i][0];
|
value = ALLOWED_COLORS[i][0];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.rs2.GameEngine;
|
|||||||
import com.rs2.game.content.music.Music;
|
import com.rs2.game.content.music.Music;
|
||||||
import com.rs2.game.globalworldobjects.Doors;
|
import com.rs2.game.globalworldobjects.Doors;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.world.GlobalDropsHandler;
|
import com.rs2.world.GlobalDropsHandler;
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ import com.rs2.world.GlobalDropsHandler;
|
|||||||
public class ChangeRegions implements PacketType {
|
public class ChangeRegions implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
if (GameConstants.SOUND && player.musicOn) {
|
if (GameConstants.SOUND && player.musicOn) {
|
||||||
Music.playMusic(player);
|
Music.playMusic(player);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.rs2.net.packets.impl;
|
|||||||
import com.rs2.Connection;
|
import com.rs2.Connection;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
import com.rs2.game.players.antimacro.AntiSpam;
|
import com.rs2.game.players.antimacro.AntiSpam;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
|
|
||||||
@@ -12,13 +13,13 @@ import com.rs2.util.Misc;
|
|||||||
public class Chat implements PacketType {
|
public class Chat implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
player.setChatTextEffects(player.getInStream().readUnsignedByteS());
|
player.setChatTextEffects(packet.readUnsignedByteS());
|
||||||
player.setChatTextColor(player.getInStream().readUnsignedByteS());
|
player.setChatTextColor(packet.readUnsignedByteS());
|
||||||
player.setChatTextSize((byte) (player.packetSize - 2));
|
player.setChatTextSize((byte) (packet.getLength() - 2));
|
||||||
player.inStream.readBytes_reverseA(player.getChatText(), player.getChatTextSize(), 0);
|
packet.readBytes_reverseA(player.getChatText(), player.getChatTextSize(), 0);
|
||||||
ReportHandler.addText(player.playerName, player.getChatText(), packetSize - 2);
|
ReportHandler.addText(player.playerName, player.getChatText(), packet.getLength() - 2);
|
||||||
String word = Misc.textUnpack(player.getChatText(), player.packetSize - 2).toLowerCase();
|
String word = Misc.textUnpack(player.getChatText(), packet.getLength() - 2).toLowerCase();
|
||||||
if (AntiSpam.blockedWords(player, word, true) && !Connection.isMuted(player)) {
|
if (AntiSpam.blockedWords(player, word, true) && !Connection.isMuted(player)) {
|
||||||
player.setChatTextUpdateRequired(true);
|
player.setChatTextUpdateRequired(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import com.rs2.game.items.impl.ExperienceLamp;
|
|||||||
import com.rs2.game.items.impl.Flowers;
|
import com.rs2.game.items.impl.Flowers;
|
||||||
import com.rs2.game.items.impl.GodBooks;
|
import com.rs2.game.items.impl.GodBooks;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.GameLogger;
|
import com.rs2.util.GameLogger;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
@@ -27,11 +28,11 @@ import com.rs2.util.Misc;
|
|||||||
public class ClickItem implements PacketType {
|
public class ClickItem implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
player.getInStream().readSignedWordBigEndianA();
|
packet.readSignedWordBigEndianA();
|
||||||
int itemSlot = player.getInStream().readUnsignedWordA();
|
int itemSlot = packet.readUnsignedWordA();
|
||||||
int itemId = player.getInStream().readUnsignedWordBigEndian();
|
int itemId = packet.readUnsignedWordBigEndian();
|
||||||
if (itemId != player.playerItems[itemSlot] - 1) {
|
if (itemId != player.playerItems[itemSlot] - 1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import com.rs2.game.content.combat.range.RangeData;
|
|||||||
import com.rs2.game.items.ItemAssistant;
|
import com.rs2.game.items.ItemAssistant;
|
||||||
import com.rs2.game.npcs.NpcHandler;
|
import com.rs2.game.npcs.NpcHandler;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,7 +24,7 @@ public class ClickNPC implements PacketType {
|
|||||||
SECOND_CLICK = 17, THIRD_CLICK = 21;
|
SECOND_CLICK = 17, THIRD_CLICK = 21;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(final Player player, int packetType, int packetSize) {
|
public void processPacket(final Player player, Packet packet) {
|
||||||
player.npcIndex = 0;
|
player.npcIndex = 0;
|
||||||
player.npcClickIndex = 0;
|
player.npcClickIndex = 0;
|
||||||
player.playerIndex = 0;
|
player.playerIndex = 0;
|
||||||
@@ -32,7 +33,7 @@ public class ClickNPC implements PacketType {
|
|||||||
player.getCombatAssistant().resetPlayerAttack();
|
player.getCombatAssistant().resetPlayerAttack();
|
||||||
player.getPlayerAssistant().requestUpdates();
|
player.getPlayerAssistant().requestUpdates();
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
switch (packetType) {
|
switch (packet.getOpcode()) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attack npc melee or range
|
* Attack npc melee or range
|
||||||
@@ -61,7 +62,7 @@ public class ClickNPC implements PacketType {
|
|||||||
player.getPacketSender().sendMessage("I can't reach that.");
|
player.getPacketSender().sendMessage("I can't reach that.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
player.npcIndex = player.getInStream().readUnsignedWordA();
|
player.npcIndex = packet.readUnsignedWordA();
|
||||||
if (NpcHandler.npcs[player.npcIndex] == null) {
|
if (NpcHandler.npcs[player.npcIndex] == null) {
|
||||||
player.npcIndex = 0;
|
player.npcIndex = 0;
|
||||||
break;
|
break;
|
||||||
@@ -188,8 +189,8 @@ public class ClickNPC implements PacketType {
|
|||||||
// c.usingSpecial = false;
|
// c.usingSpecial = false;
|
||||||
// c.getItems().updateSpecialBar();
|
// c.getItems().updateSpecialBar();
|
||||||
|
|
||||||
player.npcIndex = player.getInStream().readSignedWordBigEndianA();
|
player.npcIndex = packet.readSignedWordBigEndianA();
|
||||||
int castingSpellId = player.getInStream().readSignedWordA();
|
int castingSpellId = packet.readSignedWordA();
|
||||||
player.usingMagic = false;
|
player.usingMagic = false;
|
||||||
|
|
||||||
if (NpcHandler.npcs[player.npcIndex] == null) {
|
if (NpcHandler.npcs[player.npcIndex] == null) {
|
||||||
@@ -230,7 +231,7 @@ public class ClickNPC implements PacketType {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case FIRST_CLICK:
|
case FIRST_CLICK:
|
||||||
player.npcClickIndex = player.inStream.readSignedWordBigEndian();
|
player.npcClickIndex = packet.readSignedWordBigEndian();
|
||||||
player.npcType = NpcHandler.npcs[player.npcClickIndex].npcType;
|
player.npcType = NpcHandler.npcs[player.npcClickIndex].npcType;
|
||||||
|
|
||||||
if (player.goodDistance(NpcHandler.npcs[player.npcClickIndex].getX(),
|
if (player.goodDistance(NpcHandler.npcs[player.npcClickIndex].getX(),
|
||||||
@@ -274,7 +275,7 @@ public class ClickNPC implements PacketType {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SECOND_CLICK:
|
case SECOND_CLICK:
|
||||||
player.npcClickIndex = player.inStream.readUnsignedWordBigEndianA();
|
player.npcClickIndex = packet.readUnsignedWordBigEndianA();
|
||||||
player.npcType = NpcHandler.npcs[player.npcClickIndex].npcType;
|
player.npcType = NpcHandler.npcs[player.npcClickIndex].npcType;
|
||||||
if (player.goodDistance(NpcHandler.npcs[player.npcClickIndex].getX(),
|
if (player.goodDistance(NpcHandler.npcs[player.npcClickIndex].getX(),
|
||||||
NpcHandler.npcs[player.npcClickIndex].getY(), player.getX(),
|
NpcHandler.npcs[player.npcClickIndex].getY(), player.getX(),
|
||||||
@@ -318,7 +319,7 @@ public class ClickNPC implements PacketType {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case THIRD_CLICK:
|
case THIRD_CLICK:
|
||||||
player.npcClickIndex = player.inStream.readSignedWord();
|
player.npcClickIndex = packet.readSignedWord();
|
||||||
player.npcType = NpcHandler.npcs[player.npcClickIndex].npcType;
|
player.npcType = NpcHandler.npcs[player.npcClickIndex].npcType;
|
||||||
if (player.goodDistance(NpcHandler.npcs[player.npcClickIndex].getX(),
|
if (player.goodDistance(NpcHandler.npcs[player.npcClickIndex].getX(),
|
||||||
NpcHandler.npcs[player.npcClickIndex].getY(), player.getX(),
|
NpcHandler.npcs[player.npcClickIndex].getY(), player.getX(),
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import com.rs2.game.globalworldobjects.Doors;
|
|||||||
import com.rs2.game.npcs.NpcHandler;
|
import com.rs2.game.npcs.NpcHandler;
|
||||||
import com.rs2.game.objects.Objects;
|
import com.rs2.game.objects.Objects;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.world.clip.Region;
|
import com.rs2.world.clip.Region;
|
||||||
|
|
||||||
@@ -78,40 +79,40 @@ public class ClickObject implements PacketType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(final Player player, int packetType, int packetSize) {
|
public void processPacket(final Player player, Packet packet) {
|
||||||
player.clickObjectType = player.objectX = player.objectId = player.objectY = 0;
|
player.clickObjectType = player.objectX = player.objectId = player.objectY = 0;
|
||||||
player.getPlayerAssistant().resetFollow();
|
player.getPlayerAssistant().resetFollow();
|
||||||
player.getCombatAssistant().resetPlayerAttack();
|
player.getCombatAssistant().resetPlayerAttack();
|
||||||
player.getPlayerAssistant().requestUpdates();
|
player.getPlayerAssistant().requestUpdates();
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
switch (packetType) {
|
switch (packet.getOpcode()) {
|
||||||
|
|
||||||
case FIRST_CLICK:
|
case FIRST_CLICK:
|
||||||
player.objectX = player.getInStream().readSignedWordBigEndianA();
|
player.objectX = packet.readSignedWordBigEndianA();
|
||||||
player.objectId = player.getInStream().readUnsignedWord();
|
player.objectId = packet.readUnsignedWord();
|
||||||
player.objectY = player.getInStream().readUnsignedWordA();
|
player.objectY = packet.readUnsignedWordA();
|
||||||
onObjectReached(player, (p) -> completeObjectClick(p, 1));
|
onObjectReached(player, (p) -> completeObjectClick(p, 1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SECOND_CLICK:
|
case SECOND_CLICK:
|
||||||
player.objectId = player.getInStream().readUnsignedWordBigEndianA();
|
player.objectId = packet.readUnsignedWordBigEndianA();
|
||||||
player.objectY = player.getInStream().readSignedWordBigEndian();
|
player.objectY = packet.readSignedWordBigEndian();
|
||||||
player.objectX = player.getInStream().readUnsignedWordA();
|
player.objectX = packet.readUnsignedWordA();
|
||||||
onObjectReached(player, (p) -> completeObjectClick(p, 2));
|
onObjectReached(player, (p) -> completeObjectClick(p, 2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case THIRD_CLICK: // 'F'
|
case THIRD_CLICK: // 'F'
|
||||||
player.objectX = player.getInStream().readSignedWordBigEndian();
|
player.objectX = packet.readSignedWordBigEndian();
|
||||||
player.objectY = player.getInStream().readUnsignedWord();
|
player.objectY = packet.readUnsignedWord();
|
||||||
player.objectId = player.getInStream().readUnsignedWordBigEndianA();
|
player.objectId = packet.readUnsignedWordBigEndianA();
|
||||||
onObjectReached(player, (p) -> completeObjectClick(p, 3));
|
onObjectReached(player, (p) -> completeObjectClick(p, 3));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case FOURTH_CLICK:
|
case FOURTH_CLICK:
|
||||||
player.objectX = player.getInStream().readSignedWordBigEndianA();
|
player.objectX = packet.readSignedWordBigEndianA();
|
||||||
player.objectId = player.getInStream().readUnsignedWordA();
|
player.objectId = packet.readUnsignedWordA();
|
||||||
player.objectY = player.getInStream().readUnsignedWordBigEndianA();
|
player.objectY = packet.readUnsignedWordBigEndianA();
|
||||||
onObjectReached(player, (p) -> completeObjectClick(p, 4));
|
onObjectReached(player, (p) -> completeObjectClick(p, 4));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ package com.rs2.net.packets.impl;
|
|||||||
|
|
||||||
import com.rs2.game.items.ItemAssistant;
|
import com.rs2.game.items.ItemAssistant;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
public class ClickTab implements PacketType {
|
public class ClickTab implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(final Player player, int packetType, int packetSize) {
|
public void processPacket(final Player player, Packet packet) {
|
||||||
switch (packetSize) {
|
switch (packet.getLength()) {
|
||||||
case 1:// first part.
|
case 1:// first part.
|
||||||
if (player.tutorialProgress == 0) { // wrench
|
if (player.tutorialProgress == 0) { // wrench
|
||||||
player.getPacketSender().chatbox(6180);
|
player.getPacketSender().chatbox(6180);
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import com.rs2.game.objects.impl.Climbing;
|
|||||||
import com.rs2.game.players.Client;
|
import com.rs2.game.players.Client;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
import com.rs2.game.players.PlayerHandler;
|
import com.rs2.game.players.PlayerHandler;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
import com.rs2.world.Boundary;
|
import com.rs2.world.Boundary;
|
||||||
@@ -44,8 +45,8 @@ import com.rs2.world.Boundary;
|
|||||||
public class ClickingButtons implements PacketType {
|
public class ClickingButtons implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(final Player player, int packetType, int packetSize) {
|
public void processPacket(final Player player, Packet packet) {
|
||||||
int actionButtonId = Misc.hexToInt(player.getInStream().buffer, 0, packetSize);
|
int actionButtonId = packet.readHex();
|
||||||
player.getGlassBlowing().handleActionButtin(actionButtonId);
|
player.getGlassBlowing().handleActionButtin(actionButtonId);
|
||||||
GnomeGlider.flightButtons(player, actionButtonId);
|
GnomeGlider.flightButtons(player, actionButtonId);
|
||||||
player.getEmoteHandler().startEmote(actionButtonId);
|
player.getEmoteHandler().startEmote(actionButtonId);
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package com.rs2.net.packets.impl;
|
package com.rs2.net.packets.impl;
|
||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
public class ClickingInGame implements PacketType {
|
public class ClickingInGame implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.rs2.net.packets.impl;
|
|||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
import com.rs2.game.players.PlayerHandler;
|
import com.rs2.game.players.PlayerHandler;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ import com.rs2.util.Misc;
|
|||||||
public class ClickingStuff implements PacketType {
|
public class ClickingStuff implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
if (player.playerIsBusy()) {
|
if (player.playerIsBusy()) {
|
||||||
player.playerIsBusy = false;
|
player.playerIsBusy = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.rs2.game.bots.BotHandler;
|
|||||||
import com.rs2.game.npcs.NpcHandler;
|
import com.rs2.game.npcs.NpcHandler;
|
||||||
import com.rs2.game.players.*;
|
import com.rs2.game.players.*;
|
||||||
import com.rs2.game.players.antimacro.AntiSpam;
|
import com.rs2.game.players.antimacro.AntiSpam;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
import com.rs2.world.clip.Region;
|
import com.rs2.world.clip.Region;
|
||||||
@@ -21,8 +22,8 @@ import java.util.GregorianCalendar;
|
|||||||
public class Commands implements PacketType {
|
public class Commands implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
String[] messageArr = player.getInStream().readString().split(" ");
|
String[] messageArr = packet.readString().split(" ");
|
||||||
String playerCommand = messageArr[0];
|
String playerCommand = messageArr[0];
|
||||||
String[] commandArguments = Arrays.copyOfRange(messageArr, 1, messageArr.length);
|
String[] commandArguments = Arrays.copyOfRange(messageArr, 1, messageArr.length);
|
||||||
if ((playerCommand.startsWith("ban") || playerCommand.startsWith("ip") || playerCommand.startsWith("mute") || playerCommand.startsWith("un")) && player.playerRights > 0 && player.playerRights < 4) {
|
if ((playerCommand.startsWith("ban") || playerCommand.startsWith("ip") || playerCommand.startsWith("mute") || playerCommand.startsWith("un")) && player.playerRights > 0 && player.playerRights < 4) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.rs2.game.items.ItemConstants;
|
|||||||
import com.rs2.game.items.impl.RareProtection;
|
import com.rs2.game.items.impl.RareProtection;
|
||||||
import com.rs2.game.npcs.impl.Pets;
|
import com.rs2.game.npcs.impl.Pets;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,11 +19,11 @@ import com.rs2.net.packets.PacketType;
|
|||||||
public class DropItem implements PacketType {
|
public class DropItem implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int itemId = player.getInStream().readUnsignedWordA();
|
int itemId = packet.readUnsignedWordA();
|
||||||
player.getInStream().readUnsignedByte();
|
packet.readUnsignedByte();
|
||||||
player.getInStream().readUnsignedByte();
|
packet.readUnsignedByte();
|
||||||
int slot = player.getInStream().readUnsignedWordA();
|
int slot = packet.readUnsignedWordA();
|
||||||
if (!player.getItemAssistant().playerHasItem(itemId) || !RareProtection.removeItemOtherActions(player, itemId) || System.currentTimeMillis() - player.alchDelay < 1800 || player.stopPlayerPacket || System.currentTimeMillis() - player.buryDelay < 1800 || !CastleWars.deleteCastleWarsItems(player, itemId)) {
|
if (!player.getItemAssistant().playerHasItem(itemId) || !RareProtection.removeItemOtherActions(player, itemId) || System.currentTimeMillis() - player.alchDelay < 1800 || player.stopPlayerPacket || System.currentTimeMillis() - player.buryDelay < 1800 || !CastleWars.deleteCastleWarsItems(player, itemId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ package com.rs2.net.packets.impl;
|
|||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
import com.rs2.game.players.PlayerHandler;
|
import com.rs2.game.players.PlayerHandler;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
public class FollowPlayer implements PacketType {
|
public class FollowPlayer implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int followPlayer = player.getInStream().readUnsignedWordBigEndian();
|
int followPlayer = packet.readUnsignedWordBigEndian();
|
||||||
if (PlayerHandler.players[followPlayer] == null) {
|
if (PlayerHandler.players[followPlayer] == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.rs2.net.packets.impl;
|
package com.rs2.net.packets.impl;
|
||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,7 +11,7 @@ import com.rs2.net.packets.PacketType;
|
|||||||
public class IdleLogout implements PacketType {
|
public class IdleLogout implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
if (player.underAttackBy > 0 || player.underAttackBy2 > 0 || player.isBot) {
|
if (player.underAttackBy > 0 || player.underAttackBy2 > 0 || player.isBot) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,16 @@ import com.rs2.game.content.random.PartyRoom;
|
|||||||
import com.rs2.game.content.skills.cooking.Cooking;
|
import com.rs2.game.content.skills.cooking.Cooking;
|
||||||
import com.rs2.game.content.skills.smithing.Smelting;
|
import com.rs2.game.content.skills.smithing.Smelting;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.world.Boundary;
|
import com.rs2.world.Boundary;
|
||||||
|
|
||||||
public class InterfaceX implements PacketType {
|
public class InterfaceX implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
int Xamount = player.getInStream().readDWord();
|
int Xamount = packet.readDWord();
|
||||||
if (Xamount < 0) {
|
if (Xamount < 0) {
|
||||||
Xamount = player.getItemAssistant().getItemAmount(player.xRemoveId);
|
Xamount = player.getItemAssistant().getItemAmount(player.xRemoveId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.rs2.net.packets.impl;
|
|||||||
import com.rs2.event.impl.ItemSecondClickEvent;
|
import com.rs2.event.impl.ItemSecondClickEvent;
|
||||||
import com.rs2.game.items.impl.HandleEmpty;
|
import com.rs2.game.items.impl.HandleEmpty;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -13,8 +14,8 @@ import com.rs2.net.packets.PacketType;
|
|||||||
public class ItemClick2 implements PacketType {
|
public class ItemClick2 implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int itemId = player.getInStream().readSignedWordA();
|
int itemId = packet.readSignedWordA();
|
||||||
|
|
||||||
if (!player.getItemAssistant().playerHasItem(itemId, 1)) {
|
if (!player.getItemAssistant().playerHasItem(itemId, 1)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ package com.rs2.net.packets.impl;
|
|||||||
import com.rs2.game.content.skills.firemaking.Firemaking;
|
import com.rs2.game.content.skills.firemaking.Firemaking;
|
||||||
import com.rs2.game.content.skills.firemaking.LogData;
|
import com.rs2.game.content.skills.firemaking.LogData;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
public class ItemClick2OnGroundItem implements PacketType {
|
public class ItemClick2OnGroundItem implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
final int itemX = player.getInStream().readSignedWordBigEndian();
|
final int itemX = packet.readSignedWordBigEndian();
|
||||||
final int itemY = player.getInStream().readSignedWordBigEndianA();
|
final int itemY = packet.readSignedWordBigEndianA();
|
||||||
final int itemId = player.getInStream().readUnsignedWordA();
|
final int itemId = packet.readUnsignedWordA();
|
||||||
System.out.println("ItemClick2OnGroundItem - " + player.playerName + " - " + itemId + " - " + itemX + " - " + itemY);
|
System.out.println("ItemClick2OnGroundItem - " + player.playerName + " - " + itemId + " - " + itemX + " - " + itemY);
|
||||||
// Reset position for the telekinetic guardian statue
|
// Reset position for the telekinetic guardian statue
|
||||||
if (itemId == 6888) {
|
if (itemId == 6888) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.rs2.game.content.skills.runecrafting.Runecrafting;
|
|||||||
import com.rs2.game.items.impl.HandleEmpty;
|
import com.rs2.game.items.impl.HandleEmpty;
|
||||||
import com.rs2.game.items.impl.Teles;
|
import com.rs2.game.items.impl.Teles;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
|
|
||||||
@@ -17,10 +18,10 @@ import com.rs2.util.Misc;
|
|||||||
public class ItemClick3 implements PacketType {
|
public class ItemClick3 implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int itemId11 = player.getInStream().readSignedWordBigEndianA();
|
int itemId11 = packet.readSignedWordBigEndianA();
|
||||||
int itemId1 = player.getInStream().readSignedWordA();
|
int itemId1 = packet.readSignedWordA();
|
||||||
int itemId = player.getInStream().readSignedWordA();
|
int itemId = packet.readSignedWordA();
|
||||||
if (!player.getItemAssistant().playerHasItem(itemId, 1)) {
|
if (!player.getItemAssistant().playerHasItem(itemId, 1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,20 @@ package com.rs2.net.packets.impl;
|
|||||||
import com.rs2.GameEngine;
|
import com.rs2.GameEngine;
|
||||||
import com.rs2.game.content.skills.firemaking.Firemaking;
|
import com.rs2.game.content.skills.firemaking.Firemaking;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
|
|
||||||
public class ItemOnGroundItem implements PacketType {
|
public class ItemOnGroundItem implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
player.getInStream().readSignedWordBigEndian();
|
packet.readSignedWordBigEndian();
|
||||||
int itemUsed = player.getInStream().readSignedWordA();
|
int itemUsed = packet.readSignedWordA();
|
||||||
int groundItem = player.getInStream().readUnsignedWord();
|
int groundItem = packet.readUnsignedWord();
|
||||||
int gItemY = player.getInStream().readSignedWordA();
|
int gItemY = packet.readSignedWordA();
|
||||||
int itemUsedSlot = player.getInStream().readSignedWordBigEndianA();
|
int itemUsedSlot = packet.readSignedWordBigEndianA();
|
||||||
int gItemX = player.getInStream().readUnsignedWord();
|
int gItemX = packet.readUnsignedWord();
|
||||||
if (!player.getItemAssistant().playerHasItem(itemUsed, 1, itemUsedSlot)) {
|
if (!player.getItemAssistant().playerHasItem(itemUsed, 1, itemUsedSlot)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,15 @@ package com.rs2.net.packets.impl;
|
|||||||
|
|
||||||
import com.rs2.game.items.UseItem;
|
import com.rs2.game.items.UseItem;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
public class ItemOnItem implements PacketType {
|
public class ItemOnItem implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int usedWithSlot = player.getInStream().readUnsignedWord();
|
int usedWithSlot = packet.readUnsignedWord();
|
||||||
int itemUsedSlot = player.getInStream().readUnsignedWordA();
|
int itemUsedSlot = packet.readUnsignedWordA();
|
||||||
int useWith = player.playerItems[usedWithSlot] - 1;
|
int useWith = player.playerItems[usedWithSlot] - 1;
|
||||||
int itemUsed = player.playerItems[itemUsedSlot] - 1;
|
int itemUsed = player.playerItems[itemUsedSlot] - 1;
|
||||||
if (!player.getItemAssistant().playerHasItem(useWith, 1, usedWithSlot)|| !player.getItemAssistant().playerHasItem(itemUsed, 1, itemUsedSlot)) {
|
if (!player.getItemAssistant().playerHasItem(useWith, 1, usedWithSlot)|| !player.getItemAssistant().playerHasItem(itemUsed, 1, itemUsedSlot)) {
|
||||||
|
|||||||
@@ -5,15 +5,16 @@ import com.rs2.game.content.skills.SkillHandler;
|
|||||||
import com.rs2.game.items.UseItem;
|
import com.rs2.game.items.UseItem;
|
||||||
import com.rs2.game.npcs.NpcHandler;
|
import com.rs2.game.npcs.NpcHandler;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
public class ItemOnNpc implements PacketType {
|
public class ItemOnNpc implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(final Player player, int packetType, int packetSize) {
|
public void processPacket(final Player player, Packet packet) {
|
||||||
final int itemId = player.getInStream().readSignedWordA();
|
final int itemId = packet.readSignedWordA();
|
||||||
final int i = player.getInStream().readSignedWordA();
|
final int i = packet.readSignedWordA();
|
||||||
final int slot = player.getInStream().readSignedWordBigEndian();
|
final int slot = packet.readSignedWordBigEndian();
|
||||||
final int npcId = NpcHandler.npcs[i].npcType;
|
final int npcId = NpcHandler.npcs[i].npcType;
|
||||||
SkillHandler.resetItemOnNpc(player);
|
SkillHandler.resetItemOnNpc(player);
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import com.rs2.game.content.skills.prayer.Ectofuntus;
|
|||||||
import com.rs2.game.items.UseItem;
|
import com.rs2.game.items.UseItem;
|
||||||
import com.rs2.game.items.impl.Fillables;
|
import com.rs2.game.items.impl.Fillables;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.world.Boundary;
|
import com.rs2.world.Boundary;
|
||||||
import com.rs2.world.clip.Region;
|
import com.rs2.world.clip.Region;
|
||||||
@@ -19,13 +20,13 @@ import com.rs2.world.clip.Region;
|
|||||||
public class ItemOnObject implements PacketType {
|
public class ItemOnObject implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
player.getInStream().readUnsignedWord();
|
packet.readUnsignedWord();
|
||||||
int objectId = player.getInStream().readSignedWordBigEndian();
|
int objectId = packet.readSignedWordBigEndian();
|
||||||
int objectY = player.getInStream().readSignedWordBigEndianA();
|
int objectY = packet.readSignedWordBigEndianA();
|
||||||
player.getInStream().readUnsignedWord();
|
packet.readUnsignedWord();
|
||||||
int objectX = player.getInStream().readSignedWordBigEndianA();
|
int objectX = packet.readSignedWordBigEndianA();
|
||||||
int itemId = player.getInStream().readUnsignedWord();
|
int itemId = packet.readUnsignedWord();
|
||||||
player.turnPlayerTo(objectX, objectY);
|
player.turnPlayerTo(objectX, objectY);
|
||||||
player.objectX = objectX;
|
player.objectX = objectX;
|
||||||
player.objectY = objectY;
|
player.objectY = objectY;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.rs2.net.packets.impl;
|
|||||||
import com.rs2.game.items.impl.RareProtection;
|
import com.rs2.game.items.impl.RareProtection;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
import com.rs2.game.players.PlayerHandler;
|
import com.rs2.game.players.PlayerHandler;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
|
|
||||||
@@ -13,9 +14,9 @@ import com.rs2.util.Misc;
|
|||||||
public class ItemOnPlayer implements PacketType {
|
public class ItemOnPlayer implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int playerId = player.inStream.readUnsignedWord();
|
int playerId = packet.readUnsignedWord();
|
||||||
int itemId = player.playerItems[player.inStream.readSignedWordBigEndian()] - 1;
|
int itemId = player.playerItems[packet.readSignedWordBigEndian()] - 1;
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
switch (itemId) {
|
switch (itemId) {
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import com.rs2.event.CycleEventContainer;
|
|||||||
import com.rs2.event.CycleEventHandler;
|
import com.rs2.event.CycleEventHandler;
|
||||||
import com.rs2.game.content.combat.magic.MagicData;
|
import com.rs2.game.content.combat.magic.MagicData;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.world.GlobalDropsHandler;
|
import com.rs2.world.GlobalDropsHandler;
|
||||||
import com.rs2.world.clip.PathFinder;
|
import com.rs2.world.clip.PathFinder;
|
||||||
@@ -18,11 +19,11 @@ import com.rs2.world.clip.PathFinder;
|
|||||||
public class MagicOnFloorItems implements PacketType {
|
public class MagicOnFloorItems implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(final Player player, int packetType, int packetSize) {
|
public void processPacket(final Player player, Packet packet) {
|
||||||
final int itemY = player.getInStream().readSignedWordBigEndian();
|
final int itemY = packet.readSignedWordBigEndian();
|
||||||
int itemId = player.getInStream().readUnsignedWord();
|
int itemId = packet.readUnsignedWord();
|
||||||
final int itemX = player.getInStream().readSignedWordBigEndian();
|
final int itemX = packet.readSignedWordBigEndian();
|
||||||
player.getInStream().readUnsignedWordA();
|
packet.readUnsignedWordA();
|
||||||
player.stopMovement();
|
player.stopMovement();
|
||||||
|
|
||||||
if (!GameEngine.itemHandler.itemExists(itemId, itemX, itemY)) {
|
if (!GameEngine.itemHandler.itemExists(itemId, itemX, itemY)) {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.rs2.net.packets.impl;
|
|||||||
|
|
||||||
import com.rs2.event.impl.MagicOnItemEvent;
|
import com.rs2.event.impl.MagicOnItemEvent;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,11 +12,11 @@ import com.rs2.net.packets.PacketType;
|
|||||||
public class MagicOnItems implements PacketType {
|
public class MagicOnItems implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int slot = player.getInStream().readSignedWord();
|
int slot = packet.readSignedWord();
|
||||||
int itemId = player.getInStream().readSignedWordA();
|
int itemId = packet.readSignedWordA();
|
||||||
player.getInStream().readSignedWord();
|
packet.readSignedWord();
|
||||||
int spellId = player.getInStream().readSignedWordA();
|
int spellId = packet.readSignedWordA();
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
if(!player.getItemAssistant().playerHasItem(itemId, 1, slot)) {
|
if(!player.getItemAssistant().playerHasItem(itemId, 1, slot)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,16 +2,17 @@ package com.rs2.net.packets.impl;
|
|||||||
|
|
||||||
import com.rs2.game.content.skills.crafting.OrbCharging;
|
import com.rs2.game.content.skills.crafting.OrbCharging;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
public class MagicOnObject implements PacketType {
|
public class MagicOnObject implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int x = player.getInStream().readSignedWordBigEndian();
|
int x = packet.readSignedWordBigEndian();
|
||||||
int magicId = player.getInStream().readUnsignedWord();
|
int magicId = packet.readUnsignedWord();
|
||||||
int y = player.getInStream().readUnsignedWordA();
|
int y = packet.readUnsignedWordA();
|
||||||
int objectId = player.getInStream().readSignedWordBigEndian();
|
int objectId = packet.readSignedWordBigEndian();
|
||||||
|
|
||||||
player.turnPlayerTo(x, y);
|
player.turnPlayerTo(x, y);
|
||||||
switch (objectId) {
|
switch (objectId) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.rs2.net.packets.impl;
|
package com.rs2.net.packets.impl;
|
||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,11 +10,11 @@ import com.rs2.net.packets.PacketType;
|
|||||||
public class MoveItems implements PacketType {
|
public class MoveItems implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int interfaceId = player.getInStream().readSignedWordBigEndianA();
|
int interfaceId = packet.readSignedWordBigEndianA();
|
||||||
boolean insertMode = player.getInStream().readSignedByteC() == 1;
|
boolean insertMode = packet.readSignedByteC() == 1;
|
||||||
int from = player.getInStream().readSignedWordBigEndianA();
|
int from = packet.readSignedWordBigEndianA();
|
||||||
int to = player.getInStream().readSignedWordBigEndian();
|
int to = packet.readSignedWordBigEndian();
|
||||||
if (player.inTrade) {
|
if (player.inTrade) {
|
||||||
player.getTrading().declineTrade();
|
player.getTrading().declineTrade();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.rs2.game.content.skills.firemaking.LogData;
|
|||||||
import com.rs2.game.items.ItemAssistant;
|
import com.rs2.game.items.ItemAssistant;
|
||||||
import com.rs2.game.items.impl.RareProtection;
|
import com.rs2.game.items.impl.RareProtection;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.GameLogger;
|
import com.rs2.util.GameLogger;
|
||||||
import com.rs2.world.Boundary;
|
import com.rs2.world.Boundary;
|
||||||
@@ -24,10 +25,10 @@ public class PickupItem implements PacketType {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(final Player player, int packetType, int packetSize) {
|
public void processPacket(final Player player, Packet packet) {
|
||||||
player.pItemY = player.getInStream().readSignedWordBigEndian();
|
player.pItemY = packet.readSignedWordBigEndian();
|
||||||
player.pItemId = player.getInStream().readUnsignedWord();
|
player.pItemId = packet.readUnsignedWord();
|
||||||
player.pItemX = player.getInStream().readSignedWordBigEndian();
|
player.pItemX = packet.readSignedWordBigEndian();
|
||||||
// Cannot pickup the telekinetic guardian statue, should show overview of current maze
|
// Cannot pickup the telekinetic guardian statue, should show overview of current maze
|
||||||
if (player.pItemId == 6888) {
|
if (player.pItemId == 6888) {
|
||||||
player.getMageTrainingArena().telekinetic.observeStatue(player.pItemX, player.pItemY);
|
player.getMageTrainingArena().telekinetic.observeStatue(player.pItemX, player.pItemY);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.rs2.game.players.Client;
|
|||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
import com.rs2.game.players.PlayerHandler;
|
import com.rs2.game.players.PlayerHandler;
|
||||||
import com.rs2.game.players.antimacro.AntiSpam;
|
import com.rs2.game.players.antimacro.AntiSpam;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.GameLogger;
|
import com.rs2.util.GameLogger;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
@@ -19,12 +20,12 @@ public class PrivateMessaging implements PacketType {
|
|||||||
CHANGE_PM_STATUS = 95, REMOVE_IGNORE = 59, ADD_IGNORE = 133;
|
CHANGE_PM_STATUS = 95, REMOVE_IGNORE = 59, ADD_IGNORE = 133;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
switch (packetType) {
|
switch (packet.getOpcode()) {
|
||||||
|
|
||||||
case ADD_FRIEND:
|
case ADD_FRIEND:
|
||||||
player.friendUpdate = true;
|
player.friendUpdate = true;
|
||||||
long friendToAdd = player.getInStream().readQWord();
|
long friendToAdd = packet.readQWord();
|
||||||
boolean canAdd = true;
|
boolean canAdd = true;
|
||||||
|
|
||||||
for (long friend : player.friends) {
|
for (long friend : player.friends) {
|
||||||
@@ -55,13 +56,13 @@ public class PrivateMessaging implements PacketType {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SEND_PM:
|
case SEND_PM:
|
||||||
long sendMessageToFriendId = player.getInStream().readQWord();
|
long sendMessageToFriendId = packet.readQWord();
|
||||||
byte pmchatText[] = new byte[100];
|
byte pmchatText[] = new byte[100];
|
||||||
int pmchatTextSize = (byte) (packetSize - 8);
|
int pmchatTextSize = (byte) (packet.getLength() - 8);
|
||||||
player.getInStream().readBytes(pmchatText, pmchatTextSize, 0);
|
packet.readBytes(pmchatText, pmchatTextSize, 0);
|
||||||
String word = Misc.textUnpack(pmchatText, player.packetSize - 2).toLowerCase();// used
|
String word = Misc.textUnpack(pmchatText, packet.getLength() - 2).toLowerCase();// used
|
||||||
if (player.getPlayerAssistant().isPlayer()) {
|
if (player.getPlayerAssistant().isPlayer()) {
|
||||||
GameLogger.writeLog(player.playerName, "pmsent", player.playerName + " said " + Misc.textUnpack(pmchatText, packetSize - 8) + "");
|
GameLogger.writeLog(player.playerName, "pmsent", player.playerName + " said " + Misc.textUnpack(pmchatText, packet.getLength() - 8) + "");
|
||||||
}
|
}
|
||||||
if (!AntiSpam.blockedWords(player, word, false) || Connection.isMuted(player)) {
|
if (!AntiSpam.blockedWords(player, word, false) || Connection.isMuted(player)) {
|
||||||
return;
|
return;
|
||||||
@@ -78,7 +79,7 @@ public class PrivateMessaging implements PacketType {
|
|||||||
if (friend == sendMessageToFriendId) {
|
if (friend == sendMessageToFriendId) {
|
||||||
o.getPacketSender().sendPM(Misc.playerNameToInt64(player.playerName), player.playerRights, pmchatText, pmchatTextSize);
|
o.getPacketSender().sendPM(Misc.playerNameToInt64(player.playerName), player.playerRights, pmchatText, pmchatTextSize);
|
||||||
if (player.getPlayerAssistant().isPlayer()) {
|
if (player.getPlayerAssistant().isPlayer()) {
|
||||||
GameLogger.writeLog(o.playerName, "pmrecieved", player.playerName + " said to " + o.playerName + " " + Misc.textUnpack(pmchatText, packetSize - 8) + "");
|
GameLogger.writeLog(o.playerName, "pmrecieved", player.playerName + " said to " + o.playerName + " " + Misc.textUnpack(pmchatText, packet.getLength() - 8) + "");
|
||||||
}
|
}
|
||||||
pmSent = true;
|
pmSent = true;
|
||||||
}
|
}
|
||||||
@@ -97,7 +98,7 @@ public class PrivateMessaging implements PacketType {
|
|||||||
|
|
||||||
case REMOVE_FRIEND:
|
case REMOVE_FRIEND:
|
||||||
player.friendUpdate = true;
|
player.friendUpdate = true;
|
||||||
long friendToRemove = player.getInStream().readQWord();
|
long friendToRemove = packet.readQWord();
|
||||||
|
|
||||||
for (int i1 = 0; i1 < player.friends.length; i1++) {
|
for (int i1 = 0; i1 < player.friends.length; i1++) {
|
||||||
if (player.friends[i1] == friendToRemove) {
|
if (player.friends[i1] == friendToRemove) {
|
||||||
@@ -118,7 +119,7 @@ public class PrivateMessaging implements PacketType {
|
|||||||
|
|
||||||
case REMOVE_IGNORE:
|
case REMOVE_IGNORE:
|
||||||
player.friendUpdate = true;
|
player.friendUpdate = true;
|
||||||
long ignore = player.getInStream().readQWord();
|
long ignore = packet.readQWord();
|
||||||
|
|
||||||
for (int i = 0; i < player.ignores.length; i++) {
|
for (int i = 0; i < player.ignores.length; i++) {
|
||||||
if (player.ignores[i] == ignore) {
|
if (player.ignores[i] == ignore) {
|
||||||
@@ -129,7 +130,7 @@ public class PrivateMessaging implements PacketType {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CHANGE_PM_STATUS:
|
case CHANGE_PM_STATUS:
|
||||||
player.privateChat = player.getInStream().readUnsignedByte();
|
player.privateChat = packet.readUnsignedByte();
|
||||||
for (int i1 = 1; i1 < PlayerHandler.players.length; i1++) {
|
for (int i1 = 1; i1 < PlayerHandler.players.length; i1++) {
|
||||||
if (PlayerHandler.players[i1] != null
|
if (PlayerHandler.players[i1] != null
|
||||||
&& PlayerHandler.players[i1].isActive) {
|
&& PlayerHandler.players[i1].isActive) {
|
||||||
@@ -143,7 +144,7 @@ public class PrivateMessaging implements PacketType {
|
|||||||
|
|
||||||
case ADD_IGNORE:
|
case ADD_IGNORE:
|
||||||
player.friendUpdate = true;
|
player.friendUpdate = true;
|
||||||
long ignoreAdd = player.getInStream().readQWord();
|
long ignoreAdd = packet.readQWord();
|
||||||
for (int i = 0; i < player.ignores.length; i++) {
|
for (int i = 0; i < player.ignores.length; i++) {
|
||||||
if (player.ignores[i] == 0) {
|
if (player.ignores[i] == 0) {
|
||||||
player.ignores[i] = ignoreAdd;
|
player.ignores[i] = ignoreAdd;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import com.rs2.game.content.skills.crafting.JewelryMaking;
|
|||||||
import com.rs2.game.items.Weight;
|
import com.rs2.game.items.Weight;
|
||||||
import com.rs2.game.items.impl.RareProtection;
|
import com.rs2.game.items.impl.RareProtection;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.world.Boundary;
|
import com.rs2.world.Boundary;
|
||||||
|
|
||||||
@@ -15,10 +16,10 @@ import com.rs2.world.Boundary;
|
|||||||
public class RemoveItem implements PacketType {
|
public class RemoveItem implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int interfaceId = player.getInStream().readUnsignedWordA();
|
int interfaceId = packet.readUnsignedWordA();
|
||||||
int removeSlot = player.getInStream().readUnsignedWordA();
|
int removeSlot = packet.readUnsignedWordA();
|
||||||
int removeId = player.getInStream().readUnsignedWordA();
|
int removeId = packet.readUnsignedWordA();
|
||||||
if (!RareProtection.removeItem(player, removeId)) {
|
if (!RareProtection.removeItem(player, removeId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
package com.rs2.net.packets.impl;
|
package com.rs2.net.packets.impl;
|
||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
public class Report implements PacketType {
|
public class Report implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
try {
|
try {
|
||||||
ReportHandler.handleReport(player);
|
ReportHandler.handleReport(player, packet);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.io.IOException;
|
|||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
|
|
||||||
public class ReportHandler {
|
public class ReportHandler {
|
||||||
@@ -59,11 +60,11 @@ public class ReportHandler {
|
|||||||
* ex
|
* ex
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static void handleReport(Player c) throws Exception {
|
public static void handleReport(Player c, Packet packet) throws Exception {
|
||||||
String player = Misc.longToReportPlayerName(c.inStream.readQWord2());
|
String player = Misc.longToReportPlayerName(packet.readQWord2());
|
||||||
player = player.replaceAll("_", " ");
|
player = player.replaceAll("_", " ");
|
||||||
byte rule = (byte) c.inStream.readUnsignedByte();
|
byte rule = (byte) packet.readUnsignedByte();
|
||||||
int mute = c.getInStream().readUnsignedByte();
|
int mute = packet.readUnsignedByte();
|
||||||
|
|
||||||
if (c.lastReported.equalsIgnoreCase(player) && System.currentTimeMillis() - c.lastReport < 60000) {
|
if (c.lastReported.equalsIgnoreCase(player) && System.currentTimeMillis() - c.lastReport < 60000) {
|
||||||
c.getPacketSender().sendMessage("You can only report a player once every 60 seconds.");
|
c.getPacketSender().sendMessage("You can only report a player once every 60 seconds.");
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.rs2.net.packets.impl;
|
package com.rs2.net.packets.impl;
|
||||||
|
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -9,7 +10,7 @@ import com.rs2.net.packets.PacketType;
|
|||||||
public class SilentPacket implements PacketType {
|
public class SilentPacket implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.rs2.net.packets.impl;
|
|||||||
|
|
||||||
import com.rs2.GameConstants;
|
import com.rs2.GameConstants;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,8 +12,8 @@ import com.rs2.net.packets.PacketType;
|
|||||||
public class Trade implements PacketType {
|
public class Trade implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
int tradeId = player.getInStream().readSignedWordBigEndian();
|
int tradeId = packet.readSignedWordBigEndian();
|
||||||
player.getPlayerAssistant().resetFollow();
|
player.getPlayerAssistant().resetFollow();
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
if (player.disconnected) {
|
if (player.disconnected) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import com.rs2.game.items.impl.Greegree.MonkeyData;
|
|||||||
import com.rs2.game.players.Client;
|
import com.rs2.game.players.Client;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
import com.rs2.game.players.PlayerHandler;
|
import com.rs2.game.players.PlayerHandler;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,7 +20,7 @@ import com.rs2.net.packets.PacketType;
|
|||||||
public class Walking implements PacketType {
|
public class Walking implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
player.getDueling().checkDuelWalk();
|
player.getDueling().checkDuelWalk();
|
||||||
if (player.playerIsBusy()) {
|
if (player.playerIsBusy()) {
|
||||||
player.playerIsBusy = false;
|
player.playerIsBusy = false;
|
||||||
@@ -87,7 +88,7 @@ public class Walking implements PacketType {
|
|||||||
if (player.getPlayerAction().checkWalking() == false) {
|
if (player.getPlayerAction().checkWalking() == false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (packetType == 248 || packetType == 164) {
|
if (packet.getOpcode() == 248 || packet.getOpcode() == 164) {
|
||||||
player.faceUpdate(0);
|
player.faceUpdate(0);
|
||||||
player.npcIndex = 0;
|
player.npcIndex = 0;
|
||||||
player.playerIndex = 0;
|
player.playerIndex = 0;
|
||||||
@@ -118,12 +119,12 @@ public class Walking implements PacketType {
|
|||||||
if (player.goodDistance(player.getX(), player.getY(),
|
if (player.goodDistance(player.getX(), player.getY(),
|
||||||
PlayerHandler.players[player.playerIndex].getX(),
|
PlayerHandler.players[player.playerIndex].getX(),
|
||||||
PlayerHandler.players[player.playerIndex].getY(), 1)
|
PlayerHandler.players[player.playerIndex].getY(), 1)
|
||||||
&& packetType != 98) {
|
&& packet.getOpcode() != 98) {
|
||||||
player.playerIndex = 0;
|
player.playerIndex = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (packetType != 98) {
|
if (packet.getOpcode() != 98) {
|
||||||
player.getPacketSender().sendMessage("A magical force stops you from moving.");
|
player.getPacketSender().sendMessage("A magical force stops you from moving.");
|
||||||
player.playerIndex = 0;
|
player.playerIndex = 0;
|
||||||
}
|
}
|
||||||
@@ -136,7 +137,7 @@ public class Walking implements PacketType {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packetType == 98) {
|
if (packet.getOpcode() == 98) {
|
||||||
player.mageAllowed = true;
|
player.mageAllowed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,8 +171,8 @@ public class Walking implements PacketType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
player.endCurrentTask();
|
player.endCurrentTask();
|
||||||
|
int packetSize = packet.getLength();
|
||||||
if (packetType == 248) {
|
if (packet.getOpcode() == 248) {
|
||||||
packetSize -= 14;
|
packetSize -= 14;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
@@ -234,20 +235,20 @@ public class Walking implements PacketType {
|
|||||||
int realY = 0;
|
int realY = 0;
|
||||||
|
|
||||||
if (player.clickToTele) {
|
if (player.clickToTele) {
|
||||||
firstStepX = player.getInStream().readSignedWordBigEndianA();
|
firstStepX = packet.readSignedWordBigEndianA();
|
||||||
} else {
|
} else {
|
||||||
realX = player.getInStream().readSignedWordBigEndianA();
|
realX = packet.readSignedWordBigEndianA();
|
||||||
firstStepX = realX - player.getMapRegionX() * 8;
|
firstStepX = realX - player.getMapRegionX() * 8;
|
||||||
}
|
}
|
||||||
for (int i = 1; i < player.newWalkCmdSteps; i++) {
|
for (int i = 1; i < player.newWalkCmdSteps; i++) {
|
||||||
player.getNewWalkCmdX()[i] = player.getInStream().readSignedByte();
|
player.getNewWalkCmdX()[i] = packet.readSignedByte();
|
||||||
player.getNewWalkCmdY()[i] = player.getInStream().readSignedByte();
|
player.getNewWalkCmdY()[i] = packet.readSignedByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (player.clickToTele) {
|
if (player.clickToTele) {
|
||||||
firstStepY = player.getInStream().readSignedWordBigEndian();
|
firstStepY = packet.readSignedWordBigEndian();
|
||||||
} else {
|
} else {
|
||||||
realY = player.getInStream().readSignedWordBigEndian();
|
realY = packet.readSignedWordBigEndian();
|
||||||
firstStepY = realY - player.getMapRegionY() * 8;
|
firstStepY = realY - player.getMapRegionY() * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +258,7 @@ public class Walking implements PacketType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player.setNewWalkCmdIsRunning(player.getInStream().readSignedByteC() == 1 && player.playerEnergy > 0);
|
player.setNewWalkCmdIsRunning(packet.readSignedByteC() == 1 && player.playerEnergy > 0);
|
||||||
for (int i1 = 0; i1 < player.newWalkCmdSteps; i1++) {
|
for (int i1 = 0; i1 < player.newWalkCmdSteps; i1++) {
|
||||||
if (player.clickToTele)
|
if (player.clickToTele)
|
||||||
player.getPlayerAssistant().movePlayer(player.getNewWalkCmdX()[i1] + firstStepX, player.getNewWalkCmdY()[i1] + firstStepY, player.heightLevel);
|
player.getPlayerAssistant().movePlayer(player.getNewWalkCmdX()[i1] + firstStepX, player.getNewWalkCmdY()[i1] + firstStepY, player.heightLevel);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.rs2.GameConstants;
|
|||||||
import com.rs2.game.items.Weight;
|
import com.rs2.game.items.Weight;
|
||||||
import com.rs2.game.items.impl.RareProtection;
|
import com.rs2.game.items.impl.RareProtection;
|
||||||
import com.rs2.game.players.Player;
|
import com.rs2.game.players.Player;
|
||||||
|
import com.rs2.net.Packet;
|
||||||
import com.rs2.net.packets.PacketType;
|
import com.rs2.net.packets.PacketType;
|
||||||
import com.rs2.util.Misc;
|
import com.rs2.util.Misc;
|
||||||
|
|
||||||
@@ -13,10 +14,10 @@ import com.rs2.util.Misc;
|
|||||||
public class WearItem implements PacketType {
|
public class WearItem implements PacketType {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Player player, int packetType, int packetSize) {
|
public void processPacket(Player player, Packet packet) {
|
||||||
player.wearId = player.getInStream().readUnsignedWord();
|
player.wearId = packet.readUnsignedWord();
|
||||||
player.wearSlot = player.getInStream().readUnsignedWordA();
|
player.wearSlot = packet.readUnsignedWordA();
|
||||||
player.interfaceId = player.getInStream().readUnsignedWordA();
|
player.interfaceId = packet.readUnsignedWordA();
|
||||||
Weight.updateWeight(player);
|
Weight.updateWeight(player);
|
||||||
if (!RareProtection.equipItem(player)) {
|
if (!RareProtection.equipItem(player)) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,175 +0,0 @@
|
|||||||
package com.rs2.util;
|
|
||||||
|
|
||||||
public class ISAACRandomGen {
|
|
||||||
|
|
||||||
public int count;
|
|
||||||
public int[] results;
|
|
||||||
public int[] memory;
|
|
||||||
public int accumulator;
|
|
||||||
public int lastResult;
|
|
||||||
public int counter;
|
|
||||||
|
|
||||||
public ISAACRandomGen(int[] seed) {
|
|
||||||
memory = new int[256];
|
|
||||||
results = new int[256];
|
|
||||||
System.arraycopy(seed, 0, results, 0, seed.length);
|
|
||||||
initializeKeySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNextKey() {
|
|
||||||
// Server.add(Thread.currentThread().getName());
|
|
||||||
// System.out.println(Thread.currentThread().getName());
|
|
||||||
if (count-- == 0) {
|
|
||||||
generateNextKeySet();
|
|
||||||
count = 255;
|
|
||||||
}
|
|
||||||
return results[count];
|
|
||||||
}
|
|
||||||
|
|
||||||
public void generateNextKeySet() {
|
|
||||||
lastResult += ++counter;
|
|
||||||
for (int i = 0; i < 256; i++) {
|
|
||||||
int j = memory[i];
|
|
||||||
if ((i & 3) == 0) {
|
|
||||||
accumulator ^= accumulator << 13;
|
|
||||||
} else if ((i & 3) == 1) {
|
|
||||||
accumulator ^= accumulator >>> 6;
|
|
||||||
} else if ((i & 3) == 2) {
|
|
||||||
accumulator ^= accumulator << 2;
|
|
||||||
} else if ((i & 3) == 3) {
|
|
||||||
accumulator ^= accumulator >>> 16;
|
|
||||||
}
|
|
||||||
accumulator += memory[i + 128 & 0xff];
|
|
||||||
int k;
|
|
||||||
memory[i] = k = memory[(j & 0x3fc) >> 2] + accumulator + lastResult;
|
|
||||||
results[i] = lastResult = memory[(k >> 8 & 0x3fc) >> 2] + j;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initializeKeySet() {
|
|
||||||
int i1;
|
|
||||||
int j1;
|
|
||||||
int k1;
|
|
||||||
int l1;
|
|
||||||
int i2;
|
|
||||||
int j2;
|
|
||||||
int k2;
|
|
||||||
int l = i1 = j1 = k1 = l1 = i2 = j2 = k2 = 0x9e3779b9;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
l ^= i1 << 11;
|
|
||||||
k1 += l;
|
|
||||||
i1 += j1;
|
|
||||||
i1 ^= j1 >>> 2;
|
|
||||||
l1 += i1;
|
|
||||||
j1 += k1;
|
|
||||||
j1 ^= k1 << 8;
|
|
||||||
i2 += j1;
|
|
||||||
k1 += l1;
|
|
||||||
k1 ^= l1 >>> 16;
|
|
||||||
j2 += k1;
|
|
||||||
l1 += i2;
|
|
||||||
l1 ^= i2 << 10;
|
|
||||||
k2 += l1;
|
|
||||||
i2 += j2;
|
|
||||||
i2 ^= j2 >>> 4;
|
|
||||||
l += i2;
|
|
||||||
j2 += k2;
|
|
||||||
j2 ^= k2 << 8;
|
|
||||||
i1 += j2;
|
|
||||||
k2 += l;
|
|
||||||
k2 ^= l >>> 9;
|
|
||||||
j1 += k2;
|
|
||||||
l += i1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < 256; j += 8) {
|
|
||||||
l += results[j];
|
|
||||||
i1 += results[j + 1];
|
|
||||||
j1 += results[j + 2];
|
|
||||||
k1 += results[j + 3];
|
|
||||||
l1 += results[j + 4];
|
|
||||||
i2 += results[j + 5];
|
|
||||||
j2 += results[j + 6];
|
|
||||||
k2 += results[j + 7];
|
|
||||||
l ^= i1 << 11;
|
|
||||||
k1 += l;
|
|
||||||
i1 += j1;
|
|
||||||
i1 ^= j1 >>> 2;
|
|
||||||
l1 += i1;
|
|
||||||
j1 += k1;
|
|
||||||
j1 ^= k1 << 8;
|
|
||||||
i2 += j1;
|
|
||||||
k1 += l1;
|
|
||||||
k1 ^= l1 >>> 16;
|
|
||||||
j2 += k1;
|
|
||||||
l1 += i2;
|
|
||||||
l1 ^= i2 << 10;
|
|
||||||
k2 += l1;
|
|
||||||
i2 += j2;
|
|
||||||
i2 ^= j2 >>> 4;
|
|
||||||
l += i2;
|
|
||||||
j2 += k2;
|
|
||||||
j2 ^= k2 << 8;
|
|
||||||
i1 += j2;
|
|
||||||
k2 += l;
|
|
||||||
k2 ^= l >>> 9;
|
|
||||||
j1 += k2;
|
|
||||||
l += i1;
|
|
||||||
memory[j] = l;
|
|
||||||
memory[j + 1] = i1;
|
|
||||||
memory[j + 2] = j1;
|
|
||||||
memory[j + 3] = k1;
|
|
||||||
memory[j + 4] = l1;
|
|
||||||
memory[j + 5] = i2;
|
|
||||||
memory[j + 6] = j2;
|
|
||||||
memory[j + 7] = k2;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int k = 0; k < 256; k += 8) {
|
|
||||||
l += memory[k];
|
|
||||||
i1 += memory[k + 1];
|
|
||||||
j1 += memory[k + 2];
|
|
||||||
k1 += memory[k + 3];
|
|
||||||
l1 += memory[k + 4];
|
|
||||||
i2 += memory[k + 5];
|
|
||||||
j2 += memory[k + 6];
|
|
||||||
k2 += memory[k + 7];
|
|
||||||
l ^= i1 << 11;
|
|
||||||
k1 += l;
|
|
||||||
i1 += j1;
|
|
||||||
i1 ^= j1 >>> 2;
|
|
||||||
l1 += i1;
|
|
||||||
j1 += k1;
|
|
||||||
j1 ^= k1 << 8;
|
|
||||||
i2 += j1;
|
|
||||||
k1 += l1;
|
|
||||||
k1 ^= l1 >>> 16;
|
|
||||||
j2 += k1;
|
|
||||||
l1 += i2;
|
|
||||||
l1 ^= i2 << 10;
|
|
||||||
k2 += l1;
|
|
||||||
i2 += j2;
|
|
||||||
i2 ^= j2 >>> 4;
|
|
||||||
l += i2;
|
|
||||||
j2 += k2;
|
|
||||||
j2 ^= k2 << 8;
|
|
||||||
i1 += j2;
|
|
||||||
k2 += l;
|
|
||||||
k2 ^= l >>> 9;
|
|
||||||
j1 += k2;
|
|
||||||
l += i1;
|
|
||||||
memory[k] = l;
|
|
||||||
memory[k + 1] = i1;
|
|
||||||
memory[k + 2] = j1;
|
|
||||||
memory[k + 3] = k1;
|
|
||||||
memory[k + 4] = l1;
|
|
||||||
memory[k + 5] = i2;
|
|
||||||
memory[k + 6] = j2;
|
|
||||||
memory[k + 7] = k2;
|
|
||||||
}
|
|
||||||
|
|
||||||
generateNextKeySet();
|
|
||||||
count = 256;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -124,20 +124,7 @@ public class Misc {
|
|||||||
}
|
}
|
||||||
return temp.toUpperCase().trim();
|
return temp.toUpperCase().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int hexToInt(byte data[], int offset, int len) {
|
|
||||||
int temp = 0;
|
|
||||||
int i = 1000;
|
|
||||||
for (int cntr = 0; cntr < len; cntr++) {
|
|
||||||
int num = (data[offset + cntr] & 0xFF) * i;
|
|
||||||
temp += num;
|
|
||||||
if (i > 1) {
|
|
||||||
i = i / 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int random2(int range) {
|
public static int random2(int range) {
|
||||||
return (int) (java.lang.Math.random() * range + 1);
|
return (int) (java.lang.Math.random() * range + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.rs2.util;
|
package com.rs2.util;
|
||||||
|
|
||||||
|
import org.apollo.util.security.IsaacRandom;
|
||||||
|
|
||||||
import com.rs2.GameConstants;
|
import com.rs2.GameConstants;
|
||||||
|
|
||||||
public class Stream {
|
public class Stream {
|
||||||
@@ -12,36 +14,6 @@ public class Stream {
|
|||||||
currentOffset = 0;
|
currentOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long readQWord2() {
|
|
||||||
final long l = readDWord() & 0xffffffffL;
|
|
||||||
final long l1 = readDWord() & 0xffffffffL;
|
|
||||||
return (l << 32) + l1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte readSignedByteA() {
|
|
||||||
return (byte) (buffer[currentOffset++] - 128);
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte readSignedByteC() {
|
|
||||||
return (byte) -buffer[currentOffset++];
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte readSignedByteS() {
|
|
||||||
return (byte) (128 - buffer[currentOffset++]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readUnsignedByteA() {
|
|
||||||
return buffer[currentOffset++] - 128 & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readUnsignedByteC() {
|
|
||||||
return -buffer[currentOffset++] & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readUnsignedByteS() {
|
|
||||||
return 128 - buffer[currentOffset++] & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeByteA(int i) {
|
public void writeByteA(int i) {
|
||||||
ensureCapacity(1);
|
ensureCapacity(1);
|
||||||
buffer[currentOffset++] = (byte) (i + 128);
|
buffer[currentOffset++] = (byte) (i + 128);
|
||||||
@@ -56,49 +28,7 @@ public class Stream {
|
|||||||
ensureCapacity(1);
|
ensureCapacity(1);
|
||||||
buffer[currentOffset++] = (byte) -i;
|
buffer[currentOffset++] = (byte) -i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readSignedWordBigEndian() {
|
|
||||||
currentOffset += 2;
|
|
||||||
int i = ((buffer[currentOffset - 1] & 0xff) << 8) + (buffer[currentOffset - 2] & 0xff);
|
|
||||||
if (i > 32767) {
|
|
||||||
i -= 0x10000;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readSignedWordA() {
|
|
||||||
currentOffset += 2;
|
|
||||||
int i = ((buffer[currentOffset - 2] & 0xff) << 8) + (buffer[currentOffset - 1] - 128 & 0xff);
|
|
||||||
if (i > 32767) {
|
|
||||||
i -= 0x10000;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readSignedWordBigEndianA() {
|
|
||||||
currentOffset += 2;
|
|
||||||
int i = ((buffer[currentOffset - 1] & 0xff) << 8) + (buffer[currentOffset - 2] - 128 & 0xff);
|
|
||||||
if (i > 32767) {
|
|
||||||
i -= 0x10000;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readUnsignedWordBigEndian() {
|
|
||||||
currentOffset += 2;
|
|
||||||
return ((buffer[currentOffset - 1] & 0xff) << 8) + (buffer[currentOffset - 2] & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readUnsignedWordA() {
|
|
||||||
currentOffset += 2;
|
|
||||||
return ((buffer[currentOffset - 2] & 0xff) << 8) + (buffer[currentOffset - 1] - 128 & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readUnsignedWordBigEndianA() {
|
|
||||||
currentOffset += 2;
|
|
||||||
return ((buffer[currentOffset - 1] & 0xff) << 8) + (buffer[currentOffset - 2] - 128 & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeWordBigEndianA(int i) {
|
public void writeWordBigEndianA(int i) {
|
||||||
ensureCapacity(2);
|
ensureCapacity(2);
|
||||||
buffer[currentOffset++] = (byte) (i + 128);
|
buffer[currentOffset++] = (byte) (i + 128);
|
||||||
@@ -149,13 +79,6 @@ public class Stream {
|
|||||||
buffer[currentOffset++] = (byte) (i >> 8);
|
buffer[currentOffset++] = (byte) (i >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readBytes_reverse(byte abyte0[], int i, int j) {
|
|
||||||
for (int k = j + i - 1; k >= j; k--) {
|
|
||||||
abyte0[k] = buffer[currentOffset++];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeBytes_reverse(byte abyte0[], int i, int j) {
|
public void writeBytes_reverse(byte abyte0[], int i, int j) {
|
||||||
ensureCapacity(i);
|
ensureCapacity(i);
|
||||||
for (int k = j + i - 1; k >= j; k--) {
|
for (int k = j + i - 1; k >= j; k--) {
|
||||||
@@ -163,14 +86,6 @@ public class Stream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readBytes_reverseA(byte abyte0[], int i, int j) {
|
|
||||||
ensureCapacity(i);
|
|
||||||
for (int k = j + i - 1; k >= j; k--) {
|
|
||||||
abyte0[k] = (byte) (buffer[currentOffset++] - 128);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void writeBytes_reverseA(byte abyte0[], int i, int j) {
|
public void writeBytes_reverseA(byte abyte0[], int i, int j) {
|
||||||
ensureCapacity(i);
|
ensureCapacity(i);
|
||||||
for (int k = j + i - 1; k >= j; k--) {
|
for (int k = j + i - 1; k >= j; k--) {
|
||||||
@@ -181,7 +96,7 @@ public class Stream {
|
|||||||
|
|
||||||
public void createFrame(int id) {
|
public void createFrame(int id) {
|
||||||
ensureCapacity(1);
|
ensureCapacity(1);
|
||||||
buffer[currentOffset++] = (byte) (id + packetEncryption.getNextKey());
|
buffer[currentOffset++] = (byte) (id + packetEncryption.nextInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int frameStackSize = 10;
|
private static final int frameStackSize = 10;
|
||||||
@@ -190,7 +105,7 @@ public class Stream {
|
|||||||
|
|
||||||
public void createFrameVarSize(int id) {
|
public void createFrameVarSize(int id) {
|
||||||
ensureCapacity(3);
|
ensureCapacity(3);
|
||||||
buffer[currentOffset++] = (byte) (id + packetEncryption.getNextKey());
|
buffer[currentOffset++] = (byte) (id + packetEncryption.nextInt());
|
||||||
buffer[currentOffset++] = 0;
|
buffer[currentOffset++] = 0;
|
||||||
if (frameStackPtr >= frameStackSize - 1) {
|
if (frameStackPtr >= frameStackSize - 1) {
|
||||||
throw new RuntimeException("Stack overflow");
|
throw new RuntimeException("Stack overflow");
|
||||||
@@ -201,7 +116,7 @@ public class Stream {
|
|||||||
|
|
||||||
public void createFrameVarSizeWord(int id) {
|
public void createFrameVarSizeWord(int id) {
|
||||||
ensureCapacity(2);
|
ensureCapacity(2);
|
||||||
buffer[currentOffset++] = (byte) (id + packetEncryption.getNextKey());
|
buffer[currentOffset++] = (byte) (id + packetEncryption.nextInt());
|
||||||
writeWord(0);
|
writeWord(0);
|
||||||
if (frameStackPtr >= frameStackSize - 1) {
|
if (frameStackPtr >= frameStackSize - 1) {
|
||||||
throw new RuntimeException("Stack overflow");
|
throw new RuntimeException("Stack overflow");
|
||||||
@@ -301,57 +216,6 @@ public class Stream {
|
|||||||
buffer[currentOffset - i - 1] = (byte) i;
|
buffer[currentOffset - i - 1] = (byte) i;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int readUnsignedByte() {
|
|
||||||
return buffer[currentOffset++] & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte readSignedByte() {
|
|
||||||
return buffer[currentOffset++];
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readUnsignedWord() {
|
|
||||||
currentOffset += 2;
|
|
||||||
return ((buffer[currentOffset - 2] & 0xff) << 8) + (buffer[currentOffset - 1] & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readSignedWord() {
|
|
||||||
currentOffset += 2;
|
|
||||||
int i = ((buffer[currentOffset - 2] & 0xff) << 8) + (buffer[currentOffset - 1] & 0xff);
|
|
||||||
if (i > 32767) {
|
|
||||||
i -= 0x10000;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int readDWord() {
|
|
||||||
currentOffset += 4;
|
|
||||||
return ((buffer[currentOffset - 4] & 0xff) << 24)
|
|
||||||
+ ((buffer[currentOffset - 3] & 0xff) << 16)
|
|
||||||
+ ((buffer[currentOffset - 2] & 0xff) << 8)
|
|
||||||
+ (buffer[currentOffset - 1] & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
public long readQWord() {
|
|
||||||
long l = readDWord() & 0xffffffffL;
|
|
||||||
long l1 = readDWord() & 0xffffffffL;
|
|
||||||
return (l << 32) + l1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public java.lang.String readString() {
|
|
||||||
int i = currentOffset;
|
|
||||||
while (buffer[currentOffset++] != 10) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return new String(buffer, i, currentOffset - i - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void readBytes(byte abyte0[], int i, int j) {
|
|
||||||
for (int k = j; k < j + i; k++) {
|
|
||||||
abyte0[k] = buffer[currentOffset++];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initBitAccess() {
|
public void initBitAccess() {
|
||||||
bitPosition = currentOffset * 8;
|
bitPosition = currentOffset * 8;
|
||||||
}
|
}
|
||||||
@@ -414,6 +278,6 @@ public class Stream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ISAACRandomGen packetEncryption = null;
|
public IsaacRandom packetEncryption = null;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package com.rs2.world.clip;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.apollo.archive.Archive;
|
import org.apollo.cache.IndexedFileSystem;
|
||||||
import org.apollo.jagcached.fs.IndexedFileSystem;
|
import org.apollo.cache.archive.Archive;
|
||||||
|
|
||||||
public final class ObjectDefinition {
|
public final class ObjectDefinition {
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
package com.rs2.world.clip;
|
package com.rs2.world.clip;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
import org.apollo.archive.Archive;
|
import org.apollo.cache.IndexedFileSystem;
|
||||||
import org.apollo.archive.ArchiveEntry;
|
import org.apollo.cache.archive.Archive;
|
||||||
import org.apollo.archive.CompressionUtil;
|
import org.apollo.cache.archive.ArchiveEntry;
|
||||||
import org.apollo.jagcached.Constants;
|
import org.apollo.jagcached.Constants;
|
||||||
import org.apollo.jagcached.fs.IndexedFileSystem;
|
import org.apollo.util.CompressionUtil;
|
||||||
|
|
||||||
public class RegionFactory {
|
public class RegionFactory {
|
||||||
|
|
||||||
@@ -22,7 +20,7 @@ public class RegionFactory {
|
|||||||
public static void load() {
|
public static void load() {
|
||||||
//GameEngine.getLogger(Region.class).info("Loading region configurations...");
|
//GameEngine.getLogger(Region.class).info("Loading region configurations...");
|
||||||
try {
|
try {
|
||||||
IndexedFileSystem fs = new IndexedFileSystem(new File(Constants.FILE_SYSTEM_DIR), true);
|
IndexedFileSystem fs = new IndexedFileSystem(Paths.get(Constants.FILE_SYSTEM_DIR), true);
|
||||||
ObjectDefinition.loadConfig(fs);
|
ObjectDefinition.loadConfig(fs);
|
||||||
|
|
||||||
Archive archive = Archive.decode(fs.getFile(0, 5));
|
Archive archive = Archive.decode(fs.getFile(0, 5));
|
||||||
@@ -56,8 +54,8 @@ public class RegionFactory {
|
|||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
//GameEngine.getLogger(Region.class).info("Region: " + i + " RegionId: " + regionIds[i] + " ObjectsId: " + mapObjectsFileIds[i]
|
//GameEngine.getLogger(Region.class).info("Region: " + i + " RegionId: " + regionIds[i] + " ObjectsId: " + mapObjectsFileIds[i]
|
||||||
// + " ClippingsId: " + mapGroundFileIds[i]);
|
// + " ClippingsId: " + mapGroundFileIds[i]);
|
||||||
byte[] file1 = CompressionUtil.degzip(fs.getFileBytes(4, mapObjectsFileIds[i]));
|
byte[] file1 = CompressionUtil.degzip(fs.getFile(4, mapObjectsFileIds[i]));
|
||||||
byte[] file2 = CompressionUtil.degzip(fs.getFileBytes(4, mapGroundFileIds[i]));
|
byte[] file2 = CompressionUtil.degzip(fs.getFile(4, mapGroundFileIds[i]));
|
||||||
if (file1 == null || file2 == null) {
|
if (file1 == null || file2 == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
+38
-17
@@ -1,23 +1,27 @@
|
|||||||
package org.apollo.jagcached.fs;
|
package org.apollo.cache;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class which points to a file in the cache.
|
* A class which points to a file in the cache.
|
||||||
|
*
|
||||||
* @author Graham
|
* @author Graham
|
||||||
*/
|
*/
|
||||||
public final class FileDescriptor {
|
public final class FileDescriptor {
|
||||||
|
|
||||||
/**
|
|
||||||
* The file type.
|
|
||||||
*/
|
|
||||||
private final int type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The file id.
|
* The file id.
|
||||||
*/
|
*/
|
||||||
private final int file;
|
private final int file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file type.
|
||||||
|
*/
|
||||||
|
private final int type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the file descriptor.
|
* Creates the file descriptor.
|
||||||
|
*
|
||||||
* @param type The file type.
|
* @param type The file type.
|
||||||
* @param file The file id.
|
* @param file The file id.
|
||||||
*/
|
*/
|
||||||
@@ -25,21 +29,38 @@ public final class FileDescriptor {
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
this.file = file;
|
this.file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Gets the file type.
|
public boolean equals(Object obj) {
|
||||||
* @return The file type.
|
if (obj instanceof FileDescriptor) {
|
||||||
*/
|
FileDescriptor other = (FileDescriptor) obj;
|
||||||
public int getType() {
|
return type == other.type && file == other.file;
|
||||||
return type;
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the file id.
|
* Gets the file id.
|
||||||
|
*
|
||||||
* @return The file id.
|
* @return The file id.
|
||||||
*/
|
*/
|
||||||
public int getFile() {
|
public int getFile() {
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Gets the file type.
|
||||||
|
*
|
||||||
|
* @return The file type.
|
||||||
|
*/
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return file * FileSystemConstants.ARCHIVE_COUNT + type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+17
-21
@@ -1,46 +1,42 @@
|
|||||||
package org.apollo.jagcached.fs;
|
package org.apollo.cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds file system related constants.
|
* Holds file system related constants.
|
||||||
|
*
|
||||||
* @author Graham
|
* @author Graham
|
||||||
*/
|
*/
|
||||||
public final class FileSystemConstants {
|
public final class FileSystemConstants {
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of caches.
|
|
||||||
*/
|
|
||||||
public static final int CACHE_COUNT = 5;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of archives in cache 0.
|
* The number of archives in cache 0.
|
||||||
*/
|
*/
|
||||||
public static final int ARCHIVE_COUNT = 9;
|
public static final int ARCHIVE_COUNT = 9;
|
||||||
|
|
||||||
/**
|
|
||||||
* The size of an index.
|
|
||||||
*/
|
|
||||||
public static final int INDEX_SIZE = 6;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The size of a header.
|
|
||||||
*/
|
|
||||||
public static final int HEADER_SIZE = 8;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size of a chunk.
|
* The size of a chunk.
|
||||||
*/
|
*/
|
||||||
public static final int CHUNK_SIZE = 512;
|
public static final int CHUNK_SIZE = 512;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of a header.
|
||||||
|
*/
|
||||||
|
public static final int HEADER_SIZE = 8;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size of a block.
|
* The size of a block.
|
||||||
*/
|
*/
|
||||||
public static final int BLOCK_SIZE = HEADER_SIZE + CHUNK_SIZE;
|
public static final int BLOCK_SIZE = HEADER_SIZE + CHUNK_SIZE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of an index.
|
||||||
|
*/
|
||||||
|
public static final int INDEX_SIZE = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default private constructor to prevent instantiation.
|
* Default private constructor to prevent instantiation.
|
||||||
*/
|
*/
|
||||||
private FileSystemConstants() {
|
private FileSystemConstants() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+31
-26
@@ -1,40 +1,43 @@
|
|||||||
package org.apollo.jagcached.fs;
|
package org.apollo.cache;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link Index} points to a file in the {@code main_file_cache.dat} file.
|
* An {@link Index} points to a file in the {@code main_file_cache.dat} file.
|
||||||
|
*
|
||||||
* @author Graham
|
* @author Graham
|
||||||
*/
|
*/
|
||||||
public final class Index {
|
public final class Index {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes a buffer into an index.
|
* Decodes a buffer into an index.
|
||||||
|
*
|
||||||
* @param buffer The buffer.
|
* @param buffer The buffer.
|
||||||
* @return The decoded {@link Index}.
|
* @return The decoded {@link Index}.
|
||||||
* @throws IllegalArgumentException if the buffer length is invalid.
|
* @throws IllegalArgumentException If the buffer length is invalid.
|
||||||
*/
|
*/
|
||||||
public static Index decode(byte[] buffer) {
|
public static Index decode(byte[] buffer) {
|
||||||
if (buffer.length != FileSystemConstants.INDEX_SIZE) {
|
Preconditions.checkArgument(buffer.length == FileSystemConstants.INDEX_SIZE, "Incorrect buffer length.");
|
||||||
throw new IllegalArgumentException("Incorrect buffer length.");
|
|
||||||
}
|
int size = (buffer[0] & 0xFF) << 16 | (buffer[1] & 0xFF) << 8 | buffer[2] & 0xFF;
|
||||||
|
int block = (buffer[3] & 0xFF) << 16 | (buffer[4] & 0xFF) << 8 | buffer[5] & 0xFF;
|
||||||
int size = ((buffer[0] & 0xFF) << 16) | ((buffer[1] & 0xFF) << 8) | (buffer[2] & 0xFF);
|
|
||||||
int block = ((buffer[3] & 0xFF) << 16) | ((buffer[4] & 0xFF) << 8) | (buffer[5] & 0xFF);
|
|
||||||
|
|
||||||
return new Index(size, block);
|
return new Index(size, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* The size of the file.
|
|
||||||
*/
|
|
||||||
private final int size;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The first block of the file.
|
* The first block of the file.
|
||||||
*/
|
*/
|
||||||
private final int block;
|
private final int block;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the file.
|
||||||
|
*/
|
||||||
|
private final int size;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the index.
|
* Creates the index.
|
||||||
|
*
|
||||||
* @param size The size of the file.
|
* @param size The size of the file.
|
||||||
* @param block The first block of the file.
|
* @param block The first block of the file.
|
||||||
*/
|
*/
|
||||||
@@ -42,21 +45,23 @@ public final class Index {
|
|||||||
this.size = size;
|
this.size = size;
|
||||||
this.block = block;
|
this.block = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the size of the file.
|
|
||||||
* @return The size of the file.
|
|
||||||
*/
|
|
||||||
public int getSize() {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the first block of the file.
|
* Gets the first block of the file.
|
||||||
|
*
|
||||||
* @return The first block of the file.
|
* @return The first block of the file.
|
||||||
*/
|
*/
|
||||||
public int getBlock() {
|
public int getBlock() {
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* Gets the size of the file.
|
||||||
|
*
|
||||||
|
* @return The size of the file.
|
||||||
|
*/
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,332 @@
|
|||||||
|
package org.apollo.cache;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import org.apollo.cache.archive.Archive;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.zip.CRC32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A file system based on top of the operating system's file system. It consists of a data file and index files. Index
|
||||||
|
* files point to blocks in the data file, which contains the actual data.
|
||||||
|
*
|
||||||
|
* @author Graham
|
||||||
|
*/
|
||||||
|
public final class IndexedFileSystem implements Closeable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Map that caches already-decoded Archives.
|
||||||
|
*/
|
||||||
|
private final Map<FileDescriptor, Archive> cache = new HashMap<>(FileSystemConstants.ARCHIVE_COUNT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index files.
|
||||||
|
*/
|
||||||
|
private final RandomAccessFile[] indices = new RandomAccessFile[256];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read only flag.
|
||||||
|
*/
|
||||||
|
private final boolean readOnly;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cached CRC table.
|
||||||
|
*/
|
||||||
|
private ByteBuffer crcTable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link #crcTable} represented as an {@code int} array.
|
||||||
|
*/
|
||||||
|
private int[] crcs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data file.
|
||||||
|
*/
|
||||||
|
private RandomAccessFile data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the file system with the specified base directory.
|
||||||
|
*
|
||||||
|
* @param base The base directory.
|
||||||
|
* @param readOnly Indicates whether the file system will be read only or not.
|
||||||
|
* @throws FileNotFoundException If the data files could not be found.
|
||||||
|
*/
|
||||||
|
public IndexedFileSystem(Path base, boolean readOnly) throws FileNotFoundException {
|
||||||
|
this.readOnly = readOnly;
|
||||||
|
detectLayout(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (data != null) {
|
||||||
|
synchronized (data) {
|
||||||
|
data.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (RandomAccessFile index : indices) {
|
||||||
|
if (index != null) {
|
||||||
|
synchronized (index) {
|
||||||
|
index.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link Archive} pointed to by the specified {@link FileDescriptor}.
|
||||||
|
*
|
||||||
|
* @param type The file type.
|
||||||
|
* @param file The file id.
|
||||||
|
* @return The Archive.
|
||||||
|
* @throws IOException If there is an error decoding the Archive.
|
||||||
|
*/
|
||||||
|
public Archive getArchive(int type, int file) throws IOException {
|
||||||
|
FileDescriptor descriptor = new FileDescriptor(type, file);
|
||||||
|
Archive cached = cache.get(descriptor);
|
||||||
|
|
||||||
|
if (cached == null) {
|
||||||
|
cached = Archive.decode(getFile(descriptor));
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
cache.put(descriptor, cached);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the CRC table.
|
||||||
|
*
|
||||||
|
* @return The CRC table.
|
||||||
|
* @throws IOException If there is an error accessing files to create the table.
|
||||||
|
* @throws IllegalStateException If this file system is not read-only.
|
||||||
|
*/
|
||||||
|
public ByteBuffer getCrcTable() throws IOException {
|
||||||
|
if (readOnly) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (crcTable != null) {
|
||||||
|
return crcTable.duplicate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int archives = getFileCount(0);
|
||||||
|
int hash = 1234;
|
||||||
|
int[] crcs = new int[archives];
|
||||||
|
|
||||||
|
CRC32 crc32 = new CRC32();
|
||||||
|
for (int i = 1; i < crcs.length; i++) {
|
||||||
|
crc32.reset();
|
||||||
|
|
||||||
|
ByteBuffer buffer = getFile(0, i);
|
||||||
|
byte[] bytes = new byte[buffer.remaining()];
|
||||||
|
buffer.get(bytes, 0, bytes.length);
|
||||||
|
crc32.update(bytes, 0, bytes.length);
|
||||||
|
|
||||||
|
crcs[i] = (int) crc32.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate((crcs.length + 1) * Integer.BYTES);
|
||||||
|
for (int crc : crcs) {
|
||||||
|
hash = (hash << 1) + crc;
|
||||||
|
buffer.putInt(crc);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.putInt(hash);
|
||||||
|
buffer.flip();
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
crcTable = buffer.asReadOnlyBuffer();
|
||||||
|
return crcTable.duplicate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Cannot get CRC table from a writable file system.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the CRC table as an {@code int} array.
|
||||||
|
*
|
||||||
|
* @return The CRC table as an {@code int} array.
|
||||||
|
* @throws IOException If there is an error accessing files to create the table.
|
||||||
|
*/
|
||||||
|
public int[] getCrcs() throws IOException {
|
||||||
|
if (crcs == null) {
|
||||||
|
ByteBuffer buffer = getCrcTable();
|
||||||
|
crcs = new int[(buffer.remaining() / Integer.BYTES) - 1];
|
||||||
|
Arrays.setAll(crcs, crc -> buffer.getInt());
|
||||||
|
}
|
||||||
|
return crcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a file.
|
||||||
|
*
|
||||||
|
* @param descriptor The {@link FileDescriptor} pointing to the file.
|
||||||
|
* @return A {@link ByteBuffer} containing the contents of the file.
|
||||||
|
* @throws IOException If there is an error decoding the file.
|
||||||
|
*/
|
||||||
|
public ByteBuffer getFile(FileDescriptor descriptor) throws IOException {
|
||||||
|
Index index = getIndex(descriptor);
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(index.getSize());
|
||||||
|
|
||||||
|
long position = index.getBlock() * FileSystemConstants.BLOCK_SIZE;
|
||||||
|
int read = 0;
|
||||||
|
int size = index.getSize();
|
||||||
|
int blocks = size / FileSystemConstants.CHUNK_SIZE;
|
||||||
|
if (size % FileSystemConstants.CHUNK_SIZE != 0) {
|
||||||
|
blocks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < blocks; i++) {
|
||||||
|
byte[] header = new byte[FileSystemConstants.HEADER_SIZE];
|
||||||
|
synchronized (data) {
|
||||||
|
data.seek(position);
|
||||||
|
data.readFully(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
position += FileSystemConstants.HEADER_SIZE;
|
||||||
|
|
||||||
|
int nextFile = (header[0] & 0xFF) << 8 | header[1] & 0xFF;
|
||||||
|
int curChunk = (header[2] & 0xFF) << 8 | header[3] & 0xFF;
|
||||||
|
int nextBlock = (header[4] & 0xFF) << 16 | (header[5] & 0xFF) << 8 | header[6] & 0xFF;
|
||||||
|
int nextType = header[7] & 0xFF;
|
||||||
|
|
||||||
|
Preconditions.checkArgument(i == curChunk, "Chunk id mismatch.");
|
||||||
|
|
||||||
|
int chunkSize = size - read;
|
||||||
|
if (chunkSize > FileSystemConstants.CHUNK_SIZE) {
|
||||||
|
chunkSize = FileSystemConstants.CHUNK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] chunk = new byte[chunkSize];
|
||||||
|
synchronized (data) {
|
||||||
|
data.seek(position);
|
||||||
|
data.readFully(chunk);
|
||||||
|
}
|
||||||
|
buffer.put(chunk);
|
||||||
|
|
||||||
|
read += chunkSize;
|
||||||
|
position = (long) nextBlock * (long) FileSystemConstants.BLOCK_SIZE;
|
||||||
|
|
||||||
|
// if we still have more data to read, check the validity of the header
|
||||||
|
if (size > read) {
|
||||||
|
if (nextType != descriptor.getType() + 1) {
|
||||||
|
throw new IOException("File type mismatch.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextFile != descriptor.getFile()) {
|
||||||
|
throw new IOException("File id mismatch.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.flip();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a file.
|
||||||
|
*
|
||||||
|
* @param type The file type.
|
||||||
|
* @param file The file id.
|
||||||
|
* @return A {@link ByteBuffer} which contains the contents of the file.
|
||||||
|
* @throws IOException If an I/O error occurs.
|
||||||
|
*/
|
||||||
|
public ByteBuffer getFile(int type, int file) throws IOException {
|
||||||
|
return getFile(new FileDescriptor(type, file));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this {@link IndexedFileSystem} is read only.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean isReadOnly() {
|
||||||
|
return readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Automatically detect the layout of the specified directory.
|
||||||
|
*
|
||||||
|
* @param base The base directory.
|
||||||
|
* @throws FileNotFoundException If the data files could not be found.
|
||||||
|
*/
|
||||||
|
private void detectLayout(Path base) throws FileNotFoundException {
|
||||||
|
int indexCount = 0;
|
||||||
|
for (int index = 0; index < indices.length; index++) {
|
||||||
|
Path idx = base.resolve("main_file_cache.idx" + index);
|
||||||
|
if (Files.exists(idx) && !Files.isDirectory(idx)) {
|
||||||
|
indexCount++;
|
||||||
|
indices[index] = new RandomAccessFile(idx.toFile(), readOnly ? "r" : "rw");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (indexCount <= 0) {
|
||||||
|
throw new FileNotFoundException("No index file(s) present in " + base + ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
Path resources = base.resolve("main_file_cache.dat");
|
||||||
|
if (Files.exists(resources) && !Files.isDirectory(resources)) {
|
||||||
|
data = new RandomAccessFile(resources.toFile(), readOnly ? "r" : "rw");
|
||||||
|
} else {
|
||||||
|
throw new FileNotFoundException("No data file present.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the number of files with the specified type.
|
||||||
|
*
|
||||||
|
* @param type The type.
|
||||||
|
* @return The number of files.
|
||||||
|
* @throws IOException If there is an error getting the length of the specified index file.
|
||||||
|
* @throws IndexOutOfBoundsException If {@code type} is less than 0, or greater than or equal to the amount of
|
||||||
|
* indices.
|
||||||
|
*/
|
||||||
|
private int getFileCount(int type) throws IOException {
|
||||||
|
Preconditions.checkElementIndex(type, indices.length, "File type out of bounds.");
|
||||||
|
|
||||||
|
RandomAccessFile indexFile = indices[type];
|
||||||
|
synchronized (indexFile) {
|
||||||
|
return (int) (indexFile.length() / FileSystemConstants.INDEX_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the index of a file.
|
||||||
|
*
|
||||||
|
* @param descriptor The {@link FileDescriptor} which points to the file.
|
||||||
|
* @return The {@link Index}.
|
||||||
|
* @throws IOException If there is an error reading from the index file.
|
||||||
|
* @throws IndexOutOfBoundsException If the descriptor type is less than 0, or greater than or equal to the amount
|
||||||
|
* of indices.
|
||||||
|
*/
|
||||||
|
private Index getIndex(FileDescriptor descriptor) throws IOException {
|
||||||
|
int index = descriptor.getType();
|
||||||
|
Preconditions.checkElementIndex(index, indices.length, "File descriptor type out of bounds.");
|
||||||
|
|
||||||
|
byte[] buffer = new byte[FileSystemConstants.INDEX_SIZE];
|
||||||
|
RandomAccessFile indexFile = indices[index];
|
||||||
|
synchronized (indexFile) {
|
||||||
|
long position = descriptor.getFile() * FileSystemConstants.INDEX_SIZE;
|
||||||
|
if (position >= 0 && indexFile.length() >= position + FileSystemConstants.INDEX_SIZE) {
|
||||||
|
indexFile.seek(position);
|
||||||
|
indexFile.readFully(buffer);
|
||||||
|
} else {
|
||||||
|
throw new FileNotFoundException("Could not find find index.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Index.decode(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+9
-41
@@ -1,12 +1,11 @@
|
|||||||
package org.apollo.archive;
|
package org.apollo.cache.archive;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
|
import org.apollo.util.BufferUtil;
|
||||||
|
import org.apollo.util.CompressionUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an archive.
|
* Represents an archive.
|
||||||
@@ -23,15 +22,15 @@ public final class Archive {
|
|||||||
* @throws IOException If there is an error decompressing the archive.
|
* @throws IOException If there is an error decompressing the archive.
|
||||||
*/
|
*/
|
||||||
public static Archive decode(ByteBuffer buffer) throws IOException {
|
public static Archive decode(ByteBuffer buffer) throws IOException {
|
||||||
int extractedSize = Archive.readUnsignedMedium(buffer);
|
int extractedSize = BufferUtil.readUnsignedMedium(buffer);
|
||||||
int size = Archive.readUnsignedMedium(buffer);
|
int size = BufferUtil.readUnsignedMedium(buffer);
|
||||||
boolean extracted = false;
|
boolean extracted = false;
|
||||||
|
|
||||||
if (size != extractedSize) {
|
if (size != extractedSize) {
|
||||||
byte[] compressed = new byte[size];
|
byte[] compressed = new byte[size];
|
||||||
byte[] decompressed = new byte[extractedSize];
|
byte[] decompressed = new byte[extractedSize];
|
||||||
buffer.get(compressed);
|
buffer.get(compressed);
|
||||||
Archive.debzip2(compressed, decompressed);
|
CompressionUtil.debzip2(compressed, decompressed);
|
||||||
buffer = ByteBuffer.wrap(decompressed);
|
buffer = ByteBuffer.wrap(decompressed);
|
||||||
extracted = true;
|
extracted = true;
|
||||||
}
|
}
|
||||||
@@ -43,8 +42,8 @@ public final class Archive {
|
|||||||
|
|
||||||
for (int i = 0; i < entryCount; i++) {
|
for (int i = 0; i < entryCount; i++) {
|
||||||
identifiers[i] = buffer.getInt();
|
identifiers[i] = buffer.getInt();
|
||||||
extractedSizes[i] = Archive.readUnsignedMedium(buffer);
|
extractedSizes[i] = BufferUtil.readUnsignedMedium(buffer);
|
||||||
sizes[i] = Archive.readUnsignedMedium(buffer);
|
sizes[i] = BufferUtil.readUnsignedMedium(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchiveEntry[] entries = new ArchiveEntry[entryCount];
|
ArchiveEntry[] entries = new ArchiveEntry[entryCount];
|
||||||
@@ -54,7 +53,7 @@ public final class Archive {
|
|||||||
byte[] compressed = new byte[sizes[entry]];
|
byte[] compressed = new byte[sizes[entry]];
|
||||||
byte[] decompressed = new byte[extractedSizes[entry]];
|
byte[] decompressed = new byte[extractedSizes[entry]];
|
||||||
buffer.get(compressed);
|
buffer.get(compressed);
|
||||||
Archive.debzip2(compressed, decompressed);
|
CompressionUtil.debzip2(compressed, decompressed);
|
||||||
entryBuffer = ByteBuffer.wrap(decompressed);
|
entryBuffer = ByteBuffer.wrap(decompressed);
|
||||||
} else {
|
} else {
|
||||||
byte[] buf = new byte[extractedSizes[entry]];
|
byte[] buf = new byte[extractedSizes[entry]];
|
||||||
@@ -107,36 +106,5 @@ public final class Archive {
|
|||||||
public static int hash(String name) {
|
public static int hash(String name) {
|
||||||
return name.toUpperCase().chars().reduce(0, (hash, character) -> hash * 61 + character - 32);
|
return name.toUpperCase().chars().reduce(0, (hash, character) -> hash * 61 + character - 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Debzip2s the compressed array and places the result into the decompressed array.
|
|
||||||
*
|
|
||||||
* @param compressed The compressed array, <strong>without</strong> the header.
|
|
||||||
* @param decompressed The decompressed array.
|
|
||||||
* @throws IOException If there is an error decompressing the array.
|
|
||||||
*/
|
|
||||||
private static void debzip2(byte[] compressed, byte[] decompressed) throws IOException {
|
|
||||||
byte[] newCompressed = new byte[compressed.length + 4];
|
|
||||||
newCompressed[0] = 'B';
|
|
||||||
newCompressed[1] = 'Z';
|
|
||||||
newCompressed[2] = 'h';
|
|
||||||
newCompressed[3] = '1';
|
|
||||||
System.arraycopy(compressed, 0, newCompressed, 4, compressed.length);
|
|
||||||
|
|
||||||
try (DataInputStream is = new DataInputStream(new BZip2CompressorInputStream(new ByteArrayInputStream(newCompressed)))) {
|
|
||||||
is.readFully(decompressed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads a 24-bit medium integer from the specified {@link ByteBuffer}s current position and increases the buffers
|
|
||||||
* position by 3.
|
|
||||||
*
|
|
||||||
* @param buffer The {@link ByteBuffer} to read from.
|
|
||||||
* @return The read 24-bit medium integer.
|
|
||||||
*/
|
|
||||||
private static int readUnsignedMedium(ByteBuffer buffer) {
|
|
||||||
return (buffer.getShort() & 0xFFFF) << 8 | buffer.get() & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package org.apollo.archive;
|
package org.apollo.cache.archive;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Contains classes which deal with archives.
|
||||||
|
*/
|
||||||
|
package org.apollo.cache.archive;
|
||||||
+130
@@ -0,0 +1,130 @@
|
|||||||
|
package org.apollo.cache.decoder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.apollo.cache.IndexedFileSystem;
|
||||||
|
import org.apollo.cache.archive.Archive;
|
||||||
|
import org.apollo.cache.def.ItemDefinition;
|
||||||
|
import org.apollo.util.BufferUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes item data from the {@code obj.dat} file into {@link ItemDefinition}s.
|
||||||
|
*
|
||||||
|
* @author Graham
|
||||||
|
*/
|
||||||
|
public final class ItemDefinitionDecoder implements Runnable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IndexedFileSystem.
|
||||||
|
*/
|
||||||
|
private final IndexedFileSystem fs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the ItemDefinitionDecoder.
|
||||||
|
*
|
||||||
|
* @param fs The {@link IndexedFileSystem}.
|
||||||
|
*/
|
||||||
|
public ItemDefinitionDecoder(IndexedFileSystem fs) {
|
||||||
|
this.fs = fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Archive config = fs.getArchive(0, 2);
|
||||||
|
ByteBuffer data = config.getEntry("obj.dat").getBuffer();
|
||||||
|
ByteBuffer idx = config.getEntry("obj.idx").getBuffer();
|
||||||
|
|
||||||
|
int count = idx.getShort(), index = 2;
|
||||||
|
int[] indices = new int[count];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
indices[i] = index;
|
||||||
|
index += idx.getShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemDefinition[] definitions = new ItemDefinition[count];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
data.position(indices[i]);
|
||||||
|
definitions[i] = decode(i, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemDefinition.init(definitions);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException("Error decoding ItemDefinitions.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a single definition.
|
||||||
|
*
|
||||||
|
* @param id The item's id.
|
||||||
|
* @param buffer The buffer.
|
||||||
|
* @return The {@link ItemDefinition}.
|
||||||
|
*/
|
||||||
|
private ItemDefinition decode(int id, ByteBuffer buffer) {
|
||||||
|
ItemDefinition definition = new ItemDefinition(id);
|
||||||
|
while (true) {
|
||||||
|
int opcode = buffer.get() & 0xFF;
|
||||||
|
|
||||||
|
if (opcode == 0) {
|
||||||
|
return definition;
|
||||||
|
} else if (opcode == 1) {
|
||||||
|
buffer.getShort();
|
||||||
|
} else if (opcode == 2) {
|
||||||
|
definition.setName(BufferUtil.readString(buffer));
|
||||||
|
} else if (opcode == 3) {
|
||||||
|
definition.setDescription(BufferUtil.readString(buffer));
|
||||||
|
} else if (opcode >= 4 && opcode <= 8 || opcode == 10) {
|
||||||
|
buffer.getShort();
|
||||||
|
} else if (opcode == 11) {
|
||||||
|
definition.setStackable(true);
|
||||||
|
} else if (opcode == 12) {
|
||||||
|
definition.setValue(buffer.getInt());
|
||||||
|
} else if (opcode == 16) {
|
||||||
|
definition.setMembersOnly(true);
|
||||||
|
} else if (opcode == 23) {
|
||||||
|
buffer.getShort();
|
||||||
|
buffer.get();
|
||||||
|
} else if (opcode == 24) {
|
||||||
|
buffer.getShort();
|
||||||
|
} else if (opcode == 25) {
|
||||||
|
buffer.getShort();
|
||||||
|
buffer.get();
|
||||||
|
} else if (opcode == 26) {
|
||||||
|
buffer.getShort();
|
||||||
|
} else if (opcode >= 30 && opcode < 35) {
|
||||||
|
String str = BufferUtil.readString(buffer);
|
||||||
|
if (str.equalsIgnoreCase("hidden")) {
|
||||||
|
str = null;
|
||||||
|
}
|
||||||
|
definition.setGroundAction(opcode - 30, str);
|
||||||
|
} else if (opcode >= 35 && opcode < 40) {
|
||||||
|
definition.setInventoryAction(opcode - 35, BufferUtil.readString(buffer));
|
||||||
|
} else if (opcode == 40) {
|
||||||
|
int colourCount = buffer.get() & 0xFF;
|
||||||
|
for (int i = 0; i < colourCount; i++) {
|
||||||
|
buffer.getShort();
|
||||||
|
buffer.getShort();
|
||||||
|
}
|
||||||
|
} else if (opcode == 78 || opcode == 79 || (opcode >= 90 && opcode <= 93) || opcode == 95) {
|
||||||
|
buffer.getShort();
|
||||||
|
} else if (opcode == 97) {
|
||||||
|
definition.setNoteInfoId(buffer.getShort() & 0xFFFF);
|
||||||
|
} else if (opcode == 98) {
|
||||||
|
definition.setNoteGraphicId(buffer.getShort() & 0xFFFF);
|
||||||
|
} else if (opcode >= 100 && opcode < 110) {
|
||||||
|
buffer.getShort();
|
||||||
|
buffer.getShort();
|
||||||
|
} else if (opcode >= 110 && opcode <= 112) {
|
||||||
|
buffer.getShort();
|
||||||
|
} else if (opcode == 113 || opcode == 114) {
|
||||||
|
buffer.get();
|
||||||
|
} else if (opcode == 115) {
|
||||||
|
definition.setTeam(buffer.get() & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
package org.apollo.cache.decoder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.apollo.cache.IndexedFileSystem;
|
||||||
|
import org.apollo.cache.archive.Archive;
|
||||||
|
import org.apollo.cache.def.NpcDefinition;
|
||||||
|
import org.apollo.util.BufferUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes npc data from the {@code npc.dat} file into {@link NpcDefinition}s.
|
||||||
|
*
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public final class NpcDefinitionDecoder implements Runnable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IndexedFileSystem.
|
||||||
|
*/
|
||||||
|
private final IndexedFileSystem fs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the NpcDefinitionDecoder.
|
||||||
|
*
|
||||||
|
* @param fs The {@link IndexedFileSystem}.
|
||||||
|
*/
|
||||||
|
public NpcDefinitionDecoder(IndexedFileSystem fs) {
|
||||||
|
this.fs = fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Archive config = fs.getArchive(0, 2);
|
||||||
|
ByteBuffer data = config.getEntry("npc.dat").getBuffer();
|
||||||
|
ByteBuffer idx = config.getEntry("npc.idx").getBuffer();
|
||||||
|
|
||||||
|
int count = idx.getShort(), index = 2;
|
||||||
|
int[] indices = new int[count];
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
indices[i] = index;
|
||||||
|
index += idx.getShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
NpcDefinition[] definitions = new NpcDefinition[count];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
data.position(indices[i]);
|
||||||
|
definitions[i] = decode(i, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
NpcDefinition.init(definitions);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException("Error decoding NpcDefinitions.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a single definition.
|
||||||
|
*
|
||||||
|
* @param id The npc's id.
|
||||||
|
* @param buffer The buffer.
|
||||||
|
* @return The {@link NpcDefinition}.
|
||||||
|
*/
|
||||||
|
private NpcDefinition decode(int id, ByteBuffer buffer) {
|
||||||
|
NpcDefinition definition = new NpcDefinition(id);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
int opcode = buffer.get() & 0xFF;
|
||||||
|
|
||||||
|
if (opcode == 0) {
|
||||||
|
return definition;
|
||||||
|
} else if (opcode == 1) {
|
||||||
|
int length = buffer.get() & 0xFF;
|
||||||
|
int[] models = new int[length];
|
||||||
|
for (int index = 0; index < length; index++) {
|
||||||
|
models[index] = buffer.getShort();
|
||||||
|
}
|
||||||
|
} else if (opcode == 2) {
|
||||||
|
definition.setName(BufferUtil.readString(buffer));
|
||||||
|
} else if (opcode == 3) {
|
||||||
|
definition.setDescription(BufferUtil.readString(buffer));
|
||||||
|
} else if (opcode == 12) {
|
||||||
|
definition.setSize(buffer.get());
|
||||||
|
} else if (opcode == 13) {
|
||||||
|
definition.setStandAnimation(buffer.getShort());
|
||||||
|
} else if (opcode == 14) {
|
||||||
|
definition.setWalkAnimation(buffer.getShort());
|
||||||
|
} else if (opcode == 17) {
|
||||||
|
definition
|
||||||
|
.setWalkAnimations(buffer.getShort(), buffer.getShort(), buffer.getShort(), buffer.getShort());
|
||||||
|
} else if (opcode >= 30 && opcode < 40) {
|
||||||
|
String action = BufferUtil.readString(buffer);
|
||||||
|
if (action.equals("hidden")) {
|
||||||
|
action = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
definition.setInteraction(opcode - 30, action);
|
||||||
|
} else if (opcode == 40) {
|
||||||
|
int length = buffer.get() & 0xFF;
|
||||||
|
int[] originalColours = new int[length];
|
||||||
|
int[] replacementColours = new int[length];
|
||||||
|
|
||||||
|
for (int index = 0; index < length; index++) {
|
||||||
|
originalColours[index] = buffer.getShort();
|
||||||
|
replacementColours[index] = buffer.getShort();
|
||||||
|
}
|
||||||
|
} else if (opcode == 60) {
|
||||||
|
int length = buffer.get() & 0xFF;
|
||||||
|
int[] additionalModels = new int[length];
|
||||||
|
|
||||||
|
for (int index = 0; index < length; index++) {
|
||||||
|
additionalModels[index] = buffer.getShort();
|
||||||
|
}
|
||||||
|
} else if (opcode >= 90 && opcode <= 92) {
|
||||||
|
buffer.getShort(); // Dummy
|
||||||
|
} else if (opcode == 95) {
|
||||||
|
definition.setCombatLevel(buffer.getShort());
|
||||||
|
} else if (opcode == 97 || opcode == 98) {
|
||||||
|
buffer.getShort();
|
||||||
|
} else if (opcode == 100 || opcode == 101) {
|
||||||
|
buffer.get();
|
||||||
|
} else if (opcode == 102 || opcode == 103) {
|
||||||
|
buffer.getShort();
|
||||||
|
} else if (opcode == 106) {
|
||||||
|
wrap(buffer.getShort());
|
||||||
|
wrap(buffer.getShort());
|
||||||
|
|
||||||
|
int count = buffer.get() & 0xFF;
|
||||||
|
int[] morphisms = new int[count + 1];
|
||||||
|
Arrays.setAll(morphisms, index -> wrap(buffer.getShort()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps a morphism value around, returning -1 if the specified value is 65,535.
|
||||||
|
*
|
||||||
|
* @param value The value.
|
||||||
|
* @return -1 if {@code value} is 65,535, otherwise {@code value}.
|
||||||
|
*/
|
||||||
|
private int wrap(int value) {
|
||||||
|
return value == 65_535 ? -1 : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+142
@@ -0,0 +1,142 @@
|
|||||||
|
package org.apollo.cache.decoder;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import org.apollo.cache.IndexedFileSystem;
|
||||||
|
import org.apollo.cache.archive.Archive;
|
||||||
|
import org.apollo.cache.def.ItemDefinition;
|
||||||
|
import org.apollo.cache.def.ObjectDefinition;
|
||||||
|
import org.apollo.util.BufferUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes object data from the {@code loc.dat} file into {@link ObjectDefinition}s.
|
||||||
|
*
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public final class ObjectDefinitionDecoder implements Runnable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IndexedFileSystem.
|
||||||
|
*/
|
||||||
|
private final IndexedFileSystem fs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the ObjectDefinitionDecoder.
|
||||||
|
*
|
||||||
|
* @param fs The {@link IndexedFileSystem}.
|
||||||
|
*/
|
||||||
|
public ObjectDefinitionDecoder(IndexedFileSystem fs) {
|
||||||
|
this.fs = fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Archive config = fs.getArchive(0, 2);
|
||||||
|
ByteBuffer data = config.getEntry("loc.dat").getBuffer();
|
||||||
|
ByteBuffer idx = config.getEntry("loc.idx").getBuffer();
|
||||||
|
|
||||||
|
int count = idx.getShort(), index = 2;
|
||||||
|
int[] indices = new int[count];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
indices[i] = index;
|
||||||
|
index += idx.getShort();
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectDefinition[] definitions = new ObjectDefinition[count];
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
data.position(indices[i]);
|
||||||
|
definitions[i] = decode(i, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectDefinition.init(definitions);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException("Error decoding ObjectDefinitions.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes data from the cache into an {@link ObjectDefinition}.
|
||||||
|
*
|
||||||
|
* @param id The id of the object.
|
||||||
|
* @param data The {@link ByteBuffer} containing the data.
|
||||||
|
* @return The object definition.
|
||||||
|
*/
|
||||||
|
private ObjectDefinition decode(int id, ByteBuffer data) {
|
||||||
|
ObjectDefinition definition = new ObjectDefinition(id);
|
||||||
|
while (true) {
|
||||||
|
int opcode = data.get() & 0xFF;
|
||||||
|
|
||||||
|
if (opcode == 0) {
|
||||||
|
return definition;
|
||||||
|
} else if (opcode == 1) {
|
||||||
|
int amount = data.get() & 0xFF;
|
||||||
|
for (int i = 0; i < amount; i++) {
|
||||||
|
data.getShort();
|
||||||
|
data.get();
|
||||||
|
}
|
||||||
|
} else if (opcode == 2) {
|
||||||
|
definition.setName(BufferUtil.readString(data));
|
||||||
|
} else if (opcode == 3) {
|
||||||
|
definition.setDescription(BufferUtil.readString(data));
|
||||||
|
} else if (opcode == 5) {
|
||||||
|
int amount = data.get() & 0xFF;
|
||||||
|
for (int i = 0; i < amount; i++) {
|
||||||
|
data.getShort();
|
||||||
|
}
|
||||||
|
} else if (opcode == 14) {
|
||||||
|
definition.setWidth(data.get() & 0xFF);
|
||||||
|
} else if (opcode == 15) {
|
||||||
|
definition.setLength(data.get() & 0xFF);
|
||||||
|
} else if (opcode == 17) {
|
||||||
|
definition.setSolid(false);
|
||||||
|
} else if (opcode == 18) {
|
||||||
|
definition.setImpenetrable(false);
|
||||||
|
} else if (opcode == 19) {
|
||||||
|
definition.setInteractive((data.get() & 0xFF) == 1);
|
||||||
|
} else if (opcode == 24) {
|
||||||
|
data.getShort();
|
||||||
|
} else if (opcode == 28 || opcode == 29) {
|
||||||
|
data.get();
|
||||||
|
} else if (opcode >= 30 && opcode < 39) {
|
||||||
|
String[] actions = definition.getMenuActions();
|
||||||
|
if (actions == null) {
|
||||||
|
actions = new String[10];
|
||||||
|
}
|
||||||
|
String action = BufferUtil.readString(data);
|
||||||
|
actions[opcode - 30] = action;
|
||||||
|
definition.setMenuActions(actions);
|
||||||
|
} else if (opcode == 39) {
|
||||||
|
data.get();
|
||||||
|
} else if (opcode == 40) {
|
||||||
|
int amount = data.get() & 0xFF;
|
||||||
|
for (int i = 0; i < amount; i++) {
|
||||||
|
data.getShort();
|
||||||
|
data.getShort();
|
||||||
|
}
|
||||||
|
} else if (opcode == 60 || opcode >= 65 && opcode <= 68) {
|
||||||
|
data.getShort();
|
||||||
|
} else if (opcode == 69) {
|
||||||
|
data.get();
|
||||||
|
} else if (opcode >= 70 && opcode <= 72) {
|
||||||
|
data.getShort();
|
||||||
|
} else if (opcode == 73) {
|
||||||
|
definition.setObstructive(true);
|
||||||
|
} else if (opcode == 75) {
|
||||||
|
data.get();
|
||||||
|
} else if (opcode == 77) {
|
||||||
|
data.getShort();
|
||||||
|
data.getShort();
|
||||||
|
int count = data.get();
|
||||||
|
for (int i = 0; i <= count; i++) {
|
||||||
|
data.getShort();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Contains classes which parse files within the game's cache.
|
||||||
|
*/
|
||||||
|
package org.apollo.cache.decoder;
|
||||||
+310
@@ -0,0 +1,310 @@
|
|||||||
|
package org.apollo.cache.def;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a type of Item that may be equipped.
|
||||||
|
*
|
||||||
|
* @author Graham
|
||||||
|
*/
|
||||||
|
public final class EquipmentDefinition {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attack id.
|
||||||
|
*/
|
||||||
|
private static final int ATTACK = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The defence id.
|
||||||
|
*/
|
||||||
|
private static final int DEFENCE = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The strength id.
|
||||||
|
*/
|
||||||
|
private static final int STRENGTH = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The hitpoints id.
|
||||||
|
*/
|
||||||
|
private static final int HITPOINTS = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ranged id.
|
||||||
|
*/
|
||||||
|
private static final int RANGED = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The prayer id.
|
||||||
|
*/
|
||||||
|
private static final int PRAYER = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The magic id.
|
||||||
|
*/
|
||||||
|
private static final int MAGIC = 6;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The equipment definitions.
|
||||||
|
*/
|
||||||
|
private static final Map<Integer, EquipmentDefinition> definitions = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the total number of equipment definitions.
|
||||||
|
*
|
||||||
|
* @return The count.
|
||||||
|
*/
|
||||||
|
public static int count() {
|
||||||
|
return definitions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialises the equipment definitions.
|
||||||
|
*
|
||||||
|
* @param definitions The definitions.
|
||||||
|
* @throws RuntimeException If there is an id mismatch.
|
||||||
|
*/
|
||||||
|
public static void init(EquipmentDefinition[] definitions) {
|
||||||
|
for (int id = 0; id < definitions.length; id++) {
|
||||||
|
EquipmentDefinition def = definitions[id];
|
||||||
|
if (def != null) {
|
||||||
|
if (def.getId() != id) {
|
||||||
|
throw new RuntimeException("Equipment definition id mismatch.");
|
||||||
|
}
|
||||||
|
EquipmentDefinition.definitions.put(def.getId(), def);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an equipment definition by its id.
|
||||||
|
*
|
||||||
|
* @param id The id.
|
||||||
|
* @return {@code null} if the item is not equipment, the definition otherwise.
|
||||||
|
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||||
|
*/
|
||||||
|
public static EquipmentDefinition lookup(int id) {
|
||||||
|
Preconditions.checkElementIndex(id, ItemDefinition.count(), "Id out of bounds.");
|
||||||
|
return definitions.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item id.
|
||||||
|
*/
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of skill requirement levels.
|
||||||
|
*/
|
||||||
|
private final int[] levels = { 1, 1, 1, 1, 1, 1, 1 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The slot this equipment goes into.
|
||||||
|
*/
|
||||||
|
private int slot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Various flags.
|
||||||
|
*/
|
||||||
|
private boolean twoHanded, fullBody, fullHat, fullMask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new equipment definition.
|
||||||
|
*
|
||||||
|
* @param id The id.
|
||||||
|
*/
|
||||||
|
public EquipmentDefinition(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum attack level required to equip this item.
|
||||||
|
*
|
||||||
|
* @return The level.
|
||||||
|
*/
|
||||||
|
public int getAttackLevel() {
|
||||||
|
return levels[ATTACK];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum defence level required to equip this item.
|
||||||
|
*
|
||||||
|
* @return The level.
|
||||||
|
*/
|
||||||
|
public int getDefenceLevel() {
|
||||||
|
return levels[DEFENCE];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum hitpoints level required to equip this item.
|
||||||
|
*
|
||||||
|
* @return The level.
|
||||||
|
*/
|
||||||
|
public int getHitpointsLevel() {
|
||||||
|
return levels[HITPOINTS];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum magic level required to equip this item.
|
||||||
|
*
|
||||||
|
* @return The level.
|
||||||
|
*/
|
||||||
|
public int getMagicLevel() {
|
||||||
|
return levels[MAGIC];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum prayer level required to equip this item.
|
||||||
|
*
|
||||||
|
* @return The level.
|
||||||
|
*/
|
||||||
|
public int getPrayerLevel() {
|
||||||
|
return levels[PRAYER];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum ranged level required to equip this item.
|
||||||
|
*
|
||||||
|
* @return The level.
|
||||||
|
*/
|
||||||
|
public int getRangedLevel() {
|
||||||
|
return levels[RANGED];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum strength level required to equip this item.
|
||||||
|
*
|
||||||
|
* @return The level.
|
||||||
|
*/
|
||||||
|
public int getStrengthLevel() {
|
||||||
|
return levels[STRENGTH];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id.
|
||||||
|
*
|
||||||
|
* @return The id.
|
||||||
|
*/
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the minimum level required to equip this item for a specific skill.
|
||||||
|
*
|
||||||
|
* @param skill The skill id.
|
||||||
|
* @return The level.
|
||||||
|
*/
|
||||||
|
public int getLevel(int skill) {
|
||||||
|
Preconditions.checkArgument(skill >= ATTACK && skill <= MAGIC, "Skill id out of bounds.");
|
||||||
|
return levels[skill];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the target slot.
|
||||||
|
*
|
||||||
|
* @return The target slot.
|
||||||
|
*/
|
||||||
|
public int getSlot() {
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this equipment is a full body.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean isFullBody() {
|
||||||
|
return fullBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this equipment is a full hat.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean isFullHat() {
|
||||||
|
return fullHat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this equipment is a full mask.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean isFullMask() {
|
||||||
|
return fullMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this equipment is two-handed.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean isTwoHanded() {
|
||||||
|
return twoHanded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the flags.
|
||||||
|
*
|
||||||
|
* @param twoHanded The two handed flag.
|
||||||
|
* @param fullBody The full body flag.
|
||||||
|
* @param fullHat The full hat flag.
|
||||||
|
* @param fullMask The full mask flag.
|
||||||
|
*/
|
||||||
|
public void setFlags(boolean twoHanded, boolean fullBody, boolean fullHat, boolean fullMask) {
|
||||||
|
this.twoHanded = twoHanded;
|
||||||
|
this.fullBody = fullBody;
|
||||||
|
this.fullHat = fullHat;
|
||||||
|
this.fullMask = fullMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the required levels.
|
||||||
|
*
|
||||||
|
* @param attack The required attack level.
|
||||||
|
* @param strength The required strength level.
|
||||||
|
* @param defence The required defence level.
|
||||||
|
* @param ranged The required ranged level.
|
||||||
|
* @param prayer The required prayer level.
|
||||||
|
* @param magic The required magic level.
|
||||||
|
*/
|
||||||
|
public void setLevels(int attack, int strength, int defence, int ranged, int prayer, int magic) {
|
||||||
|
setLevels(attack, strength, defence, 1, ranged, prayer, magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the required levels.
|
||||||
|
*
|
||||||
|
* @param attack The required attack level.
|
||||||
|
* @param strength The required strength level.
|
||||||
|
* @param defence The required defence level.
|
||||||
|
* @param hitpoints The required hitpoints level.
|
||||||
|
* @param ranged The required ranged level.
|
||||||
|
* @param prayer The required prayer level.
|
||||||
|
* @param magic The required magic level.
|
||||||
|
*/
|
||||||
|
public void setLevels(int attack, int strength, int defence, int hitpoints, int ranged, int prayer, int magic) {
|
||||||
|
levels[ATTACK] = attack;
|
||||||
|
levels[STRENGTH] = strength;
|
||||||
|
levels[DEFENCE] = defence;
|
||||||
|
levels[HITPOINTS] = hitpoints;
|
||||||
|
levels[RANGED] = ranged;
|
||||||
|
levels[PRAYER] = prayer;
|
||||||
|
levels[MAGIC] = magic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the target slot.
|
||||||
|
*
|
||||||
|
* @param slot The target slot.
|
||||||
|
*/
|
||||||
|
public void setSlot(int slot) {
|
||||||
|
this.slot = slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,411 @@
|
|||||||
|
package org.apollo.cache.def;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import com.google.common.collect.HashBiMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a type of Item.
|
||||||
|
*
|
||||||
|
* @author Graham
|
||||||
|
*/
|
||||||
|
public final class ItemDefinition {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item definitions.
|
||||||
|
*/
|
||||||
|
private static ItemDefinition[] definitions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map of item ids to noted ids.
|
||||||
|
*/
|
||||||
|
private static final BiMap<Integer, Integer> notes = HashBiMap.create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map of noted ids to item ids.
|
||||||
|
*/
|
||||||
|
private static final BiMap<Integer, Integer> notesInverse = notes.inverse();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the total number of item definitions.
|
||||||
|
*
|
||||||
|
* @return The count.
|
||||||
|
*/
|
||||||
|
public static int count() {
|
||||||
|
return definitions.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the array of item definitions.
|
||||||
|
*
|
||||||
|
* @return The definitions.
|
||||||
|
*/
|
||||||
|
public static ItemDefinition[] getDefinitions() {
|
||||||
|
return definitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialises the class with the specified set of definitions.
|
||||||
|
*
|
||||||
|
* @param definitions The definitions.
|
||||||
|
* @throws RuntimeException If there is an id mismatch.
|
||||||
|
*/
|
||||||
|
public static void init(ItemDefinition[] definitions) {
|
||||||
|
ItemDefinition.definitions = definitions;
|
||||||
|
for (int id = 0; id < definitions.length; id++) {
|
||||||
|
ItemDefinition def = definitions[id];
|
||||||
|
if (def.getId() != id) {
|
||||||
|
throw new RuntimeException("Item definition id mismatch.");
|
||||||
|
}
|
||||||
|
if (def.isNote()) {
|
||||||
|
def.toNote();
|
||||||
|
notes.put(def.getNoteInfoId(), def.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an item id to a noted id.
|
||||||
|
*
|
||||||
|
* @param id The item id.
|
||||||
|
* @return The noted id.
|
||||||
|
*/
|
||||||
|
public static int itemToNote(int id) {
|
||||||
|
Integer entry = notes.get(id);
|
||||||
|
if (entry == null) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the item definition for the specified id.
|
||||||
|
*
|
||||||
|
* @param id The id.
|
||||||
|
* @return The definition.
|
||||||
|
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||||
|
*/
|
||||||
|
public static ItemDefinition lookup(int id) {
|
||||||
|
Preconditions.checkElementIndex(id, definitions.length, "Id out of bounds.");
|
||||||
|
return definitions[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a noted id to the normal item id.
|
||||||
|
*
|
||||||
|
* @param id The note id.
|
||||||
|
* @return The item id.
|
||||||
|
*/
|
||||||
|
public static int noteToItem(int id) {
|
||||||
|
Integer entry = notesInverse.get(id);
|
||||||
|
if (entry == null) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The description of the item.
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ground actions array.
|
||||||
|
*/
|
||||||
|
private final String[] groundActions = new String[5];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item's id.
|
||||||
|
*/
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The inventory actions array.
|
||||||
|
*/
|
||||||
|
private final String[] inventoryActions = new String[5];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flag indicating if this item is members only.
|
||||||
|
*/
|
||||||
|
private boolean members = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the item.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the item to copy note graphics from.
|
||||||
|
*/
|
||||||
|
private int noteGraphicId = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The id of the item to copy note info from.
|
||||||
|
*/
|
||||||
|
private int noteInfoId = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flag indicating if this item is stackable.
|
||||||
|
*/
|
||||||
|
private boolean stackable = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This item's team.
|
||||||
|
*/
|
||||||
|
private int team;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item's floor value.
|
||||||
|
*/
|
||||||
|
private int value = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an item definition with the default values.
|
||||||
|
*
|
||||||
|
* @param id The item's id.
|
||||||
|
*/
|
||||||
|
public ItemDefinition(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the description of this item.
|
||||||
|
*
|
||||||
|
* @return The item's description.
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a ground action.
|
||||||
|
*
|
||||||
|
* @param id The id.
|
||||||
|
* @return The action.
|
||||||
|
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||||
|
*/
|
||||||
|
public String getGroundAction(int id) {
|
||||||
|
Preconditions.checkElementIndex(id, groundActions.length, "Ground action id is out of bounds.");
|
||||||
|
return groundActions[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets this item's id.
|
||||||
|
*
|
||||||
|
* @return The id.
|
||||||
|
*/
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an inventory action.
|
||||||
|
*
|
||||||
|
* @param id The id.
|
||||||
|
* @return The action.
|
||||||
|
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||||
|
*/
|
||||||
|
public String getInventoryAction(int id) {
|
||||||
|
Preconditions.checkElementIndex(id, inventoryActions.length, "Inventory action id is out of bounds.");
|
||||||
|
return inventoryActions[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets this item's name.
|
||||||
|
*
|
||||||
|
* @return The name.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets this item's note graphic id.
|
||||||
|
*
|
||||||
|
* @return The note graphic id.
|
||||||
|
*/
|
||||||
|
public int getNoteGraphicId() {
|
||||||
|
return noteGraphicId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets this item's note info id.
|
||||||
|
*
|
||||||
|
* @return The note info id.
|
||||||
|
*/
|
||||||
|
public int getNoteInfoId() {
|
||||||
|
return noteInfoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets this item's team.
|
||||||
|
*
|
||||||
|
* @return The team.
|
||||||
|
*/
|
||||||
|
public int getTeam() {
|
||||||
|
return team;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets this item's value.
|
||||||
|
*
|
||||||
|
* @return The value.
|
||||||
|
*/
|
||||||
|
public int getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this item is members only.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean isMembersOnly() {
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if this item is a note.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isNote() {
|
||||||
|
return noteGraphicId != -1 && noteInfoId != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the item specified by this definition is stackable.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean isStackable() {
|
||||||
|
return stackable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this item's description.
|
||||||
|
*
|
||||||
|
* @param description The description.
|
||||||
|
*/
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a ground action.
|
||||||
|
*
|
||||||
|
* @param id The id.
|
||||||
|
* @param action The action.
|
||||||
|
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||||
|
*/
|
||||||
|
public void setGroundAction(int id, String action) {
|
||||||
|
Preconditions.checkElementIndex(id, groundActions.length, "Ground action id is out of bounds.");
|
||||||
|
groundActions[id] = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an inventory action.
|
||||||
|
*
|
||||||
|
* @param id The id.
|
||||||
|
* @param action The action.
|
||||||
|
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||||
|
*/
|
||||||
|
public void setInventoryAction(int id, String action) {
|
||||||
|
Preconditions.checkElementIndex(id, inventoryActions.length, "Inventory action id is out of bounds.");
|
||||||
|
inventoryActions[id] = action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this item's members only flag.
|
||||||
|
*
|
||||||
|
* @param members The flag.
|
||||||
|
*/
|
||||||
|
public void setMembersOnly(boolean members) {
|
||||||
|
this.members = members;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this item's name.
|
||||||
|
*
|
||||||
|
* @param name The name.
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this item's note graphic id.
|
||||||
|
*
|
||||||
|
* @param noteGraphicId The note graphic id.
|
||||||
|
*/
|
||||||
|
public void setNoteGraphicId(int noteGraphicId) {
|
||||||
|
this.noteGraphicId = noteGraphicId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this item's note info id.
|
||||||
|
*
|
||||||
|
* @param noteInfoId The note info id.
|
||||||
|
*/
|
||||||
|
public void setNoteInfoId(int noteInfoId) {
|
||||||
|
this.noteInfoId = noteInfoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this item's stackable flag.
|
||||||
|
*
|
||||||
|
* @param stackable The stackable flag.
|
||||||
|
*/
|
||||||
|
public void setStackable(boolean stackable) {
|
||||||
|
this.stackable = stackable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets this item's team.
|
||||||
|
*
|
||||||
|
* @param team The team.
|
||||||
|
*/
|
||||||
|
public void setTeam(int team) {
|
||||||
|
this.team = team;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets this item's value.
|
||||||
|
*
|
||||||
|
* @param value The value.
|
||||||
|
*/
|
||||||
|
public void setValue(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this item to a note, if possible.
|
||||||
|
*
|
||||||
|
* @throws IllegalStateException If {@link ItemDefinition#isNote()} returns {@code false}.
|
||||||
|
*/
|
||||||
|
public void toNote() {
|
||||||
|
if (isNote()) {
|
||||||
|
if (description != null && description.startsWith("Swap this note at any bank for ")) {
|
||||||
|
return; // already converted.
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemDefinition infoDef = lookup(noteInfoId);
|
||||||
|
name = infoDef.name;
|
||||||
|
members = infoDef.members;
|
||||||
|
|
||||||
|
String prefix = "a";
|
||||||
|
char firstChar = name == null ? 'n' : name.charAt(0);
|
||||||
|
|
||||||
|
if (firstChar == 'A' || firstChar == 'E' || firstChar == 'I' || firstChar == 'O' || firstChar == 'U') {
|
||||||
|
prefix = "an";
|
||||||
|
}
|
||||||
|
|
||||||
|
description = "Swap this note at any bank for " + prefix + " " + name + ".";
|
||||||
|
value = infoDef.value;
|
||||||
|
stackable = true;
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException("Item cannot be noted.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,365 @@
|
|||||||
|
package org.apollo.cache.def;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a type of Npc.
|
||||||
|
*
|
||||||
|
* @author Chris Fletcher
|
||||||
|
*/
|
||||||
|
public final class NpcDefinition {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The npc definitions.
|
||||||
|
*/
|
||||||
|
private static NpcDefinition[] definitions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the total number of npc definitions.
|
||||||
|
*
|
||||||
|
* @return The count.
|
||||||
|
*/
|
||||||
|
public static int count() {
|
||||||
|
return definitions.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the array of npc definitions.
|
||||||
|
*
|
||||||
|
* @return The definitions.
|
||||||
|
*/
|
||||||
|
public static NpcDefinition[] getDefinitions() {
|
||||||
|
return definitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialises the class with the specified set of definitions.
|
||||||
|
*
|
||||||
|
* @param definitions The definitions.
|
||||||
|
* @throws IllegalStateException If there is an id mismatch.
|
||||||
|
*/
|
||||||
|
public static void init(NpcDefinition[] definitions) {
|
||||||
|
NpcDefinition.definitions = definitions;
|
||||||
|
for (int id = 0; id < definitions.length; id++) {
|
||||||
|
NpcDefinition def = definitions[id];
|
||||||
|
if (def.getId() != id) {
|
||||||
|
throw new IllegalStateException("Npc definition id mismatch.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the npc definition for the specified id.
|
||||||
|
*
|
||||||
|
* @param id The id.
|
||||||
|
* @return The definition.
|
||||||
|
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||||
|
*/
|
||||||
|
public static NpcDefinition lookup(int id) {
|
||||||
|
Preconditions.checkElementIndex(id, definitions.length, "Id out of bounds.");
|
||||||
|
return definitions[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The combat level of the npc.
|
||||||
|
*/
|
||||||
|
private int combatLevel = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The description of the npc.
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The npc id.
|
||||||
|
*/
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of interaction options.
|
||||||
|
*/
|
||||||
|
private final String[] interactions = new String[5];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the npc.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The npc's size, in tiles.
|
||||||
|
*/
|
||||||
|
private int size = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The various animation ids.
|
||||||
|
*/
|
||||||
|
private int standAnim = -1, walkAnim = -1, walkBackAnim = -1, walkLeftAnim = -1, walkRightAnim = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new npc definition.
|
||||||
|
*
|
||||||
|
* @param id The npc id.
|
||||||
|
*/
|
||||||
|
public NpcDefinition(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the npc's combat level.
|
||||||
|
*
|
||||||
|
* @return The combat level, or -1 if it doesn't have one.
|
||||||
|
*/
|
||||||
|
public int getCombatLevel() {
|
||||||
|
return combatLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the description of the npc.
|
||||||
|
*
|
||||||
|
* @return The description.
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the npc id.
|
||||||
|
*
|
||||||
|
* @return The npc id.
|
||||||
|
*/
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an interaction option.
|
||||||
|
*
|
||||||
|
* @param slot The slot of the option.
|
||||||
|
* @return The option, or {@code null} if there isn't any at the specified slot.
|
||||||
|
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||||
|
*/
|
||||||
|
public String getInteraction(int slot) {
|
||||||
|
Preconditions.checkElementIndex(slot, interactions.length, "Npc interaction id is out of bounds.");
|
||||||
|
return interactions[slot];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the array of interaction options.
|
||||||
|
*
|
||||||
|
* @return The interaction options.
|
||||||
|
*/
|
||||||
|
public String[] getInteractions() {
|
||||||
|
return interactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the npc.
|
||||||
|
*
|
||||||
|
* @return The name of the npc.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the npc's size, in tiles.
|
||||||
|
*
|
||||||
|
* @return The size.
|
||||||
|
*/
|
||||||
|
public int getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id of the npc's standing animation.
|
||||||
|
*
|
||||||
|
* @return The stand animation id, or -1 if it doesn't have one.
|
||||||
|
*/
|
||||||
|
public int getStandAnimation() {
|
||||||
|
return standAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the walking animation of the npc.
|
||||||
|
*
|
||||||
|
* @return The walking animation.
|
||||||
|
*/
|
||||||
|
public int getWalkAnimation() {
|
||||||
|
return walkAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the walk-back animation of the npc.
|
||||||
|
*
|
||||||
|
* @return The walk-back animation.
|
||||||
|
*/
|
||||||
|
public int getWalkBackAnimation() {
|
||||||
|
return walkBackAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the walk-left animation of the npc.
|
||||||
|
*
|
||||||
|
* @return The walk-left animation.
|
||||||
|
*/
|
||||||
|
public int getWalkLeftAnimation() {
|
||||||
|
return walkLeftAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the walk-right animation of the npc.
|
||||||
|
*
|
||||||
|
* @return The walk-right animation.
|
||||||
|
*/
|
||||||
|
public int getWalkRightAnimation() {
|
||||||
|
return walkRightAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the npc has a combat level.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean hasCombatLevel() {
|
||||||
|
return combatLevel != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if there is an interaction option present.
|
||||||
|
*
|
||||||
|
* @param slot The slot to check.
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||||
|
*/
|
||||||
|
public boolean hasInteraction(int slot) {
|
||||||
|
Preconditions.checkElementIndex(slot, interactions.length, "Npc interaction id is out of bounds.");
|
||||||
|
return interactions[slot] != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the npc has a standing animation id.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean hasStandAnimation() {
|
||||||
|
return standAnim != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the npc has a walking animation.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean hasWalkAnimation() {
|
||||||
|
return walkAnim != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the npc has a walk-back animation.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean hasWalkBackAnimation() {
|
||||||
|
return walkBackAnim != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the npc has a walk-left animation.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean hasWalkLeftAnimation() {
|
||||||
|
return walkLeftAnim != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the npc has a walk-right animation.
|
||||||
|
*
|
||||||
|
* @return {@code true} if so, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean hasWalkRightAnimation() {
|
||||||
|
return walkRightAnim != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the npc's combat level.
|
||||||
|
*
|
||||||
|
* @param combatLevel The combat level.
|
||||||
|
*/
|
||||||
|
public void setCombatLevel(int combatLevel) {
|
||||||
|
this.combatLevel = combatLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the description of the npc.
|
||||||
|
*
|
||||||
|
* @param description The description.
|
||||||
|
*/
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an interaction option.
|
||||||
|
*
|
||||||
|
* @param slot The slot of the option.
|
||||||
|
* @param interaction The interaction options.
|
||||||
|
* @throws IndexOutOfBoundsException If the slot is out of bounds.
|
||||||
|
*/
|
||||||
|
public void setInteraction(int slot, String interaction) {
|
||||||
|
Preconditions.checkElementIndex(slot, interactions.length, "Npc interaction id is out of bounds.");
|
||||||
|
interactions[slot] = interaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name of the npc.
|
||||||
|
*
|
||||||
|
* @param name The name.
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the size of the npc, in tiles.
|
||||||
|
*
|
||||||
|
* @param size The size.
|
||||||
|
*/
|
||||||
|
public void setSize(int size) {
|
||||||
|
this.size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the id of the npc's standing animation.
|
||||||
|
*
|
||||||
|
* @param standAnim The stand animation id.
|
||||||
|
*/
|
||||||
|
public void setStandAnimation(int standAnim) {
|
||||||
|
this.standAnim = standAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the walking animation of the npc.
|
||||||
|
*
|
||||||
|
* @param walkAnim The walking animation.
|
||||||
|
*/
|
||||||
|
public void setWalkAnimation(int walkAnim) {
|
||||||
|
this.walkAnim = walkAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the various walking animations of the npc.
|
||||||
|
*
|
||||||
|
* @param walkAnim The walking animation.
|
||||||
|
* @param walkBackAnim The walk-back animation.
|
||||||
|
* @param walkLeftAnim The walk-left animation.
|
||||||
|
* @param walkRightAnim The walk-right animation.
|
||||||
|
*/
|
||||||
|
public void setWalkAnimations(int walkAnim, int walkBackAnim, int walkLeftAnim, int walkRightAnim) {
|
||||||
|
this.walkAnim = walkAnim;
|
||||||
|
this.walkBackAnim = walkBackAnim;
|
||||||
|
this.walkLeftAnim = walkLeftAnim;
|
||||||
|
this.walkRightAnim = walkRightAnim;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
package org.apollo.cache.def;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a type of GameObject.
|
||||||
|
*
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public final class ObjectDefinition {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of game object definitions.
|
||||||
|
*/
|
||||||
|
private static ObjectDefinition[] definitions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the total number of object definitions.
|
||||||
|
*
|
||||||
|
* @return The count.
|
||||||
|
*/
|
||||||
|
public static int count() {
|
||||||
|
return definitions.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the array of object definitions.
|
||||||
|
*
|
||||||
|
* @return The definitions.
|
||||||
|
*/
|
||||||
|
public static ObjectDefinition[] getDefinitions() {
|
||||||
|
return definitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialises the object definitions.
|
||||||
|
*
|
||||||
|
* @param definitions The decoded definitions.
|
||||||
|
* @throws RuntimeException If there is an id mismatch.
|
||||||
|
*/
|
||||||
|
public static void init(ObjectDefinition[] definitions) {
|
||||||
|
ObjectDefinition.definitions = definitions;
|
||||||
|
for (int id = 0; id < definitions.length; id++) {
|
||||||
|
ObjectDefinition def = definitions[id];
|
||||||
|
if (def.getId() != id) {
|
||||||
|
throw new RuntimeException("Item definition id mismatch.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the object definition for the specified id.
|
||||||
|
*
|
||||||
|
* @param id The id of the object.
|
||||||
|
* @return The definition.
|
||||||
|
* @throws IndexOutOfBoundsException If the id is out of bounds.
|
||||||
|
*/
|
||||||
|
public static ObjectDefinition lookup(int id) {
|
||||||
|
Preconditions.checkElementIndex(id, definitions.length, "Id out of bounds.");
|
||||||
|
return definitions[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object's description.
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object's id.
|
||||||
|
*/
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotes whether this object is impenetrable or not.
|
||||||
|
*/
|
||||||
|
private boolean impenetrable = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotes whether this object has actions associated with it or not.
|
||||||
|
*/
|
||||||
|
private boolean interactive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotes whether or not this object obstructs the ground.
|
||||||
|
*/
|
||||||
|
private boolean obstructive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This object's length.
|
||||||
|
*/
|
||||||
|
private int length = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object's menu actions.
|
||||||
|
*/
|
||||||
|
private String[] menuActions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object's name.
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Denotes whether the object can be walked over or not.
|
||||||
|
*/
|
||||||
|
private boolean solid = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This object's width.
|
||||||
|
*/
|
||||||
|
private int width = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new object definition.
|
||||||
|
*
|
||||||
|
* @param id The id of the object.
|
||||||
|
*/
|
||||||
|
public ObjectDefinition(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the description of this object.
|
||||||
|
*
|
||||||
|
* @return The description.
|
||||||
|
*/
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id of this object.
|
||||||
|
*
|
||||||
|
* @return The id.
|
||||||
|
*/
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the length of this object.
|
||||||
|
*
|
||||||
|
* @return The length.
|
||||||
|
*/
|
||||||
|
public int getLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the menu actions of this object.
|
||||||
|
*
|
||||||
|
* @return The menu actions.
|
||||||
|
*/
|
||||||
|
public String[] getMenuActions() {
|
||||||
|
return menuActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of this object.
|
||||||
|
*
|
||||||
|
* @return The name.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the with of this object.
|
||||||
|
*
|
||||||
|
* @return The width.
|
||||||
|
*/
|
||||||
|
public int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the impenetrability of this object.
|
||||||
|
*
|
||||||
|
* @return {@code true} if this object is impenetrable, otherwise {@code false}.
|
||||||
|
*/
|
||||||
|
public boolean isImpenetrable() {
|
||||||
|
return impenetrable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the interactivity of this object.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the object is interactive, otherwise {@code false}.
|
||||||
|
*/
|
||||||
|
public boolean isInteractive() {
|
||||||
|
return interactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not this object obstructs the ground.
|
||||||
|
*
|
||||||
|
* @return {@code true} if the object obstructs the ground otherwise {@code false}.
|
||||||
|
*/
|
||||||
|
public boolean isObstructive() {
|
||||||
|
return obstructive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates the solidity of this object.
|
||||||
|
*
|
||||||
|
* @return {@code true} if this object is solid, otherwise {@code false}.
|
||||||
|
*/
|
||||||
|
public boolean isSolid() {
|
||||||
|
return solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the description of this object.
|
||||||
|
*
|
||||||
|
* @param description The description.
|
||||||
|
*/
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the impenetrability of this object.
|
||||||
|
*
|
||||||
|
* @param impenetrable The impenetrability.
|
||||||
|
*/
|
||||||
|
public void setImpenetrable(boolean impenetrable) {
|
||||||
|
this.impenetrable = impenetrable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the interactivity of this object.
|
||||||
|
*
|
||||||
|
* @param interactive The interactivity.
|
||||||
|
*/
|
||||||
|
public void setInteractive(boolean interactive) {
|
||||||
|
this.interactive = interactive;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the length of this object.
|
||||||
|
*
|
||||||
|
* @param length The length.
|
||||||
|
*/
|
||||||
|
public void setLength(int length) {
|
||||||
|
this.length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the menu actions of this object.
|
||||||
|
*
|
||||||
|
* @param menuActions The menu actions.
|
||||||
|
*/
|
||||||
|
public void setMenuActions(String[] menuActions) {
|
||||||
|
this.menuActions = menuActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the name of this object.
|
||||||
|
*
|
||||||
|
* @param name The name.
|
||||||
|
*/
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the solidity of this object.
|
||||||
|
*
|
||||||
|
* @param solid The solidity.
|
||||||
|
*/
|
||||||
|
public void setSolid(boolean solid) {
|
||||||
|
this.solid = solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the width of this object.
|
||||||
|
*
|
||||||
|
* @param width The width.
|
||||||
|
*/
|
||||||
|
public void setWidth(int width) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether or not this object is obstructive to the ground.
|
||||||
|
*
|
||||||
|
* @param obstructive Whether or not this object obstructs the ground.
|
||||||
|
*/
|
||||||
|
public void setObstructive(boolean obstructive) {
|
||||||
|
this.obstructive = obstructive;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Contains definition classes which contain information about types of items, NPCs, etc.
|
||||||
|
*/
|
||||||
|
package org.apollo.cache.def;
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package org.apollo.cache.map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains {@link MapFile}-related constants.
|
||||||
|
*
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public final class MapConstants {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index containing the map files.
|
||||||
|
*/
|
||||||
|
public static final int MAP_INDEX = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The width (and length) of a {@link MapFile} in {@link Tile}s.
|
||||||
|
*/
|
||||||
|
public static final int MAP_WIDTH = 64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of planes in a MapFile.
|
||||||
|
*/
|
||||||
|
public static final int MAP_PLANES = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The multiplicand for height values.
|
||||||
|
*/
|
||||||
|
static final int HEIGHT_MULTIPLICAND = 8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lowest type value that will result in the decoding of a Tile being continued.
|
||||||
|
*/
|
||||||
|
static final int LOWEST_CONTINUED_TYPE = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum type that specifies the Tile attributes.
|
||||||
|
*/
|
||||||
|
static final int MINIMUM_ATTRIBUTES_TYPE = 81;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum type that specifies the Tile underlay id.
|
||||||
|
*/
|
||||||
|
static final int MINIMUM_OVERLAY_TYPE = 49;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of possible overlay orientations.
|
||||||
|
*/
|
||||||
|
static final int ORIENTATION_COUNT = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The height difference between two planes.
|
||||||
|
*/
|
||||||
|
static final int PLANE_HEIGHT_DIFFERENCE = 240;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sole private constructor to prevent instantiation.
|
||||||
|
*/
|
||||||
|
private MapConstants() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package org.apollo.cache.map;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A 3-dimensional 64x64 area of the map.
|
||||||
|
*
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public final class MapFile {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The array of MapPlanes.
|
||||||
|
*/
|
||||||
|
private final MapPlane[] planes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the MapFile.
|
||||||
|
*
|
||||||
|
* @param planes The {@link MapPlane}s.
|
||||||
|
*/
|
||||||
|
public MapFile(MapPlane[] planes) {
|
||||||
|
this.planes = planes.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link MapPlane} with the specified level.
|
||||||
|
*
|
||||||
|
* @param plane The plane.
|
||||||
|
* @return The MapPlane.
|
||||||
|
* @throws ArrayIndexOutOfBoundsException If {@code plane} is out of bounds.
|
||||||
|
*/
|
||||||
|
public MapPlane getPlane(int plane) {
|
||||||
|
int length = planes.length;
|
||||||
|
Preconditions.checkElementIndex(plane, length, "Plane index out of bounds, must be [0, " + length + ").");
|
||||||
|
return planes[plane];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all of the {@link MapPlane}s in this MapFile.
|
||||||
|
*
|
||||||
|
* @return The MapPlanes.
|
||||||
|
*/
|
||||||
|
public MapPlane[] getPlanes() {
|
||||||
|
return planes.clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package org.apollo.cache.map;
|
||||||
|
|
||||||
|
import org.apollo.cache.IndexedFileSystem;
|
||||||
|
import org.apollo.util.CompressionUtil;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A decoder for the terrain data stored in {@link MapFile}s.
|
||||||
|
*
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public class MapFileDecoder {
|
||||||
|
/**
|
||||||
|
* Creates a MapFileDecoder for the specified map file.
|
||||||
|
*
|
||||||
|
* @param fs The {@link IndexedFileSystem} to get the file from.
|
||||||
|
* @param index The {@link MapIndex} to get the file index from.
|
||||||
|
* @return The MapFileDecoder.
|
||||||
|
* @throws IOException If there is an error reading or decompressing the file.
|
||||||
|
*/
|
||||||
|
public static MapFileDecoder create(IndexedFileSystem fs, MapIndex index) throws IOException {
|
||||||
|
ByteBuffer compressed = fs.getFile(MapConstants.MAP_INDEX, index.getMapFile());
|
||||||
|
ByteBuffer decompressed = ByteBuffer.wrap(CompressionUtil.degzip(compressed));
|
||||||
|
|
||||||
|
return new MapFileDecoder(decompressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The DataBuffer containing the MapFile data.
|
||||||
|
*/
|
||||||
|
private final ByteBuffer buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the MapIndexDecoder.
|
||||||
|
* <p>
|
||||||
|
* This constructor expects the {@link ByteBuffer} to <strong>not</strong> be compressed.
|
||||||
|
*
|
||||||
|
* @param buffer The DataBuffer containing the MapFile data.
|
||||||
|
*/
|
||||||
|
public MapFileDecoder(ByteBuffer buffer) {
|
||||||
|
this.buffer = buffer.asReadOnlyBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the data into a {@link MapFile}.
|
||||||
|
*
|
||||||
|
* @return The MapFile.
|
||||||
|
*/
|
||||||
|
public MapFile decode() {
|
||||||
|
MapPlane[] planes = new MapPlane[MapConstants.MAP_PLANES];
|
||||||
|
|
||||||
|
for (int level = 0; level < MapConstants.MAP_PLANES; level++) {
|
||||||
|
planes[level] = decodePlane(planes, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MapFile(planes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a {@link MapPlane} with the specified level.
|
||||||
|
*
|
||||||
|
* @param planes The previously-decoded {@link MapPlane}s, for calculating the height of the tiles.
|
||||||
|
* @param level The level.
|
||||||
|
* @return The MapPlane.
|
||||||
|
*/
|
||||||
|
private MapPlane decodePlane(MapPlane[] planes, int level) {
|
||||||
|
Tile[][] tiles = new Tile[MapConstants.MAP_WIDTH][MapConstants.MAP_WIDTH];
|
||||||
|
|
||||||
|
for (int x = 0; x < MapConstants.MAP_WIDTH; x++) {
|
||||||
|
for (int z = 0; z < MapConstants.MAP_WIDTH; z++) {
|
||||||
|
tiles[x][z] = decodeTile(planes, level, x, z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MapPlane(level, tiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the data into a {@link Tile}.
|
||||||
|
*
|
||||||
|
* @param planes The previously-decoded {@link MapPlane}s, for calculating the height of the Tile.
|
||||||
|
* @param level The level the Tile is on.
|
||||||
|
* @param x The x coordinate of the Tile.
|
||||||
|
* @param z The z coordinate of the Tile.
|
||||||
|
* @return The MapFile.
|
||||||
|
*/
|
||||||
|
private Tile decodeTile(MapPlane[] planes, int level, int x, int z) {
|
||||||
|
Tile.Builder builder = Tile.builder(x, z, level);
|
||||||
|
|
||||||
|
int type;
|
||||||
|
do {
|
||||||
|
type = buffer.get() & 0xFF;
|
||||||
|
|
||||||
|
if (type == 0) {
|
||||||
|
if (level == 0) {
|
||||||
|
builder.setHeight(TileUtils.calculateHeight(x, z));
|
||||||
|
} else {
|
||||||
|
Tile below = planes[level - 1].getTile(x, z);
|
||||||
|
builder.setHeight(below.getHeight() + MapConstants.PLANE_HEIGHT_DIFFERENCE);
|
||||||
|
}
|
||||||
|
} else if (type == 1) {
|
||||||
|
int height = buffer.get();
|
||||||
|
int below = (level == 0) ? 0 : planes[level - 1].getTile(x, z).getHeight();
|
||||||
|
|
||||||
|
builder.setHeight((height == 1 ? 0 : height) * MapConstants.HEIGHT_MULTIPLICAND + below);
|
||||||
|
} else if (type <= MapConstants.MINIMUM_OVERLAY_TYPE) {
|
||||||
|
builder.setOverlay(buffer.get());
|
||||||
|
builder.setOverlayType((type - MapConstants.LOWEST_CONTINUED_TYPE)
|
||||||
|
/ MapConstants.ORIENTATION_COUNT);
|
||||||
|
builder.setOverlayOrientation(type - MapConstants.LOWEST_CONTINUED_TYPE
|
||||||
|
% MapConstants.ORIENTATION_COUNT);
|
||||||
|
} else if (type <= MapConstants.MINIMUM_ATTRIBUTES_TYPE) {
|
||||||
|
builder.setAttributes(type - MapConstants.MINIMUM_OVERLAY_TYPE);
|
||||||
|
} else {
|
||||||
|
builder.setUnderlay(type - MapConstants.MINIMUM_ATTRIBUTES_TYPE);
|
||||||
|
}
|
||||||
|
} while (type >= MapConstants.LOWEST_CONTINUED_TYPE);
|
||||||
|
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
package org.apollo.cache.map;
|
||||||
|
|
||||||
|
import org.apollo.cache.def.ItemDefinition;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A definition for a map.
|
||||||
|
*/
|
||||||
|
public final class MapIndex {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether or not this map is members-only.
|
||||||
|
*/
|
||||||
|
private final boolean members;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object file id.
|
||||||
|
*/
|
||||||
|
private final int objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The packed coordinates.
|
||||||
|
*/
|
||||||
|
private final int packedCoordinates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The terrain file id.
|
||||||
|
*/
|
||||||
|
private final int terrain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A mapping of region ids to {@link MapIndex}es.
|
||||||
|
*/
|
||||||
|
private static Map<Integer, MapIndex> indices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialises the class with the specified set of indices.
|
||||||
|
*/
|
||||||
|
public static void init(Map<Integer, MapIndex> indices) {
|
||||||
|
MapIndex.indices = Collections.unmodifiableMap(indices);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@code Map} of {@link MapIndex} instances.
|
||||||
|
*
|
||||||
|
* @return The map of {@link MapIndex} instances.
|
||||||
|
*/
|
||||||
|
public static Map<Integer, MapIndex> getIndices() {
|
||||||
|
return indices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the {@link MapIndex}.
|
||||||
|
*
|
||||||
|
* @param packedCoordinates The packed coordinates.
|
||||||
|
* @param terrain The terrain file id.
|
||||||
|
* @param objects The object file id.
|
||||||
|
* @param members Indicates whether or not this map is members-only.
|
||||||
|
*/
|
||||||
|
public MapIndex(int packedCoordinates, int terrain, int objects, boolean members) {
|
||||||
|
this.packedCoordinates = packedCoordinates;
|
||||||
|
this.terrain = terrain;
|
||||||
|
this.objects = objects;
|
||||||
|
this.members = members;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id of the file containing the object data.
|
||||||
|
*
|
||||||
|
* @return The file id.
|
||||||
|
*/
|
||||||
|
public int getObjectFile() {
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the packed coordinates.
|
||||||
|
*
|
||||||
|
* @return The packed coordinates.
|
||||||
|
*/
|
||||||
|
public int getPackedCoordinates() {
|
||||||
|
return packedCoordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the id of the file containing the terrain data.
|
||||||
|
*
|
||||||
|
* @return The file id.
|
||||||
|
*/
|
||||||
|
public int getMapFile() {
|
||||||
|
return terrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the X coordinate of this map.
|
||||||
|
*
|
||||||
|
* @return The X coordinate of this map.
|
||||||
|
*/
|
||||||
|
public int getX() {
|
||||||
|
return (packedCoordinates >> 8 & 0xFF) * MapConstants.MAP_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the Y coordinate of this map.
|
||||||
|
*
|
||||||
|
* @return The y coordinate of this map.
|
||||||
|
*/
|
||||||
|
public int getY() {
|
||||||
|
return (packedCoordinates & 0xFF) * MapConstants.MAP_WIDTH;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether or not this MapIndex is for a members-only area of the world.
|
||||||
|
*
|
||||||
|
* @return {@code true} if this MapIndex is for a members-only area, {@code false} if not.
|
||||||
|
*/
|
||||||
|
public boolean isMembersOnly() {
|
||||||
|
return members;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package org.apollo.cache.map;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apollo.cache.IndexedFileSystem;
|
||||||
|
import org.apollo.cache.archive.Archive;
|
||||||
|
import org.apollo.cache.archive.ArchiveEntry;
|
||||||
|
import org.apollo.cache.map.MapIndex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes {@link MapIndex}s from the {@link IndexedFileSystem}.
|
||||||
|
*
|
||||||
|
* @author Ryley
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public final class MapIndexDecoder implements Runnable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file id of the versions archive.
|
||||||
|
*/
|
||||||
|
private static final int VERSIONS_ARCHIVE_FILE_ID = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The IndexedFileSystem.
|
||||||
|
*/
|
||||||
|
private final IndexedFileSystem fs;
|
||||||
|
|
||||||
|
public MapIndexDecoder(IndexedFileSystem fs) {
|
||||||
|
this.fs = fs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes {@link MapIndex}s from the specified {@link IndexedFileSystem}.
|
||||||
|
*
|
||||||
|
* @return A {@link Map} of packed coordinates to their MapDefinitions.
|
||||||
|
* @throws IOException If there is an error reading or decoding the Archive.
|
||||||
|
*/
|
||||||
|
public Map<Integer, MapIndex> decode() throws IOException {
|
||||||
|
Archive archive = fs.getArchive(0, VERSIONS_ARCHIVE_FILE_ID);
|
||||||
|
ArchiveEntry entry = archive.getEntry("map_index");
|
||||||
|
Map<Integer, MapIndex> definitions = new HashMap<>();
|
||||||
|
|
||||||
|
ByteBuffer buffer = entry.getBuffer();
|
||||||
|
int count = buffer.capacity() / (3 * Short.BYTES + Byte.BYTES);
|
||||||
|
|
||||||
|
for (int times = 0; times < count; times++) {
|
||||||
|
int id = buffer.getShort() & 0xFFFF;
|
||||||
|
int terrain = buffer.getShort() & 0xFFFF;
|
||||||
|
int objects = buffer.getShort() & 0xFFFF;
|
||||||
|
boolean members = buffer.get() == 1;
|
||||||
|
|
||||||
|
definitions.put(id, new MapIndex(id, terrain, objects, members));
|
||||||
|
}
|
||||||
|
|
||||||
|
return definitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
MapIndex.init(decode());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package org.apollo.cache.map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a static world object in a map file.
|
||||||
|
*/
|
||||||
|
public final class MapObject {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The object definition id of this {@code MapObject}.
|
||||||
|
*/
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The packed coordinates (local XY and height) for this object.
|
||||||
|
*/
|
||||||
|
private int packedCoordinates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of this object.
|
||||||
|
*/
|
||||||
|
private final int type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The orientation of this object.
|
||||||
|
*/
|
||||||
|
private final int orientation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@code MapObject}.
|
||||||
|
*
|
||||||
|
* @param id The object ID of this map object.
|
||||||
|
* @param packedCoordinates A packed integer containing the coordinates of this map object.
|
||||||
|
* @param type The type of object.
|
||||||
|
* @param orientation The object facing direction.
|
||||||
|
*/
|
||||||
|
public MapObject(int id, int packedCoordinates, int type, int orientation) {
|
||||||
|
this.id = id;
|
||||||
|
this.packedCoordinates = packedCoordinates;
|
||||||
|
this.type = type;
|
||||||
|
this.orientation = orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code MapObject}.
|
||||||
|
*
|
||||||
|
* @param id The object ID of this map object.
|
||||||
|
* @param x The local X coordinate of this object.
|
||||||
|
* @param y The local Y coordinate of this object.
|
||||||
|
* @param height The height level of this object.
|
||||||
|
* @param type The type of this object.
|
||||||
|
* @param orientation The orientation of this object.
|
||||||
|
*/
|
||||||
|
public MapObject(int id, int x, int y, int height, int type, int orientation) {
|
||||||
|
this(id, (height & 0x3f) << 12 | (x & 0x3f) << 6 | (y & 0x3f), type, orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the object ID of this map object.
|
||||||
|
*
|
||||||
|
* @return The object ID for {@link org.apollo.cache.def.ObjectDefinition} lookups.
|
||||||
|
*/
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the plane this map object exists on.
|
||||||
|
*
|
||||||
|
* @return The plane this map object is on.
|
||||||
|
*/
|
||||||
|
public int getHeight() {
|
||||||
|
return packedCoordinates >> 12 & 0x3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the X coordinate of this object relative to the map position.
|
||||||
|
*
|
||||||
|
* @return The local X coordinate.
|
||||||
|
*/
|
||||||
|
public int getLocalX() {
|
||||||
|
return packedCoordinates >> 6 & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Y coordinate of this object relative to the map position.
|
||||||
|
*
|
||||||
|
* @return The local Y coordinate.
|
||||||
|
*/
|
||||||
|
public int getLocalY() {
|
||||||
|
return packedCoordinates & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the integer representation of this objects orientation (0 indexed, starting West-North-East-South).
|
||||||
|
*
|
||||||
|
* @return The orientation of this object.
|
||||||
|
*/
|
||||||
|
public int getOrientation() {
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a packed integer containing the x/y coordinates and height for this object.
|
||||||
|
*
|
||||||
|
* @return The packed coordinates.
|
||||||
|
*/
|
||||||
|
public int getPackedCoordinates() {
|
||||||
|
return packedCoordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of this object.
|
||||||
|
*
|
||||||
|
* @return The type of this object.
|
||||||
|
*/
|
||||||
|
public int getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package org.apollo.cache.map;
|
||||||
|
|
||||||
|
import org.apollo.cache.IndexedFileSystem;
|
||||||
|
import org.apollo.cache.map.MapIndex;
|
||||||
|
import org.apollo.cache.map.MapConstants;
|
||||||
|
import org.apollo.cache.map.MapObject;
|
||||||
|
import org.apollo.util.BufferUtil;
|
||||||
|
import org.apollo.util.CompressionUtil;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A decoder for reading the map objects for a given map.
|
||||||
|
*
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public final class MapObjectsDecoder {
|
||||||
|
/**
|
||||||
|
* Creates a MapObjectsDecoder for the specified map file.
|
||||||
|
*
|
||||||
|
* @param fs The {@link IndexedFileSystem} to get the file from.
|
||||||
|
* @param index The map index to decode objects for.
|
||||||
|
* @return The MapObjectsDecoder.
|
||||||
|
* @throws IOException If there is an error reading or decompressing the file.
|
||||||
|
*/
|
||||||
|
public static MapObjectsDecoder create(IndexedFileSystem fs, MapIndex index) throws IOException {
|
||||||
|
ByteBuffer compressed = fs.getFile(MapConstants.MAP_INDEX, index.getObjectFile());
|
||||||
|
ByteBuffer decompressed = ByteBuffer.wrap(CompressionUtil.degzip(compressed));
|
||||||
|
|
||||||
|
return new MapObjectsDecoder(decompressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buffer to decode {@link MapObject}s from.
|
||||||
|
*/
|
||||||
|
private final ByteBuffer buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link MapObjectsDecoder} from the given buffer and map coordinates.
|
||||||
|
*
|
||||||
|
* @param buffer The decompressed object file buffer.
|
||||||
|
*/
|
||||||
|
public MapObjectsDecoder(ByteBuffer buffer) {
|
||||||
|
this.buffer = buffer.asReadOnlyBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the data in the {@code buffer} to a list of {@link MapObject}s.
|
||||||
|
*
|
||||||
|
* @return A list of decoded {@link MapObject}s.
|
||||||
|
*/
|
||||||
|
public List<MapObject> decode() {
|
||||||
|
List<MapObject> objects = new ArrayList<>();
|
||||||
|
|
||||||
|
int id = -1;
|
||||||
|
int idOffset = BufferUtil.readSmart(buffer);
|
||||||
|
|
||||||
|
while (idOffset != 0) {
|
||||||
|
id += idOffset;
|
||||||
|
|
||||||
|
int packed = 0;
|
||||||
|
int positionOffset = BufferUtil.readSmart(buffer);
|
||||||
|
|
||||||
|
while (positionOffset != 0) {
|
||||||
|
packed += positionOffset - 1;
|
||||||
|
|
||||||
|
int attributes = buffer.get() & 0xFF;
|
||||||
|
int type = attributes >> 2;
|
||||||
|
int orientation = attributes & 0x3;
|
||||||
|
objects.add(new MapObject(id, packed, type, orientation));
|
||||||
|
|
||||||
|
positionOffset = BufferUtil.readSmart(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
idOffset = BufferUtil.readSmart(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package org.apollo.cache.map;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A plane of a map, which is a distinct height level.
|
||||||
|
*
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public final class MapPlane {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a shallow copy of the specified 2-dimensional array.
|
||||||
|
*
|
||||||
|
* @param array The array to copy. Must not be {@code null}.
|
||||||
|
* @return The copy.
|
||||||
|
*/
|
||||||
|
private static <T> T[][] clone(T[][] array) {
|
||||||
|
T[][] copy = array.clone();
|
||||||
|
for (int index = 0; index < copy.length; index++) {
|
||||||
|
copy[index] = array[index].clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The level of this MapPlane.
|
||||||
|
*/
|
||||||
|
private final int level;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The 2-dimensional array of Tiles.
|
||||||
|
*/
|
||||||
|
private final Tile[][] tiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the MapPlane.
|
||||||
|
*
|
||||||
|
* @param level The level of the MapPlane.
|
||||||
|
* @param tiles The 2D array of {@link Tile}s. Must not be {@code null}. Must be square.
|
||||||
|
*/
|
||||||
|
public MapPlane(int level, Tile[][] tiles) {
|
||||||
|
this.level = level;
|
||||||
|
this.tiles = clone(tiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the level of this MapPlane.
|
||||||
|
*
|
||||||
|
* @return The level.
|
||||||
|
*/
|
||||||
|
public int getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the amount of tiles in this MapPlane.
|
||||||
|
*
|
||||||
|
* @return The amount of tiles.
|
||||||
|
*/
|
||||||
|
public int getSize() {
|
||||||
|
return tiles.length * tiles[0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link Tile} at the specified (x, z) coordinate.
|
||||||
|
*
|
||||||
|
* @param x The x coordinate.
|
||||||
|
* @param z The z coordinate.
|
||||||
|
* @return The Tile.
|
||||||
|
*/
|
||||||
|
public Tile getTile(int x, int z) {
|
||||||
|
return tiles[x][z];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the {@link Tile}s in this MapPlane.
|
||||||
|
* <p>
|
||||||
|
* This method returns the Tiles according on a column-based ordering: for a 2x2 tile set, the order will be
|
||||||
|
* {@code (0, 0), (0, 1), (1, 0), (1, 1)}.
|
||||||
|
*
|
||||||
|
* @return The Tiles.
|
||||||
|
*/
|
||||||
|
public Stream<Tile> getTiles() {
|
||||||
|
return Arrays.stream(tiles).flatMap(Arrays::stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,295 @@
|
|||||||
|
package org.apollo.cache.map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A single tile on the map.
|
||||||
|
*
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public final class Tile {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A builder class for a Tile.
|
||||||
|
*/
|
||||||
|
public static final class Builder {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes of the Tile.
|
||||||
|
*/
|
||||||
|
private int attributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The height of the Tile.
|
||||||
|
*/
|
||||||
|
private int height;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The overlay id of the Tile.
|
||||||
|
*/
|
||||||
|
private int overlay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The overlay orientation of the Tile.
|
||||||
|
*/
|
||||||
|
private int overlayOrientation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The overlay type of the Tile.
|
||||||
|
*/
|
||||||
|
private int overlayType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The x coordinate of the Tile.
|
||||||
|
*/
|
||||||
|
private int x;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The y coordinate of the Tile.
|
||||||
|
*/
|
||||||
|
private int y;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The underlay id of the Tile.
|
||||||
|
*/
|
||||||
|
private int underlay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the Builder.
|
||||||
|
*
|
||||||
|
* @param x The x position of the Tile.
|
||||||
|
* @param y The y position of the Tile.
|
||||||
|
* @param height The height level of the Tile.
|
||||||
|
*/
|
||||||
|
public Builder(int x, int y, int height) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the contents of this Builder into a Tile.
|
||||||
|
*
|
||||||
|
* @return The Tile.
|
||||||
|
*/
|
||||||
|
public Tile build() {
|
||||||
|
return new Tile(x, y, attributes, height, overlay, overlayType, overlayOrientation, underlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the attributes of the Tile.
|
||||||
|
*
|
||||||
|
* @param attributes The attributes.
|
||||||
|
*/
|
||||||
|
public void setAttributes(int attributes) {
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the height of the Tile.
|
||||||
|
*
|
||||||
|
* @param height The height.
|
||||||
|
*/
|
||||||
|
public void setHeight(int height) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the overlay id of the Tile.
|
||||||
|
*
|
||||||
|
* @param overlay The overlay id.
|
||||||
|
*/
|
||||||
|
public void setOverlay(int overlay) {
|
||||||
|
this.overlay = overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the overlay orientation of the Tile.
|
||||||
|
*
|
||||||
|
* @param orientation The overlay orientation.
|
||||||
|
*/
|
||||||
|
public void setOverlayOrientation(int orientation) {
|
||||||
|
this.overlayOrientation = orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the overlay type of the Tile.
|
||||||
|
*
|
||||||
|
* @param type The overlay type.
|
||||||
|
*/
|
||||||
|
public void setOverlayType(int type) {
|
||||||
|
this.overlayType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the position of the Tile.
|
||||||
|
*
|
||||||
|
* @param x The x coordinate of the Tile.
|
||||||
|
* @param y the y coordinate of the Tile
|
||||||
|
* @param height The height level of the Tile.
|
||||||
|
*/
|
||||||
|
public void setPosition(int x, int y, int height) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the underlay id of the Tile.
|
||||||
|
*
|
||||||
|
* @param underlay The underlay.
|
||||||
|
*/
|
||||||
|
public void setUnderlay(int underlay) {
|
||||||
|
this.underlay = underlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link Builder} for a Tile.
|
||||||
|
*
|
||||||
|
* @param x The x coordinate of the Tile.
|
||||||
|
* @param y the y coordinate of the Tile.
|
||||||
|
* @param height The height level of the Tile.
|
||||||
|
* @return The Builder.
|
||||||
|
*/
|
||||||
|
public static Builder builder(int x, int y, int height) {
|
||||||
|
return new Builder(x, y, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes of this Tile.
|
||||||
|
*/
|
||||||
|
private final int attributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The height of this Tile.
|
||||||
|
*/
|
||||||
|
private final int height;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The overlay id of this Tile.
|
||||||
|
*/
|
||||||
|
private final int overlay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The overlay orientation of this Tile.
|
||||||
|
*/
|
||||||
|
private final int overlayOrientation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The overlay type of this Tile.
|
||||||
|
*/
|
||||||
|
private final int overlayType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The x coordinate of this Tile.
|
||||||
|
*/
|
||||||
|
private final int x;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The y coordinate of this Tile.
|
||||||
|
*/
|
||||||
|
private final int y;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The underlay id of this Tile.
|
||||||
|
*/
|
||||||
|
private final int underlay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the Tile.
|
||||||
|
*
|
||||||
|
* @param x The x coordinate of the Tile.
|
||||||
|
* @param y The y coordinate of the Tile.
|
||||||
|
* @param attributes The attributes.
|
||||||
|
* @param height The height.
|
||||||
|
* @param overlay The overlay id.
|
||||||
|
* @param overlayType The overlay type.
|
||||||
|
* @param overlayOrientation The overlay orientation.
|
||||||
|
* @param underlay The underlay id.
|
||||||
|
*/
|
||||||
|
public Tile(int x, int y, int attributes, int height, int overlay, int overlayType, int overlayOrientation,
|
||||||
|
int underlay) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.attributes = attributes;
|
||||||
|
this.height = height;
|
||||||
|
this.overlay = overlay;
|
||||||
|
this.overlayType = overlayType;
|
||||||
|
this.overlayOrientation = overlayOrientation;
|
||||||
|
this.underlay = underlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the attributes of this Tile.
|
||||||
|
*
|
||||||
|
* @return The attributes.
|
||||||
|
*/
|
||||||
|
public int getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the height of this Tile.
|
||||||
|
*
|
||||||
|
* @return The height.
|
||||||
|
*/
|
||||||
|
public int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the overlay id of this Tile.
|
||||||
|
*
|
||||||
|
* @return The overlay id.
|
||||||
|
*/
|
||||||
|
public int getOverlay() {
|
||||||
|
return overlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the overlay orientation of this Tile.
|
||||||
|
*
|
||||||
|
* @return The overlay orientation.
|
||||||
|
*/
|
||||||
|
public int getOverlayOrientation() {
|
||||||
|
return overlayOrientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the overlay type of this Tile.
|
||||||
|
*
|
||||||
|
* @return The overlay types.
|
||||||
|
*/
|
||||||
|
public int getOverlayType() {
|
||||||
|
return overlayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the underlay id of this Tile.
|
||||||
|
*
|
||||||
|
* @return The underlay id.
|
||||||
|
*/
|
||||||
|
public int getUnderlay() {
|
||||||
|
return underlay;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the x coordinate of this Tile.
|
||||||
|
*
|
||||||
|
* @return The x coordinate.
|
||||||
|
*/
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the y coordinate of this Tile.
|
||||||
|
*
|
||||||
|
* @return The y coordinate.
|
||||||
|
*/
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,161 @@
|
|||||||
|
package org.apollo.cache.map;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012-2013 Jonathan Edgecombe <jonathanedgecombe@gmail.com>
|
||||||
|
* Copyright (c) 2015 Major
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains tile-related utility methods.
|
||||||
|
*
|
||||||
|
* @author Johnny
|
||||||
|
* @author Major
|
||||||
|
*/
|
||||||
|
public final class TileUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The x coordinate offset, used for computing the Tile height.
|
||||||
|
*/
|
||||||
|
static final int TILE_HEIGHT_X_OFFSET = 0xe3b7b;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The z coordinate offset, used for computing the Tile height.
|
||||||
|
*/
|
||||||
|
static final int TILE_HEIGHT_Z_OFFSET = 0x87cce;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cosine table used for interpolation.
|
||||||
|
*/
|
||||||
|
private static final int[] COSINE = new int[2048];
|
||||||
|
|
||||||
|
static {
|
||||||
|
for (int index = 0; index < COSINE.length; index++) {
|
||||||
|
COSINE[index] = (int) (65536 * Math.cos(2 * Math.PI * index / COSINE.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the height offset for the specified coordinate pair.
|
||||||
|
*
|
||||||
|
* @param x The x coordinate of the Tile.
|
||||||
|
* @param z The z coordinate of the Tile.
|
||||||
|
* @return The height offset.
|
||||||
|
*/
|
||||||
|
public static int calculateHeight(int x, int z) {
|
||||||
|
int regionSize = 8;
|
||||||
|
int regionOffset = 6;
|
||||||
|
int offset = regionOffset * regionSize;
|
||||||
|
|
||||||
|
int baseX = x - offset;
|
||||||
|
int baseZ = z - offset;
|
||||||
|
|
||||||
|
return computeHeight(x + TILE_HEIGHT_X_OFFSET - baseX, z + TILE_HEIGHT_Z_OFFSET - baseZ)
|
||||||
|
* MapConstants.HEIGHT_MULTIPLICAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the height offset for the specified coordinate pair.
|
||||||
|
*
|
||||||
|
* @param x The offset-x coordinate of the tile.
|
||||||
|
* @param z The offset-z coordinate of the tile.
|
||||||
|
* @return The tile height offset.
|
||||||
|
*/
|
||||||
|
private static int computeHeight(int x, int z) {
|
||||||
|
int total = interpolatedNoise(x + 45365, z + 91923, 4) - 128;
|
||||||
|
|
||||||
|
total += (interpolatedNoise(x + 10294, z + 37821, 2) - 128) / 2;
|
||||||
|
total += (interpolatedNoise(x, z, 1) - 128) / 4;
|
||||||
|
|
||||||
|
total = (int) Math.max(total * 0.3 + 35, 10);
|
||||||
|
return Math.min(total, 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interpolates two smooth noise values.
|
||||||
|
*
|
||||||
|
* @param a The first smooth noise value.
|
||||||
|
* @param b The second smooth noise value.
|
||||||
|
* @param theta The angle.
|
||||||
|
* @param reciprocal The frequency reciprocal.
|
||||||
|
* @return The interpolated value.
|
||||||
|
*/
|
||||||
|
private static int interpolate(int a, int b, int theta, int reciprocal) {
|
||||||
|
int cosine = 65536 - COSINE[theta * COSINE.length / (2 * reciprocal)] / 2;
|
||||||
|
return (a * (65536 - cosine)) / 65536 + (b * cosine) / 65536;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets interpolated noise for the specified coordinate pair, using the specified frequency reciprocal.
|
||||||
|
*
|
||||||
|
* @param x The x coordinate.
|
||||||
|
* @param z The z coordinate.
|
||||||
|
* @param reciprocal The frequency reciprocal.
|
||||||
|
* @return The interpolated noise.
|
||||||
|
*/
|
||||||
|
private static int interpolatedNoise(int x, int z, int reciprocal) {
|
||||||
|
int xt = x % reciprocal;
|
||||||
|
int zt = z % reciprocal;
|
||||||
|
|
||||||
|
x /= reciprocal;
|
||||||
|
z /= reciprocal;
|
||||||
|
|
||||||
|
int c = smoothNoise(x, z);
|
||||||
|
int e = smoothNoise(x + 1, z);
|
||||||
|
int ce = interpolate(c, e, xt, reciprocal);
|
||||||
|
|
||||||
|
int n = smoothNoise(x, z + 1);
|
||||||
|
int ne = smoothNoise(x + 1, z + 1);
|
||||||
|
int u = interpolate(n, ne, xt, reciprocal);
|
||||||
|
|
||||||
|
return interpolate(ce, u, zt, reciprocal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes noise for the specified coordinate pair.
|
||||||
|
*
|
||||||
|
* @param x The x coordinate.
|
||||||
|
* @param z The z coordinate.
|
||||||
|
* @return The noise.
|
||||||
|
*/
|
||||||
|
private static int noise(int x, int z) {
|
||||||
|
int n = x + z * 57;
|
||||||
|
n = (n << 13) ^ n;
|
||||||
|
n = (n * (n * n * 15731 + 789221) + 1376312589) & Integer.MAX_VALUE;
|
||||||
|
return (n >> 19) & 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes smooth noise for the specified coordinate pair.
|
||||||
|
*
|
||||||
|
* @param x The x coordinate.
|
||||||
|
* @param z The z coordinate.
|
||||||
|
* @return The smooth noise.
|
||||||
|
*/
|
||||||
|
private static int smoothNoise(int x, int z) {
|
||||||
|
int corners = noise(x - 1, z - 1) + noise(x + 1, z - 1) + noise(x - 1, z + 1) + noise(x + 1, z + 1);
|
||||||
|
int sides = noise(x - 1, z) + noise(x + 1, z) + noise(x, z - 1) + noise(x, z + 1);
|
||||||
|
int center = noise(x, z);
|
||||||
|
|
||||||
|
return corners / 16 + sides / 8 + center / 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sole private constructor to prevent instantiation.
|
||||||
|
*/
|
||||||
|
private TileUtils() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/**
|
||||||
|
* Contains classes which deal with the file system that the client uses to store game data files.
|
||||||
|
*/
|
||||||
|
package org.apollo.cache;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user