mirror of
https://github.com/Rogiel/l2jserver2
synced 2025-12-10 09:22:49 +00:00
@@ -16,6 +16,8 @@
|
||||
*/
|
||||
package com.l2jserver.game.net;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jboss.netty.channel.Channel;
|
||||
import org.jboss.netty.channel.ChannelFuture;
|
||||
|
||||
@@ -27,10 +29,17 @@ import com.l2jserver.game.net.codec.Lineage2PacketWriter;
|
||||
import com.l2jserver.game.net.packet.ServerPacket;
|
||||
import com.l2jserver.model.id.object.CharacterID;
|
||||
import com.l2jserver.model.world.L2Character;
|
||||
import com.l2jserver.service.game.world.WorldService;
|
||||
import com.l2jserver.service.game.world.filter.impl.CharacterBroadcastFilter;
|
||||
import com.l2jserver.service.network.NetworkService;
|
||||
import com.l2jserver.util.factory.CollectionFactory;
|
||||
|
||||
/**
|
||||
* This object connects the model (structure objects normally stored in the
|
||||
* database) to the controller (protocol stuff).
|
||||
* <p>
|
||||
* This class also provides handy methods for {@link #write(ServerPacket)
|
||||
* writing} and {@link #broadcast(ServerPacket) broadcasting} packets.
|
||||
*
|
||||
* @author <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
@@ -67,13 +76,30 @@ public class Lineage2Connection {
|
||||
*/
|
||||
private ProtocolVersion version;
|
||||
|
||||
// services
|
||||
/**
|
||||
* The {@link NetworkService} instance. This service is used to retrieve the
|
||||
* {@link Lineage2Connection} based on an {@link CharacterID}.
|
||||
*/
|
||||
private final NetworkService networkService;
|
||||
/**
|
||||
* The {@link WorldService} instance. This service is used to dynamically
|
||||
* generate knownlists.
|
||||
*/
|
||||
private final WorldService worldService;
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param worldService
|
||||
* the world service
|
||||
* @param channel
|
||||
* the channel
|
||||
*/
|
||||
public Lineage2Connection(Channel channel) {
|
||||
public Lineage2Connection(WorldService worldService,
|
||||
NetworkService networkService, Channel channel) {
|
||||
this.worldService = worldService;
|
||||
this.networkService = networkService;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@@ -176,46 +202,115 @@ public class Lineage2Connection {
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the client is still open.
|
||||
* <p>
|
||||
* Please note that the channel can be open but disconnected!
|
||||
*
|
||||
* @return true if the client is still open
|
||||
* @see Channel#isOpen()
|
||||
*/
|
||||
public boolean isOpen() {
|
||||
return channel.isOpen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the client is still connected
|
||||
* <p>
|
||||
* Please note that the channel can be open but disconnected!
|
||||
*
|
||||
* @return true if the client is still connected
|
||||
* @see Channel#isConnected()
|
||||
*/
|
||||
public boolean isConnected() {
|
||||
return channel.isConnected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes an packet to this client
|
||||
* <p>
|
||||
* Please note that this method will <b>not</b> block for the packets to be
|
||||
* sent. It is possible to check if the packet was sent successfully using
|
||||
* the {@link ChannelFuture}.
|
||||
*
|
||||
* @param packet
|
||||
* the packet
|
||||
* @return the {@link ChannelFuture} that will be notified once the packet
|
||||
* has been written.
|
||||
*/
|
||||
public ChannelFuture write(ServerPacket packet) {
|
||||
return channel.write(packet);
|
||||
}
|
||||
|
||||
public ChannelFuture[] broadcast(ServerPacket packet) {
|
||||
// TODO implement broadcasting
|
||||
return new ChannelFuture[] { write(packet) };
|
||||
/**
|
||||
* Broadcast a packet to all characters in this character knownlist.
|
||||
* <p>
|
||||
* Note that in the broadcasting process, this client will be included.
|
||||
* <p>
|
||||
* Please note that this method will <b>not</b> block for all packets to be
|
||||
* sent. It is possible to check if all packets were sent successfully using
|
||||
* the {@link ChannelFuture} instances.
|
||||
*
|
||||
* @param packet
|
||||
* the packet
|
||||
* @return an {@link Set} containing all {@link ChannelFuture} instances.
|
||||
*/
|
||||
public Set<ChannelFuture> broadcast(ServerPacket packet) {
|
||||
final Set<ChannelFuture> futures = CollectionFactory.newSet(null);
|
||||
for (final L2Character character : worldService
|
||||
.iterable(new CharacterBroadcastFilter(characterID.getObject()))) {
|
||||
final Lineage2Connection conn = networkService.discover(character
|
||||
.getID());
|
||||
futures.add(conn.write(packet));
|
||||
}
|
||||
return futures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects this client, without closing the channel.
|
||||
*
|
||||
* @return the {@link ChannelFuture}
|
||||
*/
|
||||
public ChannelFuture disconnect() {
|
||||
return channel.disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the channel of this client.
|
||||
*
|
||||
* @return the {@link ChannelFuture}
|
||||
*/
|
||||
public ChannelFuture close() {
|
||||
return channel.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the client {@link Lineage2Decrypter}
|
||||
*/
|
||||
public Lineage2Decrypter getDecrypter() {
|
||||
return (Lineage2Decrypter) channel.getPipeline().get(
|
||||
Lineage2Decrypter.HANDLER_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the client {@link Lineage2Encrypter}
|
||||
*/
|
||||
public Lineage2Encrypter getEncrypter() {
|
||||
return (Lineage2Encrypter) channel.getPipeline().get(
|
||||
Lineage2Encrypter.HANDLER_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the client {@link Lineage2PacketReader}
|
||||
*/
|
||||
public Lineage2PacketReader getPacketReader() {
|
||||
return (Lineage2PacketReader) channel.getPipeline().get(
|
||||
Lineage2PacketReader.HANDLER_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the client {@link Lineage2PacketWriter}
|
||||
*/
|
||||
public Lineage2PacketWriter getPacketWriter() {
|
||||
return (Lineage2PacketWriter) channel.getPipeline().get(
|
||||
Lineage2PacketWriter.HANDLER_NAME);
|
||||
|
||||
@@ -32,7 +32,9 @@ import com.l2jserver.game.net.codec.Lineage2FrameEncoder;
|
||||
import com.l2jserver.game.net.codec.Lineage2PacketReader;
|
||||
import com.l2jserver.game.net.codec.Lineage2PacketWriter;
|
||||
import com.l2jserver.game.net.handler.Lineage2PacketHandler;
|
||||
import com.l2jserver.service.game.world.WorldService;
|
||||
import com.l2jserver.service.network.NettyNetworkService;
|
||||
import com.l2jserver.service.network.NetworkService;
|
||||
|
||||
/**
|
||||
* This class creates a new instance of {@link ChannelPipeline} and attaches all
|
||||
@@ -49,12 +51,17 @@ public class Lineage2PipelineFactory implements ChannelPipelineFactory {
|
||||
* The {@link NettyNetworkService}
|
||||
*/
|
||||
private final NettyNetworkService nettyNetworkService;
|
||||
/**
|
||||
* The {@link WorldService} instance
|
||||
*/
|
||||
private final WorldService worldService;
|
||||
|
||||
@Inject
|
||||
public Lineage2PipelineFactory(Injector injector,
|
||||
NettyNetworkService nettyNetworkService) {
|
||||
NetworkService networkService, WorldService worldService) {
|
||||
this.injector = injector;
|
||||
this.nettyNetworkService = nettyNetworkService;
|
||||
this.nettyNetworkService = (NettyNetworkService) networkService;
|
||||
this.worldService = worldService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,9 +76,6 @@ public class Lineage2PipelineFactory implements ChannelPipelineFactory {
|
||||
pipeline.addLast(Lineage2Decrypter.HANDLER_NAME,
|
||||
new Lineage2Decrypter());
|
||||
|
||||
pipeline.addLast("logger-hex", new LoggingHandler(
|
||||
InternalLogLevel.DEBUG, true));
|
||||
|
||||
pipeline.addLast(Lineage2PacketWriter.HANDLER_NAME,
|
||||
new Lineage2PacketWriter());
|
||||
pipeline.addLast(Lineage2PacketReader.HANDLER_NAME,
|
||||
@@ -80,7 +84,8 @@ public class Lineage2PipelineFactory implements ChannelPipelineFactory {
|
||||
pipeline.addLast("logger", new LoggingHandler(InternalLogLevel.DEBUG,
|
||||
true));
|
||||
|
||||
pipeline.addLast("packet.handler", new Lineage2PacketHandler(nettyNetworkService));
|
||||
pipeline.addLast("packet.handler", new Lineage2PacketHandler(
|
||||
nettyNetworkService, worldService));
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
@@ -46,9 +46,6 @@ 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)
|
||||
|
||||
@@ -64,8 +64,6 @@ public class Lineage2PacketWriter extends OneToOneEncoder {
|
||||
buffer.writeShort(0);
|
||||
buffer.writeByte(packet.getOpcode()); // packet opcode
|
||||
packet.write(connection, buffer);
|
||||
|
||||
log.debug("Writing message {}", ChannelBuffers.hexDump(buffer));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jboss.netty.channel.SimpleChannelHandler;
|
||||
|
||||
import com.l2jserver.game.net.Lineage2Connection;
|
||||
import com.l2jserver.game.net.packet.ClientPacket;
|
||||
import com.l2jserver.service.game.world.WorldService;
|
||||
import com.l2jserver.service.network.NettyNetworkService;
|
||||
|
||||
/**
|
||||
@@ -37,19 +38,26 @@ public class Lineage2PacketHandler extends SimpleChannelHandler {
|
||||
* The {@link NettyNetworkService}
|
||||
*/
|
||||
private final NettyNetworkService nettyNetworkService;
|
||||
/**
|
||||
* The {@link WorldService} instance
|
||||
*/
|
||||
private final WorldService worldService;
|
||||
/**
|
||||
* The Lineage 2 connection
|
||||
*/
|
||||
private Lineage2Connection connection;
|
||||
|
||||
public Lineage2PacketHandler(NettyNetworkService nettyNetworkService) {
|
||||
public Lineage2PacketHandler(NettyNetworkService nettyNetworkService,
|
||||
WorldService worldService) {
|
||||
this.nettyNetworkService = nettyNetworkService;
|
||||
this.worldService = worldService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
|
||||
throws Exception {
|
||||
connection = new Lineage2Connection(e.getChannel());
|
||||
connection = new Lineage2Connection(worldService, nettyNetworkService,
|
||||
e.getChannel());
|
||||
connection.getPacketWriter().setConnection(connection);
|
||||
|
||||
nettyNetworkService.register(connection);
|
||||
|
||||
@@ -198,24 +198,7 @@ public class CharacterCreatePacket extends AbstractClientPacket {
|
||||
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("intelligence, expected {}, received {}",
|
||||
// template.getIntelligence(), intelligence);
|
||||
// log.debug("strength, expected {}, received {}",
|
||||
// template.getStrength(), strength);
|
||||
// log.debug("concentration, expected {}, received {}",
|
||||
// template.getConcentration(), concentration);
|
||||
// log.debug("dextry, expected {}, received {}",
|
||||
// template.getDextry(),
|
||||
// dextry);
|
||||
// log.debug("witness, expected {}, received {}",
|
||||
// template.getWitness(), witness);
|
||||
if ((race != template.getRace())) {
|
||||
log.debug("race, expected {}, received {}", template.getRace(),
|
||||
race);
|
||||
|
||||
|
||||
@@ -17,21 +17,14 @@
|
||||
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.client.CharacterChatMessagePacket.MessageDestination;
|
||||
import com.l2jserver.game.net.packet.server.ActorChatMessagePacket;
|
||||
import com.l2jserver.game.net.packet.server.GameGuardQueryPacket;
|
||||
import com.l2jserver.game.net.packet.server.InventoryPacket;
|
||||
import com.l2jserver.game.net.packet.server.UserInformationPacket;
|
||||
import com.l2jserver.model.id.object.CharacterID;
|
||||
import com.l2jserver.model.world.character.event.CharacterLoggedInEvent;
|
||||
import com.l2jserver.service.game.chat.ChatService;
|
||||
import com.l2jserver.service.game.chat.channel.ChatChannel;
|
||||
import com.l2jserver.service.game.chat.channel.ChatChannelListener;
|
||||
import com.l2jserver.service.game.world.event.WorldEventDispatcher;
|
||||
import com.l2jserver.service.game.CharacterService;
|
||||
|
||||
/**
|
||||
* The client is requesting a logout. Currently, when this packet is received
|
||||
@@ -45,26 +38,16 @@ public class EnterWorld extends AbstractClientPacket {
|
||||
*/
|
||||
public static final int OPCODE = 0x11;
|
||||
|
||||
/**
|
||||
* The chat service
|
||||
*/
|
||||
private final ChatService chatService;
|
||||
/**
|
||||
* The World Event Dispatcher
|
||||
*/
|
||||
private final WorldEventDispatcher eventDispatcher;
|
||||
private final Logger log = LoggerFactory.getLogger(EnterWorld.class);
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*
|
||||
* @param chatService
|
||||
* the chat service
|
||||
* The {@link CharacterService}
|
||||
*/
|
||||
private final CharacterService characterService;
|
||||
|
||||
@Inject
|
||||
public EnterWorld(ChatService chatService,
|
||||
WorldEventDispatcher eventDispatcher) {
|
||||
this.chatService = chatService;
|
||||
this.eventDispatcher = eventDispatcher;
|
||||
public EnterWorld(CharacterService characterService) {
|
||||
this.characterService = characterService;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,23 +67,14 @@ public class EnterWorld extends AbstractClientPacket {
|
||||
|
||||
@Override
|
||||
public void process(final Lineage2Connection conn) {
|
||||
// register global chat listener
|
||||
chatService.getGlobalChannel().addChatChannelListener(
|
||||
new ChatChannelListener() {
|
||||
@Override
|
||||
public void onMessage(ChatChannel channel,
|
||||
CharacterID source, String message) {
|
||||
conn.write(new ActorChatMessagePacket(source
|
||||
.getObject(), MessageDestination.ALL, message));
|
||||
}
|
||||
});
|
||||
|
||||
conn.write(new UserInformationPacket(conn.getCharacter()));
|
||||
// TODO game guard enforcing
|
||||
conn.write(new GameGuardQueryPacket());
|
||||
conn.write(new InventoryPacket(conn.getCharacter().getInventory()));
|
||||
|
||||
eventDispatcher
|
||||
.dispatch(new CharacterLoggedInEvent(conn.getCharacter()));
|
||||
final CharacterID id = conn.getCharacterID();
|
||||
if (id == null) {
|
||||
log.warn(
|
||||
"Client {} is trying to enter world without select a character",
|
||||
conn);
|
||||
conn.close();
|
||||
return;
|
||||
}
|
||||
characterService.enterWorld(id.getObject());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,15 @@
|
||||
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.CharacterStopMovePacket;
|
||||
import com.l2jserver.game.net.packet.server.CharacterTeleportPacket;
|
||||
import com.l2jserver.model.world.L2Character;
|
||||
import com.l2jserver.service.game.SpawnService;
|
||||
import com.l2jserver.util.dimensional.Coordinate;
|
||||
|
||||
/**
|
||||
@@ -36,35 +39,53 @@ public class RequestMoveBackwardToLocationPacket extends AbstractClientPacket {
|
||||
*/
|
||||
public static final int OPCODE = 0x0f;
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||
|
||||
/**
|
||||
* The {@link SpawnService}
|
||||
*/
|
||||
private final SpawnService spawnService;
|
||||
|
||||
// packet
|
||||
private Coordinate target;
|
||||
private Coordinate origin;
|
||||
private int moveMovement;
|
||||
|
||||
@Inject
|
||||
public RequestMoveBackwardToLocationPacket(SpawnService spawnService) {
|
||||
this.spawnService = spawnService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Lineage2Connection conn, ChannelBuffer buffer) {
|
||||
this.target = Coordinate.fromXYZ(buffer.readInt(), buffer.readInt(),
|
||||
buffer.readInt());
|
||||
this.origin = Coordinate.fromXYZ(buffer.readInt(), buffer.readInt(),
|
||||
buffer.readInt());
|
||||
// 0 keyboard, 1 mouse
|
||||
this.moveMovement = buffer.readInt(); // seems that L2Walker does not
|
||||
// send this
|
||||
// seems that L2Walker does not send this
|
||||
if (buffer.readableBytes() >= 4) {
|
||||
// 0 keyboard, 1 mouse
|
||||
this.moveMovement = buffer.readInt();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(final Lineage2Connection conn) {
|
||||
if (target.equals(origin)) {
|
||||
log.debug("Target is same as origin. Stopping character.");
|
||||
conn.write(new CharacterStopMovePacket(conn.getCharacter()));
|
||||
return;
|
||||
}
|
||||
if (target.getDistance(origin) >= 98010000) {
|
||||
log.warn(
|
||||
"Character {} is trying to move a really big distance: {}",
|
||||
conn.getCharacter(), target.getDistance(origin));
|
||||
// TODO send action failed message!
|
||||
return;
|
||||
}
|
||||
final L2Character character = conn.getCharacter();
|
||||
character.setPosition(target);
|
||||
|
||||
conn.broadcast(new CharacterTeleportPacket(character));
|
||||
log.debug("Character {} is moving from {} to {}", new Object[] {
|
||||
character, origin, target });
|
||||
spawnService.teleport(character, target);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user