mirror of
https://github.com/Rogiel/l2jserver2
synced 2025-12-06 07:32:46 +00:00
BroadcastService implementation
Signed-off-by: Rogiel <rogiel@rogiel.com>
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
@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;
|
||||
@@ -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<PositionableObject>(
|
||||
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<WorldObject>(
|
||||
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 {
|
||||
|
||||
@@ -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 <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
@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
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.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 <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
public interface BroadcastService extends Service {
|
||||
void broadcast(Lineage2Connection conn);
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* 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.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 <a href="http://www.rogiel.com">Rogiel</a>
|
||||
*/
|
||||
@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<PositionableObject>(
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user