diff --git a/src/main/NGECore.java b/src/main/NGECore.java index 7676a83a..4f2fc5f9 100644 --- a/src/main/NGECore.java +++ b/src/main/NGECore.java @@ -673,17 +673,17 @@ public class NGECore { try { for(int minutes = 15; minutes > 1; minutes--) { - simulationService.notifyAllClients(new ChatSystemMessage("The server will be shutting down soon. Please find a safe place to logout. (" + minutes + " minutes left)", (byte) 0 ).serialize()); + chatService.broadcastGalaxy("The server will be shutting down soon. Please find a safe place to logout. (" + minutes + " minutes left)"); Thread.sleep(60000); } setGalaxyStatus(3); - simulationService.notifyAllClients(new ChatSystemMessage("The server will be shutting down soon. Please find a safe place to logout. (" + 1 + " minutes left)", (byte) 0 ).serialize()); + chatService.broadcastGalaxy("The server will be shutting down soon. Please find a safe place to logout. (" + 1 + " minutes left)"); Thread.sleep(30000); - simulationService.notifyAllClients(new ChatSystemMessage("You will be disconnected in 30 seconds so the server can perform a final save before shutting down. Please find a safe place to logout now.", (byte) 0 ).serialize()); + chatService.broadcastGalaxy("You will be disconnected in 30 seconds so the server can perform a final save before shutting down. Please find a safe place to logout now."); Thread.sleep(20000); - simulationService.notifyAllClients(new ChatSystemMessage("You will be disconnected in 10 seconds so the server can perform a final save before shutting down. Please find a safe place to logout now.", (byte) 0 ).serialize()); + chatService.broadcastGalaxy("You will be disconnected in 10 seconds so the server can perform a final save before shutting down. Please find a safe place to logout now."); Thread.sleep(10000); - simulationService.notifyAllClients(new ChatSystemMessage("You will now be disconnected so the server can perform a final save before shutting down.", (byte) 0 ).serialize()); + chatService.broadcastGalaxy("You will now be disconnected so the server can perform a final save before shutting down."); synchronized(getActiveConnectionsMap()) { for(Client client : getActiveConnectionsMap().values()) { diff --git a/src/protocol/swg/CommPlayerMessage.java b/src/protocol/swg/CommPlayerMessage.java index 59648d21..5d1274c8 100644 --- a/src/protocol/swg/CommPlayerMessage.java +++ b/src/protocol/swg/CommPlayerMessage.java @@ -26,14 +26,17 @@ import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; import resources.common.Console; +import resources.common.OutOfBand; import resources.common.StringUtilities; public class CommPlayerMessage extends SWGMessage { private long objectId; + private OutOfBand outOfBand; - public CommPlayerMessage(long objectId) { + public CommPlayerMessage(long objectId, OutOfBand outOfBand) { this.objectId = objectId; + this.outOfBand = outOfBand; } @Override @@ -44,52 +47,24 @@ public class CommPlayerMessage extends SWGMessage { @Override public IoBuffer serialize() { IoBuffer buffer = IoBuffer.allocate(200).order(ByteOrder.LITTLE_ENDIAN); - buffer.putShort((short) 2); buffer.putInt(0x594AD258); - buffer.put((byte) 0); // aurebesh borders on comm, space version? Can cause crashes - buffer.putLong(objectId); - - /*Seen numbers: + /* Seen numbers: * 52 (Starting Station Comms) * 54 (Tansarii Comms) * 57 (Supply Drops) * 58 (Faction Covert->Overt) * 68 (Imperial stop) - * */ - buffer.putInt(57); // unknown, changes for each comm message (counter?) - - buffer.putShort((short) 0); // unknonw flag, seems to do nothing - buffer.put((byte) 0); // unknown, always 0 except for imperial stop message - - buffer.putInt(0xFFFFFFFF); - - buffer.put(getAsciiString("stormtrooper")); // StfFile - buffer.putInt(0); // stf spacer - buffer.put(getAsciiString("u11")); // StfName - - buffer.putInt(0); // stf spacer - buffer.putLong(0); - buffer.putLong(0); - buffer.putLong(0); - buffer.putLong(0); // 70 bytes - buffer.putLong(0); - buffer.putLong(0); - buffer.putLong(0); - buffer.putLong(0); - buffer.put((byte) 0); - + buffer.put(outOfBand.serialize().array()); // Officer Supply Drop: 0x3E894347 // Rebel Faction Dude: 0x528CB3D7 buffer.putInt(0x528CB3D7); // model crc, can be anything w/o crashing - buffer.putInt(0); // sound - buffer.putShort((short) 0); // unk - buffer.putShort((short) 16576); // comm display time, unsure on how it's calculated + buffer.putShort((short) 16576); // comm display time, unsure on how it's calculated (probably milliseconds) buffer.flip(); Console.println("CPM: " + StringUtilities.bytesToHex(buffer.array())); return buffer; diff --git a/src/protocol/swg/chat/ChatSystemMessage.java b/src/protocol/swg/chat/ChatSystemMessage.java index af1b516d..277eb596 100644 --- a/src/protocol/swg/chat/ChatSystemMessage.java +++ b/src/protocol/swg/chat/ChatSystemMessage.java @@ -27,25 +27,18 @@ import org.apache.mina.core.buffer.IoBuffer; import protocol.swg.SWGMessage; import resources.common.Opcodes; +import resources.common.OutOfBand; -public class ChatSystemMessage extends SWGMessage{ +public class ChatSystemMessage extends SWGMessage { - private String stfFilename; - private String stfName; - private int stat; private String message; private byte displayType; + private OutOfBand outOfBand; - public ChatSystemMessage(String message, byte displayType) { + public ChatSystemMessage(String message, OutOfBand outOfBand, byte displayType) { this.message = message; this.displayType = displayType; - } - - public ChatSystemMessage(String stfFilename, String stfName, int stat, byte displayType) { - this.stfFilename = stfFilename; - this.stfName = stfName; - this.stat = stat; - this.displayType = displayType; + this.outOfBand = outOfBand; } public void deserialize(IoBuffer data) { @@ -53,40 +46,14 @@ public class ChatSystemMessage extends SWGMessage{ } public IoBuffer serialize() { - if (message != null) { - IoBuffer result = IoBuffer.allocate(15 + message.length() * 2).order(ByteOrder.LITTLE_ENDIAN); - result.putShort((short) 2); - result.putInt(Opcodes.ChatSystemMessage); - result.put(displayType); // 0x00 = Chat and Screen // 0x02 = Chat only - result.put(getUnicodeString(message)); - result.putInt(0); - return result.flip(); - } else { - IoBuffer result = IoBuffer.allocate(99 + stfFilename.length() + stfName.length()).order(ByteOrder.LITTLE_ENDIAN); - result.putShort((short) 4); - result.putInt(Opcodes.ChatSystemMessage); - result.put((byte) 0); //result.put((byte) displayType); // 0x00 = Chat and Screen // 0x02 = Chat only - result.putInt(0); - result.putInt(54); - result.putShort((short) 0); - result.put((byte) 1); - result.putInt(-1); - result.put(getAsciiString(stfFilename)); - result.putInt(0); - result.put(getAsciiString(stfName)); - result.putInt(0); - result.putLong(0); - result.putLong(0); - result.putLong(0); - result.putLong(0); - result.putLong(0); - result.putLong(0); - result.putLong(0); - result.putInt(stat); - result.putInt(0); - result.put((byte) 0); - return result.flip(); - } + IoBuffer outOfBandBuffer = outOfBand.serialize(); + IoBuffer result = IoBuffer.allocate(7 + getUnicodeString(message).length + outOfBandBuffer.array().length).order(ByteOrder.LITTLE_ENDIAN); + result.putShort((short) 2); + result.putInt(Opcodes.ChatSystemMessage); + result.put(displayType); + result.put(getUnicodeString(message)); + result.put(outOfBandBuffer.array()); + return result.flip(); } } diff --git a/src/protocol/swg/objectControllerObjects/NpcConversationMessage.java b/src/protocol/swg/objectControllerObjects/NpcConversationMessage.java index 12a2d822..eceff19c 100644 --- a/src/protocol/swg/objectControllerObjects/NpcConversationMessage.java +++ b/src/protocol/swg/objectControllerObjects/NpcConversationMessage.java @@ -36,6 +36,7 @@ public class NpcConversationMessage extends ObjControllerObject { public NpcConversationMessage(long objectId, OutOfBand outOfBand) { this.objectId = objectId; this.outOfBand = outOfBand; + outOfBand.setHeaderBytes(2); } @Override @@ -47,12 +48,10 @@ public class NpcConversationMessage extends ObjControllerObject { public IoBuffer serialize() { IoBuffer outOfBandBuffer = outOfBand.serialize(); IoBuffer buffer = IoBuffer.allocate(16 + outOfBandBuffer.array().length).order(ByteOrder.LITTLE_ENDIAN); - buffer.putInt(ObjControllerMessage.CONVERSATION_MESSAGE); buffer.putLong(objectId); buffer.putInt(0); buffer.put(outOfBandBuffer.array()); - System.out.println(buffer.getInt(16)); return buffer.flip(); } diff --git a/src/protocol/swg/objectControllerObjects/NpcConversationOptions.java b/src/protocol/swg/objectControllerObjects/NpcConversationOptions.java index e80a92c6..092b2556 100644 --- a/src/protocol/swg/objectControllerObjects/NpcConversationOptions.java +++ b/src/protocol/swg/objectControllerObjects/NpcConversationOptions.java @@ -28,6 +28,7 @@ import org.apache.mina.core.buffer.IoBuffer; import protocol.swg.ObjControllerMessage; import resources.common.ConversationOption; +import resources.objects.Delta; public class NpcConversationOptions extends ObjControllerObject { @@ -52,16 +53,13 @@ public class NpcConversationOptions extends ObjControllerObject { buffer.setAutoExpand(true); buffer.putInt(ObjControllerMessage.CONVERSATION_OPTIONS); buffer.putLong(objectId); - buffer.putInt(0); buffer.put((byte) conversationOptions.size()); - - for(ConversationOption option : conversationOptions) { - buffer.put(option.getOutOfBand().serialize()); + for (ConversationOption option : conversationOptions) { + option.getOutOfBand().setHeaderBytes(2); + buffer.put(option.getOutOfBand().serialize().array()); } - int size = buffer.position(); - buffer.flip(); - return IoBuffer.allocate(size).order(ByteOrder.LITTLE_ENDIAN).put(buffer.array(), 0, size).flip(); + return Delta.resizeBuffer(buffer); } } diff --git a/src/protocol/swg/objectControllerObjects/ShowFlyText.java b/src/protocol/swg/objectControllerObjects/ShowFlyText.java index 0413b576..39530a87 100644 --- a/src/protocol/swg/objectControllerObjects/ShowFlyText.java +++ b/src/protocol/swg/objectControllerObjects/ShowFlyText.java @@ -26,51 +26,28 @@ import java.nio.ByteOrder; import org.apache.mina.core.buffer.IoBuffer; import protocol.swg.ObjControllerMessage; +import resources.common.OutOfBand; import resources.common.RGB; +import resources.common.Stf; public class ShowFlyText extends ObjControllerObject { - private long recieverId; + private long receiverId; private long objectId; - private int unknownInt1; - private short unknownShort1; - private byte unknownByte1; - private int unknownInt2; - private String stfFile; - private String stfString; - private short xp; + private Stf stf; + private OutOfBand outOfBand; private float scale; private RGB color; private int displayType; - private boolean alternativeStructure; - private String customText; - public ShowFlyText(long recieverId, long objectId, String stfFile, String stfString, float scale, RGB color, int displayType) { - this.recieverId = recieverId; + public ShowFlyText(long receiverId, long objectId, String stf, OutOfBand outOfBand, float scale, RGB color, int displayType) { + this.receiverId = receiverId; this.objectId = objectId; - this.stfFile = stfFile; - this.stfString = stfString; + this.stf = new Stf(stf); + this.outOfBand = outOfBand; this.scale = scale; this.color = color; this.displayType = displayType; - this.alternativeStructure = false; - } - - public ShowFlyText(long recieverId, long objectId, int unknownInt1, int unknownShort1, int unknownByte1, int unknownInt2, String stfFile, String stfString, String customText, int xp, float scale, RGB color, int displayType) { - this.recieverId = recieverId; - this.objectId = objectId; - this.unknownInt1 = unknownInt1; - this.unknownShort1 = (short) unknownShort1; - this.unknownByte1 = (byte) unknownByte1; - this.unknownInt2 = unknownInt2; - this.stfFile = stfFile; - this.stfString = stfString; - this.customText = customText; - this.xp = (short) xp; - this.scale = scale; - this.color = color; - this.alternativeStructure = true; - this.displayType = displayType; } @Override @@ -81,54 +58,20 @@ public class ShowFlyText extends ObjControllerObject { @Override public IoBuffer serialize() { - if (!alternativeStructure) { - IoBuffer result = IoBuffer.allocate(47 + stfFile.length() + stfString.length()).order(ByteOrder.LITTLE_ENDIAN); - result.setAutoExpand(true); - result.putInt(ObjControllerMessage.SHOW_FLY_TEXT); - result.putLong(recieverId); - result.putInt(0); - result.putLong(objectId); - result.put(getAsciiString(stfFile)); - result.putInt(0); - result.put(getAsciiString(stfString)); - result.putInt(0); - result.putFloat(scale); - result.put(color.getBytes()); - result.putInt(displayType); - return result.flip(); - } else { - IoBuffer result = IoBuffer.allocate(124 + stfFile.length() + stfString.length()).order(ByteOrder.LITTLE_ENDIAN); - result.setAutoExpand(true); - result.putInt(ObjControllerMessage.SHOW_FLY_TEXT); - result.putLong(recieverId); - result.putInt(0); - result.putLong(objectId); - result.putLong(0); - result.putInt(unknownInt1); - result.putShort(unknownShort1); - result.put(unknownByte1); - result.putInt(unknownInt2); - result.put(getAsciiString(stfFile)); - result.putInt(0); - result.put(getAsciiString(stfString)); - result.putLong(0); - result.putLong(0); - result.putLong(0); - result.putLong(0); - result.putLong(0); - result.putLong(0); - result.putLong(0); - result.put(getUnicodeString(customText)); // %TO? - result.putShort(xp); // %DI ? - result.putLong(0); - result.putFloat(scale); - result.put(color.getBytes()); - result.putInt(displayType); - - result.flip(); - //StringUtilities.printBytes(result.array()); - return result; - } + IoBuffer outOfBandBuffer = outOfBand.serialize(); + IoBuffer result = IoBuffer.allocate(35 + outOfBandBuffer.array().length).order(ByteOrder.LITTLE_ENDIAN); + result.setAutoExpand(true); + result.putInt(ObjControllerMessage.SHOW_FLY_TEXT); + result.putLong(receiverId); + result.putInt(0); + result.putLong(objectId); + result.put(stf.getBytes()); + result.put(outOfBandBuffer.array()); + result.putFloat(scale); + result.put(color.getBytes()); + result.putInt(displayType); + result.flip(); + return result; } } diff --git a/src/resources/common/OutOfBand.java b/src/resources/common/OutOfBand.java index fd86c2dc..be36d672 100644 --- a/src/resources/common/OutOfBand.java +++ b/src/resources/common/OutOfBand.java @@ -23,13 +23,20 @@ package resources.common; import java.nio.ByteOrder; import java.util.Vector; + import resources.common.StringUtilities; +import resources.objects.Delta; + import org.apache.mina.core.buffer.IoBuffer; public class OutOfBand { - private short count; private Vector prosePackages = new Vector(); + private int headerBytes = 0; + + public OutOfBand(Vector prosePackages) { + setProsePackages(prosePackages); + } public OutOfBand(ProsePackage prosePackage) { addProsePackage(prosePackage); @@ -39,85 +46,86 @@ public class OutOfBand { } + public static OutOfBand ProsePackage(Object ... objects) { + return new OutOfBand(new ProsePackage(objects)); + } + public void addProsePackage(ProsePackage prosePackage) { prosePackages.add(prosePackage); - setCount((short) (getCount() + 1)); } public IoBuffer serialize() { - IoBuffer buffer = IoBuffer.allocate(50).order(ByteOrder.LITTLE_ENDIAN); buffer.setAutoExpand(true); - buffer.putInt(4); - buffer.putShort((short) 0); // unk - buffer.putShort(getCount()); + // The short that was here is only in conversation OutOfBands. + // Count doesn't seem to be count. It seems to be indicating if there's an extra byte. - for(ProsePackage prosePackage : prosePackages) { - + for (ProsePackage prosePackage : prosePackages) { buffer.put((byte) 1); buffer.putInt(-1); - buffer.put(StringUtilities.getAsciiString(prosePackage.getStfFile())); - buffer.putInt(0); - buffer.put(StringUtilities.getAsciiString(prosePackage.getStfLabel())); + buffer.put(prosePackage.getStf().getBytes()); buffer.putLong(prosePackage.getTuObjectId()); - buffer.put(StringUtilities.getAsciiString(prosePackage.getTuStfFile())); - buffer.putInt(0); - buffer.put(StringUtilities.getAsciiString(prosePackage.getTuStfLabel())); + buffer.put(prosePackage.getTuStf().getBytes()); buffer.put(StringUtilities.getUnicodeString(prosePackage.getTuCustomString())); - + buffer.putLong(prosePackage.getTtObjectId()); - buffer.put(StringUtilities.getAsciiString(prosePackage.getTtStfFile())); - buffer.putInt(0); - buffer.put(StringUtilities.getAsciiString(prosePackage.getTtStfLabel())); + buffer.put(prosePackage.getTtStf().getBytes()); buffer.put(StringUtilities.getUnicodeString(prosePackage.getTtCustomString())); buffer.putLong(prosePackage.getToObjectId()); - buffer.put(StringUtilities.getAsciiString(prosePackage.getToStfFile())); - buffer.putInt(0); - buffer.put(StringUtilities.getAsciiString(prosePackage.getToStfLabel())); + buffer.put(prosePackage.getToStf().getBytes()); buffer.put(StringUtilities.getUnicodeString(prosePackage.getToCustomString())); buffer.putInt(prosePackage.getDiInteger()); buffer.putFloat(prosePackage.getDfFloat()); - //buffer.put(prosePackage.getDisplayFlag()); buffer.put((byte) 0); - - int stfLength = prosePackage.getStfFile().length() + prosePackage.getStfLabel().length() + - prosePackage.getTuStfFile().length() + prosePackage.getTuStfLabel().length() + - prosePackage.getTtStfFile().length() + prosePackage.getTtStfLabel().length() + - prosePackage.getToStfFile().length() + prosePackage.getToStfLabel().length(); - - //if(stfLength % 2 == 1) { - buffer.put((byte) 0); - //} - } - setLength(buffer); int size = buffer.position(); - buffer.flip(); - return IoBuffer.allocate(size).order(ByteOrder.LITTLE_ENDIAN).put(buffer.array(), 0, size).flip(); + + if (size > 0) { + if ((size % 2) == 1) { + size++; + buffer.put((byte) 0); + buffer = Delta.createBuffer(size + 2).putShort((short) 1).put(buffer.flip().array(), 0, size); + } else { + buffer = Delta.createBuffer(size + 2).putShort((short) 0).put(buffer.flip().array(), 0, size); + } + + size += 2; + } else { + return Delta.createBuffer(4).putInt(size); + } + + if (headerBytes > 0) { + IoBuffer result = Delta.createBuffer(size + headerBytes); + + for (int i = 0; i < headerBytes; i++) { + result.put((byte) 0); + } + + buffer = result.put(buffer.flip().array(), 0, size); + size += headerBytes; + } + + return Delta.resizeBuffer(Delta.createBuffer(size + 4).putInt(size / 2).put(buffer.flip().array())); } - public void setLength(IoBuffer buffer) { - buffer.putInt(0, (buffer.position() - 4) / 2); + /* + * No idea what the extra short in conversation OutOfBands is. + * It's not in any of the other packets that use OutOfBand. + */ + public void setHeaderBytes(int headerBytes) { + this.headerBytes = headerBytes; } - - public short getCount() { - return count; - } - - public void setCount(short count) { - this.count = count; - } - + public Vector getProsePackages() { return prosePackages; } - + public void setProsePackages(Vector prosePackages) { this.prosePackages = prosePackages; } diff --git a/src/resources/common/ProsePackage.java b/src/resources/common/ProsePackage.java index 4a1ef88c..b461bb8e 100644 --- a/src/resources/common/ProsePackage.java +++ b/src/resources/common/ProsePackage.java @@ -24,183 +24,209 @@ package resources.common; public class ProsePackage { /* - * TU = Text You + * TU = Text User * TT = Text Target * TO = Text Object - * DI/DF = Decimal Value + * DI = Decimal Integer + * DF = Decimal Float */ - private byte displayFlag = 1; + private Stf stf = new Stf(); - private String stfFile = ""; - private String stfLabel = ""; - - private long tuObjectId; - private String tuStfFile = ""; - private String tuStfLabel = ""; + private long tuObjectId = 0; + private Stf tuStf = new Stf(); private String tuCustomString = ""; - private long ttObjectId; - private String ttStfFile = ""; - private String ttStfLabel = ""; + private long ttObjectId = 0; + private Stf ttStf = new Stf(); private String ttCustomString = ""; - private long toObjectId; - private String toStfFile = ""; - private String toStfLabel = ""; + private long toObjectId = 0; + private Stf toStf = new Stf(); private String toCustomString = ""; - private int diInteger; - private float dfFloat; + private int diInteger = 0; + private float dfFloat = 0; // TODO: Add more constructors public ProsePackage(String stfFile, String stfLabel) { - this.stfFile = stfFile; - this.stfLabel = stfLabel; + stf.setStfFilename(stfFile); + stf.setStfName(stfLabel); } public ProsePackage(String stfFile, String stfLabel, long tuObjectId, String tuStfFile, String tuStfLabel, String tuCustomString) { - this.stfFile = stfFile; - this.stfLabel = stfLabel; + stf.setStfFilename(stfFile); + stf.setStfName(stfLabel); this.tuObjectId = tuObjectId; - this.tuStfFile = tuStfFile; - this.tuStfLabel = tuStfLabel; + tuStf.setStfFilename(tuStfFile); + tuStf.setStfName(tuStfLabel); this.tuCustomString = tuCustomString; } - - public byte getDisplayFlag() { - return displayFlag; + + /* + * Any parameters can be entered. + * + * Any integers set diInteger + * Any floats set dfFloat + * Any "@stfFile:label" sets the default stf + * "TU" followed by objectId, "@stfFile:label" or customString + * "TT" followed by objectId, "@stfFile:label" or customString + * "TO" followed by objectId, "@stfFile:label" or customString + */ + public ProsePackage(Object ... objects) { + for (Object object: objects) { + if (object instanceof Object[]) { + objects = (Object[]) object; + break; + } + } + + for (int i = 0; i < objects.length; i++) { + Object object = objects[i]; + + if (object instanceof String) { + String string = (String) object; + + if ((i + 1) < objects.length) { + long objectId = 0; + Stf stf = null; + String customString = null; + + if (objects[i + 1] instanceof Long) { + objectId = (Long) objects[i + 1]; + } else if (objects[i + 1] instanceof String) { + String str = (String) objects[i + 1]; + + if (str.startsWith("@") && str.contains(":") && !str.contains(" ")) { + stf = new Stf(str); + } else { + customString = str; + } + } + + switch (string.toUpperCase()) { + case "TU": + tuObjectId = (objectId == 0) ? tuObjectId : objectId; + tuStf = (stf == null) ? tuStf : stf; + tuCustomString = (customString == null) ? tuCustomString : customString; + continue; + case "TT": + ttObjectId = (objectId == 0) ? ttObjectId : objectId; + ttStf = (stf == null) ? ttStf : stf; + ttCustomString = (customString == null) ? ttCustomString : customString; + continue; + case "TO": + toObjectId = (objectId == 0) ? toObjectId : objectId; + toStf = (stf == null) ? toStf : stf; + toCustomString = (customString == null) ? toCustomString : customString; + continue; + default: + // + } + } + + stf.setString((String) object); + } else if (object instanceof Integer) { + diInteger = (Integer) object; + } else if (object instanceof Float) { + dfFloat = (Float) object; + } + } } - public void setDisplayFlag(byte displayFlag) { - this.displayFlag = displayFlag; + public Stf getStf() { + return stf; } - - public String getStfFile() { - return stfFile; + + public void setStf(Stf stf) { + this.stf = stf; } - - public void setStfFile(String stfFile) { - this.stfFile = stfFile; - } - - public String getStfLabel() { - return stfLabel; - } - - public void setStfLabel(String stfLabel) { - this.stfLabel = stfLabel; - } - + public long getTuObjectId() { return tuObjectId; } - + public void setTuObjectId(long tuObjectId) { this.tuObjectId = tuObjectId; } - - public String getTuStfFile() { - return tuStfFile; + + public Stf getTuStf() { + return tuStf; } - - public void setTuStfFile(String tuStfFile) { - this.tuStfFile = tuStfFile; + + public void setTuStf(Stf tuStf) { + this.tuStf = tuStf; } - - public String getTuStfLabel() { - return tuStfLabel; - } - - public void setTuStfLabel(String tuStfLabel) { - this.tuStfLabel = tuStfLabel; - } - + public String getTuCustomString() { return tuCustomString; } - + public void setTuCustomString(String tuCustomString) { this.tuCustomString = tuCustomString; } - + public long getTtObjectId() { return ttObjectId; } - + public void setTtObjectId(long ttObjectId) { this.ttObjectId = ttObjectId; } - - public String getTtStfFile() { - return ttStfFile; + + public Stf getTtStf() { + return ttStf; } - - public void setTtStfFile(String ttStfFile) { - this.ttStfFile = ttStfFile; + + public void setTtStf(Stf ttStf) { + this.ttStf = ttStf; } - - public String getTtStfLabel() { - return ttStfLabel; - } - - public void setTtStfLabel(String ttStfLabel) { - this.ttStfLabel = ttStfLabel; - } - + public String getTtCustomString() { return ttCustomString; } - + public void setTtCustomString(String ttCustomString) { this.ttCustomString = ttCustomString; } - + public long getToObjectId() { return toObjectId; } - + public void setToObjectId(long toObjectId) { this.toObjectId = toObjectId; } - - public String getToStfFile() { - return toStfFile; + + public Stf getToStf() { + return toStf; } - public void setToStfFile(String toStfFile) { - this.toStfFile = toStfFile; + public void setToStf(Stf toStf) { + this.toStf = toStf; } - - public String getToStfLabel() { - return toStfLabel; - } - - public void setToStfLabel(String toStfLabel) { - this.toStfLabel = toStfLabel; - } - + public String getToCustomString() { return toCustomString; } - + public void setToCustomString(String toCustomString) { this.toCustomString = toCustomString; } - + public int getDiInteger() { return diInteger; } - + public void setDiInteger(int diInteger) { this.diInteger = diInteger; } - + public float getDfFloat() { return dfFloat; } - + public void setDfFloat(float dfFloat) { this.dfFloat = dfFloat; } diff --git a/src/resources/common/Stf.java b/src/resources/common/Stf.java index 468960f6..8907ecba 100644 --- a/src/resources/common/Stf.java +++ b/src/resources/common/Stf.java @@ -30,9 +30,9 @@ import com.sleepycat.persist.model.Persistent; @Persistent public class Stf extends Delta { - private AString stfFilename; + private AString stfFilename = new AString(""); private int spacer = 0; - private AString stfName; + private AString stfName = new AString(""); public Stf(String stfFilename, int spacer, String stfName) { this.stfFilename = new AString(stfFilename); @@ -40,6 +40,10 @@ public class Stf extends Delta { this.stfName = new AString(stfName); } + public Stf(String stf) { + setString(stf); + } + public Stf() { } @@ -82,15 +86,20 @@ public class Stf extends Delta { public String getString() { synchronized(objectMutex) { - return ("@" + stfFilename + ":" + stfName); + return ("@" + stfFilename.get() + ":" + stfName.get()); } } public void setString(String stf) { synchronized(objectMutex) { - stf = stf.replace("@", ""); - stfFilename.set(stf.split(":")[0]); - stfName.set(stf.split(":")[1]); + if (stf == null || stf.equals("")) { + stfFilename.set(""); + stfName.set(""); + } else if (stf.contains(":")) { + stf = stf.replace("@", ""); + stfFilename.set(stf.split(":")[0]); + stfName.set(stf.split(":")[1]); + } } } diff --git a/src/resources/datatables/DisplayType.java b/src/resources/datatables/DisplayType.java new file mode 100644 index 00000000..0e13f62a --- /dev/null +++ b/src/resources/datatables/DisplayType.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package resources.datatables; + +public class DisplayType { + + public static byte Broadcast = 0; // Level up. combatspam/skill_up + //public static byte Screen = 1; // Screen? XP gain + public static byte Chat = 2; + //public static byte Overhead = 3; // Flytext? Seen on ent duration + //public static byte Combat = 4; // CombatSpam? + //public static byte Combat = 5; // Seen in combat flytext + //public static byte Combat = 11; // Seen when blocking + +} + diff --git a/src/resources/objects/Delta.java b/src/resources/objects/Delta.java index 31782741..35ef4299 100644 --- a/src/resources/objects/Delta.java +++ b/src/resources/objects/Delta.java @@ -65,7 +65,12 @@ public abstract class Delta implements IDelta { } public static IoBuffer createBuffer(int size) { - return bufferPool.allocate(size, false).order(ByteOrder.LITTLE_ENDIAN); + return IoBuffer.allocate(size, false).order(ByteOrder.LITTLE_ENDIAN); + } + + public static IoBuffer resizeBuffer(IoBuffer buffer) { + int size = buffer.position(); + return buffer == null ? createBuffer(0) : createBuffer(size).put(buffer.flip().array(), 0, size).flip(); } } diff --git a/src/resources/objects/tangible/TangibleObject.java b/src/resources/objects/tangible/TangibleObject.java index 6a8433ef..cef963ff 100644 --- a/src/resources/objects/tangible/TangibleObject.java +++ b/src/resources/objects/tangible/TangibleObject.java @@ -37,6 +37,7 @@ import protocol.swg.PlayClientEffectObjectMessage; import protocol.swg.StopClientEffectObjectByLabel; import protocol.swg.UpdatePVPStatusMessage; import protocol.swg.objectControllerObjects.ShowFlyText; +import resources.common.OutOfBand; import resources.common.RGB; import resources.objects.creature.CreatureObject; import resources.visitors.IDManagerVisitor; @@ -373,40 +374,34 @@ public class TangibleObject extends SWGObject { return getPvPBitmask() == 1 || getPvPBitmask() == 2; } - public void showFlyText(String stfFile, String stfString, float scale, RGB color, int displayType) { - Set observers = getObservers(); - - if (getClient() != null) { - getClient().getSession().write((new ObjControllerMessage(0x0000000B, new ShowFlyText(getObjectID(), getObjectID(), stfFile, stfString, scale, color, displayType))).serialize()); - } - - for (Client client : observers) { - client.getSession().write((new ObjControllerMessage(0x0000000B, new ShowFlyText(client.getParent().getObjectID(), getObjectID(), stfFile, stfString, scale, color, displayType))).serialize()); - } + public void showFlyText(OutOfBand outOfBand, float scale, RGB color, int displayType, boolean notifyObservers) { + showFlyText("", outOfBand, scale, color, displayType, notifyObservers); } - public void showFlyText(String stfFile, String stfString, String customText, int xp, float scale, RGB color, int displayType) { - Set observers = getObservers(); - - if (getClient() != null) { - getClient().getSession().write((new ObjControllerMessage(0x0000000B, new ShowFlyText(getObjectID(), getObjectID(), 56, 1, 1, -1, stfFile, stfString, customText, xp, scale, color, displayType))).serialize()); - } - - for (Client client : observers) { - client.getSession().write((new ObjControllerMessage(0x0000000B, new ShowFlyText(client.getParent().getObjectID(), getObjectID(), 56, 1, 1, -1, stfFile, stfString, customText, xp, scale, color, displayType))).serialize()); - } + public void showFlyText(String stf, float scale, RGB color, int displayType, boolean notifyObservers) { + showFlyText(stf, new OutOfBand(), scale, color, displayType, notifyObservers); } - public void showFlyText(String stfFile, String stfString, String customText, int xp, float scale, RGB color, int displayType, int unkInt) { - //Set observers = getObservers(); - - if (getClient() != null) { - getClient().getSession().write((new ObjControllerMessage(0x0000000B, new ShowFlyText(getObjectID(), getObjectID(), unkInt, 1, 1, -1, stfFile, stfString, customText, xp, scale, color, displayType))).serialize()); + public void showFlyText(String stf, OutOfBand outOfBand, float scale, RGB color, int displayType, boolean notifyObservers) { + if (outOfBand == null) { + outOfBand = new OutOfBand(); } - /*for (Client client : observers) { - client.getSession().write((new ObjControllerMessage(0x0000000B, new ShowFlyText(client.getParent().getObjectID(), getObjectID(), unkInt, 1, 1, -1, stfFile, stfString, customText, xp, scale, color, displayType))).serialize()); - }*/ + if (color == null) { + color = new RGB(255, 255, 255); + } + + if (getClient() != null) { + getClient().getSession().write((new ObjControllerMessage(0x0000000B, new ShowFlyText(getObjectID(), getObjectID(), stf, outOfBand, scale, color, displayType))).serialize()); + } + + if (notifyObservers) { + Set observers = getObservers(); + + for (Client client : observers) { + client.getSession().write((new ObjControllerMessage(0x0000000B, new ShowFlyText(client.getParent().getObjectID(), getObjectID(), stf, outOfBand, scale, color, displayType))).serialize()); + } + } } public void playEffectObject(String effectFile, String commandString) { diff --git a/src/services/EntertainmentService.java b/src/services/EntertainmentService.java index 3c6772a9..f210cdc7 100644 --- a/src/services/EntertainmentService.java +++ b/src/services/EntertainmentService.java @@ -24,6 +24,7 @@ import resources.common.BuffBuilder; import resources.common.IDAttribute; import resources.common.MathUtilities; import resources.common.ObjControllerOpcodes; +import resources.common.OutOfBand; import resources.common.Performance; import resources.common.PerformanceEffect; import resources.common.RGB; @@ -821,7 +822,7 @@ public class EntertainmentService implements INetworkDispatch { int hMinutes = MathUtilities.secondsToHourMinutes(duration * 60); int hours = MathUtilities.secondsToWholeHours(duration * 60); - spectator.showFlyText("spam", "buff_duration_tick_observer", String.valueOf(hours) + " hours , " + hMinutes + " minutes ", 0, (float) 0.66, new RGB(255, 182, 193), 3, 78); + spectator.showFlyText(OutOfBand.ProsePackage("@spam:buff_duration_tick_observer", "TO", hours + " hours , " + hMinutes + " minutes "), 0.66f, new RGB(255, 182, 193), 3, false); spectator.setAttachment("inspireDuration", duration); //System.out.println("Inspire Duration: " + spectator.getAttachment("inspireDuration") + " on " + spectator.getCustomName()); diff --git a/src/services/PlayerService.java b/src/services/PlayerService.java index a1dc9eb3..d1694941 100644 --- a/src/services/PlayerService.java +++ b/src/services/PlayerService.java @@ -61,9 +61,12 @@ import protocol.swg.objectControllerObjects.ShowLootBox; import resources.common.FileUtilities; import resources.common.ObjControllerOpcodes; import resources.common.Opcodes; +import resources.common.OutOfBand; +import resources.common.ProsePackage; import resources.common.RGB; import resources.common.SpawnPoint; import resources.common.StringUtilities; +import resources.datatables.DisplayType; import resources.datatables.PlayerFlags; import resources.datatables.Professions; import resources.guild.Guild; @@ -811,7 +814,7 @@ public class PlayerService implements INetworkDispatch { creature.setLevel((short) level); core.scriptService.callScript("scripts/collections/", "master_" + player.getProfession(), "addMasterBadge", core, creature); - creature.showFlyText("cbt_spam", "skill_up", (float) 2.5, new RGB(154, 205, 50), 0); + creature.showFlyText(OutOfBand.ProsePackage("@cbt_spam:skill_up"), 2.5f, new RGB(154, 205, 50), 0, true); creature.playEffectObject("clienteffect/skill_granted.cef", ""); creature.playMusic("sound/music_acq_bountyhunter.snd"); } catch (InstantiationException | IllegalAccessException e) { @@ -850,7 +853,7 @@ public class PlayerService implements INetworkDispatch { // 1. Add the experience. if (experience > 0 && !creature.isStationary()) { - creature.showFlyText("base_player", "prose_flytext_xp", "", experience, (float) 2.5, new RGB(180, 60, 240), 1); + creature.showFlyText(OutOfBand.ProsePackage("@base_player:prose_flytext_xp", experience), 2.5f, new RGB(180, 60, 240), 1, true); } String xpType = ((player.getProfession().contains("entertainer")) ? "entertainer" : ((player.getProfession().contains("trader")) ? "crafting" : "combat_general")); @@ -885,49 +888,49 @@ public class PlayerService implements INetworkDispatch { if (luck >= 1) { core.skillModService.addSkillMod(creature, "luck", (int) luck); - creature.sendSystemMessage("spam", "level_up_stat_gain_0", (int) luck, 0); + creature.sendSystemMessage(OutOfBand.ProsePackage("@spam:level_up_stat_gain_0", (int) luck), DisplayType.Broadcast); } if (precision >= 1) { core.skillModService.addSkillMod(creature, "precision", (int) precision); - creature.sendSystemMessage("spam", "level_up_stat_gain_1", (int) precision, 0); + creature.sendSystemMessage(OutOfBand.ProsePackage("@spam:level_up_stat_gain_1", (int) precision), DisplayType.Broadcast); } if (strength >= 1) { core.skillModService.addSkillMod(creature, "strength", (int) strength); - creature.sendSystemMessage("spam", "level_up_stat_gain_2", (int) strength, 0); + creature.sendSystemMessage(OutOfBand.ProsePackage("@spam:level_up_stat_gain_2", (int) strength), DisplayType.Broadcast); } if (constitution >= 1) { core.skillModService.addSkillMod(creature, "constitution", (int) constitution); - creature.sendSystemMessage("spam", "level_up_stat_gain_3", (int) constitution, 0); + creature.sendSystemMessage(OutOfBand.ProsePackage("@spam:level_up_stat_gain_3", (int) constitution), DisplayType.Broadcast); } if (stamina >= 1) { core.skillModService.addSkillMod(creature, "stamina", (int) stamina); - creature.sendSystemMessage("spam", "level_up_stat_gain_4", (int) stamina, 0); + creature.sendSystemMessage(OutOfBand.ProsePackage("@spam:level_up_stat_gain_4", (int) stamina), DisplayType.Broadcast); } if (agility >= 1) { core.skillModService.addSkillMod(creature, "agility", (int) agility); - creature.sendSystemMessage("spam", "level_up_stat_gain_5", (int) agility, 0); + creature.sendSystemMessage(OutOfBand.ProsePackage("@spam:level_up_stat_gain_5", (int) agility), DisplayType.Broadcast); } if (health >= 1) { creature.setMaxHealth((creature.getMaxHealth() + (int) health + (healthGranted - creature.getGrantedHealth()))); creature.setHealth(creature.getMaxHealth()); - creature.sendSystemMessage("spam", "level_up_stat_gain_6", (((int) health) + (((int) constitution) * 8) + (((int) stamina) * 2)), 0); + creature.sendSystemMessage(OutOfBand.ProsePackage("@spam:level_up_stat_gain_6", (((int) health) + (((int) constitution) * 8) + (((int) stamina) * 2))), DisplayType.Broadcast); } if (action >= 1) { creature.setMaxAction((creature.getMaxAction() + (int) action)); creature.setAction(creature.getMaxAction()); - creature.sendSystemMessage("spam", "level_up_stat_gain_7", (((int) action) + (((int) stamina) * 8) + (((int) constitution) * 2)), 0); + creature.sendSystemMessage(OutOfBand.ProsePackage("@spam:level_up_stat_gain_7", (((int) action) + (((int) stamina) * 8) + (((int) constitution) * 2))), DisplayType.Broadcast); } creature.setGrantedHealth(((Integer) experienceTable.getObject(i, 4))); // -> Expertise point added automatically by client - creature.showFlyText("cbt_spam", "level_up", (float) 2.5, new RGB(100, 149, 237), 0); + creature.showFlyText(OutOfBand.ProsePackage("@cbt_spam:level_up"), 2.5f, new RGB(100, 149, 237), 0, true); // 4. Adds roadmap rewards int level = creature.getLevel(); @@ -950,7 +953,7 @@ public class PlayerService implements INetworkDispatch { } } - creature.showFlyText("cbt_spam", "skill_up", (float) 2.5, new RGB(154, 205, 50), 0); + creature.showFlyText(OutOfBand.ProsePackage("@cbt_spam:skill_up"), 2.5f, new RGB(154, 205, 50), 0, true); creature.playEffectObject("clienteffect/skill_granted.cef", ""); creature.playMusic("sound/music_acq_bountyhunter.snd"); core.skillService.addSkill(creature, roadmapSkillName); diff --git a/src/services/SimulationService.java b/src/services/SimulationService.java index 22b30882..f628f078 100644 --- a/src/services/SimulationService.java +++ b/src/services/SimulationService.java @@ -811,7 +811,7 @@ public class SimulationService implements INetworkDispatch { core.weatherService.sendWeather(object); if (!object.hasSkill(ghost.getProfessionWheelPosition())) { - object.showFlyText("cbt_spam", "skill_up", (float) 2.5, new RGB(154, 205, 50), 0); + object.showFlyText(OutOfBand.ProsePackage("@cbt_spam:skill_up"), 2.5f, new RGB(154, 205, 50), 0, true); object.playEffectObject("clienteffect/skill_granted.cef", ""); object.playMusic("sound/music_acq_bountyhunter.snd"); core.skillService.addSkill(object, ghost.getProfessionWheelPosition()); @@ -822,6 +822,7 @@ public class SimulationService implements INetworkDispatch { if(object.getPosture() == Posture.Dead) core.playerService.sendCloningWindow(object, false); + } public void transferToPlanet(SWGObject object, Planet planet, Point3D newPos, Quaternion newOrientation, SWGObject newParent) { diff --git a/src/services/chat/ChatService.java b/src/services/chat/ChatService.java index 06afbab6..3ba38bad 100644 --- a/src/services/chat/ChatService.java +++ b/src/services/chat/ChatService.java @@ -44,6 +44,7 @@ import engine.resources.scene.Point3D; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; import resources.common.*; +import resources.datatables.DisplayType; import resources.objects.creature.CreatureObject; import resources.objects.player.PlayerObject; import protocol.swg.AddIgnoreMessage; @@ -719,7 +720,7 @@ public class ChatService implements INetworkDispatch { } public void broadcastGalaxy(String message) { - core.simulationService.notifyAllClients(new ChatSystemMessage(message, (byte) 0).serialize()); + core.simulationService.notifyAllClients(new ChatSystemMessage(message, new OutOfBand(), DisplayType.Broadcast).serialize()); } private void loadChatRooms() { diff --git a/src/services/collections/CollectionService.java b/src/services/collections/CollectionService.java index e31bde4c..4342ff12 100644 --- a/src/services/collections/CollectionService.java +++ b/src/services/collections/CollectionService.java @@ -30,11 +30,11 @@ import org.python.core.Py; import org.python.core.PyObject; import resources.common.FileUtilities; +import resources.common.OutOfBand; +import resources.datatables.DisplayType; import resources.objects.creature.CreatureObject; import resources.objects.player.PlayerObject; - import main.NGECore; - import engine.clientdata.ClientFileManager; import engine.clientdata.visitors.DatatableVisitor; import engine.resources.scene.Point3D; @@ -311,7 +311,7 @@ public class CollectionService implements INetworkDispatch { player.setCollections(collections.toByteArray()); if (!hidden && !noMessage) { - creature.sendSystemMessage("collection_n", collection, 0, 0); + creature.sendSystemMessage(OutOfBand.ProsePackage("@collection_n:" + collection), DisplayType.Broadcast); } if (!music.equals("")) {