diff --git a/src/main/java/com/l2jserver/game/net/Lineage2Connection.java b/src/main/java/com/l2jserver/game/net/Lineage2Connection.java index 0acc752b9..a81f90526 100644 --- a/src/main/java/com/l2jserver/game/net/Lineage2Connection.java +++ b/src/main/java/com/l2jserver/game/net/Lineage2Connection.java @@ -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). + *

+ * This class also provides handy methods for {@link #write(ServerPacket) + * writing} and {@link #broadcast(ServerPacket) broadcasting} packets. * * @author Rogiel */ @@ -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. + *

+ * 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 + *

+ * 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 + *

+ * Please note that this method will not 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. + *

+ * Note that in the broadcasting process, this client will be included. + *

+ * Please note that this method will not 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 broadcast(ServerPacket packet) { + final Set 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); diff --git a/src/main/java/com/l2jserver/game/net/Lineage2PipelineFactory.java b/src/main/java/com/l2jserver/game/net/Lineage2PipelineFactory.java index ef9a7184f..7915a245d 100644 --- a/src/main/java/com/l2jserver/game/net/Lineage2PipelineFactory.java +++ b/src/main/java/com/l2jserver/game/net/Lineage2PipelineFactory.java @@ -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; } diff --git a/src/main/java/com/l2jserver/game/net/codec/Lineage2FrameDecoder.java b/src/main/java/com/l2jserver/game/net/codec/Lineage2FrameDecoder.java index 6420b74df..b0c144ccb 100644 --- a/src/main/java/com/l2jserver/game/net/codec/Lineage2FrameDecoder.java +++ b/src/main/java/com/l2jserver/game/net/codec/Lineage2FrameDecoder.java @@ -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) diff --git a/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketWriter.java b/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketWriter.java index ac1bf2546..a53e6efa0 100644 --- a/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketWriter.java +++ b/src/main/java/com/l2jserver/game/net/codec/Lineage2PacketWriter.java @@ -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; } diff --git a/src/main/java/com/l2jserver/game/net/handler/Lineage2PacketHandler.java b/src/main/java/com/l2jserver/game/net/handler/Lineage2PacketHandler.java index bddeddedb..31ca6d3e9 100644 --- a/src/main/java/com/l2jserver/game/net/handler/Lineage2PacketHandler.java +++ b/src/main/java/com/l2jserver/game/net/handler/Lineage2PacketHandler.java @@ -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); diff --git a/src/main/java/com/l2jserver/game/net/packet/client/CharacterCreatePacket.java b/src/main/java/com/l2jserver/game/net/packet/client/CharacterCreatePacket.java index a92cbf701..9e58c92ee 100644 --- a/src/main/java/com/l2jserver/game/net/packet/client/CharacterCreatePacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/CharacterCreatePacket.java @@ -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); diff --git a/src/main/java/com/l2jserver/game/net/packet/client/EnterWorld.java b/src/main/java/com/l2jserver/game/net/packet/client/EnterWorld.java index a32db3875..fc7e65637 100644 --- a/src/main/java/com/l2jserver/game/net/packet/client/EnterWorld.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/EnterWorld.java @@ -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()); } } diff --git a/src/main/java/com/l2jserver/game/net/packet/client/RequestMoveBackwardToLocationPacket.java b/src/main/java/com/l2jserver/game/net/packet/client/RequestMoveBackwardToLocationPacket.java index d89e8bf8e..113694377 100644 --- a/src/main/java/com/l2jserver/game/net/packet/client/RequestMoveBackwardToLocationPacket.java +++ b/src/main/java/com/l2jserver/game/net/packet/client/RequestMoveBackwardToLocationPacket.java @@ -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); } } diff --git a/src/main/java/com/l2jserver/model/world/Pet.java b/src/main/java/com/l2jserver/model/world/Pet.java index 786ccd9a3..661ff9413 100644 --- a/src/main/java/com/l2jserver/model/world/Pet.java +++ b/src/main/java/com/l2jserver/model/world/Pet.java @@ -36,12 +36,6 @@ public class Pet extends Player implements Summonable { */ private ItemID itemID; - @Override - public void teleport(Coordinate coordinate) { - // TODO Auto-generated method stub - - } - @Override public void summon(Coordinate coordinate) { // TODO Auto-generated method stub diff --git a/src/main/java/com/l2jserver/model/world/Player.java b/src/main/java/com/l2jserver/model/world/Player.java index 739d8ea58..1a22eca51 100644 --- a/src/main/java/com/l2jserver/model/world/Player.java +++ b/src/main/java/com/l2jserver/model/world/Player.java @@ -18,8 +18,6 @@ package com.l2jserver.model.world; import com.l2jserver.model.world.capability.Actor; import com.l2jserver.model.world.capability.Playable; -import com.l2jserver.model.world.capability.Teleportable; -import com.l2jserver.util.dimensional.Coordinate; /** * {@link Player} is any object that can be controlled by the player. The most @@ -27,13 +25,6 @@ import com.l2jserver.util.dimensional.Coordinate; * * @author Rogiel */ -public abstract class Player extends AbstractActor implements Playable, Actor, - Teleportable { - @Override - public void teleport(Coordinate coordinate) { - // final PlayerTeleportEvent event = new PlayerTeleportEvent(this, - // coordinate); - // this.setPosition(coordinate); - // event.dispatch(); - } +public abstract class Player extends AbstractActor implements Playable, Actor { + } diff --git a/src/main/java/com/l2jserver/model/world/actor/event/ActorListener.java b/src/main/java/com/l2jserver/model/world/actor/event/ActorListener.java index 7951c4140..fb68b3e61 100644 --- a/src/main/java/com/l2jserver/model/world/actor/event/ActorListener.java +++ b/src/main/java/com/l2jserver/model/world/actor/event/ActorListener.java @@ -16,13 +16,24 @@ */ package com.l2jserver.model.world.actor.event; -import com.l2jserver.model.world.capability.Actor; +import com.l2jserver.service.game.world.event.WorldEvent; import com.l2jserver.service.game.world.event.WorldListener; /** - * Base listener for {@link Actor} instances + * This listener will filter to only dispatch {@link ActorEvent} events. * * @author Rogiel */ -public interface ActorListener extends WorldListener { +public abstract class ActorListener implements WorldListener { + @Override + public boolean dispatch(WorldEvent e) { + if (!(e instanceof ActorEvent)) + return false; + return dispatch((ActorEvent) e); + } + + /** + * @see WorldListener#dispatch(WorldEvent) + */ + protected abstract boolean dispatch(ActorEvent e); } diff --git a/src/main/java/com/l2jserver/model/world/capability/Listenable.java b/src/main/java/com/l2jserver/model/world/capability/Listenable.java index f1e31e942..7c7a1e626 100644 --- a/src/main/java/com/l2jserver/model/world/capability/Listenable.java +++ b/src/main/java/com/l2jserver/model/world/capability/Listenable.java @@ -31,6 +31,6 @@ import com.l2jserver.service.game.world.event.WorldListener; * @param * the event type */ -public interface Listenable, E extends WorldEvent> +public interface Listenable extends ObjectCapability { } diff --git a/src/main/java/com/l2jserver/model/world/character/event/CharacterLoggedInEvent.java b/src/main/java/com/l2jserver/model/world/character/event/CharacterEnterWorldEvent.java similarity index 91% rename from src/main/java/com/l2jserver/model/world/character/event/CharacterLoggedInEvent.java rename to src/main/java/com/l2jserver/model/world/character/event/CharacterEnterWorldEvent.java index 7b1fe97a9..f615c51f4 100644 --- a/src/main/java/com/l2jserver/model/world/character/event/CharacterLoggedInEvent.java +++ b/src/main/java/com/l2jserver/model/world/character/event/CharacterEnterWorldEvent.java @@ -29,7 +29,7 @@ import com.l2jserver.model.world.capability.Listenable; * * @author Rogiel */ -public class CharacterLoggedInEvent implements CharacterEvent { +public class CharacterEnterWorldEvent implements CharacterEvent { /** * The character that is logging in */ @@ -47,7 +47,7 @@ public class CharacterLoggedInEvent implements CharacterEvent { * @param date * the login date */ - public CharacterLoggedInEvent(L2Character character, Date date) { + public CharacterEnterWorldEvent(L2Character character, Date date) { this.character = character; this.date = date; } @@ -58,7 +58,7 @@ public class CharacterLoggedInEvent implements CharacterEvent { * @param character * the character */ - public CharacterLoggedInEvent(L2Character character) { + public CharacterEnterWorldEvent(L2Character character) { this(character, new Date()); } diff --git a/src/main/java/com/l2jserver/model/world/character/event/CharacterLeaveWorldEvent.java b/src/main/java/com/l2jserver/model/world/character/event/CharacterLeaveWorldEvent.java new file mode 100644 index 000000000..da153e1d9 --- /dev/null +++ b/src/main/java/com/l2jserver/model/world/character/event/CharacterLeaveWorldEvent.java @@ -0,0 +1,96 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.model.world.character.event; + +import java.util.Date; + +import com.l2jserver.model.world.L2Character; +import com.l2jserver.model.world.Player; +import com.l2jserver.model.world.WorldObject; +import com.l2jserver.model.world.capability.Actor; +import com.l2jserver.model.world.capability.Listenable; + +/** + * Event triggered once a character logs-out. + * + * @author Rogiel + */ +public class CharacterLeaveWorldEvent implements CharacterEvent { + /** + * The character that is logging in + */ + private final L2Character character; + /** + * The time that this character has logged off + */ + private final Date date; + + /** + * Creates a new instance + * + * @param character + * the character + * @param date + * the logout date + */ + public CharacterLeaveWorldEvent(L2Character character, Date date) { + this.character = character; + this.date = date; + } + + /** + * Creates a new instance. Login date is set to now. + * + * @param character + * the character + */ + public CharacterLeaveWorldEvent(L2Character character) { + this(character, new Date()); + } + + /** + * @return the logout date + */ + public Date getDate() { + return date; + } + + @Override + public Player getPlayer() { + return character; + } + + @Override + public Actor getActor() { + return character; + } + + @Override + public WorldObject getObject() { + return character; + } + + @Override + public L2Character getCharacter() { + return character; + } + + @Override + public Listenable[] getDispatchableObjects() { + return new Listenable[] { character }; + } +} diff --git a/src/main/java/com/l2jserver/model/world/character/event/CharacterListener.java b/src/main/java/com/l2jserver/model/world/character/event/CharacterListener.java index d7f8e6646..5d2825d4d 100644 --- a/src/main/java/com/l2jserver/model/world/character/event/CharacterListener.java +++ b/src/main/java/com/l2jserver/model/world/character/event/CharacterListener.java @@ -16,18 +16,17 @@ */ package com.l2jserver.model.world.character.event; -import com.l2jserver.model.world.player.event.PlayerEvent; -import com.l2jserver.model.world.player.event.PlayerListener; import com.l2jserver.service.game.world.event.WorldEvent; import com.l2jserver.service.game.world.event.WorldListener; /** - * @author Rogiel + * This listener will filter to only dispatch {@link CharacterEvent} events. * + * @author Rogiel */ -public abstract class CharacterListener extends PlayerListener { +public abstract class CharacterListener implements WorldListener { @Override - protected boolean dispatch(PlayerEvent e) { + public boolean dispatch(WorldEvent e) { if (!(e instanceof CharacterEvent)) return false; return dispatch((CharacterEvent) e); diff --git a/src/main/java/com/l2jserver/model/world/clan/ClanListener.java b/src/main/java/com/l2jserver/model/world/clan/ClanListener.java index 97bb02113..8b9acdfb8 100644 --- a/src/main/java/com/l2jserver/model/world/clan/ClanListener.java +++ b/src/main/java/com/l2jserver/model/world/clan/ClanListener.java @@ -16,12 +16,24 @@ */ package com.l2jserver.model.world.clan; +import com.l2jserver.service.game.world.event.WorldEvent; import com.l2jserver.service.game.world.event.WorldListener; /** - * Base listener for {@link ClanEvent} + * This listener will filter to only dispatch {@link ClanEvent} events. * * @author Rogiel */ -public interface ClanListener extends WorldListener { +public abstract class ClanListener implements WorldListener { + @Override + public boolean dispatch(WorldEvent e) { + if (!(e instanceof ClanEvent)) + return false; + return dispatch((ClanEvent) e); + } + + /** + * @see WorldListener#dispatch(WorldEvent) + */ + protected abstract boolean dispatch(ClanEvent e); } diff --git a/src/main/java/com/l2jserver/model/world/item/ItemListener.java b/src/main/java/com/l2jserver/model/world/item/ItemListener.java index 55311c064..1fac3b58b 100644 --- a/src/main/java/com/l2jserver/model/world/item/ItemListener.java +++ b/src/main/java/com/l2jserver/model/world/item/ItemListener.java @@ -16,12 +16,24 @@ */ package com.l2jserver.model.world.item; +import com.l2jserver.service.game.world.event.WorldEvent; import com.l2jserver.service.game.world.event.WorldListener; /** - * Listener for {@link ItemEvent} + * This listener will filter to only dispatch {@link ItemEvent} events. * * @author Rogiel */ -public interface ItemListener extends WorldListener { +public abstract class ItemListener implements WorldListener { + @Override + public boolean dispatch(WorldEvent e) { + if (!(e instanceof ItemEvent)) + return false; + return dispatch((ItemEvent) e); + } + + /** + * @see WorldListener#dispatch(WorldEvent) + */ + protected abstract boolean dispatch(ItemEvent e); } diff --git a/src/main/java/com/l2jserver/model/world/party/PartyListener.java b/src/main/java/com/l2jserver/model/world/party/PartyListener.java index d1268229c..bfc6209f7 100644 --- a/src/main/java/com/l2jserver/model/world/party/PartyListener.java +++ b/src/main/java/com/l2jserver/model/world/party/PartyListener.java @@ -16,12 +16,24 @@ */ package com.l2jserver.model.world.party; +import com.l2jserver.service.game.world.event.WorldEvent; import com.l2jserver.service.game.world.event.WorldListener; /** - * Listener for {@link PartyEvent} + * This listener will filter to only dispatch {@link PartyEvent} events. * * @author Rogiel */ -public interface PartyListener extends WorldListener { +public abstract class PartyListener implements WorldListener { + @Override + public boolean dispatch(WorldEvent e) { + if (!(e instanceof PartyEvent)) + return false; + return dispatch((PartyEvent) e); + } + + /** + * @see WorldListener#dispatch(WorldEvent) + */ + protected abstract boolean dispatch(PartyEvent e); } diff --git a/src/main/java/com/l2jserver/model/world/player/event/PlayerListener.java b/src/main/java/com/l2jserver/model/world/player/event/PlayerListener.java index ab6d51541..4f0db7df0 100644 --- a/src/main/java/com/l2jserver/model/world/player/event/PlayerListener.java +++ b/src/main/java/com/l2jserver/model/world/player/event/PlayerListener.java @@ -16,8 +16,6 @@ */ package com.l2jserver.model.world.player.event; -import com.l2jserver.model.world.actor.event.ActorEvent; -import com.l2jserver.model.world.actor.event.ActorListener; import com.l2jserver.service.game.world.event.WorldEvent; import com.l2jserver.service.game.world.event.WorldListener; @@ -26,9 +24,9 @@ import com.l2jserver.service.game.world.event.WorldListener; * * @author Rogiel */ -public abstract class PlayerListener implements ActorListener { +public abstract class PlayerListener implements WorldListener { @Override - public boolean dispatch(ActorEvent e) { + public boolean dispatch(WorldEvent e) { if (!(e instanceof PlayerEvent)) return false; return dispatch((PlayerEvent) e); diff --git a/src/main/java/com/l2jserver/model/world/player/event/PlayerTeleportEvent.java b/src/main/java/com/l2jserver/model/world/player/event/PlayerTeleportEvent.java index b84e75807..e29033aa7 100644 --- a/src/main/java/com/l2jserver/model/world/player/event/PlayerTeleportEvent.java +++ b/src/main/java/com/l2jserver/model/world/player/event/PlayerTeleportEvent.java @@ -20,7 +20,7 @@ import com.l2jserver.model.world.Player; import com.l2jserver.util.dimensional.Coordinate; /** - * Event dispatched once an player is teleported. + * Event dispatched once an player is teleported to another location * * @author Rogiel */ diff --git a/src/main/java/com/l2jserver/service/ServiceModule.java b/src/main/java/com/l2jserver/service/ServiceModule.java index 71698daf4..8c361c512 100644 --- a/src/main/java/com/l2jserver/service/ServiceModule.java +++ b/src/main/java/com/l2jserver/service/ServiceModule.java @@ -27,6 +27,10 @@ import com.l2jserver.service.configuration.ConfigurationService; import com.l2jserver.service.configuration.ProxyConfigurationService; import com.l2jserver.service.database.DatabaseService; import com.l2jserver.service.database.MySQLDatabaseService; +import com.l2jserver.service.game.CharacterService; +import com.l2jserver.service.game.CharacterServiceImpl; +import com.l2jserver.service.game.SpawnService; +import com.l2jserver.service.game.SpawnServiceImpl; import com.l2jserver.service.game.chat.ChatService; import com.l2jserver.service.game.chat.SimpleChatService; import com.l2jserver.service.game.scripting.ScriptingService; @@ -70,6 +74,10 @@ public class ServiceModule extends AbstractModule { bind(ChatService.class).to(SimpleChatService.class) .in(Scopes.SINGLETON); + bind(SpawnService.class).to(SpawnServiceImpl.class) + .in(Scopes.SINGLETON); + bind(CharacterService.class).to(CharacterServiceImpl.class).in( + Scopes.SINGLETON); bind(WorldService.class).to(WorldServiceImpl.class) .in(Scopes.SINGLETON); diff --git a/src/main/java/com/l2jserver/service/game/CharacterService.java b/src/main/java/com/l2jserver/service/game/CharacterService.java new file mode 100644 index 000000000..4aec23bac --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/CharacterService.java @@ -0,0 +1,43 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.service.game; + +import com.l2jserver.model.world.L2Character; +import com.l2jserver.service.Service; + +/** + * This service manages {@link L2Character} instances + * + * @author Rogiel + */ +public interface CharacterService extends Service { + /** + * Perform all operations required to this character join the world + * + * @param character + * the character + */ + void enterWorld(L2Character character); + + /** + * Perform all operations required to this character leave the world + * + * @param character + * the character + */ + void leaveWorld(L2Character character); +} diff --git a/src/main/java/com/l2jserver/service/game/CharacterServiceImpl.java b/src/main/java/com/l2jserver/service/game/CharacterServiceImpl.java new file mode 100644 index 000000000..930bbd42d --- /dev/null +++ b/src/main/java/com/l2jserver/service/game/CharacterServiceImpl.java @@ -0,0 +1,139 @@ +/* + * This file is part of l2jserver . + * + * l2jserver is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * l2jserver is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with l2jserver. If not, see . + */ +package com.l2jserver.service.game; + +import com.google.inject.Inject; +import com.l2jserver.game.net.Lineage2Connection; +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.L2Character; +import com.l2jserver.model.world.character.event.CharacterEnterWorldEvent; +import com.l2jserver.model.world.character.event.CharacterEvent; +import com.l2jserver.model.world.character.event.CharacterLeaveWorldEvent; +import com.l2jserver.model.world.character.event.CharacterListener; +import com.l2jserver.service.AbstractService; +import com.l2jserver.service.AbstractService.Depends; +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.WorldService; +import com.l2jserver.service.game.world.event.WorldEventDispatcher; +import com.l2jserver.service.network.NetworkService; + +/** + * Default implementation for {@link CharacterService}. + * + * @author Rogiel + */ +@Depends({ WorldService.class, ChatService.class, NetworkService.class }) +public class CharacterServiceImpl extends AbstractService implements + CharacterService { + /** + * The {@link WorldService} + */ + private final WorldService worldService; + /** + * The {@link WorldService} event dispatcher + */ + private final WorldEventDispatcher eventDispatcher; + /** + * The {@link ChatService} + */ + private final ChatService chatService; + /** + * The {@link NetworkService} + */ + private final NetworkService networkService; + /** + * The {@link SpawnService} + */ + private final SpawnService spawnService; + + @Inject + public CharacterServiceImpl(WorldService worldService, + WorldEventDispatcher eventDispatcher, ChatService chatService, + NetworkService networkService, SpawnService spawnService) { + this.worldService = worldService; + this.eventDispatcher = eventDispatcher; + this.chatService = chatService; + this.networkService = networkService; + this.spawnService = spawnService; + } + + @Override + public void enterWorld(final L2Character character) { + final CharacterID id = character.getID(); + final Lineage2Connection conn = networkService.discover(id); + if (conn == null) + return; + if (!worldService.add(character)) + // character is already in the world! + return; + + // chat listener + final ChatChannelListener globalChatListener = new ChatChannelListener() { + @Override + public void onMessage(ChatChannel channel, CharacterID source, + String message) { + conn.write(new ActorChatMessagePacket(source.getObject(), + MessageDestination.ALL, message)); + } + }; + + // leave world event + eventDispatcher.addListener(id, new CharacterListener() { + @Override + protected boolean dispatch(CharacterEvent e) { + if (!(e instanceof CharacterLeaveWorldEvent)) + return true; + + // remove chat listeners + chatService.getGlobalChannel().removeChatChannelListener( + globalChatListener); + + return false; + } + }); + + // register global chat listener + chatService.getGlobalChannel().addChatChannelListener( + globalChatListener); + + // send this user information + conn.write(new UserInformationPacket(character)); + // TODO game guard enforcing + conn.write(new GameGuardQueryPacket()); + conn.write(new InventoryPacket(character.getInventory())); + + // dispatch enter world event + eventDispatcher.dispatch(new CharacterEnterWorldEvent(character)); + + // spawn the player -- this will also dispatch a spawn event + spawnService.spawn(character); + } + + @Override + public void leaveWorld(L2Character character) { + if (!worldService.remove(character)) + return; + eventDispatcher.dispatch(new CharacterLeaveWorldEvent(character)); + } +} diff --git a/src/main/java/com/l2jserver/service/game/SpawnService.java b/src/main/java/com/l2jserver/service/game/SpawnService.java index 1ce0c4ec2..401788ddd 100644 --- a/src/main/java/com/l2jserver/service/game/SpawnService.java +++ b/src/main/java/com/l2jserver/service/game/SpawnService.java @@ -16,8 +16,12 @@ */ package com.l2jserver.service.game; +import com.l2jserver.model.world.Player; import com.l2jserver.model.world.capability.Spawnable; +import com.l2jserver.model.world.event.SpawnEvent; +import com.l2jserver.model.world.player.event.PlayerTeleportEvent; import com.l2jserver.service.Service; +import com.l2jserver.util.dimensional.Coordinate; /** * This service is responsible for spawning monsters, npcs and players. @@ -27,12 +31,28 @@ import com.l2jserver.service.Service; public interface SpawnService extends Service { /** * Spawns an object in the world + *

+ * An {@link SpawnEvent} will be dispatched and the object will be + * registered in the world (if it isn't already) * * @param spawnable * the spawnable object */ void spawn(Spawnable spawnable); + /** + * Teleports the object to the given point. + *

+ * An {@link PlayerTeleportEvent} will be dispatched and the new position + * will be broadcast to all clients. + * + * @param player + * the player object + * @param coordinate + * the teleportation coordinate + */ + void teleport(Player player, Coordinate coordinate); + /** * Schedules an {@link Spawnable} object to be respawn in a certain time. * diff --git a/src/main/java/com/l2jserver/service/game/SpawnServiceImpl.java b/src/main/java/com/l2jserver/service/game/SpawnServiceImpl.java index e60c9b308..1114a9138 100644 --- a/src/main/java/com/l2jserver/service/game/SpawnServiceImpl.java +++ b/src/main/java/com/l2jserver/service/game/SpawnServiceImpl.java @@ -16,19 +16,62 @@ */ package com.l2jserver.service.game; +import com.google.inject.Inject; +import com.l2jserver.game.net.Lineage2Connection; +import com.l2jserver.game.net.packet.server.CharacterTeleportPacket; +import com.l2jserver.model.id.object.CharacterID; +import com.l2jserver.model.world.L2Character; +import com.l2jserver.model.world.Player; import com.l2jserver.model.world.capability.Spawnable; +import com.l2jserver.model.world.player.event.PlayerTeleportEvent; import com.l2jserver.service.AbstractService; +import com.l2jserver.service.AbstractService.Depends; +import com.l2jserver.service.game.world.WorldService; +import com.l2jserver.service.game.world.event.WorldEventDispatcher; +import com.l2jserver.service.network.NetworkService; +import com.l2jserver.util.dimensional.Coordinate; /** * Default implementation for {@link SpawnService} * * @author Rogiel */ +@Depends({ WorldService.class }) public class SpawnServiceImpl extends AbstractService implements SpawnService { + /** + * The {@link WorldService} event dispatcher + */ + private final WorldEventDispatcher eventDispatcher; + /** + * The {@link NetworkService} + */ + private final NetworkService networkService; + + @Inject + public SpawnServiceImpl(WorldEventDispatcher eventDispatcher, + NetworkService networkService) { + this.eventDispatcher = eventDispatcher; + this.networkService = networkService; + } + @Override public void spawn(Spawnable spawnable) { // TODO Auto-generated method stub + } + @Override + public void teleport(Player player, Coordinate coordinate) { + player.setPosition(coordinate); + if (player instanceof L2Character) { + final Lineage2Connection conn = networkService + .discover((CharacterID) player.getID()); + if (conn == null) + return; + conn.write(new CharacterTeleportPacket(conn.getCharacter())); + } + // dispatch events + eventDispatcher.dispatch(new PlayerTeleportEvent(player, coordinate)); + // TODO broadcast this player new position } @Override diff --git a/src/main/java/com/l2jserver/service/game/world/WorldService.java b/src/main/java/com/l2jserver/service/game/world/WorldService.java index e046ade11..c5b2506df 100644 --- a/src/main/java/com/l2jserver/service/game/world/WorldService.java +++ b/src/main/java/com/l2jserver/service/game/world/WorldService.java @@ -36,7 +36,7 @@ public interface WorldService extends Service, Iterable { * @param object * the object */ - public void add(WorldObject object); + boolean add(WorldObject object); /** * Removes an object of the world @@ -44,7 +44,7 @@ public interface WorldService extends Service, Iterable { * @param object * the object */ - public void remove(WorldObject object); + boolean remove(WorldObject object); /** * Check if this object is in the world. @@ -53,14 +53,14 @@ public interface WorldService extends Service, Iterable { * the object * @return true if object exists */ - public boolean contains(WorldObject object); + boolean contains(WorldObject object); /** * Get the event dispatcher * * @return the event dispatcher */ - public WorldEventDispatcher getEventDispatcher(); + WorldEventDispatcher getEventDispatcher(); /** * Creates a list of all objects matching filter @@ -71,7 +71,7 @@ public interface WorldService extends Service, Iterable { * the filter * @return the list of objects */ - public List list(WorldObjectFilter filter); + List list(WorldObjectFilter filter); /** * Creates a list of all objects of type type diff --git a/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java b/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java index e0d342956..197520d34 100644 --- a/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java +++ b/src/main/java/com/l2jserver/service/game/world/WorldServiceImpl.java @@ -74,15 +74,15 @@ public class WorldServiceImpl extends AbstractService implements WorldService { } @Override - public void add(WorldObject object) { + public boolean add(WorldObject object) { log.debug("Adding object {} to world", object); - objects.add(object); + return objects.add(object); } @Override - public void remove(WorldObject object) { + public boolean remove(WorldObject object) { log.debug("Removing object {} from world", object); - objects.remove(object); + return objects.remove(object); } @Override diff --git a/src/main/java/com/l2jserver/service/game/world/event/WorldEventDispatcher.java b/src/main/java/com/l2jserver/service/game/world/event/WorldEventDispatcher.java index beca5d041..4811fb4e6 100644 --- a/src/main/java/com/l2jserver/service/game/world/event/WorldEventDispatcher.java +++ b/src/main/java/com/l2jserver/service/game/world/event/WorldEventDispatcher.java @@ -48,8 +48,8 @@ public interface WorldEventDispatcher { * @param listener * the listener */ - > void addListener( - Listenable object, WorldListener listener); + void addListener( + Listenable object, WorldListener listener); /** * Adds a new listener to object with id id @@ -63,8 +63,8 @@ public interface WorldEventDispatcher { * @param listener * the listener */ - > void addListener( - ObjectID> id, WorldListener listener); + void addListener( + ObjectID> id, WorldListener listener); /** * Removes an existing listener from object @@ -78,8 +78,8 @@ public interface WorldEventDispatcher { * @param listener * the listener */ - > void removeListener( - Listenable object, WorldListener listener); + void removeListener( + Listenable object, WorldListener listener); /** * Removes an existing listener from the object with id id @@ -93,6 +93,6 @@ public interface WorldEventDispatcher { * @param listener * the listener */ - > void removeListener( - ObjectID> id, WorldListener listener); + void removeListener( + ObjectID> id, WorldListener listener); } diff --git a/src/main/java/com/l2jserver/service/game/world/event/WorldEventDispatcherImpl.java b/src/main/java/com/l2jserver/service/game/world/event/WorldEventDispatcherImpl.java index 6042cbe2c..938f1f699 100644 --- a/src/main/java/com/l2jserver/service/game/world/event/WorldEventDispatcherImpl.java +++ b/src/main/java/com/l2jserver/service/game/world/event/WorldEventDispatcherImpl.java @@ -87,46 +87,38 @@ public class WorldEventDispatcherImpl implements WorldEventDispatcher { } @Override - @SuppressWarnings("unchecked") - public > void addListener( - Listenable object, WorldListener listener) { + public void addListener( + Listenable object, WorldListener listener) { log.debug("Adding new listener {} to {}", listener, object.getID()); - listeners.add(new ListenerIDPair(object.getID(), - (WorldListener) listener)); + listeners.add(new ListenerIDPair(object.getID(), listener)); } @Override - @SuppressWarnings("unchecked") - public > void addListener( - ObjectID> id, WorldListener listener) { + public void addListener( + ObjectID> id, WorldListener listener) { log.debug("Adding new listener {} to {}", listener, id); - listeners.add(new ListenerIDPair(id, - (WorldListener) listener)); + listeners.add(new ListenerIDPair(id, listener)); } @Override - @SuppressWarnings("unchecked") - public > void removeListener( - Listenable object, WorldListener listener) { + public void removeListener( + Listenable object, WorldListener listener) { log.debug("Removing new listener {} from {}", listener, object.getID()); - listeners.remove(new ListenerIDPair(object.getID(), - (WorldListener) listener)); + listeners.remove(new ListenerIDPair(object.getID(), listener)); } @Override - @SuppressWarnings("unchecked") - public > void removeListener( - ObjectID> id, WorldListener listener) { + public void removeListener( + ObjectID> id, WorldListener listener) { log.debug("Removing new listener {} from {}", listener, id); - listeners.remove(new ListenerIDPair(id, - (WorldListener) listener)); + listeners.remove(new ListenerIDPair(id, listener)); } private class ListenerIDPair { private ObjectID ID; - private WorldListener listener; + private WorldListener listener; - public ListenerIDPair(ObjectID ID, WorldListener listener) { + public ListenerIDPair(ObjectID ID, WorldListener listener) { super(); this.ID = ID; this.listener = listener; diff --git a/src/main/java/com/l2jserver/service/game/world/event/WorldListener.java b/src/main/java/com/l2jserver/service/game/world/event/WorldListener.java index 9760d06bf..4ad481c7e 100644 --- a/src/main/java/com/l2jserver/service/game/world/event/WorldListener.java +++ b/src/main/java/com/l2jserver/service/game/world/event/WorldListener.java @@ -24,7 +24,7 @@ package com.l2jserver.service.game.world.event; * @param * the received event type */ -public interface WorldListener { +public interface WorldListener { /** * Once the event call is dispatched the listener WILL be removed if * false is returned. If you wish to keep this listener, you must return @@ -34,5 +34,5 @@ public interface WorldListener { * the event * @return true to keep listener alive */ - boolean dispatch(E e); + boolean dispatch(WorldEvent e); } diff --git a/src/main/java/com/l2jserver/model/world/capability/Teleportable.java b/src/main/java/com/l2jserver/service/game/world/filter/impl/CharacterBroadcastFilter.java similarity index 59% rename from src/main/java/com/l2jserver/model/world/capability/Teleportable.java rename to src/main/java/com/l2jserver/service/game/world/filter/impl/CharacterBroadcastFilter.java index 3d058b960..0b21c85a6 100644 --- a/src/main/java/com/l2jserver/model/world/capability/Teleportable.java +++ b/src/main/java/com/l2jserver/service/game/world/filter/impl/CharacterBroadcastFilter.java @@ -14,18 +14,19 @@ * You should have received a copy of the GNU General Public License * along with l2jserver. If not, see . */ -package com.l2jserver.model.world.capability; +package com.l2jserver.service.game.world.filter.impl; -import com.l2jserver.model.world.AbstractObject; -import com.l2jserver.util.dimensional.Coordinate; +import com.l2jserver.model.world.L2Character; +import com.l2jserver.service.game.world.filter.AndFilter; +import com.l2jserver.service.game.world.filter.WorldObjectFilter; /** - * Defines an {@link AbstractObject} that can be teleported by - * {@link Teleporter} objects. Note that it is also possible to teleport - * without a teleporter! - * * @author Rogiel */ -public interface Teleportable extends ObjectCapability, Positionable, Spawnable { - void teleport(Coordinate coordinate); +public class CharacterBroadcastFilter extends AndFilter { + @SuppressWarnings({ "unchecked", "rawtypes" }) + public CharacterBroadcastFilter(L2Character character) { + super(new InstanceFilter(L2Character.class), + (WorldObjectFilter) new KnownListFilter(character)); + } } diff --git a/src/main/java/com/l2jserver/model/world/capability/Teleporter.java b/src/main/java/com/l2jserver/service/game/world/filter/impl/KnownListFilter.java similarity index 58% rename from src/main/java/com/l2jserver/model/world/capability/Teleporter.java rename to src/main/java/com/l2jserver/service/game/world/filter/impl/KnownListFilter.java index d2177d458..7263eb011 100644 --- a/src/main/java/com/l2jserver/model/world/capability/Teleporter.java +++ b/src/main/java/com/l2jserver/service/game/world/filter/impl/KnownListFilter.java @@ -14,17 +14,22 @@ * You should have received a copy of the GNU General Public License * along with l2jserver. If not, see . */ -package com.l2jserver.model.world.capability; +package com.l2jserver.service.game.world.filter.impl; -import com.l2jserver.model.world.AbstractObject; -import com.l2jserver.util.dimensional.Coordinate; +import com.l2jserver.model.world.L2Character; +import com.l2jserver.model.world.capability.Positionable; +import com.l2jserver.service.game.world.filter.AndFilter; /** - * Defines an {@link AbstractObject} that can teleport {@link Teleportable} - * objects. - * * @author Rogiel + * */ -public interface Teleporter extends ObjectCapability { - void teleport(Coordinate coord, Teleportable target); +public class KnownListFilter extends AndFilter { + public static final int KNOWNLIST_RANGE = 200; + + @SuppressWarnings("unchecked") + public KnownListFilter(L2Character character) { + super(new InstanceFilter(Positionable.class), + new RangeFilter(character.getPosition(), KNOWNLIST_RANGE)); + } } diff --git a/src/main/java/com/l2jserver/service/network/NettyNetworkService.java b/src/main/java/com/l2jserver/service/network/NettyNetworkService.java index bf7636c0d..75d8383ac 100644 --- a/src/main/java/com/l2jserver/service/network/NettyNetworkService.java +++ b/src/main/java/com/l2jserver/service/network/NettyNetworkService.java @@ -49,6 +49,11 @@ import com.l2jserver.util.factory.CollectionFactory; WorldService.class }) public class NettyNetworkService extends AbstractService implements NetworkService { + /** + * The {@link WorldService} instance + */ + private final WorldService worldService; + /** * The network configuration object */ @@ -74,9 +79,10 @@ public class NettyNetworkService extends AbstractService implements @Inject public NettyNetworkService(ConfigurationService configService, - Injector injector) { + Injector injector, WorldService worldService) { this.config = configService.get(NetworkConfiguration.class); this.injector = injector; + this.worldService = worldService; InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory()); } @@ -85,7 +91,8 @@ public class NettyNetworkService extends AbstractService implements server = new ServerBootstrap(new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); - server.setPipelineFactory(new Lineage2PipelineFactory(injector, this)); + server.setPipelineFactory(new Lineage2PipelineFactory(injector, this, + worldService)); channel = (ServerChannel) server.bind(config.getListenAddress()); } diff --git a/src/main/java/com/l2jserver/util/dimensional/Coordinate.java b/src/main/java/com/l2jserver/util/dimensional/Coordinate.java index 6a7dd9d24..8230dd163 100644 --- a/src/main/java/com/l2jserver/util/dimensional/Coordinate.java +++ b/src/main/java/com/l2jserver/util/dimensional/Coordinate.java @@ -85,4 +85,14 @@ public class Coordinate { public static Coordinate fromXYZ(int x, int y, int z) { return new Coordinate(x, y, z); } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return "Coordinate [" + vector + "]"; + } }