diff --git a/src/network/PacketType.java b/src/network/PacketType.java index 7cb5b10ea..3a22eb5b5 100644 --- a/src/network/PacketType.java +++ b/src/network/PacketType.java @@ -107,6 +107,7 @@ public enum PacketType { // Chat CHAT_CREATE_ROOM (ChatCreateRoom.CRC, ChatCreateRoom.class), + CHAT_DESTROY_ROOM (ChatDestroyRoom.CRC, ChatDestroyRoom.class), CHAT_ON_CREATE_ROOM (ChatOnCreateRoom.CRC, ChatOnCreateRoom.class), CHAT_FRIENDS_LIST_UPDATE (ChatFriendsListUpdate.CRC, ChatFriendsListUpdate.class), CHAT_IGNORE_LIST (ChatIgnoreList.CRC, ChatIgnoreList.class), diff --git a/src/network/packets/swg/zone/chat/ChatDestroyRoom.java b/src/network/packets/swg/zone/chat/ChatDestroyRoom.java new file mode 100644 index 000000000..55d319ea0 --- /dev/null +++ b/src/network/packets/swg/zone/chat/ChatDestroyRoom.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * 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 java.nio.ByteBuffer; + +/** + * @author Waverunner + */ +public class ChatDestroyRoom extends SWGPacket { + public static final int CRC = getCrc("ChatDestroyRoom"); + + private int roomId; + private int sequence; + + public ChatDestroyRoom() {} + + @Override + public void decode(ByteBuffer data) { + if (!super.decode(data, CRC)) + return; + roomId = getInt(data); + sequence = getInt(data); + } + + @Override + public ByteBuffer encode() { + ByteBuffer bb = ByteBuffer.allocate(14); + addShort(bb, 3); + addInt(bb, CRC); + addInt(bb, roomId); + addInt(bb, sequence); + return bb; + } + + public int getRoomId() { + return roomId; + } + + public int getSequence() { + return sequence; + } + + @Override + public String toString() { + return "ChatDestroyRoom[roomId=" + roomId + ", sequence=" + sequence + "]"; + } +} diff --git a/src/resources/chat/ChatResult.java b/src/resources/chat/ChatResult.java index d689fd718..5d2464686 100644 --- a/src/resources/chat/ChatResult.java +++ b/src/resources/chat/ChatResult.java @@ -38,7 +38,7 @@ public enum ChatResult { ROOM_INVALID_NAME(6), ROOM_NOT_MODERATOR(9), ROOM_AVATAR_BANNED(12), - ROOM_AVATAR_NOT_INVITED(16), + ROOM_AVATAR_NO_PERMISSION(16), IGNORED(23), ROOM_ALREADY_EXISTS(24), ROOM_ALREADY_JOINED(36), diff --git a/src/resources/chat/ChatRoom.java b/src/resources/chat/ChatRoom.java index 897ec6961..74cccf4c4 100644 --- a/src/resources/chat/ChatRoom.java +++ b/src/resources/chat/ChatRoom.java @@ -163,7 +163,7 @@ public class ChatRoom implements Encodable, Serializable { if (isPublic() || invited.contains(avatar)) return ChatResult.SUCCESS; - return ChatResult.ROOM_AVATAR_NOT_INVITED; + return ChatResult.ROOM_AVATAR_NO_PERMISSION; } public ChatResult canSendMessage(ChatAvatar avatar) { diff --git a/src/resources/common/CRC.java b/src/resources/common/CRC.java index bef7a256f..31631849e 100644 --- a/src/resources/common/CRC.java +++ b/src/resources/common/CRC.java @@ -129,7 +129,7 @@ public class CRC { 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; - + public static int getCrc(String input) { byte [] bytes = input.getBytes(); int crc = 0xffffffff; diff --git a/src/resources/objects/player/PlayerObject.java b/src/resources/objects/player/PlayerObject.java index e24fbb0ed..e3fd1b828 100644 --- a/src/resources/objects/player/PlayerObject.java +++ b/src/resources/objects/player/PlayerObject.java @@ -395,13 +395,19 @@ public class PlayerObject extends IntangibleObject { public boolean addJoinedChannel(String path) { synchronized (joinedChannels) { - return !joinedChannels.contains(path) && joinedChannels.add(path); + return true; + // TODO: Refactor + /*System.out.println("add joined channel: " + path); + return !joinedChannels.contains(path) && joinedChannels.add(path);*/ } } public boolean removeJoinedChannel(String path) { synchronized (joinedChannels) { - return joinedChannels.remove(path); + return true; + // TODO: Refactor + /*System.out.println("remove joined channel: " + path); + return joinedChannels.remove(path);*/ } } diff --git a/src/services/chat/ChatRoomService.java b/src/services/chat/ChatRoomService.java index bb4332127..d99b9f143 100644 --- a/src/services/chat/ChatRoomService.java +++ b/src/services/chat/ChatRoomService.java @@ -27,11 +27,13 @@ package services.chat; +import intents.NotifyPlayersPacketIntent; import intents.chat.ChatRoomUpdateIntent; import intents.network.GalacticPacketIntent; import network.packets.Packet; import network.packets.swg.SWGPacket; import network.packets.swg.zone.chat.ChatCreateRoom; +import network.packets.swg.zone.chat.ChatDestroyRoom; import network.packets.swg.zone.chat.ChatEnterRoomById; import network.packets.swg.zone.chat.ChatOnCreateRoom; import network.packets.swg.zone.chat.ChatOnDestroyRoom; @@ -57,6 +59,7 @@ import services.player.PlayerManager; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -136,6 +139,9 @@ public class ChatRoomService extends Service { case CHAT_CREATE_ROOM: if (p instanceof ChatCreateRoom) handleChatCreateRoom(player, (ChatCreateRoom) p); break; + case CHAT_DESTROY_ROOM: + if (p instanceof ChatDestroyRoom) handleChatDestroyRoom(player, (ChatDestroyRoom) p); + break; default: break; } } @@ -143,12 +149,27 @@ public class ChatRoomService extends Service { private void processChatRoomUpdateIntent(ChatRoomUpdateIntent i) { switch(i.getUpdateType()) { case CREATE: createRoom(i.getAvatar(), i.isPublic(), i.getPath(), i.getTitle()); break; + case DESTROY: notifyDestroyRoom(i.getAvatar(), i.getPath(), 0); break; default: break; } } /* Chat Rooms */ + private void handleChatDestroyRoom(Player player, ChatDestroyRoom p) { + ChatRoom room = roomMap.get(p.getRoomId()); + ChatAvatar avatar = ChatAvatar.getFromPlayer(player); + + if ((room == null || !room.getCreator().equals(avatar) || !room.getOwner().equals(avatar))) { + player.sendPacket(new ChatOnDestroyRoom(ChatAvatar.getFromPlayer(player), ChatResult.ROOM_AVATAR_NO_PERMISSION.getCode(), p.getRoomId(), p.getSequence())); + return; + } + + if (!notifyDestroyRoom(avatar, room.getPath(), p.getSequence())) { + player.sendPacket(new ChatOnDestroyRoom(ChatAvatar.getFromPlayer(player), ChatResult.NONE.getCode(), p.getRoomId(), p.getSequence())); + } + } + private void handleChatCreateRoom(Player player, ChatCreateRoom p) { String path = p.getRoomName(); String title = p.getRoomTitle(); @@ -282,8 +303,8 @@ public class ChatRoomService extends Service { // Re-send the player the room list with just this room as it could have been private/hidden // This also "refreshes" the client, not sending this will cause a Chat channel unavailable message. - ChatRoomList roomList = new ChatRoomList(room); - player.sendPacket(roomList); + if (!room.isPublic()) + player.sendPacket(new ChatRoomList(room)); // Notify players of success, it's ChatResult.SUCCESS at this point player.sendPacket(new ChatOnEnteredRoom(avatar, result.getCode(), room.getId(), sequence)); @@ -382,6 +403,32 @@ public class ChatRoomService extends Service { return room; } + public boolean notifyDestroyRoom(ChatAvatar destroyer, String roomPath, int sequence) { + ChatRoom room = getRoom(roomPath); + if (roomPath == null) + return false; + + if (!destroyRoom(room)) + return false; + + // Send the ChatOnDestroyRoom packet to every else in the room besides the person destroying the packet + List networkIds = new ArrayList<>(); + room.getMembers().forEach(member -> { + if (!destroyer.equals(member)) + networkIds.add(member.getNetworkId()); + }); + + new NotifyPlayersPacketIntent(new ChatOnDestroyRoom(destroyer, ChatResult.SUCCESS.getCode(), room.getId(), 0), + networkIds).broadcast(); + + if (!destroyer.equals(ChatAvatar.getSystemAvatar(destroyer.getGalaxy()))) { + new NotifyPlayersPacketIntent(new ChatOnDestroyRoom(destroyer, ChatResult.SUCCESS.getCode(), room.getId(), sequence), + Collections.singletonList(destroyer.getNetworkId())).broadcast(); + } + + return true; + } + public boolean destroyRoom(ChatRoom room) { return room != null && roomMap.remove(room.getId()) != null; }