1
0
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:
rogiel
2011-05-07 01:06:17 -03:00
parent 81d2babede
commit 51aea46020
100 changed files with 2505 additions and 406 deletions

View File

@@ -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;
}

View 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;
}
}

View File

@@ -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);

View File

@@ -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++) {

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -1,5 +1,4 @@
package com.l2jserver.game.net.packet;
public abstract class AbstractClientPacket implements ClientPacket {
}

View File

@@ -1,5 +1,4 @@
package com.l2jserver.game.net.packet;
public interface Packet {
}

View File

@@ -4,5 +4,6 @@ import org.jboss.netty.buffer.ChannelBuffer;
public interface ServerPacket extends Packet {
void write(ChannelBuffer buffer);
int getOpcode();
}

View File

@@ -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])));
}
/**

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);

View File

@@ -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])));
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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);
}
}
}

View File

@@ -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>
*/