diff --git a/scripts/commands/spatialchatinternal.py b/scripts/commands/spatialchatinternal.py index 451f6318..a9dab09d 100644 --- a/scripts/commands/spatialchatinternal.py +++ b/scripts/commands/spatialchatinternal.py @@ -9,6 +9,7 @@ def run(core, actor, target, commandString): chatMsg = parsedMsg[5] chatType = int(parsedMsg[1]) moodId = int(parsedMsg[2]) - chatService.handleSpatialChat(actor, target, chatMsg, chatType, moodId) + languageId = int(parsedMsg[3]) + chatService.spatialChat(actor, target, chatMsg, chatType, moodId, languageId, None) return \ No newline at end of file diff --git a/src/protocol/swg/objectControllerObjects/SpatialChat.java b/src/protocol/swg/objectControllerObjects/SpatialChat.java index 1d2ac34e..aadd7050 100644 --- a/src/protocol/swg/objectControllerObjects/SpatialChat.java +++ b/src/protocol/swg/objectControllerObjects/SpatialChat.java @@ -26,12 +26,12 @@ import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; import protocol.swg.ObjControllerMessage; +import resources.common.OutOfBand; @SuppressWarnings("unused") - public class SpatialChat extends ObjControllerObject { - private long audienceId; + private long destinationId; private long sourceId; private long targetId; private String chatMessage; @@ -40,15 +40,19 @@ public class SpatialChat extends ObjControllerObject { private short balloonType = 1; private short chatType; private short moodId; + private byte languageId = 1; + private OutOfBand outOfBand; - public SpatialChat(long sourceId, long targetId, String chatMessage, short chatType, short moodId) { + public SpatialChat(long destinationId, long sourceId, long targetId, String chatMessage, short chatType, short moodId, int languageId, OutOfBand outOfBand) { try { - this.audienceId = sourceId; + this.destinationId = destinationId; this.sourceId = sourceId; this.targetId = targetId; this.chatMessage = chatMessage; this.chatType = chatType; this.moodId = moodId; + this.languageId = (byte) languageId; + this.outOfBand = ((outOfBand == null) ? new OutOfBand() : outOfBand); /*String[] chatMessageParse = chatMessage.split(" ", 6); @@ -62,19 +66,20 @@ public class SpatialChat extends ObjControllerObject { } } - public void setDestinationId(long audienceId) { - this.audienceId = audienceId; + public void setDestinationId(long destinationId) { + this.destinationId = destinationId; } - + public void deserialize(IoBuffer data) { } public IoBuffer serialize() { - IoBuffer result = IoBuffer.allocate(55 + chatMessage.length() * 2).order(ByteOrder.LITTLE_ENDIAN); - + outOfBand.setHeaderBytes(2); + IoBuffer outOfBandBuffer = outOfBand.serialize(); + IoBuffer result = IoBuffer.allocate(51 + (chatMessage.length() * 2) + outOfBandBuffer.array().length).order(ByteOrder.LITTLE_ENDIAN); result.putInt(ObjControllerMessage.SPACIAL_CHAT); - result.putLong(audienceId); + result.putLong(destinationId); result.putInt(0); result.putLong(sourceId); result.putLong(targetId); @@ -83,11 +88,8 @@ public class SpatialChat extends ObjControllerObject { result.putShort((short) 0x32); result.putShort(chatType); result.putShort(moodId); - result.put((byte) 1); - - result.putInt(0); - result.putInt(0); - + result.put(languageId); + result.put(outOfBandBuffer.array()); return result.flip(); } diff --git a/src/services/chat/ChatService.java b/src/services/chat/ChatService.java index c88846d6..e29ff4e7 100644 --- a/src/services/chat/ChatService.java +++ b/src/services/chat/ChatService.java @@ -37,6 +37,8 @@ import org.apache.mina.core.session.IoSession; import com.sleepycat.je.Transaction; import com.sleepycat.persist.EntityCursor; +import engine.clientdata.ClientFileManager; +import engine.clientdata.visitors.DatatableVisitor; import engine.clients.Client; import engine.resources.config.Config; import engine.resources.config.DefaultConfig; @@ -107,49 +109,49 @@ public class ChatService implements INetworkDispatch { } - public void handleSpatialChat(SWGObject speaker, SWGObject target, String chatMessage, short chatType, short moodId) { - + /* + * This gets used by NPCs as well (random shouts, mustafar miners, etc). + */ + public void spatialChat(SWGObject speaker, SWGObject target, String chatMessage, short chatType, short moodId, int languageId, OutOfBand outOfBand) { long targetId; - if(target == null) + if (target == null) { targetId = 0; - else + } else { targetId = target.getObjectID(); + } - //System.out.println(chatMessage); - //System.out.println(chatType); - //System.out.println(moodId); - - SpatialChat spatialChat = new SpatialChat(speaker.getObjectID(), targetId, chatMessage, chatType, moodId); - ObjControllerMessage objControllerMessage = new ObjControllerMessage(0x0B, spatialChat); + ObjControllerMessage objControllerMessage = new ObjControllerMessage(0x0B, new SpatialChat(speaker.getObjectId(), speaker.getObjectID(), targetId, chatMessage, chatType, moodId, languageId, outOfBand)); Client speakerClient = speaker.getClient(); - if(speakerClient == null || speakerClient.getSession() == null) + if (speakerClient == null || speakerClient.getSession() == null) { return; - + } + speakerClient.getSession().write(objControllerMessage.serialize()); - if(speaker.getObservers().isEmpty()) + if (speaker.getObservers().isEmpty()) { return; + } HashSet observers = new HashSet(speaker.getObservers()); Point3D position = speaker.getPosition(); - for(Client client : observers) { + for (Client client : observers) { float distance = client.getParent().getPosition().getDistance2D(position); - if(client != null && client.getSession() != null && distance <= 80) { - - if(((PlayerObject)client.getParent().getSlottedObject("ghost")).getIgnoreList().contains(speaker.getCustomName().toLowerCase().split(" ")[0])) + if (client != null && client.getSession() != null && distance <= 80) { + if (((PlayerObject) client.getParent().getSlottedObject("ghost")).getIgnoreList().contains(speaker.getCustomName().toLowerCase().split(" ")[0])) { continue; + } - spatialChat.setDestinationId(client.getParent().getObjectID()); - ObjControllerMessage objControllerMessage2 = new ObjControllerMessage(0x0B, spatialChat); - client.getSession().write(objControllerMessage2.serialize()); + String message = interpret(chatMessage, languageId, (CreatureObject) client.getParent()); + SpatialChat spatialChat = new SpatialChat(client.getParent().getObjectId(), speaker.getObjectID(), targetId, message, chatType, moodId, languageId, outOfBand); + objControllerMessage = new ObjControllerMessage(0x0B, spatialChat); + client.getSession().write(objControllerMessage.serialize()); } } - } public void handleEmote(SWGObject speaker, SWGObject target, short emoteId) { @@ -1003,4 +1005,38 @@ public class ChatService implements INetworkDispatch { public ConcurrentHashMap getChatRooms() { return chatRooms; } + + /* + * Language interpretation. + * Converts messages into a language if the receiver can't comprehend it + * */ + public String interpret(String message, int languageId, CreatureObject receiver) { + try { + DatatableVisitor visitor = ClientFileManager.loadFile("datatables/game_language/game_language.iff", DatatableVisitor.class); + + if (visitor.getObject(0, 0) == null) { + return message; + } + + String comprehendSkillMod = (String) visitor.getObject(languageId, 1); + + if (receiver.getSkillModBase(comprehendSkillMod) > 0) { + return message; + } + + for (int l = 3; l < 29; l++) { + String letter = ((String) visitor.getObject(0, l)); + String replacement = ((String) visitor.getObject(languageId, l)); + + if (replacement.length() > 0) { + message = message.replace(letter, replacement); + } + } + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + + return message; + } + }