mirror of
https://github.com/Rogiel/l2jserver2
synced 2025-12-09 17:02:53 +00:00
Change-Id: I0000000000000000000000000000000000000000
Change-Id: I8636776eaf000fcdfb528cc403710f6d6ee9e73e Change-Id: Iebc523681d07ecd6d7b7e89343b29a8034558f94
This commit is contained in:
@@ -17,6 +17,7 @@ import com.l2jserver.model.world.L2Character;
|
||||
public class Lineage2Connection {
|
||||
private final Channel channel;
|
||||
private L2Character character;
|
||||
private Lineage2Session session;
|
||||
|
||||
public Lineage2Connection(Channel channel) {
|
||||
this.channel = channel;
|
||||
@@ -44,6 +45,23 @@ public class Lineage2Connection {
|
||||
this.character = character;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the session
|
||||
*/
|
||||
public Lineage2Session getSession() {
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param session
|
||||
* the session to set
|
||||
*/
|
||||
public void setSession(Lineage2Session session) {
|
||||
if (this.session != null)
|
||||
throw new IllegalStateException("Session is already set!");
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
55
src/main/java/com/l2jserver/game/net/Lineage2Session.java
Normal file
55
src/main/java/com/l2jserver/game/net/Lineage2Session.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package com.l2jserver.game.net;
|
||||
|
||||
public class Lineage2Session {
|
||||
private final String username;
|
||||
|
||||
private final int playKey1;
|
||||
private final int playKey2;
|
||||
|
||||
private final int loginKey1;
|
||||
private final int loginKey2;
|
||||
|
||||
public Lineage2Session(String username, int playOK1, int playOK2,
|
||||
int loginOK1, int loginOK2) {
|
||||
this.username = username;
|
||||
this.playKey1 = playOK1;
|
||||
this.playKey2 = playOK2;
|
||||
this.loginKey1 = loginOK1;
|
||||
this.loginKey2 = loginOK2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the username
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the playKey1
|
||||
*/
|
||||
public int getPlayKey1() {
|
||||
return playKey1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the playKey2
|
||||
*/
|
||||
public int getPlayKey2() {
|
||||
return playKey2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the loginKey1
|
||||
*/
|
||||
public int getLoginKey1() {
|
||||
return loginKey1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the loginKey2
|
||||
*/
|
||||
public int getLoginKey2() {
|
||||
return loginKey2;
|
||||
}
|
||||
}
|
||||
@@ -14,14 +14,14 @@ public class Lineage2Decrypter extends OneToOneDecoder {
|
||||
private final byte[] key = new byte[16];
|
||||
|
||||
@Override
|
||||
protected synchronized Object decode(ChannelHandlerContext ctx, Channel channel,
|
||||
Object msg) throws Exception {
|
||||
protected synchronized Object decode(ChannelHandlerContext ctx,
|
||||
Channel channel, Object msg) throws Exception {
|
||||
if (!(msg instanceof ChannelBuffer))
|
||||
return msg;
|
||||
if (!enabled)
|
||||
return msg;
|
||||
final ChannelBuffer buffer = (ChannelBuffer) msg;
|
||||
|
||||
|
||||
final int offset = buffer.readerIndex();
|
||||
final int size = buffer.readableBytes();
|
||||
int temp = 0;
|
||||
@@ -45,7 +45,7 @@ public class Lineage2Decrypter extends OneToOneDecoder {
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
public byte[] enable() {
|
||||
byte[] key = BlowFishKeygen.getRandomKey();
|
||||
this.setKey(key);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.l2jserver.game.net.codec;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||
@@ -13,17 +12,15 @@ public class Lineage2Encrypter extends OneToOneEncoder {
|
||||
private final byte[] key = new byte[16];
|
||||
|
||||
@Override
|
||||
protected synchronized Object encode(ChannelHandlerContext ctx, Channel channel,
|
||||
Object msg) throws Exception {
|
||||
protected synchronized Object encode(ChannelHandlerContext ctx,
|
||||
Channel channel, Object msg) throws Exception {
|
||||
if (!(msg instanceof ChannelBuffer))
|
||||
return msg;
|
||||
if (!enabled)
|
||||
return msg;
|
||||
final ChannelBuffer buffer = (ChannelBuffer) msg;
|
||||
|
||||
System.out.println(ChannelBuffers.hexDump(buffer));
|
||||
|
||||
final int offset = buffer.readerIndex() + 2; //skip header
|
||||
final int offset = buffer.readerIndex() + 2; // skip header
|
||||
final int size = buffer.readableBytes() - 2;
|
||||
int temp = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
|
||||
@@ -7,10 +7,15 @@ import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.frame.FrameDecoder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Lineage2FrameDecoder extends FrameDecoder {
|
||||
private static final int HEADER_SIZE = 2;
|
||||
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(Lineage2FrameDecoder.class);
|
||||
|
||||
@Override
|
||||
protected Object decode(ChannelHandlerContext ctx, Channel channel,
|
||||
ChannelBuffer oldBuffer) throws Exception {
|
||||
@@ -19,12 +24,13 @@ public class Lineage2FrameDecoder extends FrameDecoder {
|
||||
ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(oldBuffer
|
||||
.toByteBuffer().order(ByteOrder.LITTLE_ENDIAN));
|
||||
|
||||
logger.debug("Received frame segment: {}",
|
||||
ChannelBuffers.hexDump(buffer));
|
||||
|
||||
buffer.markReaderIndex();
|
||||
final int pending = buffer.readUnsignedShort() - HEADER_SIZE;
|
||||
if (pending == 0) {
|
||||
if (pending == 0)
|
||||
return null;
|
||||
}
|
||||
|
||||
if (buffer.readableBytes() < pending) {
|
||||
buffer.resetReaderIndex();
|
||||
return null;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.l2jserver.game.net.codec;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.jboss.netty.buffer.ChannelBuffers;
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelHandlerContext;
|
||||
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
|
||||
@@ -13,10 +12,8 @@ public class Lineage2FrameEncoder extends OneToOneEncoder {
|
||||
if (!(msg instanceof ChannelBuffer))
|
||||
return msg;
|
||||
final ChannelBuffer buffer = (ChannelBuffer) msg;
|
||||
buffer.setShort(0, buffer.readableBytes() - 2);
|
||||
|
||||
System.out.println(ChannelBuffers.hexDump(buffer));
|
||||
|
||||
buffer.setShort(0, buffer.readableBytes());
|
||||
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,11 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.l2jserver.game.net.packet.ClientPacket;
|
||||
import com.l2jserver.game.net.packet.client.AuthLoginPacket;
|
||||
import com.l2jserver.game.net.packet.client.CharacterCreatePacket;
|
||||
import com.l2jserver.game.net.packet.client.LogoutPacket;
|
||||
import com.l2jserver.game.net.packet.client.ProtocolVersionPacket;
|
||||
import com.l2jserver.game.net.packet.client.RequestGotoLobby;
|
||||
import com.l2jserver.game.net.packet.client.RequestNewCharacterPacket;
|
||||
|
||||
public class Lineage2PacketReader extends OneToOneDecoder {
|
||||
private final Injector injector;
|
||||
@@ -45,12 +49,30 @@ public class Lineage2PacketReader extends OneToOneDecoder {
|
||||
private Class<? extends ClientPacket> getPacketClass(ChannelBuffer buffer) {
|
||||
final short opcode = buffer.readUnsignedByte();
|
||||
switch (opcode) {
|
||||
case LogoutPacket.OPCODE:
|
||||
return LogoutPacket.class;
|
||||
case ProtocolVersionPacket.OPCODE:
|
||||
return ProtocolVersionPacket.class;
|
||||
case AuthLoginPacket.OPCODE:
|
||||
return AuthLoginPacket.class;
|
||||
case CharacterCreatePacket.OPCODE:
|
||||
return CharacterCreatePacket.class;
|
||||
case RequestNewCharacterPacket.OPCODE:
|
||||
return RequestNewCharacterPacket.class;
|
||||
// COMPOSED
|
||||
case 0xd0:
|
||||
final int opcode2 = buffer.readUnsignedShort();
|
||||
switch (opcode2) {
|
||||
case RequestGotoLobby.OPCODE2:
|
||||
return RequestGotoLobby.class;
|
||||
default:
|
||||
logger.warn("Unknown opcode2: 0x{}",
|
||||
Integer.toHexString(opcode));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
logger.info("Unknown opcode: " + Integer.toHexString(opcode));
|
||||
logger.warn("Unknown opcode: 0x{}", Integer.toHexString(opcode));
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -21,7 +21,7 @@ public class Lineage2PacketWriter extends OneToOneEncoder {
|
||||
final ServerPacket packet = (ServerPacket) msg;
|
||||
buffer.writeShort(0x0000);
|
||||
buffer.writeByte(packet.getOpcode()); // packet opcode
|
||||
packet.write(buffer);
|
||||
packet.write(buffer);
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ public class Lineage2PacketHandler extends SimpleChannelHandler {
|
||||
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
|
||||
throws Exception {
|
||||
connection = new Lineage2Connection(e.getChannel());
|
||||
|
||||
|
||||
System.out.println(e);
|
||||
|
||||
|
||||
super.channelOpen(ctx, e);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
package com.l2jserver.game.net.packet;
|
||||
|
||||
|
||||
public abstract class AbstractClientPacket implements ClientPacket {
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
package com.l2jserver.game.net.packet;
|
||||
|
||||
|
||||
public interface Packet {
|
||||
}
|
||||
|
||||
@@ -4,5 +4,6 @@ import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
public interface ServerPacket extends Packet {
|
||||
void write(ChannelBuffer buffer);
|
||||
|
||||
int getOpcode();
|
||||
}
|
||||
|
||||
@@ -1,23 +1,29 @@
|
||||
package com.l2jserver.game.net.packet.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.l2jserver.db.dao.CharacterDAO;
|
||||
import com.l2jserver.game.net.Lineage2Connection;
|
||||
import com.l2jserver.game.net.Lineage2Session;
|
||||
import com.l2jserver.game.net.packet.AbstractClientPacket;
|
||||
import com.l2jserver.game.net.packet.server.CharSelectionInfoPacket;
|
||||
import com.l2jserver.model.id.object.factory.CharacterIDFactory;
|
||||
import com.l2jserver.game.net.packet.server.CharacterSelectionListPacket;
|
||||
import com.l2jserver.model.world.L2Character;
|
||||
import com.l2jserver.service.game.world.WorldService;
|
||||
import com.l2jserver.util.BufferUtil;
|
||||
|
||||
/**
|
||||
* This packet is sent by the client once the login server has authorized
|
||||
* authentication into this server. A new {@link Lineage2Session} object will be
|
||||
* set to the current connection and the character list is sent to the client.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class AuthLoginPacket extends AbstractClientPacket {
|
||||
public static final int OPCODE = 0x2b;
|
||||
|
||||
@Inject
|
||||
private WorldService world;
|
||||
@Inject
|
||||
private CharacterIDFactory idFactory;
|
||||
private final CharacterDAO characterDao;
|
||||
|
||||
// packet
|
||||
private String loginName;
|
||||
@@ -26,6 +32,11 @@ public class AuthLoginPacket extends AbstractClientPacket {
|
||||
private int loginKey1;
|
||||
private int loginKey2;
|
||||
|
||||
@Inject
|
||||
public AuthLoginPacket(CharacterDAO characterDao) {
|
||||
this.characterDao = characterDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ChannelBuffer buffer) {
|
||||
this.loginName = BufferUtil.readString(buffer);
|
||||
@@ -38,11 +49,13 @@ public class AuthLoginPacket extends AbstractClientPacket {
|
||||
|
||||
@Override
|
||||
public void process(final Lineage2Connection conn) {
|
||||
// assume it is correct, for now
|
||||
// send character list
|
||||
// world.getEventDispatcher().dispatch(null);
|
||||
final L2Character c = idFactory.createID(268435456).getObject();
|
||||
conn.write(new CharSelectionInfoPacket(loginName, playKey1, -1, c));
|
||||
conn.setSession(new Lineage2Session(loginName, playKey1, playKey2,
|
||||
loginKey1, loginKey2));
|
||||
|
||||
final List<L2Character> chars = characterDao.selectByAccount(conn
|
||||
.getSession().getUsername());
|
||||
conn.write(CharacterSelectionListPacket.fromL2Session(
|
||||
conn.getSession(), chars.toArray(new L2Character[0])));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
package com.l2jserver.game.net.packet.client;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.l2jserver.db.dao.CharacterDAO;
|
||||
import com.l2jserver.game.net.Lineage2Connection;
|
||||
import com.l2jserver.game.net.packet.AbstractClientPacket;
|
||||
import com.l2jserver.game.net.packet.server.CharacterCreateFailPacket;
|
||||
import com.l2jserver.game.net.packet.server.CharacterCreateOkPacket;
|
||||
import com.l2jserver.model.id.object.CharacterID;
|
||||
import com.l2jserver.model.id.object.factory.CharacterIDFactory;
|
||||
import com.l2jserver.model.id.template.CharacterTemplateID;
|
||||
import com.l2jserver.model.id.template.factory.CharacterTemplateIDFactory;
|
||||
import com.l2jserver.model.template.CharacterTemplate;
|
||||
import com.l2jserver.model.world.AbstractActor.Race;
|
||||
import com.l2jserver.model.world.AbstractActor.Sex;
|
||||
import com.l2jserver.model.world.L2Character;
|
||||
import com.l2jserver.model.world.character.CharacterAppearance.CharacterFace;
|
||||
import com.l2jserver.model.world.character.CharacterAppearance.CharacterHairColor;
|
||||
import com.l2jserver.model.world.character.CharacterAppearance.CharacterHairStyle;
|
||||
import com.l2jserver.util.BufferUtil;
|
||||
|
||||
/**
|
||||
* Completes the creation of an character. Creates the object, inserts into the
|
||||
* database and notifies the client abou the status of the operation.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class CharacterCreatePacket extends AbstractClientPacket {
|
||||
public static final int OPCODE = 0x0c;
|
||||
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(CharacterCreatePacket.class);
|
||||
|
||||
// services and daos
|
||||
private final CharacterDAO characterDao;
|
||||
private final CharacterIDFactory characterIdFactory;
|
||||
private final CharacterTemplateIDFactory characterTemplateIdFactory;
|
||||
|
||||
// packet
|
||||
private String name;
|
||||
private Race race;
|
||||
private Sex sex;
|
||||
private int classId;
|
||||
|
||||
private int intelligence;
|
||||
private int strength;
|
||||
private int concentration;
|
||||
private int mentality;
|
||||
private int dextry;
|
||||
private int witness;
|
||||
|
||||
private CharacterHairStyle hairStyle;
|
||||
private CharacterHairColor hairColor;
|
||||
private CharacterFace face;
|
||||
|
||||
@Inject
|
||||
public CharacterCreatePacket(CharacterDAO characterDao,
|
||||
CharacterIDFactory characterIdFactory,
|
||||
CharacterTemplateIDFactory characterTemplateIdFactory) {
|
||||
this.characterDao = characterDao;
|
||||
this.characterIdFactory = characterIdFactory;
|
||||
this.characterTemplateIdFactory = characterTemplateIdFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ChannelBuffer buffer) {
|
||||
name = BufferUtil.readString(buffer);
|
||||
race = Race.fromOption(buffer.readInt());
|
||||
sex = Sex.fromOption(buffer.readInt());
|
||||
classId = buffer.readInt();
|
||||
|
||||
intelligence = buffer.readInt();
|
||||
strength = buffer.readInt();
|
||||
concentration = buffer.readInt();
|
||||
mentality = buffer.readInt();
|
||||
dextry = buffer.readInt();
|
||||
witness = buffer.readInt();
|
||||
|
||||
hairStyle = CharacterHairStyle.fromOption(buffer.readInt());
|
||||
hairColor = CharacterHairColor.fromOption(buffer.readInt());
|
||||
face = CharacterFace.fromOption(buffer.readInt());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(final Lineage2Connection conn) {
|
||||
log.debug("Creating a new character");
|
||||
if ((name.length() < 1) || (name.length() > 16)) {
|
||||
log.debug("Character name length invalid: {}. Aborting.", name);
|
||||
conn.write(new CharacterCreateFailPacket(
|
||||
CharacterCreateFailPacket.Reason.REASON_16_ENG_CHARS));
|
||||
return;
|
||||
}
|
||||
// TODO check alphanumeric name
|
||||
if (sex == null || hairStyle == null || hairColor == null
|
||||
|| face == null) {
|
||||
log.debug("Character appearance invalid. Aborting.");
|
||||
// if some of those attributes is null, something wrong happened.
|
||||
// Maybe we don't support the value sent!
|
||||
conn.write(new CharacterCreateFailPacket(
|
||||
CharacterCreateFailPacket.Reason.REASON_CREATION_FAILED));
|
||||
return;
|
||||
}
|
||||
// existence check
|
||||
final L2Character existenceCheck = characterDao.selectByName(name);
|
||||
if (existenceCheck != null) {
|
||||
log.debug("Character name already exists: {}. Aborting.", name);
|
||||
conn.write(new CharacterCreateFailPacket(
|
||||
CharacterCreateFailPacket.Reason.REASON_NAME_ALREADY_EXISTS));
|
||||
return;
|
||||
}
|
||||
|
||||
// create template id and lookup for the template instance
|
||||
final CharacterTemplateID templateId = characterTemplateIdFactory
|
||||
.createID(classId);
|
||||
final CharacterTemplate template = templateId.getTemplate();
|
||||
log.debug("Creating character with template {}", template);
|
||||
|
||||
// ensure parameters passed by the client are true
|
||||
if ((intelligence != template.getIntelligence())
|
||||
|| (strength != template.getStrength())
|
||||
|| (concentration != template.getConcentration())
|
||||
|| (mentality != template.getMentality())
|
||||
|| (dextry != template.getDextry())
|
||||
|| (witness != template.getWitness())
|
||||
|| (race != template.getRace())) {
|
||||
log.debug(
|
||||
"Values sent by client and sent from template does not match: {}",
|
||||
template);
|
||||
// some of the values didn't match, canceling creation
|
||||
conn.write(new CharacterCreateFailPacket(
|
||||
CharacterCreateFailPacket.Reason.REASON_CREATION_FAILED));
|
||||
return;
|
||||
}
|
||||
|
||||
// everything is fine, allocate a new ID
|
||||
final CharacterID id = characterIdFactory.createID();
|
||||
// create the instance from the template
|
||||
final L2Character character = template.create();
|
||||
|
||||
log.debug("Character object created, ID: {}, Object: {}", id, character);
|
||||
|
||||
// set parameters
|
||||
character.setID(id);
|
||||
character.setName(name);
|
||||
|
||||
character.setSex(sex);
|
||||
|
||||
character.getAppearance().setHairStyle(hairStyle);
|
||||
character.getAppearance().setHairColor(hairColor);
|
||||
character.getAppearance().setFace(face);
|
||||
|
||||
if (characterDao.save(character)) {
|
||||
log.debug("Character saved to database");
|
||||
conn.write(CharacterCreateOkPacket.INSTANCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.l2jserver.game.net.packet.client;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.l2jserver.game.net.Lineage2Connection;
|
||||
import com.l2jserver.game.net.packet.AbstractClientPacket;
|
||||
|
||||
/**
|
||||
* The client is requesting a logout. Currently, when this packet is received
|
||||
* the connection is immediately closed.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class LogoutPacket extends AbstractClientPacket {
|
||||
public static final int OPCODE = 0x00;
|
||||
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(LogoutPacket.class);
|
||||
|
||||
@Override
|
||||
public void read(ChannelBuffer buffer) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(final Lineage2Connection conn) {
|
||||
log.debug("Logging out client {}", conn);
|
||||
conn.close();
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,21 @@ import com.l2jserver.game.net.Lineage2Connection;
|
||||
import com.l2jserver.game.net.packet.AbstractClientPacket;
|
||||
import com.l2jserver.game.net.packet.server.KeyPacket;
|
||||
|
||||
/**
|
||||
* In this packet the client is informing its protocol version. It is possible
|
||||
* to do an test and refuse invalid protocol versions. After this packet, the
|
||||
* messages received and sent are all encrypted, except for the encryptation key
|
||||
* which is sent here.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class ProtocolVersionPacket extends AbstractClientPacket {
|
||||
public static final int OPCODE = 0x0e;
|
||||
|
||||
// services
|
||||
private final Logger logger = LoggerFactory
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private final Logger log = LoggerFactory
|
||||
.getLogger(ProtocolVersionPacket.class);
|
||||
|
||||
// packet
|
||||
@@ -30,9 +40,11 @@ public class ProtocolVersionPacket extends AbstractClientPacket {
|
||||
public void process(final Lineage2Connection conn) {
|
||||
// generate a new key
|
||||
final byte[] key = conn.getDecrypter().enable();
|
||||
|
||||
log.debug("Decrypter has been enabled");
|
||||
|
||||
log.debug("Client protocol version: {}", version);
|
||||
if (L2JConstants.SUPPORTED_PROTOCOL != version) {
|
||||
logger.info(
|
||||
log.info(
|
||||
"Incorrect protocol version: {0}. Only {1} is supported.",
|
||||
version, L2JConstants.SUPPORTED_PROTOCOL);
|
||||
// notify wrong protocol and close connection
|
||||
@@ -53,6 +65,7 @@ public class ProtocolVersionPacket extends AbstractClientPacket {
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture future)
|
||||
throws Exception {
|
||||
log.debug("Encrypter has been enabled");
|
||||
// enable encrypter
|
||||
conn.getEncrypter().setKey(key);
|
||||
conn.getEncrypter().setEnabled(true);
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.l2jserver.game.net.packet.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.l2jserver.db.dao.CharacterDAO;
|
||||
import com.l2jserver.game.net.Lineage2Connection;
|
||||
import com.l2jserver.game.net.packet.AbstractClientPacket;
|
||||
import com.l2jserver.game.net.packet.server.CharacterSelectionListPacket;
|
||||
import com.l2jserver.model.world.L2Character;
|
||||
|
||||
/**
|
||||
* Requests the list of characters to be displayed in the lobby. The list of
|
||||
* characters is sent to the client.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class RequestGotoLobby extends AbstractClientPacket {
|
||||
public static final int OPCODE1 = 0xd0;
|
||||
public static final int OPCODE2 = 0x36;
|
||||
|
||||
private final CharacterDAO characterDao;
|
||||
|
||||
@Inject
|
||||
public RequestGotoLobby(CharacterDAO characterDao) {
|
||||
this.characterDao = characterDao;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ChannelBuffer buffer) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(final Lineage2Connection conn) {
|
||||
final List<L2Character> chars = characterDao.selectByAccount(conn
|
||||
.getSession().getUsername());
|
||||
conn.write(CharacterSelectionListPacket.fromL2Session(
|
||||
conn.getSession(), chars.toArray(new L2Character[0])));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.l2jserver.game.net.packet.client;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.l2jserver.game.net.Lineage2Connection;
|
||||
import com.l2jserver.game.net.packet.AbstractClientPacket;
|
||||
import com.l2jserver.game.net.packet.server.CharacterTemplatePacket;
|
||||
import com.l2jserver.model.id.template.CharacterTemplateID;
|
||||
import com.l2jserver.model.id.template.factory.CharacterTemplateIDFactory;
|
||||
import com.l2jserver.model.template.CharacterTemplate;
|
||||
|
||||
/**
|
||||
* Requests the creation of a new Character. The list of character templates is
|
||||
* sent to the client, meaning that the client is autorized to create
|
||||
* characters.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class RequestNewCharacterPacket extends AbstractClientPacket {
|
||||
public static final int OPCODE = 0x13;
|
||||
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(RequestNewCharacterPacket.class);
|
||||
|
||||
private final CharacterTemplateIDFactory idFactory;
|
||||
|
||||
@Inject
|
||||
public RequestNewCharacterPacket(CharacterTemplateIDFactory idFactory) {
|
||||
this.idFactory = idFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ChannelBuffer buffer) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(final Lineage2Connection conn) {
|
||||
log.debug("Requested character templates");
|
||||
final CharacterTemplateID id = idFactory
|
||||
.createID(Integer.MAX_VALUE - 1);
|
||||
final CharacterTemplate template = id.getTemplate();
|
||||
|
||||
final CharacterTemplatePacket templatePacket = new CharacterTemplatePacket(
|
||||
template);
|
||||
conn.write(templatePacket);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.l2jserver.game.net.packet.server;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
import com.l2jserver.game.net.packet.AbstractServerPacket;
|
||||
|
||||
/**
|
||||
* An packet informing that the character could not be created.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
* @see Reason
|
||||
*/
|
||||
public class CharacterCreateFailPacket extends AbstractServerPacket {
|
||||
public static final int OPCODE = 0x10;
|
||||
|
||||
private Reason reason;
|
||||
|
||||
/**
|
||||
* The character creation error reason
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public enum Reason {
|
||||
/**
|
||||
* "Your character creation has failed."
|
||||
*/
|
||||
REASON_CREATION_FAILED(0x00),
|
||||
/**
|
||||
* "You cannot create another character. Please delete the existing
|
||||
* character and try again." Removes all settings that were selected
|
||||
* (race, class, etc)"
|
||||
*/
|
||||
REASON_TOO_MANY_CHARACTERS(0x01),
|
||||
/**
|
||||
* "This name already exists."
|
||||
*/
|
||||
REASON_NAME_ALREADY_EXISTS(0x02),
|
||||
/**
|
||||
* "Your title cannot exceed 16 characters in length. Please try again."
|
||||
*/
|
||||
REASON_16_ENG_CHARS(0x03),
|
||||
/**
|
||||
* "Incorrect name. Please try again."
|
||||
*/
|
||||
REASON_INCORRECT_NAME(0x04),
|
||||
/**
|
||||
* "Characters cannot be created from this server."
|
||||
*/
|
||||
REASON_CREATE_NOT_ALLOWED(0x05),
|
||||
/**
|
||||
* "Unable to create character. You are unable to create a new character
|
||||
* on the selected server. A restriction is in place which restricts
|
||||
* users from creating characters on different servers where no previous
|
||||
* character exists. Please choose another server."
|
||||
*/
|
||||
REASON_CHOOSE_ANOTHER_SVR(0x06);
|
||||
|
||||
public final int id;
|
||||
|
||||
private Reason(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
||||
public CharacterCreateFailPacket(Reason reason) {
|
||||
super(OPCODE);
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelBuffer buffer) {
|
||||
buffer.writeInt(reason.id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.l2jserver.game.net.packet.server;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
import com.l2jserver.game.net.packet.AbstractServerPacket;
|
||||
|
||||
/**
|
||||
* An packet informing that the character was created with success.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class CharacterCreateOkPacket extends AbstractServerPacket {
|
||||
public static final int OPCODE = 0x0f;
|
||||
|
||||
public static final CharacterCreateOkPacket INSTANCE = new CharacterCreateOkPacket();
|
||||
|
||||
public CharacterCreateOkPacket() {
|
||||
super(OPCODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelBuffer buffer) {
|
||||
buffer.writeInt(0x01);
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,17 @@ package com.l2jserver.game.net.packet.server;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
import com.l2jserver.game.net.Lineage2Session;
|
||||
import com.l2jserver.game.net.packet.AbstractServerPacket;
|
||||
import com.l2jserver.model.world.L2Character;
|
||||
import com.l2jserver.util.BufferUtil;
|
||||
|
||||
public class CharSelectionInfoPacket extends AbstractServerPacket {
|
||||
/**
|
||||
* The list of characters sent to the client.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class CharacterSelectionListPacket extends AbstractServerPacket {
|
||||
public static final int OPCODE = 0x09;
|
||||
|
||||
private final String loginName;
|
||||
@@ -14,7 +20,7 @@ public class CharSelectionInfoPacket extends AbstractServerPacket {
|
||||
private int lastCharacterId;
|
||||
private final L2Character[] characters;
|
||||
|
||||
public CharSelectionInfoPacket(String loginName, int sessionId,
|
||||
public CharacterSelectionListPacket(String loginName, int sessionId,
|
||||
int lastCharacterId, L2Character... characters) {
|
||||
super(OPCODE);
|
||||
this.loginName = loginName;
|
||||
@@ -23,6 +29,12 @@ public class CharSelectionInfoPacket extends AbstractServerPacket {
|
||||
this.characters = characters;
|
||||
}
|
||||
|
||||
public static CharacterSelectionListPacket fromL2Session(
|
||||
Lineage2Session session, L2Character... characters) {
|
||||
return new CharacterSelectionListPacket(session.getUsername(),
|
||||
session.getPlayKey1(), -1, characters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelBuffer buffer) {
|
||||
// buffer.writeByte(0x09);
|
||||
@@ -30,44 +42,28 @@ public class CharSelectionInfoPacket extends AbstractServerPacket {
|
||||
|
||||
// Can prevent players from creating new characters (if 0); (if 1,
|
||||
// the client will ask if chars may be created (0x13) Response: (0x0D) )
|
||||
buffer.writeInt(0x07);
|
||||
buffer.writeInt(0x01);
|
||||
buffer.writeByte(0x00);
|
||||
|
||||
long lastAccess = 0L;
|
||||
|
||||
if (lastCharacterId == -1) {
|
||||
for (int i = 0; i < characters.length; i++) {
|
||||
if (characters[i].getLastAccess() == null)
|
||||
continue;
|
||||
if (lastAccess < characters[i].getLastAccess().getTime()) {
|
||||
lastAccess = characters[i].getLastAccess().getTime();
|
||||
lastCharacterId = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (final L2Character character : characters) {
|
||||
// buffer.writeBytes(character.getName().getBytes());
|
||||
// buffer.writeByte(0x00); // NULL termination
|
||||
BufferUtil.writeString(buffer, character.getName());
|
||||
buffer.writeInt(character.getID().getID());
|
||||
BufferUtil.writeString(buffer, loginName);
|
||||
// buffer.writeBytes(loginName.getBytes());
|
||||
// buffer.writeByte(0x00); // NULL termination
|
||||
buffer.writeInt(sessionId);
|
||||
if (character.getClanID() == null) {
|
||||
buffer.writeInt(0x00); // clan id
|
||||
} else {
|
||||
buffer.writeInt(character.getClanID().getID()); // clan id
|
||||
}
|
||||
// if (character.getClanID() == null) {
|
||||
buffer.writeInt(0x00); // clan id
|
||||
// } else {
|
||||
// buffer.writeInt(character.getClanID().getID()); // clan id
|
||||
// }
|
||||
buffer.writeInt(0x00); // ??
|
||||
|
||||
buffer.writeInt(0x00); // sex
|
||||
buffer.writeInt(0x00); // race
|
||||
buffer.writeInt(character.getSex().option); // sex
|
||||
buffer.writeInt(character.getRace().option); // race
|
||||
|
||||
// if (character.getClassId() == character.getBaseClassId())
|
||||
buffer.writeInt(0x00);
|
||||
buffer.writeInt(character.getCharacterClass().id); // base class id
|
||||
// or class id
|
||||
// else
|
||||
// buffer.writeInt(character.getBaseClassId());
|
||||
|
||||
@@ -81,20 +77,20 @@ public class CharSelectionInfoPacket extends AbstractServerPacket {
|
||||
buffer.writeDouble(20); // mp cur
|
||||
|
||||
buffer.writeInt(3000); // sp
|
||||
buffer.writeLong(0); // exp
|
||||
buffer.writeLong(2000); // exp
|
||||
buffer.writeInt(0x01); // level
|
||||
|
||||
buffer.writeInt(0x00); // karma
|
||||
buffer.writeInt(0x00); // pk
|
||||
|
||||
buffer.writeInt(0x00); // pvp
|
||||
buffer.writeInt(0x00);
|
||||
buffer.writeInt(0x00);
|
||||
buffer.writeInt(0x00);
|
||||
buffer.writeInt(0x00);
|
||||
buffer.writeInt(0x00);
|
||||
buffer.writeInt(0x00);
|
||||
buffer.writeInt(0x00);
|
||||
|
||||
buffer.writeInt(0x00); // unk
|
||||
buffer.writeInt(0x00); // unk
|
||||
buffer.writeInt(0x00); // unk
|
||||
buffer.writeInt(0x00); // unk
|
||||
buffer.writeInt(0x00); // unk
|
||||
buffer.writeInt(0x00); // unk
|
||||
buffer.writeInt(0x00); // unk
|
||||
|
||||
for (int id = 0; id < 26; id++) {
|
||||
buffer.writeInt(0x00); // paperdolls
|
||||
@@ -126,22 +122,19 @@ public class CharSelectionInfoPacket extends AbstractServerPacket {
|
||||
// buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_DECO6));
|
||||
// buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_BELT));
|
||||
|
||||
buffer.writeInt(0x01); // hair style
|
||||
buffer.writeInt(0x01); // hair color
|
||||
buffer.writeInt(0x01); // face
|
||||
// hair style
|
||||
buffer.writeInt(character.getAppearance().getHairStyle().option);
|
||||
// hair color
|
||||
buffer.writeInt(character.getAppearance().getHairColor().option);
|
||||
// face
|
||||
buffer.writeInt(character.getAppearance().getFace().option);
|
||||
|
||||
buffer.writeDouble(30); // hp max
|
||||
buffer.writeDouble(30); // mp max
|
||||
|
||||
long deleteTime = 0;
|
||||
int deletedays = 0;
|
||||
if (deleteTime > 0)
|
||||
deletedays = (int) ((deleteTime - System.currentTimeMillis()) / 1000);
|
||||
buffer.writeInt(deletedays); // days left before
|
||||
// delete .. if != 0
|
||||
// then char is inactive
|
||||
buffer.writeInt(0x00); // class
|
||||
buffer.writeInt(0x01); // c3 auto-select char
|
||||
buffer.writeInt(0x0); // seconds left before delete
|
||||
buffer.writeInt(character.getCharacterClass().id); // class
|
||||
buffer.writeInt(0x00); // c3 auto-select char
|
||||
|
||||
buffer.writeByte(0x00); // enchant effect
|
||||
|
||||
@@ -153,8 +146,8 @@ public class CharSelectionInfoPacket extends AbstractServerPacket {
|
||||
// character select you don't see your transformation.
|
||||
|
||||
// Freya by Vistall:
|
||||
buffer.writeInt(0); // npdid - 16024 Tame Tiny Baby Kookaburra
|
||||
// A9E89C
|
||||
// buffer.writeInt(0); // npdid - 16024 Tame Tiny Baby Kookaburra
|
||||
// // A9E89C
|
||||
buffer.writeInt(0); // level
|
||||
buffer.writeInt(0); // ?
|
||||
buffer.writeInt(0); // food? - 1200
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.l2jserver.game.net.packet.server;
|
||||
|
||||
import org.jboss.netty.buffer.ChannelBuffer;
|
||||
|
||||
import com.l2jserver.game.net.packet.AbstractServerPacket;
|
||||
import com.l2jserver.model.template.CharacterTemplate;
|
||||
|
||||
/**
|
||||
* An packet that sends all character templates to the client.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public class CharacterTemplatePacket extends AbstractServerPacket {
|
||||
public static final int OPCODE = 0x0d;
|
||||
|
||||
private CharacterTemplate[] templates;
|
||||
|
||||
public CharacterTemplatePacket(CharacterTemplate... templates) {
|
||||
super(OPCODE);
|
||||
this.templates = templates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelBuffer buffer) {
|
||||
buffer.writeInt(templates.length);
|
||||
for (final CharacterTemplate template : templates) {
|
||||
buffer.writeInt(template.getRace().option);
|
||||
buffer.writeInt(template.getCharacterClass().id);
|
||||
buffer.writeInt(0x46);
|
||||
buffer.writeInt(template.getBaseAttributes().getStrength());
|
||||
buffer.writeInt(0x0a);
|
||||
buffer.writeInt(0x46);
|
||||
buffer.writeInt(template.getBaseAttributes().getDextry());
|
||||
buffer.writeInt(0x0a);
|
||||
buffer.writeInt(0x46);
|
||||
buffer.writeInt(template.getBaseAttributes().getConcentration());
|
||||
buffer.writeInt(0x0a);
|
||||
buffer.writeInt(0x46);
|
||||
buffer.writeInt(template.getBaseAttributes().getIntelligence());
|
||||
buffer.writeInt(0x0a);
|
||||
buffer.writeInt(0x46);
|
||||
buffer.writeInt(template.getBaseAttributes().getWitness());
|
||||
buffer.writeInt(0x0a);
|
||||
buffer.writeInt(0x46);
|
||||
buffer.writeInt(template.getBaseAttributes().getMentality());
|
||||
buffer.writeInt(0x0a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,10 +7,8 @@ import org.jboss.netty.buffer.ChannelBuffer;
|
||||
import com.l2jserver.game.net.packet.AbstractServerPacket;
|
||||
|
||||
/**
|
||||
* <h1>0x2e "KeyPacket"</h1>
|
||||
* <p>
|
||||
* byte[8] key<br>
|
||||
* byte protocolStatus
|
||||
* This packet send the encryptation keys for the client. After this message all
|
||||
* communication is done with the cryptography engine enabled.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user