diff --git a/src/network/PacketType.java b/src/network/PacketType.java index de5141510..faa1abb5e 100644 --- a/src/network/PacketType.java +++ b/src/network/PacketType.java @@ -127,6 +127,7 @@ public enum PacketType { CHAT_ROOM_LIST (ChatRoomList.CRC, ChatRoomList.class), CHAT_ROOM_MESSAGE (ChatRoomMessage.CRC, ChatRoomMessage.class), CHAT_SEND_TO_ROOM (ChatSendToRoom.CRC, ChatSendToRoom.class), + CHAT_REMOVE_AVATAR_FROM_ROOM (ChatRemoveAvatarFromRoom.CRC, ChatRemoveAvatarFromRoom.class), CHAT_SERVER_STATUS (0x7102B15F, ChatServerStatus.class), CHAT_SYSTEM_MESSAGE (0x6D2A6413, ChatSystemMessage.class), CON_GENERIC_MESSAGE (0x08C5FC76, ConGenericMessage.class), @@ -174,7 +175,7 @@ public enum PacketType { UNKNOWN (0xFFFFFFFF, SWGPacket.class); - private static final Map packetMap = new HashMap(); + private static final Map packetMap = new HashMap<>(); static { for (PacketType type : values()) { @@ -194,14 +195,14 @@ public enum PacketType { return crc; } - public static final PacketType fromCrc(int crc) { + public static PacketType fromCrc(int crc) { PacketType type = packetMap.get(crc); if (type == null) return UNKNOWN; return type; } - public static final SWGPacket getForCrc(int crc) { + public static SWGPacket getForCrc(int crc) { PacketType type = packetMap.get(crc); if (type == null) return null; diff --git a/src/network/packets/swg/SWGPacket.java b/src/network/packets/swg/SWGPacket.java index 962e122e4..c6cf18d5e 100644 --- a/src/network/packets/swg/SWGPacket.java +++ b/src/network/packets/swg/SWGPacket.java @@ -33,6 +33,7 @@ import resources.Location; import network.PacketType; import network.packets.Packet; import resources.encodables.OutOfBandPackage; +import resources.network.BaselineBuilder; public class SWGPacket extends Packet { @@ -81,9 +82,7 @@ public class SWGPacket extends Packet { super.decode(data); data.position(2); setSWGOpcode(getInt(data)); - if (getSWGOpcode() != crc) - return false; - return true; + return getSWGOpcode() == crc; } public void decode(ByteBuffer data) { @@ -108,4 +107,8 @@ public class SWGPacket extends Packet { outOfBandPackage.decode(data); return outOfBandPackage; } + + public static void addEncodable(ByteBuffer data, BaselineBuilder.Encodable encodable) { + data.put(encodable.encode()); + } } diff --git a/src/network/packets/swg/zone/chat/ChatEnterRoomById.java b/src/network/packets/swg/zone/chat/ChatEnterRoomById.java index 54e6f253c..03fb31a04 100644 --- a/src/network/packets/swg/zone/chat/ChatEnterRoomById.java +++ b/src/network/packets/swg/zone/chat/ChatEnterRoomById.java @@ -49,7 +49,6 @@ public class ChatEnterRoomById extends SWGPacket { sequence = getInt(data); roomId = getInt(data); roomPath = getAscii(data); - System.out.println("ChatEnterRoomById: " + roomId + roomPath); } @Override @@ -69,8 +68,4 @@ public class ChatEnterRoomById extends SWGPacket { public int getRoomId() { return roomId; } - - public String getRoomPath() { - return roomPath; - } } diff --git a/src/network/packets/swg/zone/chat/ChatOnEnteredRoom.java b/src/network/packets/swg/zone/chat/ChatOnEnteredRoom.java index 851902eba..0fe731ca9 100644 --- a/src/network/packets/swg/zone/chat/ChatOnEnteredRoom.java +++ b/src/network/packets/swg/zone/chat/ChatOnEnteredRoom.java @@ -47,7 +47,14 @@ public class ChatOnEnteredRoom extends SWGPacket { this.chatRoomId = chatRoomId; this.sequence = sequence; } - + + public ChatOnEnteredRoom(ChatAvatar avatar, int result, int chatRoomId, int sequence) { + this.avatar = avatar; + this.result = result; + this.chatRoomId = chatRoomId; + this.sequence = sequence; + } + public ChatOnEnteredRoom(ByteBuffer data) { decode(data); } diff --git a/src/network/packets/swg/zone/chat/ChatOnLeaveRoom.java b/src/network/packets/swg/zone/chat/ChatOnLeaveRoom.java index ee1dd7285..c495a17a5 100644 --- a/src/network/packets/swg/zone/chat/ChatOnLeaveRoom.java +++ b/src/network/packets/swg/zone/chat/ChatOnLeaveRoom.java @@ -33,17 +33,16 @@ import network.packets.swg.SWGPacket; import resources.chat.ChatAvatar; public class ChatOnLeaveRoom extends SWGPacket { - - public static final int CRC = 0x60B5098B; + public static final int CRC = resources.common.CRC.getCrc("ChatOnLeaveRoom"); private ChatAvatar avatar; private int result; private int chatRoomId; private int sequence; - public ChatOnLeaveRoom(ChatAvatar avatar, int errorCode, int chatRoomId, int sequence) { + public ChatOnLeaveRoom(ChatAvatar avatar, int result, int chatRoomId, int sequence) { this.avatar = avatar; - this.result = errorCode; + this.result = result; this.chatRoomId = chatRoomId; this.sequence = sequence; } @@ -64,9 +63,9 @@ public class ChatOnLeaveRoom extends SWGPacket { public ByteBuffer encode() { ByteBuffer data = ByteBuffer.allocate(18 + avatar.encode().length); - addShort(data, 2); + addShort(data, 5); addInt( data, CRC); - data.put(avatar.encode()); + addEncodable(data, avatar); addInt(data, result); addInt (data, chatRoomId); addInt (data, sequence); diff --git a/src/network/packets/swg/zone/chat/ChatRemoveAvatarFromRoom.java b/src/network/packets/swg/zone/chat/ChatRemoveAvatarFromRoom.java new file mode 100644 index 000000000..05e06727d --- /dev/null +++ b/src/network/packets/swg/zone/chat/ChatRemoveAvatarFromRoom.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * 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 network.packets.swg.zone.chat; + +import network.packets.swg.SWGPacket; +import resources.chat.ChatAvatar; + +import java.nio.ByteBuffer; + +/** + * @author Waverunner + */ +public class ChatRemoveAvatarFromRoom extends SWGPacket { + public static final int CRC = resources.common.CRC.getCrc("ChatRemoveAvatarFromRoom"); + + private ChatAvatar avatar; + private String path; + + @Override + public void decode(ByteBuffer data) { + if (!super.decode(data, CRC)) + return; + + avatar = new ChatAvatar(); + avatar.decode(data); + path = getAscii(data); + } + + @Override + public ByteBuffer encode() { + ByteBuffer bb = ByteBuffer.allocate(6 + path.length() + avatar.encode().length); + addShort(bb, 3); + addInt(bb, CRC); + addEncodable(bb, avatar); + addAscii(bb, path); + return bb; + } + + public ChatAvatar getAvatar() { + return avatar; + } + + public String getPath() { + return path; + } + +} diff --git a/src/resources/Terrain.java b/src/resources/Terrain.java index 38469cb39..a1a761241 100644 --- a/src/resources/Terrain.java +++ b/src/resources/Terrain.java @@ -102,10 +102,10 @@ public enum Terrain { WATERTABLETEST ("terrain/watertabletest.trn"), YAVIN4 ("terrain/yavin4.trn"); - private static final Map CRC_TO_NAME = new ConcurrentHashMap(); - private static final Map NAME_TO_CRC = new ConcurrentHashMap(); - private static final Map NAME_TO_TERRAIN = new ConcurrentHashMap(); - private static final Map CRC_TO_TERRAIN = new ConcurrentHashMap(); + private static final Map CRC_TO_NAME = new ConcurrentHashMap<>(); + private static final Map NAME_TO_CRC = new ConcurrentHashMap<>(); + private static final Map NAME_TO_TERRAIN = new ConcurrentHashMap<>(); + private static final Map CRC_TO_TERRAIN = new ConcurrentHashMap<>(); private String file; private String name; @@ -129,6 +129,7 @@ public enum Terrain { public String getFile() { return file; } public String getName() { return name; } + public String getNameCapitalized() { return Character.toUpperCase(name.charAt(0)) + name.substring(1); } public int getCrc() { return crc; } public Location getStartLocation() { @@ -146,14 +147,14 @@ public enum Terrain { return l; } - public static final String getNameFromCrc(int crc) { + public static String getNameFromCrc(int crc) { String name = CRC_TO_NAME.get(crc); if (name == null) return ""; return name; } - public static final int getCrcFromName(String name) { + public static int getCrcFromName(String name) { Integer crc = NAME_TO_CRC.get(name.toLowerCase(Locale.ENGLISH)); if (crc == null) return 0; @@ -163,7 +164,7 @@ public enum Terrain { /** * Note: Defaults to TATOOINE */ - public static final Terrain getTerrainFromCrc(int crc) { + public static Terrain getTerrainFromCrc(int crc) { Terrain p = CRC_TO_TERRAIN.get(crc); if (p == null) return TATOOINE; @@ -173,14 +174,14 @@ public enum Terrain { /** * Note: Defaults to TATOOINE */ - public static final Terrain getTerrainFromName(String name) { + public static Terrain getTerrainFromName(String name) { Terrain p = NAME_TO_TERRAIN.get(name.toLowerCase(Locale.ENGLISH)); if (p == null) return TATOOINE; return p; } - public static final boolean doesTerrainExistForName(String name) { + public static boolean doesTerrainExistForName(String name) { return NAME_TO_TERRAIN.containsKey(name.toLowerCase(Locale.ENGLISH)); } diff --git a/src/resources/chat/ChatAvatar.java b/src/resources/chat/ChatAvatar.java index bb7a7002c..07113eab9 100644 --- a/src/resources/chat/ChatAvatar.java +++ b/src/resources/chat/ChatAvatar.java @@ -115,7 +115,9 @@ public class ChatAvatar implements BaselineBuilder.Encodable, BaselineBuilder.De @Override public void decode(ByteBuffer data) { - + game = Packet.getAscii(data); + galaxy = Packet.getAscii(data); + name = Packet.getAscii(data); } @Override @@ -131,12 +133,17 @@ public class ChatAvatar implements BaselineBuilder.Encodable, BaselineBuilder.De if (getClass() != o.getClass()) return false; - return ((ChatAvatar) o).getNetworkId() == networkId; + // NetworkId will be 0 if decoded from a packet + if (networkId != 0) return ((ChatAvatar) o).getNetworkId() == networkId; + else return ((ChatAvatar) o).getName().equals(getName()); } @Override public int hashCode() { - return (int) (networkId ^ (networkId >>> 32)); + // NetworkId will be 0 if decoded from a packet + int result = (networkId != 0 ? (int) (networkId ^ (networkId >>> 32)) : 0); + result = 31 * result + name.hashCode(); + return result; } public static ChatAvatar getFromPlayer(Player player) { diff --git a/src/resources/chat/ChatRoom.java b/src/resources/chat/ChatRoom.java index 8a4ccf92a..abc545727 100644 --- a/src/resources/chat/ChatRoom.java +++ b/src/resources/chat/ChatRoom.java @@ -28,6 +28,7 @@ package resources.chat; import network.packets.Packet; +import network.packets.swg.SWGPacket; import network.packets.swg.zone.chat.ChatRoomMessage; import resources.encodables.OutOfBandPackage; import resources.network.BaselineBuilder; @@ -177,13 +178,16 @@ public class ChatRoom implements Serializable, BaselineBuilder.Encodable, Baseli public void sendMessage(ChatAvatar sender, String message, OutOfBandPackage oob, PlayerManager playerManager) { ChatRoomMessage chatRoomMessage = new ChatRoomMessage(sender, getId(), message, oob); + sendPacketToMembers(playerManager, chatRoomMessage); + } - for (ChatAvatar avatar : members) { - Player player = playerManager.getPlayerFromNetworkId(avatar.getNetworkId()); + public void sendPacketToMembers(PlayerManager manager, SWGPacket... packets) { + for (ChatAvatar member : members) { + Player player = manager.getPlayerFromNetworkId(member.getNetworkId()); if (player == null) - return; + continue; - player.sendPacket(chatRoomMessage); + player.sendPacket(packets); } } diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index ae7a53e51..15e442143 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -44,7 +44,7 @@ import resources.player.PlayerFlags; import utilities.MathUtils; import utilities.Encoder.StringType; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; public class PlayerObject extends IntangibleObject { @@ -52,7 +52,7 @@ public class PlayerObject extends IntangibleObject { private static final long serialVersionUID = 1L; private String biography = ""; - private List joinedChannels = new LinkedList<>(); + private List joinedChannels = new ArrayList<>(); // PLAY 03 private SWGBitSet flagsList = new SWGBitSet(BaselineType.PLAY, 3, 5); @@ -388,7 +388,7 @@ public class PlayerObject extends IntangibleObject { flagsList.sendDeltaMessage(this); } - public List getJoinedChannels() { + public List getJoinedChannels() { return joinedChannels; } diff --git a/src/services/chat/ChatService.java b/src/services/chat/ChatService.java index 9e086e890..e7a71a4e8 100644 --- a/src/services/chat/ChatService.java +++ b/src/services/chat/ChatService.java @@ -39,26 +39,7 @@ import intents.player.ZonePlayerSwapIntent; import intents.server.ServerStatusIntent; import network.packets.Packet; import network.packets.swg.SWGPacket; -import network.packets.swg.zone.chat.ChatDeletePersistentMessage; -import network.packets.swg.zone.chat.ChatEnterRoomById; -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.ChatOnAddFriend; -import network.packets.swg.zone.chat.ChatOnChangeFriendStatus; -import network.packets.swg.zone.chat.ChatOnEnteredRoom; -import network.packets.swg.zone.chat.ChatOnGetFriendsList; -import network.packets.swg.zone.chat.ChatOnSendInstantMessage; -import network.packets.swg.zone.chat.ChatOnSendPersistentMessage; -import network.packets.swg.zone.chat.ChatOnSendRoomMessage; -import network.packets.swg.zone.chat.ChatPersistentMessageToClient; -import network.packets.swg.zone.chat.ChatPersistentMessageToServer; -import network.packets.swg.zone.chat.ChatQueryRoom; -import network.packets.swg.zone.chat.ChatQueryRoomResults; -import network.packets.swg.zone.chat.ChatRequestPersistentMessage; -import network.packets.swg.zone.chat.ChatRequestRoomList; -import network.packets.swg.zone.chat.ChatSendToRoom; -import network.packets.swg.zone.chat.ChatSystemMessage; +import network.packets.swg.zone.chat.*; import network.packets.swg.zone.chat.ChatSystemMessage.SystemChatType; import network.packets.swg.zone.insertion.ChatRoomList; import network.packets.swg.zone.object_controller.SpatialChat; @@ -83,6 +64,8 @@ import resources.server_info.ObjectDatabase; import resources.server_info.ObjectDatabase.Traverser; import services.player.PlayerManager; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; @@ -94,10 +77,10 @@ import java.util.concurrent.ConcurrentHashMap; public class ChatService extends Service { // Array of only the valid terrains in relation to zones able to use planetary-based chat - private static final Terrain[] terrains = new Terrain[] { + private static final List terrains = Arrays.asList( Terrain.CORELLIA, Terrain.DANTOOINE, Terrain.DATHOMIR, Terrain.ENDOR, Terrain.KASHYYYK, Terrain.LOK, Terrain.MUSTAFAR, Terrain.NABOO, Terrain.RORI, Terrain.TATOOINE, Terrain.TALUS, Terrain.YAVIN4 - }; + ); private ObjectDatabase mails; private int maxMailId; private int maxChatRoomId; @@ -203,6 +186,10 @@ public class ChatService extends Service { enterChatChannel(player, enterRoomById.getRoomId(), enterRoomById.getSequence()); } break; + case CHAT_REMOVE_AVATAR_FROM_ROOM: + if (p instanceof ChatRemoveAvatarFromRoom) + leaveChatChannel(player, ((ChatRemoveAvatarFromRoom) p).getPath()); + break; case CHAT_SEND_TO_ROOM: if (p instanceof ChatSendToRoom) handleChatSendToRoom(player, (ChatSendToRoom) p); @@ -233,25 +220,25 @@ public class ChatService extends Service { } private void handlePlayerEventIntent(PlayerEventIntent intent) { + Player player = intent.getPlayer(); + if (player == null) + return; + switch (intent.getEvent()) { case PE_ZONE_IN: - // TODO: Add players to proper planet chat room + switchPlanetaryChatChannels(player); break; case PE_FIRST_ZONE: - Player player = intent.getPlayer(); sendPersistentMessageHeaders(player, intent.getGalaxy()); updateChatAvatarStatus(player, intent.getGalaxy(), true); enterJoinedChatChannels(player); - enterChatChannel(intent.getPlayer(), "SWG.Localhost.Tatooine.Planet"); - enterChatChannel(intent.getPlayer(), "SWG.Localhost.Tatooine.system"); break; case PE_LOGGED_OUT: - if (intent.getPlayer() == null || intent.getPlayer().getCreatureObject() == null) + if (player.getCreatureObject() == null) return; - updateChatAvatarStatus(intent.getPlayer(), intent.getGalaxy(), false); - break; - default: + updateChatAvatarStatus(player, intent.getGalaxy(), false); break; + default: break; } } @@ -331,8 +318,16 @@ public class ChatService extends Service { } private void handleChatRoomListRequest(Player player) { - // TODO: Filter out private rooms - ChatRoomList response = new ChatRoomList(roomMap.values()); + ChatAvatar avatar = ChatAvatar.getFromPlayer(player); + + List rooms = new ArrayList<>(); + for (ChatRoom chatRoom : roomMap.values()) { + if (!chatRoom.isPublic() && !chatRoom.getInvited().contains(avatar) && !chatRoom.getOwner().equals(avatar)) + continue; + rooms.add(chatRoom); + } + + ChatRoomList response = new ChatRoomList(rooms); player.sendPacket(response); } @@ -343,18 +338,44 @@ public class ChatService extends Service { } private void enterJoinedChatChannels(Player player) { - if (player == null || player.getPlayerState() != PlayerState.ZONED_IN) - return; - PlayerObject ghost = player.getPlayerObject(); if (ghost == null) return; - for (Integer id : ghost.getJoinedChannels()) { - enterChatChannel(player, id); + for (String s : ghost.getJoinedChannels()) { + enterChatChannel(player, s); } } + private void switchPlanetaryChatChannels(Player player) { + PlayerObject ghost = player.getPlayerObject(); + if (ghost == null) + return; + + // Leave old zone-only chat channels + String planetEndPath = ".Planet"; + for (String channel : ghost.getJoinedChannels()) { + if (channel.endsWith(planetEndPath)) { + leaveChatChannel(player, channel); + } else { + // Better way of doing this? + String[] split = channel.split("\\."); + if (split.length == 3 && split[2].equals("system")) + leaveChatChannel(player, channel); + } + } + + Terrain terrain = player.getCreatureObject().getLocation().getTerrain(); + + // Enter the new zone-only chat channels + if (!terrains.contains(terrain)) + return; + + String planetPath = "SWG." + player.getGalaxyName() + "." + terrain.getNameCapitalized() + "."; + enterChatChannel(player, planetPath + "Planet"); + enterChatChannel(player, planetPath + "system"); + } + /** * Attempts to join the specified chat channel * @param player Player joining the chat channel @@ -377,10 +398,9 @@ public class ChatService extends Service { // TODO: Check if player is appropriate faction for the room (Rebel and imperial chat rooms) // Server-based list so we can join chat channels automatically - /* // TODO: Disabled until planet chat is automatically entered/removed from the list - List joinedChannels = ghost.getJoinedChannels(); - if (!joinedChannels.contains(room.getId())) - joinedChannels.add(room.getId());*/ + List joinedChannels = ghost.getJoinedChannels(); + if (!joinedChannels.contains(room.getPath())) + joinedChannels.add(room.getPath()); room.getMembers().add(avatar); @@ -389,25 +409,12 @@ public class ChatService extends Service { ChatRoomList roomList = new ChatRoomList(room); player.sendPacket(roomList); - // Notify players of success - ChatOnEnteredRoom onEnteredRoom = new ChatOnEnteredRoom(avatar, room.getId(), sequence); - onEnteredRoom.setResult(result.getCode()); // ChatResult.SUCCESS at this point - player.sendPacket(onEnteredRoom); + // Notify players of success, it's ChatResult.SUCCESS at this point + player.sendPacket(new ChatOnEnteredRoom(avatar, result.getCode(), room.getId(), sequence)); PlayerManager manager = player.getPlayerManager(); // Notify everyone that a player entered the room - for (ChatAvatar chatAvatar : room.getMembers()) { - if (chatAvatar.equals(avatar)) - continue; - - Player member = manager.getPlayerFromNetworkId(chatAvatar.getNetworkId()); - if (member == null || member.getPlayerState() != PlayerState.ZONED_IN) - continue; - // TODO: Should sequence be set to 0 for other members? - member.sendPacket(onEnteredRoom); - } - - System.out.println(avatar + " has entered room " + room); + room.sendPacketToMembers(manager, new ChatOnEnteredRoom(avatar, result.getCode(), room.getId(), 0)); } public void enterChatChannel(Player player, int id, int sequence) { @@ -419,10 +426,6 @@ public class ChatService extends Service { enterChatChannel(player, room, sequence); } - public void enterChatChannel(Player player, int id) { - enterChatChannel(player, id, 0); - } - public void enterChatChannel(Player player, String path) { for (ChatRoom room : roomMap.values()) { if (room.getPath().equals(path)) { @@ -430,9 +433,30 @@ public class ChatService extends Service { return; } } - System.out.println("Couldn't find room with path " + path); + System.err.println("Tried to join a room with a path that does not exist: " + path); } + public void leaveChatChannel(Player player, ChatRoom room, int sequence) { + ChatAvatar avatar = ChatAvatar.getFromPlayer(player); + + PlayerObject ghost = player.getPlayerObject(); + if (ghost == null) + return; // ChatOnLeaveRoom doesn't do anything other than for a ChatResult.SUCCESS, so no need to send a fail + + if (!room.getMembers().remove(avatar) && !ghost.getJoinedChannels().remove(room.getPath())) + return; + + player.sendPacket(new ChatOnLeaveRoom(avatar, ChatResult.SUCCESS.getCode(), room.getId(), sequence)); + + room.sendPacketToMembers(player.getPlayerManager(), new ChatOnLeaveRoom(avatar, ChatResult.SUCCESS.getCode(), room.getId(), 0)); + } + + public void leaveChatChannel(Player player, String path) { + for (ChatRoom chatRoom : roomMap.values()) { + if (chatRoom.getPath().equals(path)) + leaveChatChannel(player, chatRoom, 0); + } + } /** * Creates a new, non-persistent, chat room with the specified address path. * @param creator Room creator who will also become the owner of this room @@ -475,7 +499,7 @@ public class ChatService extends Service { private void createSystemChannels(String galaxy) { ChatAvatar systemAvatar = ChatAvatar.getSystemAvatar(galaxy); - + // TODO: Move these to a Server Data File? String basePath = "SWG." + galaxy + "."; createRoom(systemAvatar, true, basePath + "Galaxy", "public chat for the whole galaxy, cannot create rooms here"); createRoom(systemAvatar, true, basePath + "system", "system messages for this galaxy"); @@ -502,7 +526,7 @@ public class ChatService extends Service { private void createPlanetChannels(ChatAvatar systemAvatar, String basePath) { for (Terrain terrain : terrains) { - String path = basePath + Character.toUpperCase(terrain.getName().charAt(0)) + terrain.getName().substring(1) + "."; + String path = basePath + terrain.getNameCapitalized() + "."; createRoom(systemAvatar, true, path + "Planet", "public chat for this planet, cannot create rooms here"); createRoom(systemAvatar, true, path + "system", "system messages for this planet, cannot create rooms here"); createRoom(systemAvatar, true, path + "Chat", "public chat for this planet, can create rooms here"); @@ -526,8 +550,8 @@ public class ChatService extends Service { } public void initializeGalaxyChannels(Galaxy galaxy) { - ChatAvatar systemAvatar = new ChatAvatar(-1, "System", galaxy.getName()); createSystemChannels(galaxy.getName()); + // TODO: Load up persistent channels /** Channel Notes * Group channels: created by System * - SWG.serverName.group.GroupObjectId.GroupChat title = GroupId