1
0
mirror of https://github.com/Rogiel/l2jserver2 synced 2025-12-06 07:32:46 +00:00

Better event system

Signed-off-by: Rogiel <rogiel@rogiel.com>
This commit is contained in:
2011-05-18 02:09:14 -03:00
parent be329a50e9
commit cd41122035
34 changed files with 660 additions and 186 deletions

View File

@@ -16,6 +16,8 @@
*/ */
package com.l2jserver.game.net; package com.l2jserver.game.net;
import java.util.Set;
import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture; 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.game.net.packet.ServerPacket;
import com.l2jserver.model.id.object.CharacterID; import com.l2jserver.model.id.object.CharacterID;
import com.l2jserver.model.world.L2Character; 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 * This object connects the model (structure objects normally stored in the
* database) to the controller (protocol stuff). * 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> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
@@ -67,13 +76,30 @@ public class Lineage2Connection {
*/ */
private ProtocolVersion version; 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 * Creates a new instance
* *
* @param worldService
* the world service
* @param channel * @param channel
* the channel * the channel
*/ */
public Lineage2Connection(Channel channel) { public Lineage2Connection(WorldService worldService,
NetworkService networkService, Channel channel) {
this.worldService = worldService;
this.networkService = networkService;
this.channel = channel; this.channel = channel;
} }
@@ -176,46 +202,115 @@ public class Lineage2Connection {
return channel; 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() { public boolean isOpen() {
return channel.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() { public boolean isConnected() {
return channel.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) { public ChannelFuture write(ServerPacket packet) {
return channel.write(packet); return channel.write(packet);
} }
public ChannelFuture[] broadcast(ServerPacket packet) { /**
// TODO implement broadcasting * Broadcast a packet to all characters in this character knownlist.
return new ChannelFuture[] { write(packet) }; * <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() { public ChannelFuture disconnect() {
return channel.disconnect(); return channel.disconnect();
} }
/**
* Closes the channel of this client.
*
* @return the {@link ChannelFuture}
*/
public ChannelFuture close() { public ChannelFuture close() {
return channel.close(); return channel.close();
} }
/**
* @return the client {@link Lineage2Decrypter}
*/
public Lineage2Decrypter getDecrypter() { public Lineage2Decrypter getDecrypter() {
return (Lineage2Decrypter) channel.getPipeline().get( return (Lineage2Decrypter) channel.getPipeline().get(
Lineage2Decrypter.HANDLER_NAME); Lineage2Decrypter.HANDLER_NAME);
} }
/**
* @return the client {@link Lineage2Encrypter}
*/
public Lineage2Encrypter getEncrypter() { public Lineage2Encrypter getEncrypter() {
return (Lineage2Encrypter) channel.getPipeline().get( return (Lineage2Encrypter) channel.getPipeline().get(
Lineage2Encrypter.HANDLER_NAME); Lineage2Encrypter.HANDLER_NAME);
} }
/**
* @return the client {@link Lineage2PacketReader}
*/
public Lineage2PacketReader getPacketReader() { public Lineage2PacketReader getPacketReader() {
return (Lineage2PacketReader) channel.getPipeline().get( return (Lineage2PacketReader) channel.getPipeline().get(
Lineage2PacketReader.HANDLER_NAME); Lineage2PacketReader.HANDLER_NAME);
} }
/**
* @return the client {@link Lineage2PacketWriter}
*/
public Lineage2PacketWriter getPacketWriter() { public Lineage2PacketWriter getPacketWriter() {
return (Lineage2PacketWriter) channel.getPipeline().get( return (Lineage2PacketWriter) channel.getPipeline().get(
Lineage2PacketWriter.HANDLER_NAME); Lineage2PacketWriter.HANDLER_NAME);

View File

@@ -32,7 +32,9 @@ import com.l2jserver.game.net.codec.Lineage2FrameEncoder;
import com.l2jserver.game.net.codec.Lineage2PacketReader; import com.l2jserver.game.net.codec.Lineage2PacketReader;
import com.l2jserver.game.net.codec.Lineage2PacketWriter; import com.l2jserver.game.net.codec.Lineage2PacketWriter;
import com.l2jserver.game.net.handler.Lineage2PacketHandler; 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.NettyNetworkService;
import com.l2jserver.service.network.NetworkService;
/** /**
* This class creates a new instance of {@link ChannelPipeline} and attaches all * This class creates a new instance of {@link ChannelPipeline} and attaches all
@@ -49,12 +51,17 @@ public class Lineage2PipelineFactory implements ChannelPipelineFactory {
* The {@link NettyNetworkService} * The {@link NettyNetworkService}
*/ */
private final NettyNetworkService nettyNetworkService; private final NettyNetworkService nettyNetworkService;
/**
* The {@link WorldService} instance
*/
private final WorldService worldService;
@Inject @Inject
public Lineage2PipelineFactory(Injector injector, public Lineage2PipelineFactory(Injector injector,
NettyNetworkService nettyNetworkService) { NetworkService networkService, WorldService worldService) {
this.injector = injector; this.injector = injector;
this.nettyNetworkService = nettyNetworkService; this.nettyNetworkService = (NettyNetworkService) networkService;
this.worldService = worldService;
} }
@Override @Override
@@ -69,9 +76,6 @@ public class Lineage2PipelineFactory implements ChannelPipelineFactory {
pipeline.addLast(Lineage2Decrypter.HANDLER_NAME, pipeline.addLast(Lineage2Decrypter.HANDLER_NAME,
new Lineage2Decrypter()); new Lineage2Decrypter());
pipeline.addLast("logger-hex", new LoggingHandler(
InternalLogLevel.DEBUG, true));
pipeline.addLast(Lineage2PacketWriter.HANDLER_NAME, pipeline.addLast(Lineage2PacketWriter.HANDLER_NAME,
new Lineage2PacketWriter()); new Lineage2PacketWriter());
pipeline.addLast(Lineage2PacketReader.HANDLER_NAME, pipeline.addLast(Lineage2PacketReader.HANDLER_NAME,
@@ -80,7 +84,8 @@ public class Lineage2PipelineFactory implements ChannelPipelineFactory {
pipeline.addLast("logger", new LoggingHandler(InternalLogLevel.DEBUG, pipeline.addLast("logger", new LoggingHandler(InternalLogLevel.DEBUG,
true)); true));
pipeline.addLast("packet.handler", new Lineage2PacketHandler(nettyNetworkService)); pipeline.addLast("packet.handler", new Lineage2PacketHandler(
nettyNetworkService, worldService));
return pipeline; return pipeline;
} }

View File

@@ -46,9 +46,6 @@ public class Lineage2FrameDecoder extends FrameDecoder {
ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(oldBuffer ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(oldBuffer
.toByteBuffer().order(ByteOrder.LITTLE_ENDIAN)); .toByteBuffer().order(ByteOrder.LITTLE_ENDIAN));
logger.debug("Received frame segment: {}",
ChannelBuffers.hexDump(buffer));
buffer.markReaderIndex(); buffer.markReaderIndex();
final int pending = buffer.readUnsignedShort() - HEADER_SIZE; final int pending = buffer.readUnsignedShort() - HEADER_SIZE;
if (pending == 0) if (pending == 0)

View File

@@ -64,8 +64,6 @@ public class Lineage2PacketWriter extends OneToOneEncoder {
buffer.writeShort(0); buffer.writeShort(0);
buffer.writeByte(packet.getOpcode()); // packet opcode buffer.writeByte(packet.getOpcode()); // packet opcode
packet.write(connection, buffer); packet.write(connection, buffer);
log.debug("Writing message {}", ChannelBuffers.hexDump(buffer));
return buffer; return buffer;
} }

View File

@@ -23,6 +23,7 @@ import org.jboss.netty.channel.SimpleChannelHandler;
import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.Lineage2Connection;
import com.l2jserver.game.net.packet.ClientPacket; import com.l2jserver.game.net.packet.ClientPacket;
import com.l2jserver.service.game.world.WorldService;
import com.l2jserver.service.network.NettyNetworkService; import com.l2jserver.service.network.NettyNetworkService;
/** /**
@@ -37,19 +38,26 @@ public class Lineage2PacketHandler extends SimpleChannelHandler {
* The {@link NettyNetworkService} * The {@link NettyNetworkService}
*/ */
private final NettyNetworkService nettyNetworkService; private final NettyNetworkService nettyNetworkService;
/**
* The {@link WorldService} instance
*/
private final WorldService worldService;
/** /**
* The Lineage 2 connection * The Lineage 2 connection
*/ */
private Lineage2Connection connection; private Lineage2Connection connection;
public Lineage2PacketHandler(NettyNetworkService nettyNetworkService) { public Lineage2PacketHandler(NettyNetworkService nettyNetworkService,
WorldService worldService) {
this.nettyNetworkService = nettyNetworkService; this.nettyNetworkService = nettyNetworkService;
this.worldService = worldService;
} }
@Override @Override
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception { throws Exception {
connection = new Lineage2Connection(e.getChannel()); connection = new Lineage2Connection(worldService, nettyNetworkService,
e.getChannel());
connection.getPacketWriter().setConnection(connection); connection.getPacketWriter().setConnection(connection);
nettyNetworkService.register(connection); nettyNetworkService.register(connection);

View File

@@ -198,24 +198,7 @@ public class CharacterCreatePacket extends AbstractClientPacket {
log.debug("Creating character with template {}", template); log.debug("Creating character with template {}", template);
// ensure parameters passed by the client are true // ensure parameters passed by the client are true
if (/* if ((race != template.getRace())) {
* (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);
log.debug("race, expected {}, received {}", template.getRace(), log.debug("race, expected {}, received {}", template.getRace(),
race); race);

View File

@@ -17,21 +17,14 @@
package com.l2jserver.game.net.packet.client; package com.l2jserver.game.net.packet.client;
import org.jboss.netty.buffer.ChannelBuffer; import org.jboss.netty.buffer.ChannelBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.l2jserver.game.net.Lineage2Connection; import com.l2jserver.game.net.Lineage2Connection;
import com.l2jserver.game.net.packet.AbstractClientPacket; 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.id.object.CharacterID;
import com.l2jserver.model.world.character.event.CharacterLoggedInEvent; import com.l2jserver.service.game.CharacterService;
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;
/** /**
* The client is requesting a logout. Currently, when this packet is received * 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; public static final int OPCODE = 0x11;
/** private final Logger log = LoggerFactory.getLogger(EnterWorld.class);
* The chat service
*/
private final ChatService chatService;
/**
* The World Event Dispatcher
*/
private final WorldEventDispatcher eventDispatcher;
/** /**
* Creates a new instance * The {@link CharacterService}
*
* @param chatService
* the chat service
*/ */
private final CharacterService characterService;
@Inject @Inject
public EnterWorld(ChatService chatService, public EnterWorld(CharacterService characterService) {
WorldEventDispatcher eventDispatcher) { this.characterService = characterService;
this.chatService = chatService;
this.eventDispatcher = eventDispatcher;
} }
@Override @Override
@@ -84,23 +67,14 @@ public class EnterWorld extends AbstractClientPacket {
@Override @Override
public void process(final Lineage2Connection conn) { public void process(final Lineage2Connection conn) {
// register global chat listener final CharacterID id = conn.getCharacterID();
chatService.getGlobalChannel().addChatChannelListener( if (id == null) {
new ChatChannelListener() { log.warn(
@Override "Client {} is trying to enter world without select a character",
public void onMessage(ChatChannel channel, conn);
CharacterID source, String message) { conn.close();
conn.write(new ActorChatMessagePacket(source return;
.getObject(), MessageDestination.ALL, message)); }
} characterService.enterWorld(id.getObject());
});
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()));
} }
} }

View File

@@ -17,12 +17,15 @@
package com.l2jserver.game.net.packet.client; package com.l2jserver.game.net.packet.client;
import org.jboss.netty.buffer.ChannelBuffer; 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.Lineage2Connection;
import com.l2jserver.game.net.packet.AbstractClientPacket; import com.l2jserver.game.net.packet.AbstractClientPacket;
import com.l2jserver.game.net.packet.server.CharacterStopMovePacket; 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.model.world.L2Character;
import com.l2jserver.service.game.SpawnService;
import com.l2jserver.util.dimensional.Coordinate; import com.l2jserver.util.dimensional.Coordinate;
/** /**
@@ -36,35 +39,53 @@ public class RequestMoveBackwardToLocationPacket extends AbstractClientPacket {
*/ */
public static final int OPCODE = 0x0f; public static final int OPCODE = 0x0f;
private final Logger log = LoggerFactory.getLogger(this.getClass());
/**
* The {@link SpawnService}
*/
private final SpawnService spawnService;
// packet // packet
private Coordinate target; private Coordinate target;
private Coordinate origin; private Coordinate origin;
private int moveMovement; private int moveMovement;
@Inject
public RequestMoveBackwardToLocationPacket(SpawnService spawnService) {
this.spawnService = spawnService;
}
@Override @Override
public void read(Lineage2Connection conn, ChannelBuffer buffer) { public void read(Lineage2Connection conn, ChannelBuffer buffer) {
this.target = Coordinate.fromXYZ(buffer.readInt(), buffer.readInt(), this.target = Coordinate.fromXYZ(buffer.readInt(), buffer.readInt(),
buffer.readInt()); buffer.readInt());
this.origin = Coordinate.fromXYZ(buffer.readInt(), buffer.readInt(), this.origin = Coordinate.fromXYZ(buffer.readInt(), buffer.readInt(),
buffer.readInt()); buffer.readInt());
// 0 keyboard, 1 mouse // seems that L2Walker does not send this
this.moveMovement = buffer.readInt(); // seems that L2Walker does not if (buffer.readableBytes() >= 4) {
// send this // 0 keyboard, 1 mouse
this.moveMovement = buffer.readInt();
}
} }
@Override @Override
public void process(final Lineage2Connection conn) { public void process(final Lineage2Connection conn) {
if (target.equals(origin)) { if (target.equals(origin)) {
log.debug("Target is same as origin. Stopping character.");
conn.write(new CharacterStopMovePacket(conn.getCharacter())); conn.write(new CharacterStopMovePacket(conn.getCharacter()));
return; return;
} }
if (target.getDistance(origin) >= 98010000) { 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! // TODO send action failed message!
return; return;
} }
final L2Character character = conn.getCharacter(); final L2Character character = conn.getCharacter();
character.setPosition(target); log.debug("Character {} is moving from {} to {}", new Object[] {
character, origin, target });
conn.broadcast(new CharacterTeleportPacket(character)); spawnService.teleport(character, target);
} }
} }

View File

@@ -36,12 +36,6 @@ public class Pet extends Player implements Summonable {
*/ */
private ItemID itemID; private ItemID itemID;
@Override
public void teleport(Coordinate coordinate) {
// TODO Auto-generated method stub
}
@Override @Override
public void summon(Coordinate coordinate) { public void summon(Coordinate coordinate) {
// TODO Auto-generated method stub // TODO Auto-generated method stub

View File

@@ -18,8 +18,6 @@ package com.l2jserver.model.world;
import com.l2jserver.model.world.capability.Actor; import com.l2jserver.model.world.capability.Actor;
import com.l2jserver.model.world.capability.Playable; 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 * {@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 * @author Rogiel
*/ */
public abstract class Player extends AbstractActor implements Playable, Actor, 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();
}
} }

View File

@@ -16,13 +16,24 @@
*/ */
package com.l2jserver.model.world.actor.event; 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; 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 <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public interface ActorListener extends WorldListener<ActorEvent> { 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);
} }

View File

@@ -31,6 +31,6 @@ import com.l2jserver.service.game.world.event.WorldListener;
* @param <E> * @param <E>
* the event type * the event type
*/ */
public interface Listenable<L extends WorldListener<E>, E extends WorldEvent> public interface Listenable<L extends WorldListener, E extends WorldEvent>
extends ObjectCapability { extends ObjectCapability {
} }

View File

@@ -29,7 +29,7 @@ import com.l2jserver.model.world.capability.Listenable;
* *
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public class CharacterLoggedInEvent implements CharacterEvent { public class CharacterEnterWorldEvent implements CharacterEvent {
/** /**
* The character that is logging in * The character that is logging in
*/ */
@@ -47,7 +47,7 @@ public class CharacterLoggedInEvent implements CharacterEvent {
* @param date * @param date
* the login date * the login date
*/ */
public CharacterLoggedInEvent(L2Character character, Date date) { public CharacterEnterWorldEvent(L2Character character, Date date) {
this.character = character; this.character = character;
this.date = date; this.date = date;
} }
@@ -58,7 +58,7 @@ public class CharacterLoggedInEvent implements CharacterEvent {
* @param character * @param character
* the character * the character
*/ */
public CharacterLoggedInEvent(L2Character character) { public CharacterEnterWorldEvent(L2Character character) {
this(character, new Date()); this(character, new Date());
} }

View File

@@ -0,0 +1,96 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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 <a href="http://www.rogiel.com">Rogiel</a>
*/
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 };
}
}

View File

@@ -16,18 +16,17 @@
*/ */
package com.l2jserver.model.world.character.event; 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.WorldEvent;
import com.l2jserver.service.game.world.event.WorldListener; import com.l2jserver.service.game.world.event.WorldListener;
/** /**
* @author <a href="http://www.rogiel.com">Rogiel</a> * This listener will filter to only dispatch {@link CharacterEvent} events.
* *
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public abstract class CharacterListener extends PlayerListener { public abstract class CharacterListener implements WorldListener {
@Override @Override
protected boolean dispatch(PlayerEvent e) { public boolean dispatch(WorldEvent e) {
if (!(e instanceof CharacterEvent)) if (!(e instanceof CharacterEvent))
return false; return false;
return dispatch((CharacterEvent) e); return dispatch((CharacterEvent) e);

View File

@@ -16,12 +16,24 @@
*/ */
package com.l2jserver.model.world.clan; package com.l2jserver.model.world.clan;
import com.l2jserver.service.game.world.event.WorldEvent;
import com.l2jserver.service.game.world.event.WorldListener; import com.l2jserver.service.game.world.event.WorldListener;
/** /**
* Base listener for {@link ClanEvent} * This listener will filter to only dispatch {@link ClanEvent} events.
* *
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public interface ClanListener extends WorldListener<ClanEvent> { 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);
} }

View File

@@ -16,12 +16,24 @@
*/ */
package com.l2jserver.model.world.item; package com.l2jserver.model.world.item;
import com.l2jserver.service.game.world.event.WorldEvent;
import com.l2jserver.service.game.world.event.WorldListener; import com.l2jserver.service.game.world.event.WorldListener;
/** /**
* Listener for {@link ItemEvent} * This listener will filter to only dispatch {@link ItemEvent} events.
* *
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public interface ItemListener extends WorldListener<ItemEvent> { 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);
} }

View File

@@ -16,12 +16,24 @@
*/ */
package com.l2jserver.model.world.party; package com.l2jserver.model.world.party;
import com.l2jserver.service.game.world.event.WorldEvent;
import com.l2jserver.service.game.world.event.WorldListener; import com.l2jserver.service.game.world.event.WorldListener;
/** /**
* Listener for {@link PartyEvent} * This listener will filter to only dispatch {@link PartyEvent} events.
* *
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public interface PartyListener extends WorldListener<PartyEvent> { 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);
} }

View File

@@ -16,8 +16,6 @@
*/ */
package com.l2jserver.model.world.player.event; 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.WorldEvent;
import com.l2jserver.service.game.world.event.WorldListener; import com.l2jserver.service.game.world.event.WorldListener;
@@ -26,9 +24,9 @@ import com.l2jserver.service.game.world.event.WorldListener;
* *
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public abstract class PlayerListener implements ActorListener { public abstract class PlayerListener implements WorldListener {
@Override @Override
public boolean dispatch(ActorEvent e) { public boolean dispatch(WorldEvent e) {
if (!(e instanceof PlayerEvent)) if (!(e instanceof PlayerEvent))
return false; return false;
return dispatch((PlayerEvent) e); return dispatch((PlayerEvent) e);

View File

@@ -20,7 +20,7 @@ import com.l2jserver.model.world.Player;
import com.l2jserver.util.dimensional.Coordinate; import com.l2jserver.util.dimensional.Coordinate;
/** /**
* Event dispatched once an player is teleported. * Event dispatched once an player is teleported to another location
* *
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */

View File

@@ -27,6 +27,10 @@ import com.l2jserver.service.configuration.ConfigurationService;
import com.l2jserver.service.configuration.ProxyConfigurationService; import com.l2jserver.service.configuration.ProxyConfigurationService;
import com.l2jserver.service.database.DatabaseService; import com.l2jserver.service.database.DatabaseService;
import com.l2jserver.service.database.MySQLDatabaseService; 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.ChatService;
import com.l2jserver.service.game.chat.SimpleChatService; import com.l2jserver.service.game.chat.SimpleChatService;
import com.l2jserver.service.game.scripting.ScriptingService; import com.l2jserver.service.game.scripting.ScriptingService;
@@ -70,6 +74,10 @@ public class ServiceModule extends AbstractModule {
bind(ChatService.class).to(SimpleChatService.class) bind(ChatService.class).to(SimpleChatService.class)
.in(Scopes.SINGLETON); .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) bind(WorldService.class).to(WorldServiceImpl.class)
.in(Scopes.SINGLETON); .in(Scopes.SINGLETON);

View File

@@ -0,0 +1,43 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
package com.l2jserver.service.game;
import com.l2jserver.model.world.L2Character;
import com.l2jserver.service.Service;
/**
* This service manages {@link L2Character} instances
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
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);
}

View File

@@ -0,0 +1,139 @@
/*
* This file is part of l2jserver <l2jserver.com>.
*
* 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 <http://www.gnu.org/licenses/>.
*/
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 <a href="http://www.rogiel.com">Rogiel</a>
*/
@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));
}
}

View File

@@ -16,8 +16,12 @@
*/ */
package com.l2jserver.service.game; package com.l2jserver.service.game;
import com.l2jserver.model.world.Player;
import com.l2jserver.model.world.capability.Spawnable; 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.service.Service;
import com.l2jserver.util.dimensional.Coordinate;
/** /**
* This service is responsible for spawning monsters, npcs and players. * This service is responsible for spawning monsters, npcs and players.
@@ -27,12 +31,28 @@ import com.l2jserver.service.Service;
public interface SpawnService extends Service { public interface SpawnService extends Service {
/** /**
* Spawns an object in the world * Spawns an object in the world
* <p>
* An {@link SpawnEvent} will be dispatched and the object will be
* registered in the world (if it isn't already)
* *
* @param spawnable * @param spawnable
* the spawnable object * the spawnable object
*/ */
void spawn(Spawnable spawnable); void spawn(Spawnable spawnable);
/**
* Teleports the object to the given <tt>point</tt>.
* <p>
* 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. * Schedules an {@link Spawnable} object to be respawn in a certain time.
* *

View File

@@ -16,19 +16,62 @@
*/ */
package com.l2jserver.service.game; 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.capability.Spawnable;
import com.l2jserver.model.world.player.event.PlayerTeleportEvent;
import com.l2jserver.service.AbstractService; 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} * Default implementation for {@link SpawnService}
* *
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
@Depends({ WorldService.class })
public class SpawnServiceImpl extends AbstractService implements SpawnService { 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 @Override
public void spawn(Spawnable spawnable) { public void spawn(Spawnable spawnable) {
// TODO Auto-generated method stub // 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 @Override

View File

@@ -36,7 +36,7 @@ public interface WorldService extends Service, Iterable<WorldObject> {
* @param object * @param object
* the object * the object
*/ */
public void add(WorldObject object); boolean add(WorldObject object);
/** /**
* Removes an object of the world * Removes an object of the world
@@ -44,7 +44,7 @@ public interface WorldService extends Service, Iterable<WorldObject> {
* @param object * @param object
* the object * the object
*/ */
public void remove(WorldObject object); boolean remove(WorldObject object);
/** /**
* Check if this object is in the world. * Check if this object is in the world.
@@ -53,14 +53,14 @@ public interface WorldService extends Service, Iterable<WorldObject> {
* the object * the object
* @return true if object exists * @return true if object exists
*/ */
public boolean contains(WorldObject object); boolean contains(WorldObject object);
/** /**
* Get the event dispatcher * Get the event dispatcher
* *
* @return the event dispatcher * @return the event dispatcher
*/ */
public WorldEventDispatcher getEventDispatcher(); WorldEventDispatcher getEventDispatcher();
/** /**
* Creates a list of all objects matching <tt>filter</tt> * Creates a list of all objects matching <tt>filter</tt>
@@ -71,7 +71,7 @@ public interface WorldService extends Service, Iterable<WorldObject> {
* the filter * the filter
* @return the list of objects * @return the list of objects
*/ */
public <T extends WorldObject> List<T> list(WorldObjectFilter<T> filter); <T extends WorldObject> List<T> list(WorldObjectFilter<T> filter);
/** /**
* Creates a list of all objects of type <tt>type</tt> * Creates a list of all objects of type <tt>type</tt>

View File

@@ -74,15 +74,15 @@ public class WorldServiceImpl extends AbstractService implements WorldService {
} }
@Override @Override
public void add(WorldObject object) { public boolean add(WorldObject object) {
log.debug("Adding object {} to world", object); log.debug("Adding object {} to world", object);
objects.add(object); return objects.add(object);
} }
@Override @Override
public void remove(WorldObject object) { public boolean remove(WorldObject object) {
log.debug("Removing object {} from world", object); log.debug("Removing object {} from world", object);
objects.remove(object); return objects.remove(object);
} }
@Override @Override

View File

@@ -48,8 +48,8 @@ public interface WorldEventDispatcher {
* @param listener * @param listener
* the listener * the listener
*/ */
<E extends WorldEvent, L extends WorldListener<E>> void addListener( <E extends WorldEvent, L extends WorldListener> void addListener(
Listenable<L, E> object, WorldListener<E> listener); Listenable<L, E> object, WorldListener listener);
/** /**
* Adds a new <tt>listener</tt> to object with id <tt>id</tt> * Adds a new <tt>listener</tt> to object with id <tt>id</tt>
@@ -63,8 +63,8 @@ public interface WorldEventDispatcher {
* @param listener * @param listener
* the listener * the listener
*/ */
<E extends WorldEvent, L extends WorldListener<E>> void addListener( <E extends WorldEvent, L extends WorldListener> void addListener(
ObjectID<? extends Listenable<L, E>> id, WorldListener<E> listener); ObjectID<? extends Listenable<L, E>> id, WorldListener listener);
/** /**
* Removes an existing <tt>listener</tt> from <tt>object</tt> * Removes an existing <tt>listener</tt> from <tt>object</tt>
@@ -78,8 +78,8 @@ public interface WorldEventDispatcher {
* @param listener * @param listener
* the listener * the listener
*/ */
<E extends WorldEvent, L extends WorldListener<E>> void removeListener( <E extends WorldEvent, L extends WorldListener> void removeListener(
Listenable<L, E> object, WorldListener<E> listener); Listenable<L, E> object, WorldListener listener);
/** /**
* Removes an existing <tt>listener</tt> from the object with id <tt>id</tt> * Removes an existing <tt>listener</tt> from the object with id <tt>id</tt>
@@ -93,6 +93,6 @@ public interface WorldEventDispatcher {
* @param listener * @param listener
* the listener * the listener
*/ */
<E extends WorldEvent, L extends WorldListener<E>> void removeListener( <E extends WorldEvent, L extends WorldListener> void removeListener(
ObjectID<? extends Listenable<L, E>> id, WorldListener<E> listener); ObjectID<? extends Listenable<L, E>> id, WorldListener listener);
} }

View File

@@ -87,46 +87,38 @@ public class WorldEventDispatcherImpl implements WorldEventDispatcher {
} }
@Override @Override
@SuppressWarnings("unchecked") public <E extends WorldEvent, L extends WorldListener> void addListener(
public <E extends WorldEvent, L extends WorldListener<E>> void addListener( Listenable<L, E> object, WorldListener listener) {
Listenable<L, E> object, WorldListener<E> listener) {
log.debug("Adding new listener {} to {}", listener, object.getID()); log.debug("Adding new listener {} to {}", listener, object.getID());
listeners.add(new ListenerIDPair(object.getID(), listeners.add(new ListenerIDPair(object.getID(), listener));
(WorldListener<WorldEvent>) listener));
} }
@Override @Override
@SuppressWarnings("unchecked") public <E extends WorldEvent, L extends WorldListener> void addListener(
public <E extends WorldEvent, L extends WorldListener<E>> void addListener( ObjectID<? extends Listenable<L, E>> id, WorldListener listener) {
ObjectID<? extends Listenable<L, E>> id, WorldListener<E> listener) {
log.debug("Adding new listener {} to {}", listener, id); log.debug("Adding new listener {} to {}", listener, id);
listeners.add(new ListenerIDPair(id, listeners.add(new ListenerIDPair(id, listener));
(WorldListener<WorldEvent>) listener));
} }
@Override @Override
@SuppressWarnings("unchecked") public <E extends WorldEvent, L extends WorldListener> void removeListener(
public <E extends WorldEvent, L extends WorldListener<E>> void removeListener( Listenable<L, E> object, WorldListener listener) {
Listenable<L, E> object, WorldListener<E> listener) {
log.debug("Removing new listener {} from {}", listener, object.getID()); log.debug("Removing new listener {} from {}", listener, object.getID());
listeners.remove(new ListenerIDPair(object.getID(), listeners.remove(new ListenerIDPair(object.getID(), listener));
(WorldListener<WorldEvent>) listener));
} }
@Override @Override
@SuppressWarnings("unchecked") public <E extends WorldEvent, L extends WorldListener> void removeListener(
public <E extends WorldEvent, L extends WorldListener<E>> void removeListener( ObjectID<? extends Listenable<L, E>> id, WorldListener listener) {
ObjectID<? extends Listenable<L, E>> id, WorldListener<E> listener) {
log.debug("Removing new listener {} from {}", listener, id); log.debug("Removing new listener {} from {}", listener, id);
listeners.remove(new ListenerIDPair(id, listeners.remove(new ListenerIDPair(id, listener));
(WorldListener<WorldEvent>) listener));
} }
private class ListenerIDPair { private class ListenerIDPair {
private ObjectID<?> ID; private ObjectID<?> ID;
private WorldListener<WorldEvent> listener; private WorldListener listener;
public ListenerIDPair(ObjectID<?> ID, WorldListener<WorldEvent> listener) { public ListenerIDPair(ObjectID<?> ID, WorldListener listener) {
super(); super();
this.ID = ID; this.ID = ID;
this.listener = listener; this.listener = listener;

View File

@@ -24,7 +24,7 @@ package com.l2jserver.service.game.world.event;
* @param <E> * @param <E>
* the received event type * the received event type
*/ */
public interface WorldListener<E extends WorldEvent> { public interface WorldListener {
/** /**
* Once the event call is dispatched the listener <b>WILL</b> be removed if * Once the event call is dispatched the listener <b>WILL</b> be removed if
* false is returned. If you wish to keep this listener, you must return * false is returned. If you wish to keep this listener, you must return
@@ -34,5 +34,5 @@ public interface WorldListener<E extends WorldEvent> {
* the event * the event
* @return true to keep listener alive * @return true to keep listener alive
*/ */
boolean dispatch(E e); boolean dispatch(WorldEvent e);
} }

View File

@@ -14,18 +14,19 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>. * along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.l2jserver.model.world.capability; package com.l2jserver.service.game.world.filter.impl;
import com.l2jserver.model.world.AbstractObject; import com.l2jserver.model.world.L2Character;
import com.l2jserver.util.dimensional.Coordinate; 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
* <b>without</b> a teleporter!
*
* @author <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*/ */
public interface Teleportable extends ObjectCapability, Positionable, Spawnable { public class CharacterBroadcastFilter extends AndFilter<L2Character> {
void teleport(Coordinate coordinate); @SuppressWarnings({ "unchecked", "rawtypes" })
public CharacterBroadcastFilter(L2Character character) {
super(new InstanceFilter<L2Character>(L2Character.class),
(WorldObjectFilter) new KnownListFilter(character));
}
} }

View File

@@ -14,17 +14,22 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with l2jserver. If not, see <http://www.gnu.org/licenses/>. * along with l2jserver. If not, see <http://www.gnu.org/licenses/>.
*/ */
package com.l2jserver.model.world.capability; package com.l2jserver.service.game.world.filter.impl;
import com.l2jserver.model.world.AbstractObject; import com.l2jserver.model.world.L2Character;
import com.l2jserver.util.dimensional.Coordinate; 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 <a href="http://www.rogiel.com">Rogiel</a> * @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/ */
public interface Teleporter extends ObjectCapability { public class KnownListFilter extends AndFilter<Positionable> {
void teleport(Coordinate coord, Teleportable target); public static final int KNOWNLIST_RANGE = 200;
@SuppressWarnings("unchecked")
public KnownListFilter(L2Character character) {
super(new InstanceFilter<Positionable>(Positionable.class),
new RangeFilter(character.getPosition(), KNOWNLIST_RANGE));
}
} }

View File

@@ -49,6 +49,11 @@ import com.l2jserver.util.factory.CollectionFactory;
WorldService.class }) WorldService.class })
public class NettyNetworkService extends AbstractService implements public class NettyNetworkService extends AbstractService implements
NetworkService { NetworkService {
/**
* The {@link WorldService} instance
*/
private final WorldService worldService;
/** /**
* The network configuration object * The network configuration object
*/ */
@@ -74,9 +79,10 @@ public class NettyNetworkService extends AbstractService implements
@Inject @Inject
public NettyNetworkService(ConfigurationService configService, public NettyNetworkService(ConfigurationService configService,
Injector injector) { Injector injector, WorldService worldService) {
this.config = configService.get(NetworkConfiguration.class); this.config = configService.get(NetworkConfiguration.class);
this.injector = injector; this.injector = injector;
this.worldService = worldService;
InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory()); InternalLoggerFactory.setDefaultFactory(new Slf4JLoggerFactory());
} }
@@ -85,7 +91,8 @@ public class NettyNetworkService extends AbstractService implements
server = new ServerBootstrap(new NioServerSocketChannelFactory( server = new ServerBootstrap(new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(), Executors.newCachedThreadPool(),
Executors.newCachedThreadPool())); Executors.newCachedThreadPool()));
server.setPipelineFactory(new Lineage2PipelineFactory(injector, this)); server.setPipelineFactory(new Lineage2PipelineFactory(injector, this,
worldService));
channel = (ServerChannel) server.bind(config.getListenAddress()); channel = (ServerChannel) server.bind(config.getListenAddress());
} }

View File

@@ -85,4 +85,14 @@ public class Coordinate {
public static Coordinate fromXYZ(int x, int y, int z) { public static Coordinate fromXYZ(int x, int y, int z) {
return new Coordinate(x, y, z); return new Coordinate(x, y, z);
} }
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Coordinate [" + vector + "]";
}
} }