mirror of
https://github.com/ProjectSWGCore/Holocore.git
synced 2026-09-21 06:13:49 -04:00
Default system chat rooms are now created
Added basic joining and room info retrieval functionality for chat rooms and the ability to send messages to the room
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
|
||||
def execute(galacticManager, player, target, args):
|
||||
return
|
||||
@@ -0,0 +1,111 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
package intents.chat;
|
||||
|
||||
import resources.chat.ChatAvatar;
|
||||
import resources.control.Intent;
|
||||
|
||||
/**
|
||||
* @author Waverunner
|
||||
*/
|
||||
public class ChatRoomUpdateIntent extends Intent {
|
||||
public static final String TYPE = "ChatRoomIntent";
|
||||
|
||||
private String path;
|
||||
private String title;
|
||||
private String target;
|
||||
private ChatAvatar avatar;
|
||||
private String message;
|
||||
private UpdateType updateType;
|
||||
private boolean isPublic;
|
||||
|
||||
public ChatRoomUpdateIntent(String path, String title, String target, ChatAvatar avatar, String message, UpdateType updateType) {
|
||||
super(TYPE);
|
||||
this.path = path;
|
||||
this.updateType = updateType;
|
||||
this.avatar = avatar;
|
||||
|
||||
switch(updateType) {
|
||||
case DESTROY: break;
|
||||
case CREATE: this.title = title; break;
|
||||
case SEND_MESSAGE: this.message = message; break;
|
||||
default: this.target = target; break;
|
||||
}
|
||||
}
|
||||
|
||||
public ChatRoomUpdateIntent(ChatAvatar avatar, String path, String title, boolean isPublic) {
|
||||
this(path, title, null, avatar, null, UpdateType.CREATE);
|
||||
this.isPublic = isPublic;
|
||||
}
|
||||
|
||||
public ChatRoomUpdateIntent(ChatAvatar avatar, String path, UpdateType updateType) {
|
||||
this(path, null, null, avatar, null, updateType);
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public ChatAvatar getAvatar() {
|
||||
return avatar;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public UpdateType getUpdateType() {
|
||||
return updateType;
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
return isPublic;
|
||||
}
|
||||
|
||||
public enum UpdateType {
|
||||
CREATE,
|
||||
DESTROY,
|
||||
JOIN,
|
||||
LEAVE,
|
||||
MODERATORS_ADD_TARGET,
|
||||
MODERATORS_REMOVE_TARGET,
|
||||
BANNED_ADD_TARGET,
|
||||
BANNED_REMOVE_TARGET,
|
||||
INVITED_ADD_TARGET,
|
||||
INVITED_REMOVE_TARGET,
|
||||
SEND_MESSAGE
|
||||
}
|
||||
}
|
||||
@@ -121,9 +121,12 @@ public enum PacketType {
|
||||
CHAT_PERSISTENT_MESSAGE_TO_SERVER (0x25A29FA6, ChatPersistentMessageToServer.class),
|
||||
CHAT_DELETE_PERSISTENT_MESSAGE (0x8F251641, ChatDeletePersistentMessage.class),
|
||||
CHAT_REQUEST_PERSISTENT_MESSAGE (0x07E3559F, ChatRequestPersistentMessage.class),
|
||||
CHAT_REQUEST_ROOM_LIST (0x4C3d2CfA, ChatRequestRoomList.class),
|
||||
CHAT_ROOM_LIST (0x70DEB197, ChatRoomList.class),
|
||||
CHAT_ROOM_MESSAGE (0xCD4CE444, ChatRoomMessage.class),
|
||||
CHAT_REQUEST_ROOM_LIST (ChatRequestRoomList.CRC, ChatRequestRoomList.class),
|
||||
CHAT_ENTER_ROOM_BY_ID (ChatEnterRoomById.CRC, ChatEnterRoomById.class),
|
||||
CHAT_QUERY_ROOM (ChatQueryRoom.CRC, ChatQueryRoom.class),
|
||||
CHAT_ROOM_LIST (ChatRoomList.CRC, ChatRoomList.class),
|
||||
CHAT_ROOM_MESSAGE (ChatRoomMessage.CRC, ChatRoomMessage.class),
|
||||
CHAT_SEND_TO_ROOM (ChatSendToRoom.CRC, ChatSendToRoom.class),
|
||||
CHAT_SERVER_STATUS (0x7102B15F, ChatServerStatus.class),
|
||||
CHAT_SYSTEM_MESSAGE (0x6D2A6413, ChatSystemMessage.class),
|
||||
CON_GENERIC_MESSAGE (0x08C5FC76, ConGenericMessage.class),
|
||||
|
||||
@@ -27,10 +27,13 @@
|
||||
***********************************************************************************/
|
||||
package network.packets;
|
||||
|
||||
import resources.network.BaselineBuilder;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class Packet {
|
||||
@@ -72,7 +75,14 @@ public class Packet {
|
||||
public int getOpcode() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
|
||||
public static void addList(ByteBuffer bb, List<? extends BaselineBuilder.Encodable> list) {
|
||||
addInt(bb, list.size());
|
||||
for (BaselineBuilder.Encodable encodable : list) {
|
||||
addData(bb, encodable.encode());
|
||||
}
|
||||
}
|
||||
|
||||
public static void addBoolean(ByteBuffer bb, boolean b) {
|
||||
bb.put(b ? (byte)1 : (byte)0);
|
||||
}
|
||||
@@ -120,7 +130,11 @@ public class Packet {
|
||||
public static void addByte(ByteBuffer bb, int b) {
|
||||
bb.put((byte)b);
|
||||
}
|
||||
|
||||
|
||||
public static void addData(ByteBuffer bb, byte[] data) {
|
||||
bb.put(data);
|
||||
}
|
||||
|
||||
public static void addArray(ByteBuffer bb, byte [] b) {
|
||||
addShort(bb, b.length);
|
||||
bb.put(b);
|
||||
|
||||
@@ -32,6 +32,7 @@ import java.nio.ByteBuffer;
|
||||
import resources.Location;
|
||||
import network.PacketType;
|
||||
import network.packets.Packet;
|
||||
import resources.encodables.OutOfBandPackage;
|
||||
|
||||
|
||||
public class SWGPacket extends Packet {
|
||||
@@ -61,7 +62,7 @@ public class SWGPacket extends Packet {
|
||||
l.setZ(getFloat(data));
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
public void setSWGOpcode(int opcode) {
|
||||
this.opcode = opcode;
|
||||
this.type = PacketType.fromCrc(opcode);
|
||||
@@ -101,4 +102,10 @@ public class SWGPacket extends Packet {
|
||||
public ByteBuffer getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public static OutOfBandPackage getOutOfBand(ByteBuffer data) {
|
||||
OutOfBandPackage outOfBandPackage = new OutOfBandPackage();
|
||||
outOfBandPackage.decode(data);
|
||||
return outOfBandPackage;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
package network.packets.swg.zone.chat;
|
||||
|
||||
import network.packets.swg.SWGPacket;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* @author Waverunner
|
||||
*/
|
||||
public class ChatEnterRoomById extends SWGPacket {
|
||||
public static final int CRC = resources.common.CRC.getCrc("ChatEnterRoomById");
|
||||
|
||||
private int sequence;
|
||||
private int roomId;
|
||||
private String roomPath;
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
|
||||
sequence = getInt(data);
|
||||
roomId = getInt(data);
|
||||
roomPath = getAscii(data);
|
||||
System.out.println("ChatEnterRoomById: " + roomId + roomPath);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer encode() {
|
||||
ByteBuffer bb = ByteBuffer.allocate(10 + roomPath.length());
|
||||
addShort(bb, 4);
|
||||
addInt(bb, sequence);
|
||||
addInt(bb, roomId);
|
||||
addAscii(bb, roomPath);
|
||||
return bb;
|
||||
}
|
||||
|
||||
public int getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public int getRoomId() {
|
||||
return roomId;
|
||||
}
|
||||
|
||||
public String getRoomPath() {
|
||||
return roomPath;
|
||||
}
|
||||
}
|
||||
@@ -48,8 +48,7 @@ public class ChatOnConnectAvatar extends SWGPacket {
|
||||
}
|
||||
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
super.decode(data, CRC);
|
||||
}
|
||||
|
||||
public ByteBuffer encode() {
|
||||
|
||||
@@ -30,27 +30,22 @@ package network.packets.swg.zone.chat;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import network.packets.swg.SWGPacket;
|
||||
import resources.chat.ChatAvatar;
|
||||
|
||||
public class ChatOnDestroyRoom extends SWGPacket {
|
||||
|
||||
public static final int CRC = 0xE8EC5877;
|
||||
|
||||
private String galaxy;
|
||||
private String owner;
|
||||
private boolean success;
|
||||
|
||||
private ChatAvatar owner;
|
||||
private int result;
|
||||
private int roomId;
|
||||
private int requestId;
|
||||
|
||||
public ChatOnDestroyRoom() {
|
||||
this("", "", true, 0, 0);
|
||||
}
|
||||
|
||||
public ChatOnDestroyRoom(String galaxy, String owner, boolean success, int roomId, int requestId) {
|
||||
this.galaxy = galaxy;
|
||||
private int sequence;
|
||||
|
||||
public ChatOnDestroyRoom(ChatAvatar owner, int result, int roomId, int sequence) {
|
||||
this.owner = owner;
|
||||
this.success = success;
|
||||
this.result = result;
|
||||
this.roomId = roomId;
|
||||
this.requestId = requestId;
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
public ChatOnDestroyRoom(ByteBuffer data) {
|
||||
@@ -60,24 +55,21 @@ public class ChatOnDestroyRoom extends SWGPacket {
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
getAscii(data); // SWG
|
||||
galaxy = getAscii(data);
|
||||
owner = getAscii(data);
|
||||
success = getInt(data) == 0;
|
||||
owner = new ChatAvatar();
|
||||
owner.decode(data);
|
||||
result = getInt(data);
|
||||
roomId = getInt(data);
|
||||
requestId = getInt(data);
|
||||
sequence = getInt(data);
|
||||
}
|
||||
|
||||
public ByteBuffer encode() {
|
||||
ByteBuffer data = ByteBuffer.allocate(27 + galaxy.length() + owner.length());
|
||||
ByteBuffer data = ByteBuffer.allocate(18 + owner.encode().length);
|
||||
addShort(data, 5);
|
||||
addInt (data, CRC);
|
||||
addAscii(data, "SWG");
|
||||
addAscii(data, galaxy);
|
||||
addAscii(data, owner);
|
||||
addInt (data, success ? 0 : 1);
|
||||
data.put(owner.encode());
|
||||
addInt (data, result);
|
||||
addInt (data, roomId);
|
||||
addInt (data, requestId);
|
||||
addInt (data, sequence);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,76 +30,52 @@ package network.packets.swg.zone.chat;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import network.packets.swg.SWGPacket;
|
||||
import resources.chat.ChatAvatar;
|
||||
import resources.chat.ChatResult;
|
||||
|
||||
public class ChatOnEnteredRoom extends SWGPacket {
|
||||
|
||||
public static final int CRC = 0xE69BDC0A;
|
||||
|
||||
private String galaxy;
|
||||
private String character;
|
||||
private ChannelStatus status;
|
||||
|
||||
private ChatAvatar avatar;
|
||||
private int result;
|
||||
private int chatRoomId;
|
||||
|
||||
public ChatOnEnteredRoom() {
|
||||
this("", "", ChannelStatus.SUCCESS, 0);
|
||||
}
|
||||
|
||||
public ChatOnEnteredRoom(String galaxy, String character, ChannelStatus status, int chatRoomId) {
|
||||
this.galaxy = galaxy;
|
||||
this.character = character;
|
||||
this.status = status;
|
||||
private int sequence;
|
||||
|
||||
public ChatOnEnteredRoom(ChatAvatar avatar, int chatRoomId, int sequence) {
|
||||
this.avatar = avatar;
|
||||
this.chatRoomId = chatRoomId;
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
public ChatOnEnteredRoom(ByteBuffer data) {
|
||||
decode(data);
|
||||
}
|
||||
|
||||
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
getAscii(data);
|
||||
galaxy = getAscii(data);
|
||||
character = getAscii(data);
|
||||
status = ChannelStatus.fromInteger(getInt(data));
|
||||
avatar = new ChatAvatar();
|
||||
avatar.decode(data);
|
||||
result = getInt(data);
|
||||
chatRoomId = getInt(data);
|
||||
getInt(data);
|
||||
sequence = getInt(data);
|
||||
}
|
||||
|
||||
public ByteBuffer encode() {
|
||||
ByteBuffer data = ByteBuffer.allocate(27 + galaxy.length() + character.length());
|
||||
byte[] avatarData = avatar.encode();
|
||||
ByteBuffer data = ByteBuffer.allocate(avatarData.length + 18);
|
||||
addShort(data, 5);
|
||||
addInt (data, CRC);
|
||||
addAscii(data, "SWG");
|
||||
addAscii(data, galaxy);
|
||||
addAscii(data, character);
|
||||
addInt (data, status.getBitmask());
|
||||
data.put(avatarData);
|
||||
addInt(data, result);
|
||||
addInt (data, chatRoomId);
|
||||
addInt (data, 0);
|
||||
addInt (data, sequence);
|
||||
return data;
|
||||
}
|
||||
|
||||
public enum ChannelStatus {
|
||||
SUCCESS(0), // "You have joined the channel."
|
||||
NOT_INVITED(0x10), // "You cannot join '%TU (room name)' because you are not invted to the room."
|
||||
UNKNOWN(0x20); // "Chatroom '%TU (room name)' join failed for an unknown reason."
|
||||
|
||||
private int bitmask;
|
||||
|
||||
ChannelStatus(int bitmask) {
|
||||
this.bitmask = bitmask;
|
||||
}
|
||||
public int getBitmask() {
|
||||
return bitmask;
|
||||
}
|
||||
public static final ChannelStatus fromInteger(int i) {
|
||||
if (i == 0)
|
||||
return SUCCESS;
|
||||
if (i == 0x10)
|
||||
return NOT_INVITED;
|
||||
return UNKNOWN;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public void setResult(int result) {
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,27 +30,22 @@ package network.packets.swg.zone.chat;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import network.packets.swg.SWGPacket;
|
||||
import resources.chat.ChatAvatar;
|
||||
|
||||
public class ChatOnLeaveRoom extends SWGPacket {
|
||||
|
||||
public static final int CRC = 0x60B5098B;
|
||||
|
||||
private String galaxyName;
|
||||
private String characterName;
|
||||
private int errorCode;
|
||||
private ChatAvatar avatar;
|
||||
private int result;
|
||||
private int chatRoomId;
|
||||
private int requestId;
|
||||
|
||||
public ChatOnLeaveRoom() {
|
||||
this("", "", 0, 0, 0);
|
||||
}
|
||||
|
||||
public ChatOnLeaveRoom(String galaxy, String character, int errorCode, int chatRoomId, int requestId) {
|
||||
this.galaxyName = galaxy;
|
||||
this.characterName = character;
|
||||
this.errorCode = errorCode;
|
||||
private int sequence;
|
||||
|
||||
public ChatOnLeaveRoom(ChatAvatar avatar, int errorCode, int chatRoomId, int sequence) {
|
||||
this.avatar = avatar;
|
||||
this.result = errorCode;
|
||||
this.chatRoomId = chatRoomId;
|
||||
this.requestId = requestId;
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
public ChatOnLeaveRoom(ByteBuffer data) {
|
||||
@@ -60,24 +55,21 @@ public class ChatOnLeaveRoom extends SWGPacket {
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
getAscii(data);
|
||||
galaxyName = getAscii(data);
|
||||
characterName = getAscii(data);
|
||||
errorCode = getInt(data);
|
||||
avatar = new ChatAvatar();
|
||||
avatar.decode(data);
|
||||
result = getInt(data);
|
||||
chatRoomId = getInt(data);
|
||||
requestId = getInt(data);
|
||||
sequence = getInt(data);
|
||||
}
|
||||
|
||||
public ByteBuffer encode() {
|
||||
ByteBuffer data = ByteBuffer.allocate(27+galaxyName.length()+characterName.length());
|
||||
ByteBuffer data = ByteBuffer.allocate(18 + avatar.encode().length);
|
||||
addShort(data, 2);
|
||||
addInt( data, CRC);
|
||||
addAscii(data, "SWG");
|
||||
addAscii(data, galaxyName);
|
||||
addAscii(data, characterName);
|
||||
addInt (data, errorCode);
|
||||
data.put(avatar.encode());
|
||||
addInt(data, result);
|
||||
addInt (data, chatRoomId);
|
||||
addInt (data, requestId);
|
||||
addInt (data, sequence);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,21 +35,14 @@ public class ChatOnReceiveRoomInvitation extends SWGPacket {
|
||||
|
||||
public static final int CRC = 0xC17EB06D;
|
||||
|
||||
public ChatOnReceiveRoomInvitation() {
|
||||
|
||||
}
|
||||
|
||||
public ChatOnReceiveRoomInvitation(String command) {
|
||||
|
||||
}
|
||||
|
||||
public ChatOnReceiveRoomInvitation() {}
|
||||
|
||||
public ChatOnReceiveRoomInvitation(ByteBuffer data) {
|
||||
decode(data);
|
||||
}
|
||||
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
super.decode(data, CRC);
|
||||
}
|
||||
|
||||
public ByteBuffer encode() {
|
||||
|
||||
@@ -28,10 +28,9 @@
|
||||
package network.packets.swg.zone.chat;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import network.packets.swg.SWGPacket;
|
||||
import services.chat.ChatResult;
|
||||
import resources.chat.ChatResult;
|
||||
|
||||
public class ChatOnSendPersistentMessage extends SWGPacket {
|
||||
public static final int CRC = 0x94E7A7AE;
|
||||
|
||||
@@ -32,34 +32,29 @@ import java.nio.ByteBuffer;
|
||||
import network.packets.swg.SWGPacket;
|
||||
|
||||
public class ChatOnSendRoomMessage extends SWGPacket {
|
||||
|
||||
public static final int CRC = 0xE7B61633;
|
||||
private int error = 0;
|
||||
private int messageId = 0;
|
||||
|
||||
public ChatOnSendRoomMessage() {
|
||||
|
||||
}
|
||||
|
||||
public ChatOnSendRoomMessage(int error, int messageId) {
|
||||
this.error = error;
|
||||
this.messageId = messageId;
|
||||
public static final int CRC = resources.common.CRC.getCrc("ChatOnSendRoomMessage");
|
||||
|
||||
private int result = 0;
|
||||
private int sequence = 0;
|
||||
|
||||
public ChatOnSendRoomMessage(int result, int sequence) {
|
||||
this.result = result;
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
error = getInt(data);
|
||||
messageId = getInt(data);
|
||||
result = getInt(data);
|
||||
sequence = getInt(data);
|
||||
}
|
||||
|
||||
public ByteBuffer encode() {
|
||||
int length = 14;
|
||||
ByteBuffer data = ByteBuffer.allocate(length);
|
||||
ByteBuffer data = ByteBuffer.allocate(14);
|
||||
addShort(data, 3);
|
||||
addInt( data, CRC);
|
||||
addInt( data, error);
|
||||
addInt( data, messageId);
|
||||
addInt( data, result);
|
||||
addInt( data, sequence);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
package network.packets.swg.zone.chat;
|
||||
|
||||
import network.packets.swg.SWGPacket;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* @author Waverunner
|
||||
*/
|
||||
public class ChatQueryRoom extends SWGPacket {
|
||||
public static final int CRC = resources.common.CRC.getCrc("ChatQueryRoom");
|
||||
|
||||
private int sequence;
|
||||
private String roomPath;
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
sequence = getInt(data);
|
||||
roomPath = getAscii(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer encode() {
|
||||
ByteBuffer bb = ByteBuffer.allocate(12 + roomPath.length());
|
||||
addShort(bb, 3);
|
||||
addInt(bb, CRC);
|
||||
addInt(bb, sequence);
|
||||
addAscii(bb, roomPath);
|
||||
return bb;
|
||||
}
|
||||
|
||||
public int getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public String getRoomPath() {
|
||||
return roomPath;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
package network.packets.swg.zone.chat;
|
||||
|
||||
import network.packets.swg.SWGPacket;
|
||||
import resources.chat.ChatAvatar;
|
||||
import resources.chat.ChatRoom;
|
||||
import resources.network.BaselineBuilder;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Waverunner
|
||||
*/
|
||||
public class ChatQueryRoomResults extends SWGPacket {
|
||||
public static final int CRC = resources.common.CRC.getCrc("ChatQueryRoomResults");
|
||||
|
||||
private ChatRoom room;
|
||||
private int sequence;
|
||||
|
||||
public ChatQueryRoomResults(ChatRoom room, int sequence) {
|
||||
this.room = room;
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {
|
||||
super.decode(data, CRC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer encode() {
|
||||
byte[] data = room.encode();
|
||||
int size = data.length;
|
||||
|
||||
List<ChatAvatar> members = room.getMembers();
|
||||
List<ChatAvatar> invited = room.getInvited();
|
||||
List<ChatAvatar> moderators = room.getModerators();
|
||||
List<ChatAvatar> banned = room.getBanned();
|
||||
|
||||
for (ChatAvatar avatar : members) { size += avatar.getSize(); }
|
||||
for (ChatAvatar avatar : invited) { size += avatar.getSize(); }
|
||||
for (ChatAvatar avatar : moderators) { size += avatar.getSize(); }
|
||||
for (ChatAvatar avatar : banned) { size += avatar.getSize(); }
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(20 + size);
|
||||
addList(bb, members);
|
||||
addList(bb, invited);
|
||||
addList(bb, moderators);
|
||||
addList(bb, banned);
|
||||
addInt(bb, sequence);
|
||||
addData(bb, data);
|
||||
|
||||
return bb;
|
||||
}
|
||||
}
|
||||
+3
-6
@@ -25,7 +25,7 @@
|
||||
* along with Holocore. If not, see <http://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
***********************************************************************************/
|
||||
package network.packets.swg.zone;
|
||||
package network.packets.swg.zone.chat;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -35,13 +35,10 @@ public class ChatRequestRoomList extends SWGPacket {
|
||||
|
||||
public static final int CRC = 0x4C3D2CFA;
|
||||
|
||||
public ChatRequestRoomList() {
|
||||
|
||||
}
|
||||
public ChatRequestRoomList() {}
|
||||
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
super.decode(data, CRC);
|
||||
}
|
||||
|
||||
public ByteBuffer encode() {
|
||||
@@ -30,49 +30,43 @@ package network.packets.swg.zone.chat;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import network.packets.swg.SWGPacket;
|
||||
import network.packets.swg.zone.insertion.ChatRoomList.ChatRoom.User;
|
||||
import resources.chat.ChatAvatar;
|
||||
import resources.encodables.OutOfBandPackage;
|
||||
|
||||
public class ChatRoomMessage extends SWGPacket {
|
||||
|
||||
public static final int CRC = 0xCD4CE444;
|
||||
private User user = new User();
|
||||
public static final int CRC = resources.common.CRC.getCrc("ChatRoomMessage");
|
||||
|
||||
private ChatAvatar avatar;
|
||||
private int roomId = 0;
|
||||
private String message = "";
|
||||
|
||||
public ChatRoomMessage() {
|
||||
|
||||
}
|
||||
|
||||
public ChatRoomMessage(String game, String server, String name, int roomId, String message) {
|
||||
this.user.game = game;
|
||||
this.user.server = server;
|
||||
this.user.name = name;
|
||||
private OutOfBandPackage outOfBandPackage;
|
||||
|
||||
public ChatRoomMessage(ChatAvatar avatar, int roomId, String message, OutOfBandPackage oob) {
|
||||
this.avatar = avatar;
|
||||
this.roomId = roomId;
|
||||
this.message = message;
|
||||
this.outOfBandPackage = oob;
|
||||
}
|
||||
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
user.game = getAscii(data);
|
||||
user.server = getAscii(data);
|
||||
user.name = getAscii(data);
|
||||
avatar.decode(data);
|
||||
roomId = getInt(data);
|
||||
message = getUnicode(data);
|
||||
getUnicode(data);
|
||||
outOfBandPackage.decode(data);
|
||||
}
|
||||
|
||||
public ByteBuffer encode() {
|
||||
int length = 24 + user.game.length() + user.server.length() + user.name.length() + message.length() * 2;
|
||||
byte[] oob = outOfBandPackage.encode();
|
||||
int length = 14 + avatar.encode().length + oob.length + message.length() * 2;
|
||||
ByteBuffer data = ByteBuffer.allocate(length);
|
||||
addShort( data, 5);
|
||||
addInt( data, CRC);
|
||||
addAscii( data, user.game);
|
||||
addAscii( data, user.server);
|
||||
addAscii( data, user.name);
|
||||
data.put(avatar.encode());
|
||||
addInt( data, roomId);
|
||||
addUnicode(data, message);
|
||||
addUnicode(data, "");
|
||||
data.put(outOfBandPackage.encode());
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
package network.packets.swg.zone.chat;
|
||||
|
||||
import network.packets.swg.SWGPacket;
|
||||
import resources.encodables.OutOfBandPackage;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* @author Waverunner
|
||||
*/
|
||||
public class ChatSendToRoom extends SWGPacket {
|
||||
public static final int CRC = resources.common.CRC.getCrc("ChatSendToRoom");
|
||||
|
||||
private String message;
|
||||
private OutOfBandPackage outOfBandPackage;
|
||||
private int roomId;
|
||||
private int sequence; // This seems to vary from room to room, client keeps track individually for each room?
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
|
||||
message = getUnicode(data);
|
||||
outOfBandPackage = getOutOfBand(data);
|
||||
roomId = getInt(data);
|
||||
sequence = getInt(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer encode() {
|
||||
return super.encode();
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public OutOfBandPackage getOutOfBandPackage() {
|
||||
return outOfBandPackage;
|
||||
}
|
||||
|
||||
public int getRoomId() {
|
||||
return roomId;
|
||||
}
|
||||
|
||||
public int getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
}
|
||||
@@ -28,209 +28,47 @@
|
||||
package network.packets.swg.zone.insertion;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import network.packets.swg.SWGPacket;
|
||||
import network.packets.swg.zone.insertion.ChatRoomList.ChatRoom.User;
|
||||
import resources.chat.ChatRoom;
|
||||
|
||||
public class ChatRoomList extends SWGPacket {
|
||||
|
||||
public static final int CRC = 0x70DEB197;
|
||||
private List <ChatRoom> chatrooms = new ArrayList<ChatRoom>();
|
||||
|
||||
public ChatRoomList() {
|
||||
|
||||
public static final int CRC = resources.common.CRC.getCrc("ChatRoomList");
|
||||
|
||||
private Collection<ChatRoom> rooms;
|
||||
|
||||
public ChatRoomList(ChatRoom ... rooms) {
|
||||
this.rooms = Arrays.asList(rooms);
|
||||
}
|
||||
|
||||
public ChatRoomList(ChatRoom room) {
|
||||
chatrooms.add(room);
|
||||
|
||||
public ChatRoomList(Collection<ChatRoom> rooms) {
|
||||
this.rooms = rooms;
|
||||
}
|
||||
|
||||
public ChatRoomList(ChatRoom [] rooms) {
|
||||
for (ChatRoom r : rooms) {
|
||||
chatrooms.add(r);
|
||||
}
|
||||
}
|
||||
|
||||
public void addChatRoom(ChatRoom r) {
|
||||
chatrooms.add(r);
|
||||
}
|
||||
|
||||
|
||||
public void decode(ByteBuffer data) {
|
||||
if (!super.decode(data, CRC))
|
||||
return;
|
||||
int chatroomCount = getInt(data);
|
||||
for (int i = 0; i < chatroomCount; i++) {
|
||||
ChatRoom room = new ChatRoom();
|
||||
room.setRoomId(getInt(data));
|
||||
room.setPrivateFlag(getInt(data));
|
||||
room.setModeratedFlag(getByte(data));
|
||||
room.setRoomPathName(getAscii(data));
|
||||
room.setGame(getAscii(data));
|
||||
room.setServer(getAscii(data));
|
||||
room.setOwner(getAscii(data));
|
||||
getAscii(data); // SWG
|
||||
getAscii(data); // galaxy
|
||||
room.setCreator(getAscii(data));
|
||||
room.setTitle(getUnicode(data));
|
||||
int moderatorCount = getInt(data);
|
||||
for (int m = 0; m < moderatorCount; m++) {
|
||||
User user = new User();
|
||||
user.setGame(getAscii(data));
|
||||
user.setServer(getAscii(data));
|
||||
user.setName(getAscii(data));
|
||||
room.addModerator(user);
|
||||
}
|
||||
int userCount = getInt(data);
|
||||
for (int u = 0; u < userCount; u++) {
|
||||
User user = new User();
|
||||
user.setGame(getAscii(data));
|
||||
user.setServer(getAscii(data));
|
||||
user.setName(getAscii(data));
|
||||
room.addUser(user);
|
||||
}
|
||||
room.decode(data);
|
||||
}
|
||||
}
|
||||
|
||||
public ByteBuffer encode() {
|
||||
int length = 10;
|
||||
for (ChatRoom r : chatrooms) {
|
||||
length += r.getSize();
|
||||
for (ChatRoom r : rooms) {
|
||||
length += r.encode().length;
|
||||
}
|
||||
ByteBuffer data = ByteBuffer.allocate(length);
|
||||
addShort(data, 2);
|
||||
addInt( data, CRC);
|
||||
addInt( data, chatrooms.size());
|
||||
for (ChatRoom r : chatrooms) {
|
||||
addInt(data, r.getRoomId());
|
||||
addInt(data, r.getPrivateFlag());
|
||||
addByte(data, r.getModeratedFlag());
|
||||
addAscii(data, r.getRoomPathName());
|
||||
addAscii(data, r.getGame());
|
||||
addAscii(data, r.getServer());
|
||||
addAscii(data, r.getOwner());
|
||||
addAscii(data, r.getCreator());
|
||||
addUnicode(data, r.getTitle());
|
||||
addInt(data, r.getModerators().size());
|
||||
for (User u : r.getModerators()) {
|
||||
addAscii(data, u.game);
|
||||
addAscii(data, u.server);
|
||||
addAscii(data, u.name);
|
||||
}
|
||||
addInt(data, r.getUsers().size());
|
||||
for (User u : r.getUsers()) {
|
||||
addAscii(data, u.game);
|
||||
addAscii(data, u.server);
|
||||
addAscii(data, u.name);
|
||||
}
|
||||
addInt(data, rooms.size());
|
||||
for (ChatRoom room : rooms) {
|
||||
data.put(room.encode());
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
public static class ChatRoom {
|
||||
private int roomId = 0;
|
||||
private int privateFlag = 0;
|
||||
private int moderatedFlag = 0;
|
||||
private String roomPathName = "";
|
||||
private String game = "";
|
||||
private String server = "";
|
||||
private String owner = "";
|
||||
private String creator = "";
|
||||
private String title = "";
|
||||
private Vector <User> moderators = new Vector<User>();
|
||||
private Vector <User> users = new Vector<User>();
|
||||
|
||||
public ChatRoom() {
|
||||
|
||||
}
|
||||
|
||||
public ChatRoom(int roomId, int privateFlag, int moderatedFlag, String roomPathName, String game, String server, String owner, String creator, String title) {
|
||||
this.roomId = roomId;
|
||||
this.privateFlag = privateFlag;
|
||||
this.moderatedFlag = moderatedFlag;
|
||||
this.roomPathName = roomPathName;
|
||||
this.game = game;
|
||||
this.server = server;
|
||||
this.owner = owner;
|
||||
this.creator = creator;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public void addModerator(String game, String server, String name) {
|
||||
moderators.add(new User(game, server, name));
|
||||
}
|
||||
|
||||
public void addUser(String game, String server, String name) {
|
||||
users.add(new User(game, server, name));
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
int length = 31;
|
||||
length += roomPathName.length();
|
||||
length += game.length();
|
||||
length += server.length();
|
||||
length += owner.length();
|
||||
length += creator.length();
|
||||
length += title.length() * 2;
|
||||
for (User u : moderators) length += u.getSize();
|
||||
for (User u : users) length += u.getSize();
|
||||
return length;
|
||||
}
|
||||
|
||||
public int getRoomId() { return roomId; }
|
||||
public int getPrivateFlag() { return privateFlag; }
|
||||
public int getModeratedFlag() { return moderatedFlag; }
|
||||
public String getRoomPathName() { return roomPathName; }
|
||||
public String getGame() { return game; }
|
||||
public String getServer() { return server; }
|
||||
public String getOwner() { return owner; }
|
||||
public String getCreator() { return creator; }
|
||||
public String getTitle() { return title; }
|
||||
public List <User> getUsers() { return users; }
|
||||
public List <User> getModerators() { return moderators; }
|
||||
|
||||
public void setRoomId(int id) { this.roomId = id; }
|
||||
public void setPrivateFlag(int flag) { this.privateFlag = flag; }
|
||||
public void setModeratedFlag(int flag) { this.moderatedFlag = flag; }
|
||||
public void setRoomPathName(String path) { this.roomPathName = path; }
|
||||
public void setGame(String game) { this.game = game; }
|
||||
public void setServer(String server) { this.server = server; }
|
||||
public void setOwner(String owner) { this.owner = owner; }
|
||||
public void setCreator(String creator) { this.creator = creator; }
|
||||
public void setTitle(String title) { this.title = title; }
|
||||
public void setUsers(Vector<User> users) { this.users = users; }
|
||||
public void setModerators(Vector<User> moderators) { this.moderators = moderators; }
|
||||
public void addUser(User user) { this.users.add(user); }
|
||||
public void addModerator(User moderator) { this.moderators.add(moderator); }
|
||||
|
||||
public static class User {
|
||||
public String game = "";
|
||||
public String server = "";
|
||||
public String name = "";
|
||||
|
||||
public User() {
|
||||
|
||||
}
|
||||
|
||||
public User(String game, String server, String name) {
|
||||
this.game = game;
|
||||
this.server = server;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return 6 + game.length() + server.length() + name.length();
|
||||
}
|
||||
|
||||
public String getGame() { return game; }
|
||||
public String getServer() { return server; }
|
||||
public String getName() { return name; }
|
||||
|
||||
public void setGame(String game) { this.game = game; }
|
||||
public void setServer(String server) { this.server = server; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
package resources.chat;
|
||||
|
||||
import network.packets.Packet;
|
||||
import resources.network.BaselineBuilder;
|
||||
import resources.objects.creature.CreatureObject;
|
||||
import resources.player.Player;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* @author Waverunner
|
||||
*/
|
||||
public class ChatAvatar implements BaselineBuilder.Encodable, BaselineBuilder.Decodable {
|
||||
private long networkId;
|
||||
private String name;
|
||||
private String game = "SWG";
|
||||
private String galaxy;
|
||||
|
||||
// Instances of the class will hardly ever change, so we can just pre-build the data.
|
||||
private transient byte[] data;
|
||||
private transient boolean modified;
|
||||
private transient int size = 0;
|
||||
|
||||
public ChatAvatar() {
|
||||
modified = true;
|
||||
}
|
||||
|
||||
public ChatAvatar(long networkId, String name, String galaxy) {
|
||||
this();
|
||||
this.networkId = networkId;
|
||||
this.name = name;
|
||||
this.galaxy = galaxy;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
public String getGame() {
|
||||
return game;
|
||||
}
|
||||
|
||||
public void setGame(String game) {
|
||||
this.game = game;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
public String getGalaxy() {
|
||||
return galaxy;
|
||||
}
|
||||
|
||||
public void setGalaxy(String galaxy) {
|
||||
this.galaxy = galaxy;
|
||||
modified = true;
|
||||
}
|
||||
|
||||
public long getNetworkId() {
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
if (size == 0)
|
||||
size = 6 + game.length() + name.length() + galaxy.length();
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] encode() {
|
||||
if (!modified && data != null)
|
||||
return data;
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocate(getSize());
|
||||
Packet.addAscii(buffer, game);
|
||||
Packet.addAscii(buffer, galaxy);
|
||||
Packet.addAscii(buffer, name);
|
||||
|
||||
data = buffer.array();
|
||||
modified = false;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChatAvatar:" + getNetworkId() + "[" + getGame() + "." + getGalaxy() + "." + getName() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null) return false;
|
||||
|
||||
if (getClass() != o.getClass())
|
||||
return false;
|
||||
|
||||
return ((ChatAvatar) o).getNetworkId() == networkId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) (networkId ^ (networkId >>> 32));
|
||||
}
|
||||
|
||||
public static ChatAvatar getFromPlayer(Player player) {
|
||||
return new ChatAvatar(player.getNetworkId(), player.getCharacterName().split(" ")[0].toLowerCase(), player.getGalaxyName());
|
||||
}
|
||||
|
||||
public static ChatAvatar getSystemAvatar(String galaxy) {
|
||||
return new ChatAvatar(-1, "system", galaxy);
|
||||
}
|
||||
}
|
||||
@@ -25,16 +25,25 @@
|
||||
* along with Holocore. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
package services.chat;
|
||||
package resources.chat;
|
||||
|
||||
/**
|
||||
* @author Waverunner
|
||||
*/
|
||||
public enum ChatResult {
|
||||
NONE(-1),
|
||||
NONE(-1), // The client will just display an "unknown error code" if this is used.
|
||||
SUCCESS(0),
|
||||
TARGET_AVATAR_DOESNT_EXIST(4),
|
||||
IGNORED(23);
|
||||
ROOM_INVALID_ID(5),
|
||||
ROOM_INVALID_NAME(6),
|
||||
ROOM_NOT_MODERATOR(9),
|
||||
ROOM_AVATAR_BANNED(12),
|
||||
ROOM_AVATAR_NOT_INVITED(16),
|
||||
IGNORED(23),
|
||||
ROOM_ALREADY_JOINED(36),
|
||||
CHAT_SERVER_UNAVAILABLE(1000000),
|
||||
ROOM_DIFFERENT_FACTION(1000001),
|
||||
ROOM_NOT_GCW_DEFENDER_FACTION(1000005);
|
||||
|
||||
|
||||
private final int code;
|
||||
@@ -45,4 +54,12 @@ public enum ChatResult {
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public static ChatResult fromInteger(int code) {
|
||||
for (ChatResult result : ChatResult.values()) {
|
||||
if (code == result.getCode())
|
||||
return result;
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
/*******************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
|
||||
package resources.chat;
|
||||
|
||||
import network.packets.Packet;
|
||||
import network.packets.swg.zone.chat.ChatRoomMessage;
|
||||
import resources.encodables.OutOfBandPackage;
|
||||
import resources.network.BaselineBuilder;
|
||||
import resources.player.Player;
|
||||
import services.player.PlayerManager;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Waverunner
|
||||
*/
|
||||
public class ChatRoom implements Serializable, BaselineBuilder.Encodable, BaselineBuilder.Decodable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int id;
|
||||
private int type;
|
||||
private String path;
|
||||
private ChatAvatar owner;
|
||||
private ChatAvatar creator;
|
||||
private String title;
|
||||
private List<ChatAvatar> moderators;
|
||||
private List<ChatAvatar> invited;
|
||||
private boolean muted; // No one but moderators can talk
|
||||
private boolean isPublic;
|
||||
private List<ChatAvatar> banned;
|
||||
// Members are only actually apart of a room when they're "in the room", so we don't need to save this info
|
||||
// as each player will automatically re-join the room based on their joined channels list
|
||||
private transient List<ChatAvatar> members;
|
||||
|
||||
// Large amount of data that's sent frequently, best if we can pre-encode everything and save it for later
|
||||
private transient boolean modified = true;
|
||||
private transient byte[] data;
|
||||
|
||||
public ChatRoom() {
|
||||
moderators = new ArrayList<>();
|
||||
invited = new ArrayList<>();
|
||||
members = new ArrayList<>();
|
||||
banned = new ArrayList<>();
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(int type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public ChatAvatar getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(ChatAvatar owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public ChatAvatar getCreator() {
|
||||
return creator;
|
||||
}
|
||||
|
||||
public void setCreator(ChatAvatar creator) {
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public List<ChatAvatar> getModerators() {
|
||||
return moderators;
|
||||
}
|
||||
|
||||
public List<ChatAvatar> getInvited() {
|
||||
return invited;
|
||||
}
|
||||
|
||||
public boolean isMuted() {
|
||||
return muted;
|
||||
}
|
||||
|
||||
public void setMuted(boolean muted) {
|
||||
this.muted = muted;
|
||||
}
|
||||
|
||||
public List<ChatAvatar> getMembers() {
|
||||
return members;
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
return isPublic;
|
||||
}
|
||||
|
||||
public void setIsPublic(boolean isPublic) {
|
||||
this.isPublic = isPublic;
|
||||
}
|
||||
|
||||
public List<ChatAvatar> getBanned() {
|
||||
return banned;
|
||||
}
|
||||
|
||||
public ChatResult canJoinRoom(ChatAvatar avatar) {
|
||||
if (banned.contains(avatar))
|
||||
return ChatResult.ROOM_AVATAR_BANNED;
|
||||
|
||||
if (members.contains(avatar))
|
||||
return ChatResult.ROOM_ALREADY_JOINED;
|
||||
|
||||
if (isPublic || invited.contains(avatar))
|
||||
return ChatResult.SUCCESS;
|
||||
|
||||
return ChatResult.ROOM_AVATAR_NOT_INVITED;
|
||||
}
|
||||
|
||||
public ChatResult canSendMessage(ChatAvatar avatar) {
|
||||
if (banned.contains(avatar))
|
||||
return ChatResult.ROOM_AVATAR_BANNED;
|
||||
|
||||
if (muted && !moderators.contains(avatar))
|
||||
return ChatResult.ROOM_NOT_MODERATOR;
|
||||
|
||||
return ChatResult.SUCCESS;
|
||||
}
|
||||
|
||||
public void sendMessage(ChatAvatar sender, String message, OutOfBandPackage oob, PlayerManager playerManager) {
|
||||
ChatRoomMessage chatRoomMessage = new ChatRoomMessage(sender, getId(), message, oob);
|
||||
|
||||
for (ChatAvatar avatar : members) {
|
||||
Player player = playerManager.getPlayerFromNetworkId(avatar.getNetworkId());
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
player.sendPacket(chatRoomMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(ByteBuffer data) {}
|
||||
|
||||
@Override
|
||||
public byte[] encode() {
|
||||
if (!modified && data != null)
|
||||
return data;
|
||||
|
||||
int avatarIdSize = 0; // The encode method for ChatAvatar saves the encode result if the class was modified/null data
|
||||
for (ChatAvatar moderator : moderators) {
|
||||
avatarIdSize += moderator.encode().length;
|
||||
}
|
||||
|
||||
for (ChatAvatar invitee : invited) {
|
||||
avatarIdSize += invitee.encode().length;
|
||||
}
|
||||
avatarIdSize += owner.encode().length + creator.encode().length;
|
||||
|
||||
ByteBuffer bb = ByteBuffer.allocate(23 + path.length() + (title.length() * 2) + avatarIdSize).order(ByteOrder.LITTLE_ENDIAN);
|
||||
bb.putInt(id);
|
||||
bb.putInt(type);
|
||||
bb.put(muted ? (byte) 1 : (byte) 0);
|
||||
Packet.addAscii(bb, path);
|
||||
bb.put(owner.encode());
|
||||
bb.put(creator.encode());
|
||||
Packet.addUnicode(bb, title);
|
||||
bb.putInt(moderators.size());
|
||||
for (ChatAvatar moderator : moderators) {
|
||||
bb.put(moderator.encode());
|
||||
}
|
||||
bb.putInt(invited.size());
|
||||
for (ChatAvatar invitee : invited) {
|
||||
bb.put(invitee.encode());
|
||||
}
|
||||
|
||||
data = bb.array();
|
||||
modified = false;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ChatRoom{" +
|
||||
"id=" + id +
|
||||
", path='" + path + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -162,7 +162,7 @@ public class WaypointCmdCallback implements ICmdCallback {
|
||||
}
|
||||
}
|
||||
|
||||
if (name == null)
|
||||
if (name == null || name.isEmpty())
|
||||
name = "Waypoint";
|
||||
|
||||
WaypointObject waypoint = createWaypoint(galacticManager.getObjectManager(), color, name, location);
|
||||
|
||||
@@ -165,5 +165,8 @@ public class BaselineBuilder {
|
||||
public interface Encodable extends Serializable {
|
||||
byte [] encode();
|
||||
}
|
||||
|
||||
|
||||
public interface Decodable {
|
||||
void decode(ByteBuffer data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,13 +44,16 @@ import resources.player.PlayerFlags;
|
||||
import utilities.MathUtils;
|
||||
import utilities.Encoder.StringType;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class PlayerObject extends IntangibleObject {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String biography = "";
|
||||
private String biography = "";
|
||||
private List<Integer> joinedChannels = new LinkedList<>();
|
||||
|
||||
// PLAY 03
|
||||
private SWGBitSet flagsList = new SWGBitSet(BaselineType.PLAY, 3, 5);
|
||||
private SWGBitSet profileFlags = new SWGBitSet(BaselineType.PLAY, 3, 6);
|
||||
@@ -384,7 +387,11 @@ public class PlayerObject extends IntangibleObject {
|
||||
flagsList.flip(flag.getFlag());
|
||||
flagsList.sendDeltaMessage(this);
|
||||
}
|
||||
|
||||
|
||||
public List<Integer> getJoinedChannels() {
|
||||
return joinedChannels;
|
||||
}
|
||||
|
||||
private int getProfessionIcon() {
|
||||
switch (profession) {
|
||||
case "entertainer_1a":
|
||||
|
||||
@@ -31,6 +31,7 @@ import intents.NotifyPlayersPacketIntent;
|
||||
import intents.PlayerEventIntent;
|
||||
import intents.chat.ChatAvatarRequestIntent;
|
||||
import intents.chat.ChatBroadcastIntent;
|
||||
import intents.chat.ChatRoomUpdateIntent;
|
||||
import intents.chat.PersistentMessageIntent;
|
||||
import intents.chat.SpatialChatIntent;
|
||||
import intents.network.GalacticPacketIntent;
|
||||
@@ -38,23 +39,34 @@ import intents.player.ZonePlayerSwapIntent;
|
||||
import intents.server.ServerStatusIntent;
|
||||
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.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.ChatSystemMessage.SystemChatType;
|
||||
import network.packets.swg.zone.insertion.ChatRoomList;
|
||||
import network.packets.swg.zone.object_controller.SpatialChat;
|
||||
import resources.Galaxy;
|
||||
import resources.Terrain;
|
||||
import resources.chat.ChatAvatar;
|
||||
import resources.chat.ChatResult;
|
||||
import resources.chat.ChatRoom;
|
||||
import resources.collections.SWGList;
|
||||
import resources.control.Intent;
|
||||
import resources.control.Service;
|
||||
@@ -63,6 +75,7 @@ import resources.encodables.ProsePackage;
|
||||
import resources.encodables.player.Mail;
|
||||
import resources.objects.SWGObject;
|
||||
import resources.objects.player.PlayerObject;
|
||||
import resources.player.AccessLevel;
|
||||
import resources.player.Player;
|
||||
import resources.player.PlayerState;
|
||||
import resources.server_info.CachedObjectDatabase;
|
||||
@@ -71,18 +84,33 @@ import resources.server_info.ObjectDatabase.Traverser;
|
||||
import services.player.PlayerManager;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
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[] {
|
||||
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<Mail> mails;
|
||||
private int maxMailId;
|
||||
|
||||
private int maxChatRoomId;
|
||||
private Map<Integer, ChatRoom> roomMap;
|
||||
// Map to keep track of each player's recent message for a room to prevent duplicates from client
|
||||
private Map<Long, Map<Integer, Integer>> messages;
|
||||
|
||||
public ChatService() {
|
||||
roomMap = new HashMap<>();
|
||||
mails = new CachedObjectDatabase<>("odb/mails.db");
|
||||
maxMailId = 1;
|
||||
maxChatRoomId = 1;
|
||||
messages = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -95,6 +123,7 @@ public class ChatService extends Service {
|
||||
registerForIntent(ServerStatusIntent.TYPE);
|
||||
registerForIntent(ChatAvatarRequestIntent.TYPE);
|
||||
registerForIntent(ZonePlayerSwapIntent.TYPE);
|
||||
registerForIntent(ChatRoomUpdateIntent.TYPE);
|
||||
mails.load();
|
||||
mails.traverse(new Traverser<Mail>() {
|
||||
@Override
|
||||
@@ -138,6 +167,17 @@ public class ChatService extends Service {
|
||||
if (i instanceof ChatAvatarRequestIntent)
|
||||
handleChatAvatarStatusRequestIntent((ChatAvatarRequestIntent) i);
|
||||
break;
|
||||
case ChatRoomUpdateIntent.TYPE:
|
||||
if (i instanceof ChatRoomUpdateIntent)
|
||||
handleChatRoomUpdateIntent((ChatRoomUpdateIntent) i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void handleChatRoomUpdateIntent(ChatRoomUpdateIntent i) {
|
||||
switch(i.getUpdateType()) {
|
||||
case CREATE: createRoom(i.getAvatar(), i.isPublic(), i.getPath(), i.getTitle());
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +185,7 @@ public class ChatService extends Service {
|
||||
Player player = intent.getPlayerManager().getPlayerFromNetworkId(intent.getNetworkId());
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
Packet p = intent.getPacket();
|
||||
if (p instanceof SWGPacket)
|
||||
processSwgPacket(intent.getPlayerManager(), player, intent.getGalaxy().getName(), (SWGPacket) p);
|
||||
@@ -152,9 +193,23 @@ public class ChatService extends Service {
|
||||
|
||||
private void processSwgPacket(PlayerManager pm, Player player, String galaxyName, SWGPacket p) {
|
||||
switch (p.getPacketType()) {
|
||||
case CHAT_QUERY_ROOM:
|
||||
if (p instanceof ChatQueryRoom)
|
||||
handleChatQueryRoom(player, (ChatQueryRoom) p);
|
||||
break;
|
||||
case CHAT_ENTER_ROOM_BY_ID:
|
||||
if (p instanceof ChatEnterRoomById) {
|
||||
ChatEnterRoomById enterRoomById = (ChatEnterRoomById) p;
|
||||
enterChatChannel(player, enterRoomById.getRoomId(), enterRoomById.getSequence());
|
||||
}
|
||||
break;
|
||||
case CHAT_SEND_TO_ROOM:
|
||||
if (p instanceof ChatSendToRoom)
|
||||
handleChatSendToRoom(player, (ChatSendToRoom) p);
|
||||
break;
|
||||
case CHAT_REQUEST_ROOM_LIST:
|
||||
if (p instanceof ChatRequestRoomList)
|
||||
handleChatRoomListRequest(player, (ChatRequestRoomList) p);
|
||||
handleChatRoomListRequest(player);
|
||||
break;
|
||||
case CHAT_INSTANT_MESSAGE_TO_CHARACTER:
|
||||
if (p instanceof ChatInstantMessageToCharacter)
|
||||
@@ -176,13 +231,19 @@ public class ChatService extends Service {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void handlePlayerEventIntent(PlayerEventIntent intent) {
|
||||
switch (intent.getEvent()) {
|
||||
case PE_ZONE_IN:
|
||||
// TODO: Add players to proper planet chat room
|
||||
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)
|
||||
@@ -232,6 +293,265 @@ public class ChatService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
/* Chat Rooms */
|
||||
|
||||
private void handleChatSendToRoom(Player player, ChatSendToRoom p) {
|
||||
ChatResult result = ChatResult.SUCCESS;
|
||||
|
||||
ChatRoom room = getRoom(p.getRoomId());
|
||||
if (room == null)
|
||||
result = ChatResult.ROOM_INVALID_ID;
|
||||
|
||||
if (result != ChatResult.SUCCESS) {
|
||||
player.sendPacket(new ChatOnSendRoomMessage(result.getCode(), p.getSequence()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!incrementMessageCounter(player.getNetworkId(), room.getId(), p.getSequence()))
|
||||
return;
|
||||
|
||||
ChatAvatar avatar = ChatAvatar.getFromPlayer(player);
|
||||
|
||||
result = room.canSendMessage(avatar);
|
||||
|
||||
// TODO: Check length of messages -- Result 16 is used for too long message
|
||||
|
||||
player.sendPacket(new ChatOnSendRoomMessage(result.getCode(), p.getSequence()));
|
||||
|
||||
if (result == ChatResult.SUCCESS)
|
||||
room.sendMessage(avatar, p.getMessage(), p.getOutOfBandPackage(), player.getPlayerManager());
|
||||
}
|
||||
|
||||
private void handleChatQueryRoom(Player player, ChatQueryRoom p) {
|
||||
ChatRoom room = getRoom(p.getRoomPath()); // No result code is sent for queries
|
||||
if (room == null)
|
||||
return;
|
||||
|
||||
player.sendPacket(new ChatQueryRoomResults(room, p.getSequence()));
|
||||
}
|
||||
|
||||
private void handleChatRoomListRequest(Player player) {
|
||||
// TODO: Filter out private rooms
|
||||
ChatRoomList response = new ChatRoomList(roomMap.values());
|
||||
player.sendPacket(response);
|
||||
}
|
||||
|
||||
private void sendOnEnteredChatRoom(Player player, ChatAvatar avatar, ChatResult result, int id, int sequence) {
|
||||
ChatOnEnteredRoom onEnteredRoom = new ChatOnEnteredRoom(avatar, id, sequence);
|
||||
onEnteredRoom.setResult(result.getCode());
|
||||
player.sendPacket(onEnteredRoom);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to join the specified chat channel
|
||||
* @param player Player joining the chat channel
|
||||
* @param room Chat room to enter
|
||||
*/
|
||||
public void enterChatChannel(Player player, ChatRoom room, int sequence) {
|
||||
ChatAvatar avatar = ChatAvatar.getFromPlayer(player);
|
||||
|
||||
PlayerObject ghost = player.getPlayerObject();
|
||||
if (ghost == null) {
|
||||
sendOnEnteredChatRoom(player, avatar, ChatResult.NONE, room.getId(), sequence);
|
||||
return;
|
||||
}
|
||||
|
||||
ChatResult result = room.canJoinRoom(avatar);
|
||||
if (result != ChatResult.SUCCESS && player.getAccessLevel() != AccessLevel.PLAYER) {
|
||||
sendOnEnteredChatRoom(player, avatar, result, room.getId(), sequence);
|
||||
return;
|
||||
}
|
||||
// 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<Integer> joinedChannels = ghost.getJoinedChannels();
|
||||
if (!joinedChannels.contains(room.getId()))
|
||||
joinedChannels.add(room.getId());*/
|
||||
|
||||
room.getMembers().add(avatar);
|
||||
|
||||
// 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);
|
||||
|
||||
// Notify players of success
|
||||
ChatOnEnteredRoom onEnteredRoom = new ChatOnEnteredRoom(avatar, room.getId(), sequence);
|
||||
onEnteredRoom.setResult(result.getCode()); // ChatResult.SUCCESS at this point
|
||||
player.sendPacket(onEnteredRoom);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public void enterChatChannel(Player player, int id, int sequence) {
|
||||
ChatRoom room = getRoom(id);
|
||||
if (room == null) {
|
||||
sendOnEnteredChatRoom(player, ChatAvatar.getFromPlayer(player), ChatResult.NONE, id, sequence);
|
||||
return;
|
||||
}
|
||||
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)) {
|
||||
enterChatChannel(player, room, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
System.out.println("Couldn't find room with path " + path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param isPublic Determines if the room should be publicly displayed in the channel listing
|
||||
* @param path Address for the channel (Ex: SWG.serverName.Imperial)
|
||||
* @param title Descriptive name of the chat channel (Ex: Imperial chat for this galaxy)
|
||||
* @return {@link ChatRoom}
|
||||
*/
|
||||
public ChatRoom createRoom(ChatAvatar creator, boolean isPublic, String path, String title) {
|
||||
if (path.isEmpty() || path.endsWith("."))
|
||||
return null;
|
||||
|
||||
String base = "SWG." + creator.getGalaxy();
|
||||
if (!path.startsWith(base) || path.equals(base))
|
||||
return null;
|
||||
|
||||
// All paths should have parents, lets validate to make sure they exist first. Create them if they don't.
|
||||
int lastIndex = path.lastIndexOf(".");
|
||||
if (lastIndex != -1) {
|
||||
String parentPath = path.substring(0, lastIndex);
|
||||
if (getRoom(parentPath) == null) {
|
||||
createRoom(creator, isPublic, parentPath, "");
|
||||
}
|
||||
}
|
||||
|
||||
ChatRoom room = new ChatRoom();
|
||||
int id = maxChatRoomId;
|
||||
maxChatRoomId++;
|
||||
|
||||
room.setId(id);
|
||||
room.setOwner(creator);
|
||||
room.setCreator(creator);
|
||||
room.setIsPublic(isPublic);
|
||||
room.setPath(path);
|
||||
room.setTitle(title);
|
||||
|
||||
roomMap.put(id, room);
|
||||
return room;
|
||||
}
|
||||
|
||||
private void createSystemChannels(String galaxy) {
|
||||
ChatAvatar systemAvatar = ChatAvatar.getSystemAvatar(galaxy);
|
||||
|
||||
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");
|
||||
createRoom(systemAvatar, true, basePath + "Chat", "public chat for this galaxy, can create rooms here");
|
||||
createRoom(systemAvatar, true, basePath + "Imperial", "Imperial chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "ImperialWarRoom", "Imperial war room chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Rebel", "Rebel chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "RebelWarRoom", "Rebel war room chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "BountyHunter", "Bounty Hunter chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Commando", "Commando chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Entertainer", "Entertainer chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "ForceSensitive", "Force Sensitive chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Medic", "Medic chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Officer", "Officer chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Pilot", "Pilot chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Politician", "Politician chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Smuggler", "Smuggler chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Spy", "Spy chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Trader", "Trader chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "BeastMastery", "Beast Mastery chat for this galaxy");
|
||||
createRoom(systemAvatar, true, basePath + "Auction", "Auction chat for this galaxy");
|
||||
createPlanetChannels(systemAvatar, basePath);
|
||||
}
|
||||
|
||||
private void createPlanetChannels(ChatAvatar systemAvatar, String basePath) {
|
||||
for (Terrain terrain : terrains) {
|
||||
String path = basePath + Character.toUpperCase(terrain.getName().charAt(0)) + terrain.getName().substring(1) + ".";
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean incrementMessageCounter(long networkId, int roomId, int messageId) {
|
||||
if (networkId == -1) // System ChatAvatar uses -1 for networkId
|
||||
return true;
|
||||
|
||||
Map<Integer, Integer> messageHistory = messages.get(networkId);
|
||||
if (messageHistory != null) {
|
||||
if (messageHistory.containsKey(roomId) && messageHistory.get(roomId) == messageId)
|
||||
return false;
|
||||
} else {
|
||||
messageHistory = new HashMap<>();
|
||||
messages.put(networkId, messageHistory);
|
||||
}
|
||||
messageHistory.put(roomId, messageId);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void initializeGalaxyChannels(Galaxy galaxy) {
|
||||
ChatAvatar systemAvatar = new ChatAvatar(-1, "System", galaxy.getName());
|
||||
createSystemChannels(galaxy.getName());
|
||||
/** Channel Notes
|
||||
* Group channels: created by System
|
||||
* - SWG.serverName.group.GroupObjectId.GroupChat title = GroupId
|
||||
* Guild channels: created by System
|
||||
* - SWG.serverName.guild.GuildId.GuildChat title = GuildId
|
||||
* City channels: created by System
|
||||
* - SWG.serverName.city.CityId.CityChat title = CityId
|
||||
*/
|
||||
}
|
||||
|
||||
public ChatRoom getRoom(String path) {
|
||||
for (ChatRoom room : roomMap.values()) {
|
||||
if (room.getPath().equals(path))
|
||||
return room;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ChatRoom getRoom(int roomId) {
|
||||
return roomMap.get(roomId);
|
||||
}
|
||||
|
||||
/* Friends List */
|
||||
|
||||
private void handleRequestFriendList(Player player) {
|
||||
PlayerObject ghost = player.getPlayerObject();
|
||||
if (ghost == null)
|
||||
@@ -290,10 +610,6 @@ public class ChatService extends Service {
|
||||
new ChatBroadcastIntent(player, new ProsePackage("@cmnty:friend_added", "TT", target)).broadcast();
|
||||
}
|
||||
|
||||
private void handleChatRoomListRequest(Player player, ChatRequestRoomList request) {
|
||||
|
||||
}
|
||||
|
||||
private void handleSpatialChat(SpatialChatIntent i) {
|
||||
Player sender = i.getPlayer();
|
||||
SWGObject actor = sender.getCreatureObject();
|
||||
@@ -329,7 +645,9 @@ public class ChatService extends Service {
|
||||
|
||||
receiver.sendPacket(new ChatInstantMessageToClient(request.getGalaxy(), strSender, request.getMessage()));
|
||||
}
|
||||
|
||||
|
||||
/* Mails */
|
||||
|
||||
private void handleSendPersistentMessage(PlayerManager playerMgr, Player sender, String galaxy, ChatPersistentMessageToServer request) {
|
||||
String recipientStr = request.getRecipient().toLowerCase(Locale.ENGLISH);
|
||||
|
||||
@@ -501,7 +819,7 @@ public class ChatService extends Service {
|
||||
private void deletePersistentMessage(int mailId) {
|
||||
mails.remove(mailId);
|
||||
}
|
||||
|
||||
|
||||
private enum MailFlagType {
|
||||
FULL_MESSAGE,
|
||||
HEADER_ONLY
|
||||
|
||||
@@ -33,6 +33,7 @@ import intents.network.InboundPacketIntent;
|
||||
import resources.Galaxy;
|
||||
import resources.control.Intent;
|
||||
import resources.control.Manager;
|
||||
import services.chat.ChatService;
|
||||
import services.objects.ObjectManager;
|
||||
import services.player.PlayerManager;
|
||||
|
||||
@@ -43,6 +44,7 @@ public class GalacticManager extends Manager {
|
||||
private ObjectManager objectManager;
|
||||
private PlayerManager playerManager;
|
||||
private GameManager gameManager;
|
||||
private ChatService chatService;
|
||||
private Intent prevPacketIntent;
|
||||
private Galaxy galaxy;
|
||||
|
||||
@@ -51,16 +53,19 @@ public class GalacticManager extends Manager {
|
||||
objectManager = new ObjectManager();
|
||||
playerManager = new PlayerManager();
|
||||
gameManager = new GameManager();
|
||||
chatService = new ChatService();
|
||||
prevPacketIntent = null;
|
||||
|
||||
addChildService(objectManager);
|
||||
addChildService(playerManager);
|
||||
addChildService(gameManager);
|
||||
addChildService(chatService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initialize() {
|
||||
registerForIntent(InboundPacketIntent.TYPE);
|
||||
chatService.initializeGalaxyChannels(galaxy);
|
||||
return super.initialize();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,21 +33,18 @@ import services.commands.CommandService;
|
||||
import services.sui.SuiService;
|
||||
|
||||
public class GameManager extends Manager {
|
||||
|
||||
private ChatService chatService;
|
||||
|
||||
private CommandService commandService;
|
||||
private ConnectionService connectionService;
|
||||
private SuiService suiService;
|
||||
private WeatherService weatherService;
|
||||
|
||||
public GameManager() {
|
||||
chatService = new ChatService();
|
||||
commandService = new CommandService();
|
||||
connectionService = new ConnectionService();
|
||||
suiService = new SuiService();
|
||||
weatherService = new WeatherService();
|
||||
|
||||
addChildService(chatService);
|
||||
|
||||
addChildService(commandService);
|
||||
addChildService(connectionService);
|
||||
addChildService(suiService);
|
||||
|
||||
Reference in New Issue
Block a user