diff --git a/src/main/java/com/l2jserver/game/net/packet/client/AuthLoginPacket.java b/src/main/java/com/l2jserver/game/net/packet/client/AuthLoginPacket.java new file mode 100644 index 000000000..9a32ef26e --- /dev/null +++ b/src/main/java/com/l2jserver/game/net/packet/client/AuthLoginPacket.java @@ -0,0 +1,76 @@ +package com.l2jserver.game.net.packet.client; + +import java.nio.charset.Charset; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.google.inject.Inject; +import com.l2jserver.game.net.Lineage2Connection; +import com.l2jserver.game.net.packet.AbstractClientPacket; +import com.l2jserver.service.game.world.WorldService; + +public class AuthLoginPacket extends AbstractClientPacket { + public static final int OPCODE = 0x0e; + + @Inject + private WorldService world; + + // packet + private String loginName; + private int playKey1; + private int playKey2; + private int loginKey1; + private int loginKey2; + + @Override + public void read(ChannelBuffer buffer) { + this.loginName = buffer.readBytes(buffer.bytesBefore((byte) 0x00)) + .toString(Charset.defaultCharset()); + this.playKey1 = buffer.readInt(); + this.playKey2 = buffer.readInt(); + this.loginKey1 = buffer.readInt(); + this.loginKey2 = buffer.readInt(); + } + + @Override + public void process(final Lineage2Connection conn) { + // assume it is correct, for now + // send character list + world.getEventDispatcher().dispatch(null); + } + + /** + * @return the loginName + */ + public String getLoginName() { + return loginName; + } + + /** + * @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; + } +} diff --git a/src/main/java/com/l2jserver/game/net/packet/server/CharSelectionInfoPacket.java b/src/main/java/com/l2jserver/game/net/packet/server/CharSelectionInfoPacket.java new file mode 100644 index 000000000..84162b2c5 --- /dev/null +++ b/src/main/java/com/l2jserver/game/net/packet/server/CharSelectionInfoPacket.java @@ -0,0 +1,185 @@ +package com.l2jserver.game.net.packet.server; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.l2jserver.game.net.packet.AbstractServerPacket; + +public class CharSelectionInfoPacket extends AbstractServerPacket { + public static final int OPCODE = 0x09; + + private final String loginName; + private final int sessionId; + private final int activeId; + private final Character[] characters; + + public CharSelectionInfoPacket(int opcode, String loginName, int sessionId, + int activeId, Character... characters) { + super(opcode); + this.loginName = loginName; + this.sessionId = sessionId; + this.activeId = activeId; + this.characters = characters; + } + + @Override + public void write(ChannelBuffer buffer) { + // buffer.writeByte(0x09); + // int size = (characters.length); + // buffer.writeInt(size); + // + // // 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.writeByte(0x00); + // + // long lastAccess = 0L; + // + // // if (activeId == -1) { + // // for (int i = 0; i < size; i++) { + // // if (lastAccess < characters[i].getLastAccess()) { + // // lastAccess = characters[i].getLastAccess(); + // // _activeId = i; + // // } + // // } + // // } + // + // for (int i = 0; i < size; i++) + // { + // Character character = characters[i]; + // + // buffer.writeBytes(character.getName()); + // buffer.writeInt(character.getCharId()); + // writeS(_loginName); + // buffer.writeInt(_sessionId); + // buffer.writeInt(character.getClanId()); + // buffer.writeInt(0x00); // ?? + // + // buffer.writeInt(character.getSex()); + // buffer.writeInt(character.getRace()); + // + // if (character.getClassId() == character.getBaseClassId()) + // buffer.writeInt(character.getClassId()); + // else + // buffer.writeInt(character.getBaseClassId()); + // + // buffer.writeInt(0x01); // active ?? + // + // buffer.writeInt(character.getX()); // x + // buffer.writeInt(character.getY()); // y + // buffer.writeInt(character.getZ()); // z + // + // buffer.writeDouble(character.getCurrentHp()); // hp cur + // buffer.writeDouble(character.getCurrentMp()); // mp cur + // + // buffer.writeInt(character.getSp()); + // writeQ(character.getExp()); + // buffer.writeInt(character.getLevel()); + // + // buffer.writeInt(character.getKarma()); // karma + // buffer.writeInt(character.getPkKills()); + // + // buffer.writeInt(character.getPvPKills()); + // buffer.writeInt(0x00); + // buffer.writeInt(0x00); + // buffer.writeInt(0x00); + // buffer.writeInt(0x00); + // buffer.writeInt(0x00); + // buffer.writeInt(0x00); + // buffer.writeInt(0x00); + // + // + // for(int id = 0; id <27; id++) { + // buffer.writeInt(0x00); + // } + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_HAIR)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_REAR)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_LEAR)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_NECK)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_RFINGER)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_LFINGER)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_HEAD)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_RHAND)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_LHAND)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_GLOVES)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_CHEST)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_LEGS)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_FEET)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_CLOAK)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_RHAND)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_HAIR)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_HAIR2)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_RBRACELET)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_LBRACELET)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_DECO1)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_DECO2)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_DECO3)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_DECO4)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_DECO5)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_DECO6)); + // // + // buffer.writeInt(charInfoPackage.getPaperdollItemId(Inventory.PAPERDOLL_BELT)); + // + // buffer.writeInt(character.getHairStyle()); + // buffer.writeInt(character.getHairColor()); + // buffer.writeInt(character.getFace()); + // + // buffer.writeDouble(character.getMaxHp()); // hp max + // buffer.writeDouble(character.getMaxMp()); // mp max + // + // long deleteTime = character.getDeleteTimer(); + // 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(character.getClassId()); + // if (i == _activeId) + // buffer.writeInt(0x01); + // else + // buffer.writeInt(0x00); //c3 auto-select char + // + // buffer.writeByte(character.getEnchantEffect() > 127 ? 127 : + // character.getEnchantEffect()); + // + // buffer.writeInt(character.getAugmentationId()); + // + // //buffer.writeInt(charInfoPackage.getTransformId()); // Used to + // display Transformations + // buffer.writeInt(0x00); // Currently on retail when you are on + // character select you don't see your transformation. + // + // // Freya by Vistall: + // buffer.writeInt(0); // npdid - 16024 Tame Tiny Baby Kookaburra A9E89C + // buffer.writeInt(0); // level + // buffer.writeInt(0); // ? + // buffer.writeInt(0); // food? - 1200 + // buffer.writeDouble(0); // max Hp + // buffer.writeDouble(0); // cur Hp + } +} diff --git a/src/main/java/com/l2jserver/game/net/packet/server/KeyPacket.java b/src/main/java/com/l2jserver/game/net/packet/server/KeyPacket.java new file mode 100644 index 000000000..0f6ee39ac --- /dev/null +++ b/src/main/java/com/l2jserver/game/net/packet/server/KeyPacket.java @@ -0,0 +1,102 @@ +package com.l2jserver.game.net.packet.server; + +import java.util.Arrays; + +import org.jboss.netty.buffer.ChannelBuffer; + +import com.l2jserver.game.net.packet.AbstractServerPacket; + +/** + *
+ * byte[8] key
+ * byte protocolStatus
+ *
+ * @author Rogiel
+ */
+public class KeyPacket extends AbstractServerPacket {
+ /**
+ * Message OPCODE
+ */
+ public static final int OPCODE = 0x2e;
+
+ /**
+ * 8-byte key cryptography key
+ */
+ private byte[] key;
+ /**
+ * The protocol state. True if valid, false if not.
+ */
+ private boolean status;
+
+ public KeyPacket(byte[] key, boolean status) {
+ super(OPCODE);
+ this.key = Arrays.copyOfRange(key, 0, 8);
+ this.status = status;
+ }
+
+ /**
+ * Creates a new {@link KeyPacket} with key and valid protocol.
+ *
+ * @param key
+ * the key
+ * @return the new instance
+ */
+ public static KeyPacket valid(byte[] key) {
+ return new KeyPacket(key, true);
+ }
+
+ /**
+ * Creates a new {@link KeyPacket} with key and invalid protocol.
+ *
+ * @param key
+ * the key
+ * @return the new instance
+ */
+ public static KeyPacket invalid(byte[] key) {
+ return new KeyPacket(key, false);
+ }
+
+ @Override
+ public void write(ChannelBuffer buffer) {
+ buffer.writeByte((status ? 0x01 : 0x00));
+ for (int i = 0; i < 8; i++) {
+ buffer.writeByte(key[i]);
+ }
+ // buffer.writeBytes(key);
+ buffer.writeInt(0x01);
+ buffer.writeInt(0x01); // server id
+ buffer.writeByte(0x01);
+ buffer.writeInt(0x00); // obfuscation key
+ }
+
+ /**
+ * @return the key
+ */
+ public byte[] getKey() {
+ return key;
+ }
+
+ /**
+ * @param key
+ * the key to set
+ */
+ public void setKey(byte[] key) {
+ this.key = key;
+ }
+
+ /**
+ * @return the status
+ */
+ public boolean isStatus() {
+ return status;
+ }
+
+ /**
+ * @param status
+ * the status to set
+ */
+ public void setStatus(boolean status) {
+ this.status = status;
+ }
+}
diff --git a/src/main/java/com/l2jserver/model/world/AbstractActor.java b/src/main/java/com/l2jserver/model/world/AbstractActor.java
new file mode 100644
index 000000000..22478bd17
--- /dev/null
+++ b/src/main/java/com/l2jserver/model/world/AbstractActor.java
@@ -0,0 +1,144 @@
+package com.l2jserver.model.world;
+
+import java.util.List;
+
+import com.l2jserver.model.template.SkillTemplate;
+import com.l2jserver.model.template.capability.Attackable;
+import com.l2jserver.model.world.actor.ActorEvent;
+import com.l2jserver.model.world.actor.ActorListener;
+import com.l2jserver.model.world.capability.Actor;
+import com.l2jserver.model.world.capability.Attacker;
+import com.l2jserver.model.world.capability.Castable;
+import com.l2jserver.model.world.capability.Equipable;
+import com.l2jserver.model.world.capability.Equiper;
+import com.l2jserver.util.Coordinate;
+import com.l2jserver.util.factory.CollectionFactory;
+
+public abstract class AbstractActor extends AbstractObject implements Actor {
+ private final List
+ * Thus when getting a key with interests other then read-only a copy must
+ * be performed.
+ *
+ * @return A key from this keygen pool.
+ */
+ public static byte[] getRandomKey() {
+ return CRYPT_KEYS[random.nextInt(CRYPT_KEYS_SIZE)];
+ }
+}
diff --git a/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java b/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java
new file mode 100644
index 000000000..e298fa2f8
--- /dev/null
+++ b/src/test/java/com/l2jserver/service/world/WorldEventDispatcherImplTest.java
@@ -0,0 +1,121 @@
+package com.l2jserver.service.world;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Scopes;
+import com.l2jserver.model.world.L2Character;
+import com.l2jserver.model.world.Item;
+import com.l2jserver.model.world.item.ItemDropEvent;
+import com.l2jserver.model.world.item.ItemEvent;
+import com.l2jserver.model.world.item.ItemListener;
+import com.l2jserver.model.world.player.PlayerEvent;
+import com.l2jserver.model.world.player.PlayerListener;
+import com.l2jserver.model.world.player.PlayerSpawnEvent;
+import com.l2jserver.service.BasicServiceModule;
+import com.l2jserver.service.ServiceStartException;
+import com.l2jserver.service.game.world.WorldEventDispatcher;
+import com.l2jserver.service.game.world.WorldEventDispatcherImpl;
+import com.l2jserver.service.game.world.WorldService;
+import com.l2jserver.service.game.world.WorldServiceImpl;
+
+public class WorldEventDispatcherImplTest {
+ private WorldService world;
+ private WorldEventDispatcher dispatcher;
+
+ @Before
+ public void tearUp() throws ServiceStartException {
+ Injector injector = Guice.createInjector(new BasicServiceModule(),
+ new AbstractModule() {
+ @Override
+ protected void configure() {
+ bind(WorldService.class).to(WorldServiceImpl.class).in(
+ Scopes.SINGLETON);
+ bind(WorldEventDispatcher.class).to(
+ WorldEventDispatcherImpl.class).in(
+ Scopes.SINGLETON);
+ }
+ });
+
+ world = injector.getInstance(WorldService.class);
+ dispatcher = injector.getInstance(WorldEventDispatcher.class);
+ Assert.assertNotNull(world);
+ Assert.assertNotNull(dispatcher);
+ world.start();
+ }
+
+ @Test
+ public void testListeners1() {
+ final L2Character character1 = new L2Character();
+ final L2Character character2 = new L2Character();
+ final Item item1 = new Item();
+ world.add(character1);
+ world.add(character2);
+ world.add(item1);
+
+ final AtomicBoolean bool = new AtomicBoolean();
+ Assert.assertFalse(bool.get());
+ character1.addListener(new PlayerListener() {
+ @Override
+ protected void dispatch(PlayerEvent e) {
+ bool.set(true);
+ e.getPlayer().removeListener(this);
+ }
+ });
+ character1.addListener(new PlayerListener() {
+ @Override
+ protected void dispatch(PlayerEvent e) {
+ // bool.set(true);
+ }
+ });
+ dispatcher.dispatch(new PlayerSpawnEvent(character1, null));
+ Assert.assertTrue(bool.get());
+
+ bool.set(false);
+
+ dispatcher.dispatch(new PlayerSpawnEvent(character1, null));
+ Assert.assertFalse(bool.get());
+ }
+
+ @Test
+ public void testListeners2() {
+ final L2Character character1 = new L2Character();
+ final L2Character character2 = new L2Character();
+ final Item item1 = new Item();
+ final Item item2 = new Item();
+ world.add(character1);
+ world.add(character2);
+ world.add(item1);
+ world.add(item2);
+
+ final AtomicBoolean bool1 = new AtomicBoolean();
+ final AtomicBoolean bool2 = new AtomicBoolean();
+
+ Assert.assertFalse(bool1.get());
+ Assert.assertFalse(bool2.get());
+
+ character1.addListener(new PlayerListener() {
+ @Override
+ public void dispatch(PlayerEvent e) {
+ bool1.set(true);
+ }
+ });
+ item1.addListener(new ItemListener() {
+ @Override
+ public void dispatch(ItemEvent e) {
+ bool2.set(true);
+ }
+ });
+
+ dispatcher.dispatch(new ItemDropEvent(character1, item1));
+ Assert.assertTrue(bool1.get());
+ Assert.assertTrue(bool2.get());
+ }
+}