diff --git a/src/main/java/com/l2jserver/L2JGameServerMain.java b/src/main/java/com/l2jserver/L2JGameServerMain.java
index 35a69ce86..1be4ead35 100644
--- a/src/main/java/com/l2jserver/L2JGameServerMain.java
+++ b/src/main/java/com/l2jserver/L2JGameServerMain.java
@@ -57,8 +57,14 @@ public class L2JGameServerMain {
serviceManager.start(BlowfishKeygenService.class);
serviceManager.start(NetworkService.class);
- // spawn
+ // spawn everything
serviceManager.get(NPCService.class).spawnAll();
+
+ // final long free = Runtime.getRuntime().freeMemory();
+ // final long allocated = Runtime.getRuntime().totalMemory();
+ // final long maximum = Runtime.getRuntime().maxMemory();
+ // final long processors =
+ // Runtime.getRuntime().availableProcessors();
} catch (Exception e) {
System.out.println("GameServer could not be started!");
e.printStackTrace();
diff --git a/src/main/java/com/l2jserver/game/net/packet/client/CM_PROTOCOL_VERSION.java b/src/main/java/com/l2jserver/game/net/packet/client/CM_PROTOCOL_VERSION.java
index 5af43a5a3..ec6b13182 100644
--- a/src/main/java/com/l2jserver/game/net/packet/client/CM_PROTOCOL_VERSION.java
+++ b/src/main/java/com/l2jserver/game/net/packet/client/CM_PROTOCOL_VERSION.java
@@ -88,7 +88,7 @@ public class CM_PROTOCOL_VERSION extends AbstractClientPacket {
log.debug("Client protocol version: {}", version);
conn.setVersion(version);
if (L2JConstant.SUPPORTED_PROTOCOL != version) {
- log.info("Incorrect protocol version: {0}. Only {1} is supported.",
+ log.info("Incorrect protocol version: {}. Only {} is supported.",
version, L2JConstant.SUPPORTED_PROTOCOL);
// notify wrong protocol and close connection
conn.write(new SM_KEY(inKey, false)).addListener(
diff --git a/src/main/java/com/l2jserver/service/ServiceManager.java b/src/main/java/com/l2jserver/service/ServiceManager.java
index eef3e8746..23e82a691 100644
--- a/src/main/java/com/l2jserver/service/ServiceManager.java
+++ b/src/main/java/com/l2jserver/service/ServiceManager.java
@@ -74,18 +74,18 @@ public class ServiceManager {
knownServices.add(service);
try {
startDependencies(service.getDependencies());
- logger.info("{}: Starting service...",
- serviceClass.getCanonicalName());
+ logger.debug("{}: Starting service...",
+ serviceClass.getSimpleName());
service.start();
- logger.info("{}: Service started!", serviceClass.getCanonicalName());
+ logger.info("{} started", serviceClass.getSimpleName());
return service;
} catch (ServiceStartException e) {
logger.error("{}: Error starting service: {}",
- serviceClass.getCanonicalName(), e);
+ serviceClass.getSimpleName(), e);
throw e;
} catch (Exception e) {
logger.error("{}: Error starting service: {}",
- serviceClass.getCanonicalName(), e);
+ serviceClass.getSimpleName(), e);
throw new ServiceStartException(e);
}
}
@@ -110,15 +110,15 @@ public class ServiceManager {
return;
knownServices.add(service);
try {
- logger.info("{0}: Stopping service...",
- serviceClass.getCanonicalName());
+ logger.debug("{0}: Stopping service...",
+ serviceClass.getSimpleName());
stopDependencies(service);
service.stop();
logger.info("{0}: Service stopped!",
- serviceClass.getCanonicalName());
+ serviceClass.getSimpleName());
} catch (ServiceStopException e) {
logger.error("{0}: Error stopping service: {1}",
- serviceClass.getCanonicalName(), e.getCause());
+ serviceClass.getSimpleName(), e.getCause());
throw e;
}
}
@@ -160,23 +160,23 @@ public class ServiceManager {
throw new ServiceStopException("Service is already stopped");
knownServices.add(service);
try {
- logger.info("{0}: Restaring service...",
- serviceClass.getCanonicalName());
+ logger.debug("{0}: Restaring service...",
+ serviceClass.getSimpleName());
service.restart();
logger.info("{0}: Service restarted!",
- serviceClass.getCanonicalName());
+ serviceClass.getSimpleName());
return service;
} catch (ServiceStartException e) {
logger.error("{0}: Error starting service: {1}",
- serviceClass.getCanonicalName(), e.getCause());
+ serviceClass.getSimpleName(), e.getCause());
throw e;
} catch (ServiceStopException e) {
logger.error("{0}: Error stopping service: {1}",
- serviceClass.getCanonicalName(), e.getCause());
+ serviceClass.getSimpleName(), e.getCause());
throw e;
} catch (ServiceException e) {
logger.error("{0}: Error restarting service: {1}",
- serviceClass.getCanonicalName(), e.getCause());
+ serviceClass.getSimpleName(), e.getCause());
throw e;
}
}
diff --git a/src/main/java/com/l2jserver/service/ServiceModule.java b/src/main/java/com/l2jserver/service/ServiceModule.java
index fbf4bb02f..547cf44b4 100644
--- a/src/main/java/com/l2jserver/service/ServiceModule.java
+++ b/src/main/java/com/l2jserver/service/ServiceModule.java
@@ -55,6 +55,8 @@ import com.l2jserver.service.game.world.event.WorldEventDispatcher;
import com.l2jserver.service.game.world.event.WorldEventDispatcherImpl;
import com.l2jserver.service.network.NettyNetworkService;
import com.l2jserver.service.network.NetworkService;
+import com.l2jserver.service.network.broadcast.BroadcastService;
+import com.l2jserver.service.network.broadcast.BroadcastServiceImpl;
import com.l2jserver.service.network.gameguard.GameGuardService;
import com.l2jserver.service.network.gameguard.GameGuardServiceImpl;
import com.l2jserver.service.network.keygen.BlowfishKeygenService;
@@ -101,6 +103,8 @@ public class ServiceModule extends AbstractModule {
.in(Scopes.SINGLETON);
bind(SpawnService.class).to(SpawnServiceImpl.class)
.in(Scopes.SINGLETON);
+ bind(BroadcastService.class).to(BroadcastServiceImpl.class).in(
+ Scopes.SINGLETON);
bind(CharacterService.class).to(CharacterServiceImpl.class).in(
Scopes.SINGLETON);
bind(AttackService.class).to(AttackServiceImpl.class).in(
diff --git a/src/main/java/com/l2jserver/service/configuration/ProxyConfigurationService.java b/src/main/java/com/l2jserver/service/configuration/ProxyConfigurationService.java
index b9860b740..feeb1f7bd 100644
--- a/src/main/java/com/l2jserver/service/configuration/ProxyConfigurationService.java
+++ b/src/main/java/com/l2jserver/service/configuration/ProxyConfigurationService.java
@@ -81,13 +81,13 @@ public class ProxyConfigurationService extends AbstractService implements
if (cache.containsKey(config))
return (C) cache.get(config);
- logger.info("Trying to create {} proxy", config);
+ logger.debug("Trying to create {} proxy", config);
Properties properties;
try {
properties = findProperties(config);
} catch (IOException e) {
properties = new Properties();
- logger.info(
+ logger.warn(
"Configuration file for {} not found, falling back to default values",
config);
}
diff --git a/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java b/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java
index 3e5e39a1d..4d07b612e 100644
--- a/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java
+++ b/src/main/java/com/l2jserver/service/game/character/CharacterServiceImpl.java
@@ -21,16 +21,12 @@ import com.google.inject.Inject;
import com.l2jserver.db.dao.ItemDAO;
import com.l2jserver.game.net.Lineage2Connection;
import com.l2jserver.game.net.SystemMessage;
-import com.l2jserver.game.net.packet.server.SM_ATTACK;
import com.l2jserver.game.net.packet.server.SM_CHAR_INFO;
-import com.l2jserver.game.net.packet.server.SM_CHAR_INFO_BROADCAST;
import com.l2jserver.game.net.packet.server.SM_CHAR_INFO_EXTRA;
import com.l2jserver.game.net.packet.server.SM_CHAR_INVENTORY;
import com.l2jserver.game.net.packet.server.SM_CHAT;
import com.l2jserver.game.net.packet.server.SM_MOVE;
import com.l2jserver.game.net.packet.server.SM_MOVE_TYPE;
-import com.l2jserver.game.net.packet.server.SM_NPC_INFO;
-import com.l2jserver.game.net.packet.server.SM_OBJECT_REMOVE;
import com.l2jserver.game.net.packet.server.SM_TARGET;
import com.l2jserver.model.id.object.CharacterID;
import com.l2jserver.model.world.Actor;
@@ -38,9 +34,6 @@ import com.l2jserver.model.world.L2Character;
import com.l2jserver.model.world.L2Character.CharacterMoveType;
import com.l2jserver.model.world.L2Character.CharacterState;
import com.l2jserver.model.world.NPC;
-import com.l2jserver.model.world.PositionableObject;
-import com.l2jserver.model.world.WorldObject;
-import com.l2jserver.model.world.actor.event.ActorAttackHitEvent;
import com.l2jserver.model.world.character.event.CharacterEnterWorldEvent;
import com.l2jserver.model.world.character.event.CharacterEvent;
import com.l2jserver.model.world.character.event.CharacterLeaveWorldEvent;
@@ -50,9 +43,6 @@ import com.l2jserver.model.world.character.event.CharacterRunningEvent;
import com.l2jserver.model.world.character.event.CharacterTargetDeselectedEvent;
import com.l2jserver.model.world.character.event.CharacterTargetSelectedEvent;
import com.l2jserver.model.world.character.event.CharacterWalkingEvent;
-import com.l2jserver.model.world.npc.event.NPCSpawnEvent;
-import com.l2jserver.model.world.player.event.PlayerTeleportedEvent;
-import com.l2jserver.model.world.player.event.PlayerTeleportingEvent;
import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractService.Depends;
import com.l2jserver.service.game.AttackService;
@@ -67,14 +57,9 @@ import com.l2jserver.service.game.spawn.NotSpawnedServiceException;
import com.l2jserver.service.game.spawn.SpawnPointNotFoundServiceException;
import com.l2jserver.service.game.spawn.SpawnService;
import com.l2jserver.service.game.world.WorldService;
-import com.l2jserver.service.game.world.event.FilteredWorldListener;
-import com.l2jserver.service.game.world.event.WorldEvent;
import com.l2jserver.service.game.world.event.WorldEventDispatcher;
-import com.l2jserver.service.game.world.event.WorldListener;
-import com.l2jserver.service.game.world.filter.impl.IDFilter;
-import com.l2jserver.service.game.world.filter.impl.KnownListFilter;
-import com.l2jserver.service.game.world.filter.impl.KnownListUpdateFilter;
import com.l2jserver.service.network.NetworkService;
+import com.l2jserver.service.network.broadcast.BroadcastService;
import com.l2jserver.service.network.gameguard.GameGuardService;
import com.l2jserver.util.geometry.Coordinate;
import com.l2jserver.util.geometry.Point3D;
@@ -85,14 +70,15 @@ import com.l2jserver.util.geometry.Point3D;
* @author Rogiel
*/
@Depends({ WorldService.class, ChatService.class, NetworkService.class,
- SpawnService.class, AttackService.class, GameGuardService.class })
+ SpawnService.class, AttackService.class, GameGuardService.class,
+ BroadcastService.class })
public class CharacterServiceImpl extends AbstractService implements
CharacterService {
/**
- * The {@link WorldService}
+ * The {@link BroadcastService}
*/
- private final WorldService worldService;
- /*
+ private final BroadcastService broadcastService;
+ /**
* The {@link WorldService} event dispatcher
*/
private final WorldEventDispatcher eventDispatcher;
@@ -127,11 +113,11 @@ public class CharacterServiceImpl extends AbstractService implements
// private final AIService aiService;
@Inject
- public CharacterServiceImpl(WorldService worldService,
+ public CharacterServiceImpl(BroadcastService broadcastService,
WorldEventDispatcher eventDispatcher, ChatService chatService,
NetworkService networkService, SpawnService spawnService,
NPCService npcService, GameGuardService ggService, ItemDAO itemDao) {
- this.worldService = worldService;
+ this.broadcastService = broadcastService;
this.eventDispatcher = eventDispatcher;
this.chatService = chatService;
this.networkService = networkService;
@@ -154,7 +140,7 @@ public class CharacterServiceImpl extends AbstractService implements
itemDao.loadInventory(character);
character.setOnline(true);
-
+
// inventory interfere on calculators
character.getStats().updateCalculator();
@@ -176,77 +162,8 @@ public class CharacterServiceImpl extends AbstractService implements
}
};
- // event broadcast listener
- // this listener will be filtered so that only interesting events are
- // dispatched, once a event arrives will be possible to check check if
- // the given event will be broadcasted or not
- // TODO this should not be here, it should be in world service or a
- // newly created broadcast service.
- final WorldListener neighboorListener = new FilteredWorldListener(
- new KnownListFilter(character)) {
- @Override
- protected boolean dispatch(WorldEvent e, PositionableObject object) {
- if (e instanceof NPCSpawnEvent) {
- conn.write(new SM_NPC_INFO((NPC) object));
- } else if (e instanceof CharacterMoveEvent) {
- final CharacterMoveEvent evt = (CharacterMoveEvent) e;
- conn.write(new SM_MOVE((L2Character) object, evt.getPoint()
- .getCoordinate()));
- } else if (e instanceof PlayerTeleportedEvent
- || e instanceof CharacterEnterWorldEvent) {
- if (object instanceof NPC) {
- conn.write(new SM_NPC_INFO((NPC) object));
- } else if (object instanceof L2Character) {
- conn.write(new SM_CHAR_INFO_BROADCAST(
- (L2Character) object));
- }
- } else if (e instanceof PlayerTeleportingEvent
- || e instanceof CharacterLeaveWorldEvent) {
- // object is not out of sight
- conn.write(new SM_OBJECT_REMOVE(object));
- } else if (e instanceof CharacterWalkingEvent) {
- conn.write(new SM_MOVE_TYPE(((CharacterWalkingEvent) e)
- .getCharacter()));
- } else if (e instanceof CharacterRunningEvent) {
- conn.write(new SM_MOVE_TYPE(((CharacterRunningEvent) e)
- .getCharacter()));
- }
- // keep listener alive
- return true;
- }
- };
- eventDispatcher.addListener(neighboorListener);
- final WorldListener sendPacketListener = new FilteredWorldListener(
- new IDFilter(character.getID())) {
- @Override
- protected boolean dispatch(WorldEvent e, WorldObject object) {
- if (e instanceof CharacterMoveEvent) {
- final CharacterMoveEvent evt = (CharacterMoveEvent) e;
- // process update known list
- for (final WorldObject o : worldService
- .iterable(new KnownListUpdateFilter(character, evt
- .getPoint()))) {
- if (o instanceof NPC) {
- conn.write(new SM_NPC_INFO((NPC) o));
- } else if (o instanceof L2Character) {
- conn.write(new SM_CHAR_INFO_BROADCAST(
- (L2Character) o));
- }
- }
- } else if (e instanceof PlayerTeleportedEvent
- || e instanceof CharacterEnterWorldEvent) {
- broadcast(conn, character);
- } else if (e instanceof ActorAttackHitEvent) {
- conn.write(new SM_ATTACK(((ActorAttackHitEvent) e).getHit()));
- conn.sendSystemMessage(SystemMessage.YOU_DID_S1_DMG,
- (int) ((ActorAttackHitEvent) e).getHit()
- .getDamage());
- }
- // keep listener alive
- return true;
- }
- };
- eventDispatcher.addListener(sendPacketListener);
+ // start broadcasting -- will broadcast all nearby objects
+ broadcastService.broadcast(conn);
// leave world event
eventDispatcher.addListener(id, new CharacterListener() {
@@ -261,9 +178,9 @@ public class CharacterServiceImpl extends AbstractService implements
chatService.getTradeChannel().removeChatChannelListener(
tradeChatListener);
- // remove broadcast listener
- eventDispatcher.removeListener(neighboorListener);
- eventDispatcher.removeListener(sendPacketListener);
+ // // remove broadcast listener
+ // eventDispatcher.removeListener(neighboorListener);
+ // eventDispatcher.removeListener(id, sendPacketListener);s
// we can kill this listener now
return false;
@@ -295,7 +212,7 @@ public class CharacterServiceImpl extends AbstractService implements
// we can ignore this one
}
- broadcast(conn, character);
+ // broadcast(conn, character);
// spawn the player -- this will also dispatch a spawn event
// here the object is registered in the world
@@ -305,20 +222,6 @@ public class CharacterServiceImpl extends AbstractService implements
eventDispatcher.dispatch(new CharacterEnterWorldEvent(character));
}
- // broadcast knownlist -- trashy implementation
- // TODO should be moved to world service or a newly created broadcast
- // service, whichever fits the purpose
- private void broadcast(Lineage2Connection conn, L2Character character) {
- for (final WorldObject o : worldService.iterable(new KnownListFilter(
- character))) {
- if (o instanceof NPC) {
- conn.write(new SM_NPC_INFO((NPC) o));
- } else if (o instanceof L2Character) {
- conn.write(new SM_CHAR_INFO_BROADCAST((L2Character) o));
- }
- }
- }
-
@Override
public void leaveWorld(L2Character character)
throws NotSpawnedServiceException {
diff --git a/src/main/java/com/l2jserver/service/game/npc/NPCServiceImpl.java b/src/main/java/com/l2jserver/service/game/npc/NPCServiceImpl.java
index 154969660..0198fdfe3 100644
--- a/src/main/java/com/l2jserver/service/game/npc/NPCServiceImpl.java
+++ b/src/main/java/com/l2jserver/service/game/npc/NPCServiceImpl.java
@@ -36,6 +36,7 @@ import com.l2jserver.service.AbstractService;
import com.l2jserver.service.AbstractService.Depends;
import com.l2jserver.service.core.threading.AsyncFuture;
import com.l2jserver.service.core.threading.ThreadService;
+import com.l2jserver.service.database.DatabaseService;
import com.l2jserver.service.game.AttackService;
import com.l2jserver.service.game.character.CannotSetTargetServiceException;
import com.l2jserver.service.game.character.CharacterService;
@@ -53,7 +54,7 @@ import com.l2jserver.util.geometry.Point3D;
* @author Rogiel
*/
@Depends({ SpawnService.class, NetworkService.class, CharacterService.class,
- ThreadService.class, AttackService.class })
+ ThreadService.class, AttackService.class, DatabaseService.class })
public class NPCServiceImpl extends AbstractService implements NPCService {
/**
* The {@link SpawnService} used to spawn the {@link NPC} instances
diff --git a/src/main/java/com/l2jserver/service/network/broadcast/BroadcastService.java b/src/main/java/com/l2jserver/service/network/broadcast/BroadcastService.java
new file mode 100644
index 000000000..fcfe29717
--- /dev/null
+++ b/src/main/java/com/l2jserver/service/network/broadcast/BroadcastService.java
@@ -0,0 +1,31 @@
+/*
+ * 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.network.broadcast;
+
+import com.l2jserver.game.net.Lineage2Connection;
+import com.l2jserver.model.world.WorldObject;
+import com.l2jserver.service.Service;
+
+/**
+ * This service is responsible for sending neighbor {@link WorldObject} packets.
+ * This service also sends some packets that are bounded to an event.
+ *
+ * @author Rogiel
+ */
+public interface BroadcastService extends Service {
+ void broadcast(Lineage2Connection conn);
+}
diff --git a/src/main/java/com/l2jserver/service/network/broadcast/BroadcastServiceImpl.java b/src/main/java/com/l2jserver/service/network/broadcast/BroadcastServiceImpl.java
new file mode 100644
index 000000000..4de2cd490
--- /dev/null
+++ b/src/main/java/com/l2jserver/service/network/broadcast/BroadcastServiceImpl.java
@@ -0,0 +1,190 @@
+/*
+ * 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.network.broadcast;
+
+import com.google.common.base.Preconditions;
+import com.google.inject.Inject;
+import com.l2jserver.game.net.Lineage2Connection;
+import com.l2jserver.game.net.SystemMessage;
+import com.l2jserver.game.net.packet.server.SM_ATTACK;
+import com.l2jserver.game.net.packet.server.SM_CHAR_INFO_BROADCAST;
+import com.l2jserver.game.net.packet.server.SM_MOVE;
+import com.l2jserver.game.net.packet.server.SM_MOVE_TYPE;
+import com.l2jserver.game.net.packet.server.SM_NPC_INFO;
+import com.l2jserver.game.net.packet.server.SM_OBJECT_REMOVE;
+import com.l2jserver.model.id.object.CharacterID;
+import com.l2jserver.model.world.L2Character;
+import com.l2jserver.model.world.NPC;
+import com.l2jserver.model.world.PositionableObject;
+import com.l2jserver.model.world.WorldObject;
+import com.l2jserver.model.world.actor.event.ActorAttackHitEvent;
+import com.l2jserver.model.world.character.event.CharacterEnterWorldEvent;
+import com.l2jserver.model.world.character.event.CharacterLeaveWorldEvent;
+import com.l2jserver.model.world.character.event.CharacterMoveEvent;
+import com.l2jserver.model.world.character.event.CharacterRunningEvent;
+import com.l2jserver.model.world.character.event.CharacterWalkingEvent;
+import com.l2jserver.model.world.npc.event.NPCSpawnEvent;
+import com.l2jserver.model.world.player.event.PlayerTeleportedEvent;
+import com.l2jserver.model.world.player.event.PlayerTeleportingEvent;
+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.FilteredWorldListener;
+import com.l2jserver.service.game.world.event.WorldEvent;
+import com.l2jserver.service.game.world.event.WorldEventDispatcher;
+import com.l2jserver.service.game.world.event.WorldListener;
+import com.l2jserver.service.game.world.filter.impl.KnownListFilter;
+import com.l2jserver.service.game.world.filter.impl.KnownListUpdateFilter;
+import com.l2jserver.service.network.NetworkService;
+import com.l2jserver.util.geometry.Point3D;
+
+/**
+ * @author Rogiel
+ */
+@Depends({ NetworkService.class, WorldService.class })
+public class BroadcastServiceImpl extends AbstractService implements
+ BroadcastService {
+ private final WorldService worldService;
+ private final WorldEventDispatcher eventDispatcher;
+
+ @Inject
+ public BroadcastServiceImpl(WorldService worldService,
+ WorldEventDispatcher eventDispatcher) {
+ this.worldService = worldService;
+ this.eventDispatcher = eventDispatcher;
+ }
+
+ @Override
+ public void broadcast(final Lineage2Connection conn) {
+ Preconditions.checkNotNull(conn, "conn");
+ final L2Character character = conn.getCharacter();
+ Preconditions.checkNotNull(character, "character");
+ final CharacterID id = character.getID();
+
+ // broadcast everything nearby
+ broadcast(conn);
+
+ // event broadcast listener
+ // this listener will be filtered so that only interesting events are
+ // dispatched, once a event arrives will be possible to check check if
+ // the given event will be broadcasted or not
+ final WorldListener neighborListener = new FilteredWorldListener(
+ new KnownListFilter(character)) {
+ @Override
+ protected boolean dispatch(WorldEvent e, PositionableObject object) {
+ if (e instanceof NPCSpawnEvent) {
+ broadcast(conn, e.getObject());
+ } else if (e instanceof CharacterMoveEvent) {
+ final CharacterMoveEvent evt = (CharacterMoveEvent) e;
+ conn.write(new SM_MOVE((L2Character) object, evt.getPoint()
+ .getCoordinate()));
+ } else if (e instanceof PlayerTeleportedEvent
+ || e instanceof CharacterEnterWorldEvent) {
+ broadcast(conn, e.getObject());
+ } else if (e instanceof PlayerTeleportingEvent
+ || e instanceof CharacterLeaveWorldEvent) {
+ // object is now out of sight
+ conn.write(new SM_OBJECT_REMOVE(object));
+ } else if (e instanceof CharacterWalkingEvent) {
+ conn.write(new SM_MOVE_TYPE(((CharacterWalkingEvent) e)
+ .getCharacter()));
+ } else if (e instanceof CharacterRunningEvent) {
+ conn.write(new SM_MOVE_TYPE(((CharacterRunningEvent) e)
+ .getCharacter()));
+ }
+ // keep listener alive
+ return true;
+ }
+ };
+ // add the global listener
+ eventDispatcher.addListener(neighborListener);
+ // this listener is bound directly to the character, no need for filters
+ // or any other test inside listener
+ final WorldListener sendPacketListener = new WorldListener() {
+ @Override
+ public boolean dispatch(WorldEvent e) {
+ if (e instanceof CharacterMoveEvent) {
+ final CharacterMoveEvent evt = (CharacterMoveEvent) e;
+ // process update known list
+ broadcastUpdate(conn, character, evt.getPoint());
+ } else if (e instanceof PlayerTeleportedEvent
+ || e instanceof CharacterEnterWorldEvent) {
+ broadcastAll(conn, character);
+ } else if (e instanceof ActorAttackHitEvent) {
+ conn.write(new SM_ATTACK(((ActorAttackHitEvent) e).getHit()));
+ conn.sendSystemMessage(SystemMessage.YOU_DID_S1_DMG,
+ (int) ((ActorAttackHitEvent) e).getHit()
+ .getDamage());
+ }
+ // keep listener alive
+ return true;
+ }
+ };
+ // add listener only for this character
+ eventDispatcher.addListener(id, sendPacketListener);
+ }
+
+ /**
+ * Broadcast all nearby objects to this client
+ *
+ * @param conn
+ * the connection
+ * @param character
+ * the character
+ */
+ private void broadcastAll(Lineage2Connection conn, L2Character character) {
+ for (final WorldObject o : worldService.iterable(new KnownListFilter(
+ character))) {
+ broadcast(conn, o);
+ }
+ }
+
+ /**
+ * Broadcast new nearby objects to this client. Will only broadcast if the
+ * object was out-of-range before and now is in range.
+ *
+ * @param conn
+ * the connection
+ * @param character
+ * the character
+ * @param point
+ * the old point
+ */
+ private void broadcastUpdate(Lineage2Connection conn,
+ L2Character character, Point3D point) {
+ for (final WorldObject o : worldService
+ .iterable(new KnownListUpdateFilter(character, point))) {
+ broadcast(conn, o);
+ }
+ }
+
+ /**
+ * Broadcast an object to this client
+ *
+ * @param conn
+ * the connection
+ * @param character
+ * the character
+ */
+ private void broadcast(Lineage2Connection conn, WorldObject o) {
+ if (o instanceof NPC) {
+ conn.write(new SM_NPC_INFO((NPC) o));
+ } else if (o instanceof L2Character) {
+ conn.write(new SM_CHAR_INFO_BROADCAST((L2Character) o));
+ }
+ }
+}