diff --git a/scripts/commands/generic/addFriend.py b/scripts/commands/generic/addFriend.py
new file mode 100644
index 000000000..b60887a21
--- /dev/null
+++ b/scripts/commands/generic/addFriend.py
@@ -0,0 +1,29 @@
+from intents.chat import ChatAvatarRequestIntent
+from intents.chat import ChatBroadcastIntent
+from resources.encodables import ProsePackage
+from intents.chat.ChatAvatarRequestIntent.RequestType import TARGET_STATUS
+import sys
+
+def execute(galacticManager, player, target, args):
+ ghost = player.getPlayerObject()
+ if ghost is None:
+ return
+
+ name = str(args.split(" ")[0])
+ name.lower()
+
+ # TODO: Check ignore list for name -- return message @cmnty:friend_fail_is_ignored TT name if ignored
+
+ if ghost.getFriendsList().contains(name):
+ #ChatBroadcastIntent(player, ProsePackage("@cmnty:friend_duplicate", "TT", name)).broadcast() # Need to fix OOB packet crash
+ return
+
+ if galacticManager.getPlayerManager().getPlayerByCreatureFirstName(name) is None:
+ #ChatBroadcastIntent(player, ProsePackage("@cmnty:friend_not_found", "TT", name)).broadcast() # Need to fix OOB packet crash
+ return
+
+ ghost.addFriend(name)
+ #ChatBroadcastIntent(player, ProsePackage("@cmnty:friend_added", "TT", name)).broadcast() # Need to fix OOB packet crash
+
+ ChatAvatarRequestIntent(player, name, TARGET_STATUS).broadcast()
+ return
diff --git a/src/intents/NotifyPlayersPacketIntent.java b/src/intents/NotifyPlayersPacketIntent.java
index 2854a8644..ce2674f42 100644
--- a/src/intents/NotifyPlayersPacketIntent.java
+++ b/src/intents/NotifyPlayersPacketIntent.java
@@ -30,6 +30,7 @@ package intents;
import network.packets.Packet;
import resources.Terrain;
import resources.control.Intent;
+import resources.player.Player;
public class NotifyPlayersPacketIntent extends Intent {
@@ -37,16 +38,28 @@ public class NotifyPlayersPacketIntent extends Intent {
private Packet packet;
private Terrain terrain;
+ private ConditionalNotify condition;
- public NotifyPlayersPacketIntent(Packet packet, Terrain terrain) {
+ public NotifyPlayersPacketIntent(Packet packet, Terrain terrain, ConditionalNotify condition) {
super(TYPE);
this.packet = packet;
this.terrain = terrain;
+ this.condition = condition;
}
+
+ public NotifyPlayersPacketIntent(Packet packet, Terrain terrain) {
+ this(packet, terrain, null);
+ }
+
public NotifyPlayersPacketIntent(Packet p) {
- this(p, null);
+ this(p, null, null);
}
public Packet getPacket() { return packet; }
public Terrain getTerrain() { return terrain; }
+ public ConditionalNotify getCondition() { return condition; }
+
+ public interface ConditionalNotify {
+ boolean meetsCondition(Player player);
+ }
}
diff --git a/src/intents/chat/ChatAvatarRequestIntent.java b/src/intents/chat/ChatAvatarRequestIntent.java
new file mode 100644
index 000000000..8243cbb2a
--- /dev/null
+++ b/src/intents/chat/ChatAvatarRequestIntent.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2015 /// Project SWG /// www.projectswg.com
+ *
+ * ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on
+ * July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies.
+ * Our goal is to create an emulator which will provide a server for players to
+ * continue playing a game similar to the one they used to play. We are basing
+ * it on the final publish of the game prior to end-game events.
+ *
+ * This file is part of Holocore.
+ *
+ * --------------------------------------------------------------------------------
+ *
+ * Holocore is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * Holocore 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Holocore. If not, see
+ ******************************************************************************/
+
+package intents.chat;
+
+import resources.control.Intent;
+import resources.player.Player;
+
+/**
+ * @author Waverunner
+ */
+public class ChatAvatarRequestIntent extends Intent{
+ public static final String TYPE = "ChatAvatarRequestIntent";
+
+ private Player player;
+ private String target;
+ private RequestType requestType;
+
+ public ChatAvatarRequestIntent(Player player, String target, RequestType requestType) {
+ super(TYPE);
+ this.player = player;
+ this.target = target;
+ this.requestType = requestType;
+ }
+
+ public Player getPlayer() {
+ return player;
+ }
+
+ public String getTarget() {
+ return target;
+ }
+
+ public RequestType getRequestType() {
+ return requestType;
+ }
+
+ public enum RequestType {
+ TARGET_STATUS,
+ IGNORE_ADD_TARGET,
+ IGNORE_REMOVE_TARGET
+ }
+}
diff --git a/src/network/PacketType.java b/src/network/PacketType.java
index 823ca9e5c..e4645342e 100644
--- a/src/network/PacketType.java
+++ b/src/network/PacketType.java
@@ -46,12 +46,12 @@ import network.packets.swg.zone.server_ui.*;
import network.packets.swg.zone.spatial.*;
public enum PacketType {
-
+
// Both
SERVER_UNIX_EPOCH_TIME (0x24b73893, ServerUnixEpochTime.class),
SERVER_ID (0x58c07f21, ServerId.class),
SERVER_STRING (0x0e20d7e9, ServerString.class),
-
+
// Login
CLIENT_ID_MSG (0xd5899226, ClientIdMsg.class),
ERROR_MESSAGE (0xb5abf91a, ErrorMessage.class),
@@ -59,7 +59,7 @@ public enum PacketType {
CLIENT_PERMISSIONS_MESSAGE (0xe00730e5, ClientPermissionsMessage.class),
REQUEST_EXTENDED_CLUSTERS (0x8e33ed05, RequestExtendedClusters.class),
OFFLINE_SERVERS_MESSAGE (0xF41A5265, OfflineServersMessage.class),
-
+
// Post-Login
LOGIN_CLIENT_ID (0x41131F96, LoginClientId.class),
LOGIN_INCORRECT_CLIENT_ID (0x20E7E510, LoginIncorrectClientId.class),
@@ -69,7 +69,7 @@ public enum PacketType {
ENUMERATE_CHARACTER_ID (0x65ea4574, EnumerateCharacterId.class),
STATION_ID_HAS_JEDI_SLOT (0xcc9fccf8, StationIdHasJediSlot.class),
CHARACTER_CREATION_DISABLED (0xf4a15265, CharacterCreationDisabled.class),
-
+
// Character Creation
CLIENT_CREATE_CHARACTER (0xb97f3074, ClientCreateCharacter.class),
CREATE_CHARACTER_SUCCESS (0x1db575cc, CreateCharacterSuccess.class),
@@ -78,11 +78,11 @@ public enum PacketType {
APPROVE_NAME_RESPONSE (0x9b2c6ba7, ClientVerifyAndLockNameResponse.class),
RANDOM_NAME_REQUEST (0xd6d1b6d1, RandomNameRequest.class),
RANDOM_NAME_RESPONSE (0xe85fb868, RandomNameResponse.class),
-
+
// Character Deletion
DELETE_CHARACTER_RESPONSE (0x8268989b, DeleteCharacterResponse.class),
DELETE_CHARACTER_REQUEST (0xe87ad031, DeleteCharacterRequest.class),
-
+
// Zone
COMMAND_QUEUE_ENQUEUE (0x00000116, CommandQueueEnqueue.class),
SELECT_CHARACTER (0xb5098d76, SelectCharacter.class),
@@ -103,8 +103,8 @@ public enum PacketType {
SET_WAYPOINT_COLOR (0x90C59FDE, SetWaypointColor.class),
SHOW_BACKPACK (ShowBackpack.CRC, ShowBackpack.class),
SHOW_HELMET (ShowHelmet.CRC, ShowHelmet.class),
- SERVER_WEATHER_MESSAGE (ServerWeatherMessage.CRC, ServerWeatherMessage.class),
-
+ SERVER_WEATHER_MESSAGE (ServerWeatherMessage.CRC, ServerWeatherMessage.class),
+
// Chat
CHAT_FRIENDS_LIST_UPDATE (0x6CD2FCD8, ChatFriendsListUpdate.class),
CHAT_IGNORE_LIST (0xF8C275B0, ChatIgnoreList.class),
@@ -128,16 +128,16 @@ public enum PacketType {
CHAT_SYSTEM_MESSAGE (0x6D2A6413, ChatSystemMessage.class),
CON_GENERIC_MESSAGE (0x08C5FC76, ConGenericMessage.class),
VOICE_CHAT_STATUS (0x9E601905, VoiceChatStatus.class),
-
+
// Scene
SCENE_END_BASELINES (0x2C436037, SceneEndBaselines.class),
SCENE_CREATE_OBJECT_BY_CRC (0xFE89DDEA, SceneCreateObjectByCrc.class),
- SCENE_DESTROY_OBJECT (0x4D45D504, SceneDestroyObject.class),
+ SCENE_DESTROY_OBJECT (0x4D45D504, SceneDestroyObject.class),
UPDATE_CONTAINMENT_MESSAGE (0x56CBDE9E, UpdateContainmentMessage.class),
UPDATE_CELL_PERMISSIONS_MESSAGE (0xF612499C, UpdateCellPermissionMessage.class),
GET_MAP_LOCATIONS_MESSAGE (0x1A7AB839, GetMapLocationsMessage.class),
GET_MAP_LOCATIONS_RESPONSE_MESSAGE (0x9F80464C, GetMapLocationsResponseMessage.class),
-
+
// Spatial
UPDATE_POSTURE_MESSAGE (0x0bde6b41, UpdatePostureMessage.class),
UPDATE_TRANSFORMS_MESSAGE (0x1B24F808, UpdateTransformsMessage.class),
@@ -147,17 +147,17 @@ public enum PacketType {
ATTRIBUTE_LIST_MESSAGE (0xF3F12F2A, AttributeListMessage.class),
STOP_CLIENT_EFFECT_OBJECT_BY_LABEL (0xAD6F6B26, StopClientEffectObjectByLabelMessage.class),
OPENED_CONTAINER_MESSAGE (0x2E11E4AB, OpenedContainerMessage.class),
-
+
// Combat
UPDATE_PVP_STATUS_MESSAGE (0x08a1c126, UpdatePvpStatusMessage.class),
GRANT_COMMAND_MESSAGE (0xE67E3875, GrantCommandMessage.class),
-
+
// Server UI
OBJECT_MENU_REQUEST (0x00000146, ObjectMenuRequest.class),
OBJECT_MENU_RESPONSE (0x00000147, ObjectMenuResponse.class),
SUI_CREATE_PAGE_MESSAGE (0xD44B7259, SuiCreatePageMessage.class),
SUI_EVENT_NOTIFICATION (0x092D3564, SuiEventNotification.class),
-
+
// Auction
IS_VENDOR_OWNER_RESPONSE_MESSAGE (0xCE04173E, IsVendorOwnerResponseMessage.class),
AUCTION_QUERY_HEADERS_MESSAGE (0x679E0D00, AuctionQueryHeadersMessage.class),
@@ -168,36 +168,36 @@ public enum PacketType {
AUCTION_QUERY_HEADERS_RESPONSE_MESSAGE (0xFA500E52, AuctionQueryHeadersResponseMessage.class),
RETRIEVE_AUCTION_ITEM_MESSAGE (0x12B0D449, RetrieveAuctionItemMessage.class),
RETRIEVE_AUCTION_ITEM_RESPONSE_MESSAGE (0x9499EF8C, RetrieveAuctionItemResponseMessage.class),
-
+
UNKNOWN (0xFFFFFFFF, SWGPacket.class);
-
+
private static final Map packetMap = new HashMap();
-
+
static {
for (PacketType type : values()) {
packetMap.put(type.crc, type);
}
}
-
+
private int crc;
private Class extends SWGPacket> c;
-
+
PacketType(int crc, Class extends SWGPacket> c) {
this.crc = crc;
this.c = c;
}
-
+
public int getCrc() {
return crc;
}
-
+
public static final PacketType fromCrc(int crc) {
PacketType type = packetMap.get(crc);
if (type == null)
return UNKNOWN;
return type;
}
-
+
public static final SWGPacket getForCrc(int crc) {
PacketType type = packetMap.get(crc);
if (type == null)
@@ -210,5 +210,5 @@ public enum PacketType {
}
return null;
}
-
+
}
diff --git a/src/network/packets/swg/zone/chat/ChatFriendsListUpdate.java b/src/network/packets/swg/zone/chat/ChatFriendsListUpdate.java
index 1f90eaa73..efbe34d25 100644
--- a/src/network/packets/swg/zone/chat/ChatFriendsListUpdate.java
+++ b/src/network/packets/swg/zone/chat/ChatFriendsListUpdate.java
@@ -39,14 +39,14 @@ public class ChatFriendsListUpdate extends SWGPacket {
private String friendName;
private boolean online;
- public ChatFriendsListUpdate() {
-
+ public ChatFriendsListUpdate() {}
+
+ public ChatFriendsListUpdate(String galaxy, String friendName, boolean online) {
+ this.galaxy = galaxy;
+ this.friendName = friendName;
+ this.online = online;
}
-
- public ChatFriendsListUpdate(String command) {
-
- }
-
+
public ChatFriendsListUpdate(ByteBuffer data) {
decode(data);
}
@@ -61,7 +61,8 @@ public class ChatFriendsListUpdate extends SWGPacket {
}
public ByteBuffer encode() {
- ByteBuffer data = ByteBuffer.allocate(6);
+ int stringLength = 9 + galaxy.length() + friendName.length();
+ ByteBuffer data = ByteBuffer.allocate(stringLength + 7);
addShort (data, 3);
addInt (data, CRC);
addAscii (data, "SWG");
@@ -71,4 +72,7 @@ public class ChatFriendsListUpdate extends SWGPacket {
return data;
}
+ public String getFriendName() {
+ return friendName;
+ }
}
diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java
index dc17b48c2..0cfed02b9 100644
--- a/src/resources/objects/player/PlayerObject.java
+++ b/src/resources/objects/player/PlayerObject.java
@@ -44,6 +44,8 @@ import resources.player.PlayerFlags;
import utilities.MathUtils;
import utilities.Encoder.StringType;
+import java.util.List;
+
public class PlayerObject extends IntangibleObject {
private static final long serialVersionUID = 1L;
@@ -86,8 +88,8 @@ public class PlayerObject extends IntangibleObject {
private long nearbyCraftStation = 0;
private SWGList draftSchemList = new SWGList<>(BaselineType.PLAY, 9, 3);
private int experimentPoints = 0;
- private SWGList friendsList = new SWGList<>(BaselineType.PLAY, 9, 7);
- private SWGList ignoreList = new SWGList<>(BaselineType.PLAY, 9, 8);
+ private SWGList friendsList = new SWGList<>(BaselineType.PLAY, 9, 7, StringType.ASCII);
+ private SWGList ignoreList = new SWGList<>(BaselineType.PLAY, 9, 8, StringType.ASCII);
private int languageId = 0;
private SWGList defenders = new SWGList<>(BaselineType.PLAY, 9, 17); // TODO: Change to set
private int killMeter = 0;
@@ -338,6 +340,24 @@ public class PlayerObject extends IntangibleObject {
sendDelta(8, 6, activeQuest);
}
+ public void removeFriend(String friend) {
+ synchronized (friendsList) {
+ friendsList.remove(friend);
+ }
+ friendsList.sendDeltaMessage(this);
+ }
+
+ public void addFriend(String friend) {
+ synchronized (friendsList) {
+ friendsList.add(friend);
+ }
+ friendsList.sendDeltaMessage(this);
+ }
+
+ public List getFriendsList() {
+ return this.friendsList;
+ }
+
public String getProfWheelPosition() {
return profWheelPosition;
}
diff --git a/src/resources/player/Player.java b/src/resources/player/Player.java
index 922f57f86..bb06a83cd 100644
--- a/src/resources/player/Player.java
+++ b/src/resources/player/Player.java
@@ -34,6 +34,7 @@ import resources.control.Service;
import resources.objects.SWGObject;
import resources.objects.creature.CreatureObject;
import resources.objects.player.PlayerObject;
+import services.player.PlayerManager;
public class Player implements Serializable, Comparable {
@@ -63,11 +64,15 @@ public class Player implements Serializable, Comparable {
this.playerManager = playerManager;
setNetworkId(networkId);
}
-
+
+ public PlayerManager getPlayerManager() {
+ return (PlayerManager) playerManager;
+ }
+
public void setPlayerManager(Service playerManager) {
this.playerManager = playerManager;
}
-
+
public void setNetworkId(long networkId) {
this.networkId = networkId;
}
diff --git a/src/services/chat/ChatService.java b/src/services/chat/ChatService.java
index 665fb168e..fc7e3011a 100644
--- a/src/services/chat/ChatService.java
+++ b/src/services/chat/ChatService.java
@@ -27,13 +27,9 @@
***********************************************************************************/
package services.chat;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Locale;
-
import intents.NotifyPlayersPacketIntent;
import intents.PlayerEventIntent;
+import intents.chat.ChatAvatarRequestIntent;
import intents.chat.ChatBroadcastIntent;
import intents.chat.PersistentMessageIntent;
import intents.chat.SpatialChatIntent;
@@ -43,6 +39,7 @@ import network.packets.Packet;
import network.packets.swg.SWGPacket;
import network.packets.swg.zone.ChatRequestRoomList;
import network.packets.swg.zone.chat.ChatDeletePersistentMessage;
+import network.packets.swg.zone.chat.ChatFriendsListUpdate;
import network.packets.swg.zone.chat.ChatInstantMessageToCharacter;
import network.packets.swg.zone.chat.ChatInstantMessageToClient;
import network.packets.swg.zone.chat.ChatOnSendInstantMessage;
@@ -60,12 +57,19 @@ import resources.encodables.OutOfBand;
import resources.encodables.ProsePackage;
import resources.encodables.player.Mail;
import resources.objects.SWGObject;
+import resources.objects.player.PlayerObject;
import resources.player.Player;
+import resources.player.PlayerState;
import resources.server_info.CachedObjectDatabase;
import resources.server_info.ObjectDatabase;
import resources.server_info.ObjectDatabase.Traverser;
import services.player.PlayerManager;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+
public class ChatService extends Service {
private ObjectDatabase mails;
@@ -84,6 +88,7 @@ public class ChatService extends Service {
registerForIntent(PlayerEventIntent.TYPE);
registerForIntent(ChatBroadcastIntent.TYPE);
registerForIntent(ServerStatusIntent.TYPE);
+ registerForIntent(ChatAvatarRequestIntent.TYPE);
mails.load();
mails.traverse(new Traverser() {
@Override
@@ -123,9 +128,13 @@ public class ChatService extends Service {
if (i instanceof ChatBroadcastIntent)
handleChatBroadcast((ChatBroadcastIntent) i);
break;
+ case ChatAvatarRequestIntent.TYPE:
+ if (i instanceof ChatAvatarRequestIntent)
+ handleChatAvatarStatusRequestIntent((ChatAvatarRequestIntent) i);
+ break;
}
}
-
+
private void processPacket(GalacticPacketIntent intent) {
Player player = intent.getPlayerManager().getPlayerFromNetworkId(intent.getNetworkId());
if (player == null)
@@ -164,34 +173,49 @@ public class ChatService extends Service {
private void handlePlayerEventIntent(PlayerEventIntent intent) {
switch (intent.getEvent()) {
- case PE_ZONE_IN:
+ case PE_FIRST_ZONE:
sendPersistentMessageHeaders(intent.getPlayer(), intent.getGalaxy());
+ updateChatAvatarStatus(intent.getPlayer(), intent.getGalaxy(), true);
+ break;
+ case PE_LOGGED_OUT:
+ updateChatAvatarStatus(intent.getPlayer(), intent.getGalaxy(), false);
break;
- default: break;
}
}
-
+
private void handleChatBroadcast(ChatBroadcastIntent i) {
switch(i.getBroadcastType()) {
case AREA:
broadcastAreaMessage(i.getMessage(), i.getBroadcaster());
break;
case PLANET:
- broadcastGalaxyMessage(i.getMessage(), i.getTerrain()); // TODO: Planet specific system messages
+ broadcastPlanetMessage(i.getMessage(), i.getTerrain());
break;
case GALAXY:
- broadcastGalaxyMessage(i.getMessage(), i.getTerrain());
+ broadcastGalaxyMessage(i.getMessage());
break;
case PERSONAL:
broadcastPersonalMessage(i.getProse(), i.getBroadcaster());
break;
}
}
-
- private void handleChatRoomListRequest(Player player, ChatRequestRoomList request) {
-
+
+ private void handleChatAvatarStatusRequestIntent(ChatAvatarRequestIntent i) {
+ switch (i.getRequestType()) {
+ case TARGET_STATUS:
+ sendTargetAvatarStatus(i.getPlayer(), i.getTarget());
+ break;
+ case IGNORE_REMOVE_TARGET:
+ break;
+ case IGNORE_ADD_TARGET:
+ break;
+ }
}
-
+
+ private void handleChatRoomListRequest(Player player, ChatRequestRoomList request) {
+
+ }
+
private void handleSpatialChat(SpatialChatIntent i) {
Player sender = i.getPlayer();
SWGObject actor = sender.getCreatureObject();
@@ -217,12 +241,12 @@ public class ChatService extends Service {
Player receiver = playerMgr.getPlayerByCreatureFirstName(strReceiver);
int errorCode = 0; // 0 = No issue, 4 = "strReceiver is not online"
- if (receiver == null)
+ if (receiver == null || receiver.getPlayerState() != PlayerState.ZONED_IN)
errorCode = 4;
sender.sendPacket(new ChatOnSendInstantMessage(errorCode, request.getSequence()));
- if (receiver == null)
+ if (errorCode == 4)
return;
receiver.sendPacket(new ChatInstantMessageToClient(request.getGalaxy(), strSender, request.getMessage()));
@@ -284,17 +308,72 @@ public class ChatService extends Service {
mail.setStatus(Mail.READ);
sendPersistentMessage(player, mail, MailFlagType.FULL_MESSAGE, galaxy);
}
-
+
+ private void updateChatAvatarStatus(Player player, String galaxy, boolean online) {
+ PlayerManager playerManager = player.getPlayerManager();
+ String firstName = player.getCharacterName().toLowerCase();
+ if (firstName.contains(" "))
+ firstName = firstName.substring(0, firstName.indexOf(' '));
+
+ if (online) {
+ PlayerObject playerObject = player.getPlayerObject();
+ if (playerObject == null || playerObject.getFriendsList().size() <= 0)
+ return;
+
+ for (String friend : playerObject.getFriendsList()) {
+ sendTargetAvatarStatus(player, friend);
+ }
+ }
+
+ final ChatFriendsListUpdate update = new ChatFriendsListUpdate(galaxy, firstName, online);
+ playerManager.notifyPlayersWithCondition(new NotifyPlayersPacketIntent.ConditionalNotify() {
+ @Override
+ public boolean meetsCondition(Player player) {
+ if (player.getPlayerState() != PlayerState.ZONED_IN)
+ return false;
+
+ PlayerObject playerObject = player.getPlayerObject();
+ if (playerObject == null || playerObject.getFriendsList().size() <= 0)
+ return false;
+
+ List friends = playerObject.getFriendsList();
+ if (friends.contains(update.getFriendName()))
+ return true;
+ return false;
+ }
+ }, update);
+ }
+
+ private void sendTargetAvatarStatus(Player player, String target) {
+ PlayerObject object = player.getPlayerObject();
+ if (object == null)
+ return;
+
+ Player targetPlayer = player.getPlayerManager().getPlayerByCreatureFirstName(target);
+
+ boolean online = true;
+ if (targetPlayer == null || targetPlayer.getPlayerState() != PlayerState.ZONED_IN)
+ online = false;
+
+ ChatFriendsListUpdate update = new ChatFriendsListUpdate(player.getGalaxyName(), target, online);
+ player.sendPacket(update);
+ }
+
private void broadcastAreaMessage(String message, Player broadcaster) {
ChatSystemMessage packet = new ChatSystemMessage(SystemChatType.SCREEN_AND_CHAT.ordinal(), message);
broadcaster.sendPacket(packet);
broadcaster.getCreatureObject().sendObservers(packet);
}
-
- private void broadcastGalaxyMessage(String message, Terrain terrain) {
+
+ private void broadcastPlanetMessage(String message, Terrain terrain) {
ChatSystemMessage packet = new ChatSystemMessage(SystemChatType.SCREEN_AND_CHAT.ordinal(), message);
- new NotifyPlayersPacketIntent(packet, terrain).broadcast();
+ new NotifyPlayersPacketIntent(packet, terrain, null).broadcast();
+ }
+
+ private void broadcastGalaxyMessage(String message) {
+ ChatSystemMessage packet = new ChatSystemMessage(SystemChatType.SCREEN_AND_CHAT.ordinal(), message);
+ new NotifyPlayersPacketIntent(packet).broadcast();
}
private void broadcastPersonalMessage(ProsePackage prose, Player player) {
diff --git a/src/services/galaxy/ConnectionService.java b/src/services/galaxy/ConnectionService.java
index 00e5a026c..defdd5aab 100644
--- a/src/services/galaxy/ConnectionService.java
+++ b/src/services/galaxy/ConnectionService.java
@@ -220,6 +220,7 @@ public class ConnectionService extends Service {
disappearPlayers.add(new DisappearPlayer(System.nanoTime(), p));
}
updateService.schedule(disappearRunnable, (long) DISAPPEAR_THRESHOLD, TimeUnit.MILLISECONDS);
+ new PlayerEventIntent(p, p.getGalaxyName(), PlayerEvent.PE_LOGGED_OUT).broadcast();
}
}
diff --git a/src/services/player/PlayerManager.java b/src/services/player/PlayerManager.java
index 8c073a6b0..93aa13654 100644
--- a/src/services/player/PlayerManager.java
+++ b/src/services/player/PlayerManager.java
@@ -155,7 +155,17 @@ public class PlayerManager extends Manager {
}
}
}
-
+
+ public void notifyPlayersWithCondition(NotifyPlayersPacketIntent.ConditionalNotify conditional, Packet... packets) {
+ synchronized (players) {
+ for (Player player : players.values()) {
+ if (conditional.meetsCondition(player)) {
+ player.sendPacket(packets);
+ }
+ }
+ }
+ }
+
public Player getPlayerFromNetworkId(long networkId) {
synchronized (players) {
return players.get(networkId);
@@ -247,10 +257,12 @@ public class PlayerManager extends Manager {
}
private void onNotifyPlayersPacketIntent(NotifyPlayersPacketIntent nppi) {
- if (nppi.getTerrain() != null)
+ if (nppi.getCondition() != null) {
+ notifyPlayersWithCondition(nppi.getCondition(), nppi.getPacket());
+ } else if (nppi.getTerrain() != null) {
notifyPlayersAtPlanet(nppi.getTerrain(), nppi.getPacket());
- else
+ } else {
notifyPlayers(nppi.getPacket());
+ }
}
-
}