Late-pulling
This commit is contained in:
parent
0b1270a916
commit
fff9fb90fa
@ -2,7 +2,9 @@ package dev.wiing.gossip.client;
|
||||
|
||||
import dev.wiing.gossip.lib.PacketHandler;
|
||||
import dev.wiing.gossip.lib.PacketManager;
|
||||
import dev.wiing.gossip.lib.data.LongData;
|
||||
import dev.wiing.gossip.lib.models.SecretUser;
|
||||
import dev.wiing.gossip.lib.models.Topic;
|
||||
import dev.wiing.gossip.lib.models.User;
|
||||
import dev.wiing.gossip.lib.packets.*;
|
||||
|
||||
@ -103,9 +105,11 @@ public class Connection {
|
||||
}
|
||||
|
||||
public Packet nextPacket(boolean useQueue) throws SocketException {
|
||||
synchronized (queuedPackets) {
|
||||
if (useQueue && !queuedPackets.isEmpty()) {
|
||||
return queuedPackets.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return getPacketManager().readPacket(getSocket().getInputStream());
|
||||
@ -137,6 +141,7 @@ public class Connection {
|
||||
public Packet findPacketOfTypes(List<Short> types) {
|
||||
Packet packet = null;
|
||||
|
||||
synchronized (queuedPackets) {
|
||||
int i;
|
||||
for (i = 0; i < queuedPackets.size(); i++) {
|
||||
Packet queuedPacket = queuedPackets.get(i);
|
||||
@ -154,6 +159,7 @@ public class Connection {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean findAck(short acknowledgement) throws IOException {
|
||||
|
||||
@ -162,6 +168,7 @@ public class Connection {
|
||||
|
||||
AckPacket ack = null;
|
||||
|
||||
synchronized (queuedPackets) {
|
||||
int i;
|
||||
for (i = 0; i < queuedPackets.size(); i++) {
|
||||
Packet queuedPacket = queuedPackets.get(i);
|
||||
@ -183,6 +190,7 @@ public class Connection {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SecretUser getSelf() {
|
||||
return self;
|
||||
@ -198,17 +206,9 @@ public class Connection {
|
||||
));
|
||||
}
|
||||
|
||||
private final Map<Long, User> userCache = new ConcurrentHashMap<>();
|
||||
|
||||
public User getUser(long userID) {
|
||||
User result;
|
||||
|
||||
if ((result = userCache.getOrDefault(userID, null)) != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
private final DataCache<User> userCache = new DataCache<>(id -> {
|
||||
UserFetchPacket fetch = new UserFetchPacket();
|
||||
fetch.setUserID(userID);
|
||||
fetch.setUserID(id);
|
||||
Connection.getInstance().sendPacket(fetch);
|
||||
|
||||
Packet resp;
|
||||
@ -219,14 +219,50 @@ public class Connection {
|
||||
}
|
||||
if (resp.getType() == UserDataPacket.TYPE) {
|
||||
UserDataPacket userData = (UserDataPacket)resp;
|
||||
result = new User(
|
||||
return new User(
|
||||
userData.getUsername(),
|
||||
userData.getAvatarID(),
|
||||
userData.getUserID()
|
||||
);
|
||||
userCache.put(result.getUserID(), result);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
public User getUser(long userID) {
|
||||
return userCache.get(userID);
|
||||
}
|
||||
|
||||
private final DataCache<Topic> topicCache = new DataCache<>(id -> {
|
||||
TopicFetchPacket fetch = new TopicFetchPacket();
|
||||
fetch.setTopicID(id);
|
||||
Connection.getInstance().sendPacket(fetch);
|
||||
|
||||
Packet resp;
|
||||
try {
|
||||
resp = Connection.getInstance().nextPacket(TopicDataPacket.TYPE);
|
||||
} catch (SocketException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (resp.getType() == TopicDataPacket.TYPE) {
|
||||
TopicDataPacket topicData = (TopicDataPacket)resp;
|
||||
Topic result = new Topic(
|
||||
topicData.getTopicID(),
|
||||
topicData.getTopicName(),
|
||||
topicData.getTopicDescription(),
|
||||
getUser(topicData.getHostID()),
|
||||
topicData.getTopicColor()
|
||||
);
|
||||
for (LongData userID : topicData.getUserIDs()) {
|
||||
result.addUser(getUser(userID.getValue()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
|
||||
public Topic getTopic(long topicID) {
|
||||
return topicCache.get(topicID);
|
||||
}
|
||||
}
|
||||
|
||||
48
Client/src/main/java/dev/wiing/gossip/client/DataCache.java
Normal file
48
Client/src/main/java/dev/wiing/gossip/client/DataCache.java
Normal file
@ -0,0 +1,48 @@
|
||||
package dev.wiing.gossip.client;
|
||||
|
||||
import dev.wiing.gossip.lib.data.LongData;
|
||||
import dev.wiing.gossip.lib.models.Topic;
|
||||
import dev.wiing.gossip.lib.packets.Packet;
|
||||
import dev.wiing.gossip.lib.packets.TopicDataPacket;
|
||||
import dev.wiing.gossip.lib.packets.TopicFetchPacket;
|
||||
|
||||
import java.net.SocketException;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class DataCache<T> {
|
||||
|
||||
private final DataFetchFunction<T> fetchFunction;
|
||||
|
||||
public DataCache(DataFetchFunction<T> fetchFunction) {
|
||||
this.fetchFunction = fetchFunction;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface DataFetchFunction<U> {
|
||||
U fetch(long id);
|
||||
}
|
||||
|
||||
private final Map<Long, T> cache = new ConcurrentHashMap<>();
|
||||
|
||||
public T get(long id) {
|
||||
if (id == 0) return null;
|
||||
|
||||
T result;
|
||||
|
||||
if ((result = cache.getOrDefault(id, null)) != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = fetchFunction.fetch(id);
|
||||
if (result != null) {
|
||||
cache.put(id, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void put(long id, T val) {
|
||||
cache.put(id, val);
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,7 @@ public class GossipApp extends Application {
|
||||
System.setProperty("prism.lcdtext", "false");
|
||||
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(Program.class.getResource("views/login-view.fxml"));
|
||||
Scene scene = new Scene(fxmlLoader.load(), 320, 240);
|
||||
Scene scene = new Scene(fxmlLoader.load(), 500, 400);
|
||||
|
||||
stage.setTitle("GossipApp");
|
||||
stage.setScene(scene);
|
||||
|
||||
@ -2,9 +2,11 @@ package dev.wiing.gossip.client.controllers;
|
||||
|
||||
import dev.wiing.gossip.client.Connection;
|
||||
import dev.wiing.gossip.client.controllers.item.MessageItemController;
|
||||
import dev.wiing.gossip.client.controllers.item.SystemMessageItemController;
|
||||
import dev.wiing.gossip.client.generic.Pair;
|
||||
import dev.wiing.gossip.client.utils.Utils;
|
||||
import dev.wiing.gossip.lib.models.Message;
|
||||
import dev.wiing.gossip.lib.models.SystemMessage;
|
||||
import dev.wiing.gossip.lib.models.UserMessage;
|
||||
import dev.wiing.gossip.lib.models.Topic;
|
||||
import dev.wiing.gossip.lib.packets.MessagePushPacket;
|
||||
import dev.wiing.gossip.lib.packets.TopicJoinPacket;
|
||||
@ -17,6 +19,7 @@ import javafx.scene.control.TextArea;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -81,7 +84,13 @@ public class MainChatController {
|
||||
|
||||
if (evt.getPropertyName().equals("messageAdd")) {
|
||||
Platform.runLater(() -> {
|
||||
addMessage((Message)evt.getNewValue());
|
||||
if (evt.getNewValue() instanceof UserMessage) {
|
||||
addMessage((UserMessage)evt.getNewValue());
|
||||
}
|
||||
|
||||
else if (evt.getNewValue() instanceof SystemMessage) {
|
||||
addSystemMessage((SystemMessage)evt.getNewValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -113,18 +122,28 @@ public class MainChatController {
|
||||
vboxVisitPage.setVisible(!participating);
|
||||
}
|
||||
|
||||
private void addMessage(Message message) {
|
||||
if (latestMessageItem == null || latestMessageItem.getAuthor().getUserID() != message.getAuthor().getUserID()) {
|
||||
private void addMessage(UserMessage userMessage) {
|
||||
if (latestMessageItem == null || latestMessageItem.getAuthor().getUserID() != userMessage.getAuthor().getUserID()) {
|
||||
var newPair = MessageItemController.createInstance();
|
||||
|
||||
newPair.second().setAuthor(message.getAuthor());
|
||||
newPair.second().setAuthor(userMessage.getAuthor());
|
||||
|
||||
vboxMessages.getChildren().add(newPair.first());
|
||||
|
||||
latestMessageItem = newPair.second();
|
||||
}
|
||||
|
||||
latestMessageItem.addMessage(message);
|
||||
latestMessageItem.addMessage(userMessage);
|
||||
}
|
||||
|
||||
private void addSystemMessage(SystemMessage systemMessage) {
|
||||
latestMessageItem = null;
|
||||
|
||||
var pair = SystemMessageItemController.createInstance();
|
||||
|
||||
pair.second().setSystemMessage(systemMessage);
|
||||
|
||||
vboxMessages.getChildren().add(pair.first());
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
||||
@ -6,9 +6,7 @@ import dev.wiing.gossip.client.data.UserAvatar;
|
||||
import dev.wiing.gossip.client.generic.Pair;
|
||||
import dev.wiing.gossip.client.utils.Utils;
|
||||
import dev.wiing.gossip.lib.data.LongData;
|
||||
import dev.wiing.gossip.lib.models.Message;
|
||||
import dev.wiing.gossip.lib.models.Topic;
|
||||
import dev.wiing.gossip.lib.models.User;
|
||||
import dev.wiing.gossip.lib.models.*;
|
||||
import dev.wiing.gossip.lib.packets.*;
|
||||
import javafx.application.Platform;
|
||||
import javafx.event.ActionEvent;
|
||||
@ -20,6 +18,7 @@ import javafx.scene.layout.AnchorPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import java.net.SocketException;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
@ -56,6 +55,25 @@ public class MainController implements Initializable {
|
||||
|
||||
UserAvatar.getAvatar(user.getAvatarID()).applyToRegionBackground(paneIcon, true);
|
||||
|
||||
TopicListFetchPacket topicListFetchPacket = new TopicListFetchPacket();
|
||||
Connection.getInstance().sendPacket(topicListFetchPacket);
|
||||
|
||||
try {
|
||||
Packet topicListFetchResult = Connection.getInstance().nextPacket(TopicListDataPacket.TYPE);
|
||||
if (topicListFetchResult != null) {
|
||||
TopicListDataPacket topicListData = (TopicListDataPacket) topicListFetchResult;
|
||||
for (LongData topicID : topicListData.getTopicIDs()) {
|
||||
Topic topic = Connection.getInstance().getTopic(topicID.getValue());
|
||||
|
||||
if (topic == null) continue;
|
||||
|
||||
addTopic(topic);
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Connection.getInstance().getPacketHandler().addListener(TopicCreatedPacket.class, packet -> {
|
||||
User host = Connection.getInstance().getUser(packet.getHostID());
|
||||
|
||||
@ -67,29 +85,7 @@ public class MainController implements Initializable {
|
||||
packet.getTopicColor()
|
||||
);
|
||||
|
||||
var pair = TopicItemController.createInstance();
|
||||
pair.second().setTopic(topic);
|
||||
|
||||
var contentPair = MainChatController.createInstance();
|
||||
contentPair.second().setTopic(topic);
|
||||
|
||||
topicMap.put(topic.getId(), contentPair);
|
||||
|
||||
AnchorPane.setLeftAnchor(contentPair.first(), 0.0);
|
||||
AnchorPane.setBottomAnchor(contentPair.first(), 0.0);
|
||||
AnchorPane.setTopAnchor(contentPair.first(), 0.0);
|
||||
AnchorPane.setRightAnchor(contentPair.first(), 0.0);
|
||||
contentPair.first().setVisible(false);
|
||||
|
||||
Platform.runLater(() -> {
|
||||
paneContent.getChildren().add(contentPair.first());
|
||||
|
||||
vboxTopics.getChildren().add(pair.first());
|
||||
});
|
||||
|
||||
pair.second().setOnMouseClicked(event -> {
|
||||
setActiveTopic(topic, pair.first());
|
||||
});
|
||||
addTopic(topic);
|
||||
});
|
||||
|
||||
Connection.getInstance().getPacketHandler().addListener(TopicUpdatePacket.class, packet -> {
|
||||
@ -122,9 +118,24 @@ public class MainController implements Initializable {
|
||||
|
||||
User author = Connection.getInstance().getUser(packet.getAuthorID());
|
||||
|
||||
Message message = new Message(author, topic, packet.getContents());
|
||||
UserMessage userMessage = new UserMessage(packet.getMessageID(), author, topic, packet.getContents());
|
||||
|
||||
topic.addMessage(message);
|
||||
topic.addMessage(userMessage);
|
||||
});
|
||||
|
||||
Connection.getInstance().getPacketHandler().addListener(MessageSystemPacket.class, packet -> {
|
||||
if (!topicMap.containsKey(packet.getTopicID())) return;
|
||||
|
||||
Topic topic = topicMap.get(packet.getTopicID()).second().getTopic();
|
||||
|
||||
User targetUser = null;
|
||||
if (packet.getUserID() != 0) {
|
||||
targetUser = Connection.getInstance().getUser(packet.getUserID());
|
||||
}
|
||||
|
||||
SystemMessage systemMessage = new SystemMessage(packet.getMessageID(), topic, packet.getSystemType(), targetUser, packet.getContent());
|
||||
|
||||
topic.addMessage(systemMessage);
|
||||
});
|
||||
|
||||
Connection.getInstance().beginHandlingPackets();
|
||||
@ -132,6 +143,90 @@ public class MainController implements Initializable {
|
||||
vboxTopics.getChildren().clear();
|
||||
}
|
||||
|
||||
private void fetchTopicMessage(Topic topic, long messageID) {
|
||||
MessageFetchPacket messageFetchPacket = new MessageFetchPacket();
|
||||
messageFetchPacket.setMessageID(messageID);
|
||||
messageFetchPacket.setTopicID(topic.getId());
|
||||
Connection.getInstance().sendPacket(messageFetchPacket);
|
||||
|
||||
try {
|
||||
Packet messageFetchResult = Connection.getInstance().nextPacket(MessageDataPacket.TYPE);
|
||||
if (messageFetchResult == null) return;
|
||||
|
||||
MessageDataPacket messageData = (MessageDataPacket) messageFetchResult;
|
||||
|
||||
Message message = null;
|
||||
if (messageData.isUserMessage()) {
|
||||
message = new UserMessage(
|
||||
messageData.getMessageID(),
|
||||
Connection.getInstance().getUser(messageData.getUserAuthorID()),
|
||||
Connection.getInstance().getTopic(messageData.getTopicID()),
|
||||
messageData.getUserContents()
|
||||
);
|
||||
}
|
||||
else if (messageData.isSystemMessage()) {
|
||||
message = new SystemMessage(
|
||||
messageData.getMessageID(),
|
||||
Connection.getInstance().getTopic(messageData.getTopicID()),
|
||||
messageData.getSystemType(),
|
||||
Connection.getInstance().getUser(messageData.getSystemUserID()),
|
||||
messageData.getSystemContents()
|
||||
);
|
||||
}
|
||||
|
||||
if (message != null) {
|
||||
message.getTopic().addMessage(message);
|
||||
}
|
||||
|
||||
} catch (SocketException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void addTopic(Topic topic) {
|
||||
var pair = TopicItemController.createInstance();
|
||||
pair.second().setTopic(topic);
|
||||
|
||||
var contentPair = MainChatController.createInstance();
|
||||
contentPair.second().setTopic(topic);
|
||||
|
||||
topicMap.put(topic.getId(), contentPair);
|
||||
|
||||
AnchorPane.setLeftAnchor(contentPair.first(), 0.0);
|
||||
AnchorPane.setBottomAnchor(contentPair.first(), 0.0);
|
||||
AnchorPane.setTopAnchor(contentPair.first(), 0.0);
|
||||
AnchorPane.setRightAnchor(contentPair.first(), 0.0);
|
||||
contentPair.first().setVisible(false);
|
||||
|
||||
MessageListFetchPacket messageListFetchPacket = new MessageListFetchPacket();
|
||||
messageListFetchPacket.setTopicID(topic.getId());
|
||||
Connection.getInstance().sendPacket(messageListFetchPacket);
|
||||
|
||||
Platform.runLater(() -> {
|
||||
paneContent.getChildren().add(contentPair.first());
|
||||
|
||||
vboxTopics.getChildren().add(pair.first());
|
||||
});
|
||||
|
||||
pair.second().setOnMouseClicked(event -> {
|
||||
setActiveTopic(topic, pair.first());
|
||||
});
|
||||
|
||||
try {
|
||||
Packet messageListFetchResult = Connection.getInstance().nextPacket(MessageListDataPacket.TYPE);
|
||||
if (messageListFetchResult == null) return;
|
||||
|
||||
MessageListDataPacket messageListDataPacket = (MessageListDataPacket) messageListFetchResult;
|
||||
|
||||
for (LongData messageID : messageListDataPacket.getMessageIDs()) {
|
||||
fetchTopicMessage(topic, messageID.getValue());
|
||||
}
|
||||
|
||||
} catch (SocketException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void setActiveTopic(Topic topic, Parent element) {
|
||||
if (activeTopic != null) {
|
||||
activeTopicElement.getStyleClass().remove("tag-min");
|
||||
|
||||
@ -4,7 +4,7 @@ import dev.wiing.gossip.client.Connection;
|
||||
import dev.wiing.gossip.client.data.UserAvatar;
|
||||
import dev.wiing.gossip.client.generic.Pair;
|
||||
import dev.wiing.gossip.client.utils.Utils;
|
||||
import dev.wiing.gossip.lib.models.Message;
|
||||
import dev.wiing.gossip.lib.models.UserMessage;
|
||||
import dev.wiing.gossip.lib.models.User;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.Initializable;
|
||||
@ -22,7 +22,7 @@ import java.util.ResourceBundle;
|
||||
public class MessageItemController implements Initializable {
|
||||
|
||||
private User author;
|
||||
private final List<Message> messages = Collections.synchronizedList(new ArrayList<>());
|
||||
private final List<UserMessage> userMessages = Collections.synchronizedList(new ArrayList<>());
|
||||
|
||||
@FXML
|
||||
private Label lblAuthor;
|
||||
@ -61,24 +61,24 @@ public class MessageItemController implements Initializable {
|
||||
UserAvatar.getAvatar(this.author.getAvatarID()).applyToRegionBackground(paneIcon, true);
|
||||
}
|
||||
|
||||
public void addMessage(Message message) {
|
||||
if (message.getAuthor() != author) return;
|
||||
public void addMessage(UserMessage userMessage) {
|
||||
if (userMessage.getAuthor() != author) return;
|
||||
|
||||
if (!this.lblTag.isVisible() && messages.isEmpty() && message.getTopic().getHost().getUserID() == message.getAuthor().getUserID()) {
|
||||
if (!this.lblTag.isVisible() && userMessages.isEmpty() && userMessage.getTopic().getHost().getUserID() == userMessage.getAuthor().getUserID()) {
|
||||
this.lblTag.setVisible(true);
|
||||
this.lblTag.setText("Host");
|
||||
this.lblTag.getStyleClass().add("secondary");
|
||||
}
|
||||
|
||||
messages.add(message);
|
||||
userMessages.add(userMessage);
|
||||
|
||||
Label label = new Label(message.getContents());
|
||||
Label label = new Label(userMessage.getContents());
|
||||
|
||||
vboxMessages.getChildren().add(label);
|
||||
}
|
||||
|
||||
public List<Message> getMessageReadOnly() {
|
||||
return Collections.unmodifiableList(messages);
|
||||
public List<UserMessage> getMessageReadOnly() {
|
||||
return Collections.unmodifiableList(userMessages);
|
||||
}
|
||||
|
||||
public static Pair<Parent, MessageItemController> createInstance() {
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
package dev.wiing.gossip.client.controllers.item;
|
||||
|
||||
import dev.wiing.gossip.client.generic.Pair;
|
||||
import dev.wiing.gossip.client.utils.Utils;
|
||||
import dev.wiing.gossip.lib.models.SystemMessage;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.Pane;
|
||||
|
||||
public class SystemMessageItemController {
|
||||
|
||||
private SystemMessage systemMessage;
|
||||
|
||||
@FXML
|
||||
private ImageView imgIcon;
|
||||
|
||||
@FXML
|
||||
private Label lblPrefix;
|
||||
|
||||
@FXML
|
||||
private Label lblSuffix;
|
||||
|
||||
@FXML
|
||||
private Label lblTimeAgo;
|
||||
|
||||
@FXML
|
||||
private Label lblContent;
|
||||
|
||||
public void setSystemMessage(SystemMessage systemMessage) {
|
||||
this.systemMessage = systemMessage;
|
||||
|
||||
switch (this.systemMessage.getType()) {
|
||||
case SystemMessage.SystemType.USER_JOIN:
|
||||
removeNode(lblPrefix);
|
||||
lblContent.setText(systemMessage.getUser().getUsernameDisplay());
|
||||
lblSuffix.setText("joined the Topic");
|
||||
break;
|
||||
|
||||
case SystemMessage.SystemType.USER_LEAVE:
|
||||
removeNode(lblPrefix);
|
||||
lblContent.setText(systemMessage.getUser().getUsernameDisplay());
|
||||
lblSuffix.setText("left the Topic");
|
||||
break;
|
||||
|
||||
case SystemMessage.SystemType.NAME_CHANGE:
|
||||
lblPrefix.setText("Topic changed to");
|
||||
lblContent.setText(systemMessage.getContents());
|
||||
removeNode(lblSuffix);
|
||||
break;
|
||||
|
||||
case SystemMessage.SystemType.DESCRIPTION_CHANGE:
|
||||
lblPrefix.setText("Topic Description changed");
|
||||
removeNode(lblContent);
|
||||
removeNode(lblSuffix);
|
||||
break;
|
||||
|
||||
case SystemMessage.SystemType.HOST_CHANGE:
|
||||
lblPrefix.setText("Host changed to");
|
||||
lblContent.setText(systemMessage.getUser().getUsernameDisplay());
|
||||
removeNode(lblSuffix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void removeNode(Node node) {
|
||||
((Pane)node.getParent()).getChildren().remove(node);
|
||||
}
|
||||
|
||||
public static Pair<Parent, SystemMessageItemController> createInstance() {
|
||||
return Utils.createInstance("views/system-message-item.fxml");
|
||||
}
|
||||
|
||||
}
|
||||
@ -12,11 +12,10 @@
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Pane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.shape.Circle?>
|
||||
|
||||
<AnchorPane prefHeight="318.0" prefWidth="523.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="dev.wiing.gossip.client.controllers.MainChatController">
|
||||
<AnchorPane prefHeight="318.0" prefWidth="523.0" xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="dev.wiing.gossip.client.controllers.MainChatController">
|
||||
<children>
|
||||
<VBox fx:id="vboxVisitPage" alignment="CENTER" layoutX="10.0" layoutY="10.0" spacing="8.0" visible="false" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||
<children>
|
||||
@ -59,63 +58,6 @@
|
||||
<ScrollPane fitToWidth="true" hbarPolicy="NEVER" VBox.vgrow="ALWAYS">
|
||||
<content>
|
||||
<VBox fx:id="vboxMessages" spacing="16.0">
|
||||
<children>
|
||||
<HBox spacing="8.0">
|
||||
<children>
|
||||
<Pane maxHeight="40.0" maxWidth="40.0" minHeight="40.0" minWidth="40.0" style="-fx-background-color: white;" />
|
||||
<VBox alignment="CENTER_LEFT" minHeight="40.0" spacing="4.0" HBox.hgrow="ALWAYS">
|
||||
<children>
|
||||
<HBox alignment="BOTTOM_LEFT" spacing="8.0">
|
||||
<children>
|
||||
<Label style="-fx-font-size: 14;" text="\@ Username">
|
||||
<styleClass>
|
||||
<String fx:value="axis" />
|
||||
<String fx:value="accent" />
|
||||
</styleClass>
|
||||
</Label>
|
||||
<Label text="You">
|
||||
<styleClass>
|
||||
<String fx:value="tag" />
|
||||
<String fx:value="small" />
|
||||
<String fx:value="axis" />
|
||||
</styleClass>
|
||||
</Label>
|
||||
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" maxWidth="1.7976931348623157E308" style="-fx-font-size: 10;" styleClass="faint" text="10 minutes ago" textAlignment="RIGHT" HBox.hgrow="ALWAYS" />
|
||||
</children>
|
||||
</HBox>
|
||||
<VBox spacing="4.0">
|
||||
<children>
|
||||
<Label text="Message contents" />
|
||||
</children>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
</children>
|
||||
</HBox>
|
||||
<HBox alignment="CENTER_LEFT" layoutX="26.0" layoutY="26.0" spacing="8.0">
|
||||
<children>
|
||||
<ImageView fitHeight="20.0" fitWidth="20.0" opacity="0.5" pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@../icons/door-enter.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
<Label style="-fx-font-size: 14;" styleClass="axis" text="\@ Username" />
|
||||
<Label layoutX="46.0" layoutY="19.0" style="-fx-font-size: 12;" text="joined the Topic" />
|
||||
<Label alignment="CENTER_RIGHT" contentDisplay="RIGHT" maxWidth="1.7976931348623157E308" style="-fx-font-size: 10;" styleClass="faint" text="10 minutes ago" textAlignment="RIGHT" HBox.hgrow="ALWAYS">
|
||||
<HBox.margin>
|
||||
<Insets />
|
||||
</HBox.margin>
|
||||
</Label>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="8.0" left="16.0" right="16.0" top="8.0" />
|
||||
</padding>
|
||||
<styleClass>
|
||||
<String fx:value="elevated" />
|
||||
<String fx:value="border-radius-small" />
|
||||
</styleClass>
|
||||
</HBox>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="16.0" left="16.0" right="16.0" top="16.0" />
|
||||
</padding>
|
||||
|
||||
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import java.lang.String?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
|
||||
<HBox alignment="CENTER_LEFT" spacing="8.0" stylesheets="@../styling.css" xmlns="http://javafx.com/javafx/20.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="dev.wiing.gossip.client.controllers.item.SystemMessageItemController">
|
||||
<children>
|
||||
<ImageView fx:id="imgIcon" fitHeight="20.0" fitWidth="20.0" opacity="0.5" pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@../icons/door-enter.png" />
|
||||
</image>
|
||||
</ImageView>
|
||||
<Label fx:id="lblPrefix" style="-fx-font-size: 12;" text="joined the Topic" />
|
||||
<Label fx:id="lblContent" style="-fx-font-size: 14;" styleClass="axis" text="\@ Username" />
|
||||
<Label fx:id="lblSuffix" layoutX="46.0" layoutY="19.0" style="-fx-font-size: 12;" text="joined the Topic" />
|
||||
<Label fx:id="lblTimeAgo" alignment="CENTER_RIGHT" contentDisplay="RIGHT" maxWidth="1.7976931348623157E308" style="-fx-font-size: 10;" styleClass="faint" text="10 minutes ago" textAlignment="RIGHT" HBox.hgrow="ALWAYS">
|
||||
<HBox.margin>
|
||||
<Insets />
|
||||
</HBox.margin>
|
||||
</Label>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="8.0" left="16.0" right="16.0" top="8.0" />
|
||||
</padding>
|
||||
<styleClass>
|
||||
<String fx:value="elevated" />
|
||||
<String fx:value="border-radius-small" />
|
||||
</styleClass>
|
||||
</HBox>
|
||||
@ -1,9 +1,6 @@
|
||||
package dev.wiing.gossip.lib;
|
||||
|
||||
import dev.wiing.gossip.lib.packets.MessageCreatedPacket;
|
||||
import dev.wiing.gossip.lib.packets.Packet;
|
||||
import dev.wiing.gossip.lib.packets.TopicCreatedPacket;
|
||||
import dev.wiing.gossip.lib.packets.TopicUpdatePacket;
|
||||
import dev.wiing.gossip.lib.packets.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
@ -42,17 +39,14 @@ public class PacketHandler {
|
||||
}
|
||||
|
||||
public boolean runPacket(Packet packet) {
|
||||
switch (packet.getType()) {
|
||||
case TopicCreatedPacket.TYPE:
|
||||
return runPacket(TopicCreatedPacket.class, (TopicCreatedPacket)packet);
|
||||
|
||||
case TopicUpdatePacket.TYPE:
|
||||
return runPacket(TopicUpdatePacket.class, (TopicUpdatePacket)packet);
|
||||
|
||||
case MessageCreatedPacket.TYPE:
|
||||
return runPacket(MessageCreatedPacket.class, (MessageCreatedPacket)packet);
|
||||
}
|
||||
return false;
|
||||
return switch (packet.getType()) {
|
||||
case TopicCreatedPacket.TYPE -> runPacket(TopicCreatedPacket.class, (TopicCreatedPacket) packet);
|
||||
case TopicUpdatePacket.TYPE -> runPacket(TopicUpdatePacket.class, (TopicUpdatePacket) packet);
|
||||
case TopicListDataPacket.TYPE -> runPacket(TopicListDataPacket.class, (TopicListDataPacket) packet);
|
||||
case MessageCreatedPacket.TYPE -> runPacket(MessageCreatedPacket.class, (MessageCreatedPacket) packet);
|
||||
case MessageSystemPacket.TYPE -> runPacket(MessageSystemPacket.class, (MessageSystemPacket) packet);
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
public <T extends Packet> Set<PacketListener<T>> getListeners(Class<T> packetClass) {
|
||||
@ -69,7 +63,9 @@ public class PacketHandler {
|
||||
{
|
||||
add(TopicCreatedPacket.TYPE);
|
||||
add(TopicUpdatePacket.TYPE);
|
||||
add(TopicListDataPacket.TYPE);
|
||||
add(MessageCreatedPacket.TYPE);
|
||||
add(MessageSystemPacket.TYPE);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -23,12 +23,21 @@ public class PacketManager {
|
||||
add(new TopicCreatedPacket());
|
||||
add(new TopicJoinPacket());
|
||||
add(new TopicUpdatePacket());
|
||||
add(new TopicListFetchPacket());
|
||||
add(new TopicListDataPacket());
|
||||
add(new TopicFetchPacket());
|
||||
add(new TopicDataPacket());
|
||||
|
||||
add(new UserFetchPacket());
|
||||
add(new UserDataPacket());
|
||||
|
||||
add(new MessagePushPacket());
|
||||
add(new MessageCreatedPacket());
|
||||
add(new MessageSystemPacket());
|
||||
add(new MessageListFetchPacket());
|
||||
add(new MessageListDataPacket());
|
||||
add(new MessageFetchPacket());
|
||||
add(new MessageDataPacket());
|
||||
}
|
||||
};
|
||||
|
||||
@ -49,7 +58,7 @@ public class PacketManager {
|
||||
}
|
||||
}
|
||||
|
||||
public Packet readPacket(BufferedInputStream stream) throws IOException {
|
||||
public Packet readPacket(InputStream stream) throws IOException {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(stream.readNBytes(6));
|
||||
|
||||
if (buffer.capacity() < 6) return null;
|
||||
@ -64,10 +73,6 @@ public class PacketManager {
|
||||
return packet.readBytes(ByteBuffer.wrap(stream.readNBytes(size)), size);
|
||||
}
|
||||
|
||||
public Packet readPacket(InputStream stream) throws IOException {
|
||||
return readPacket(new BufferedInputStream(stream));
|
||||
}
|
||||
|
||||
public void writePacket(BufferedOutputStream stream, Packet packet) throws IOException {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(packet.getTotalLength());
|
||||
|
||||
@ -77,7 +82,6 @@ public class PacketManager {
|
||||
packet.writeBytes(buffer);
|
||||
|
||||
stream.write(buffer.array());
|
||||
stream.flush();
|
||||
}
|
||||
|
||||
public void writePacket(OutputStream stream, Packet packet) throws IOException {
|
||||
@ -86,6 +90,14 @@ public class PacketManager {
|
||||
outputStream.flush();
|
||||
}
|
||||
|
||||
public void writeAllPackets(OutputStream stream, Packet ...packets) throws IOException {
|
||||
BufferedOutputStream outputStream = new BufferedOutputStream(stream);
|
||||
for (Packet packet : packets) {
|
||||
writePacket(outputStream, packet);
|
||||
}
|
||||
outputStream.flush();
|
||||
}
|
||||
|
||||
public void replyPacket(Packet source, Packet reply) throws IOException {
|
||||
BufferedOutputStream outputStream = new BufferedOutputStream(source.getSource().getOutputStream());
|
||||
writePacket(outputStream, reply);
|
||||
|
||||
@ -3,34 +3,32 @@ package dev.wiing.gossip.lib.models;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class Message {
|
||||
private final User author;
|
||||
private long id;
|
||||
private final Topic topic;
|
||||
private final String contents;
|
||||
private final LocalDateTime postTime;
|
||||
|
||||
public Message(User author, Topic topic, String contents, LocalDateTime postTime) {
|
||||
this.author = author;
|
||||
public Message(long id, Topic topic, LocalDateTime postTime) {
|
||||
this.id = id;
|
||||
this.topic = topic;
|
||||
this.contents = contents;
|
||||
this.postTime = postTime;
|
||||
}
|
||||
|
||||
public Message(User author, Topic topic, String contents) {
|
||||
this(author, topic, contents, LocalDateTime.now());
|
||||
public Message(long id, Topic topic) {
|
||||
this(id, topic, LocalDateTime.now());
|
||||
}
|
||||
|
||||
public User getAuthor() {
|
||||
return author;
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Topic getTopic() {
|
||||
return topic;
|
||||
}
|
||||
|
||||
public String getContents() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
public LocalDateTime getPostTime() {
|
||||
return postTime;
|
||||
}
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
package dev.wiing.gossip.lib.models;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SystemMessage extends Message {
|
||||
|
||||
public static class SystemType {
|
||||
public static final short USER_JOIN = 1;
|
||||
public static final short USER_LEAVE = 2;
|
||||
public static final short NAME_CHANGE = 3;
|
||||
public static final short DESCRIPTION_CHANGE = 4;
|
||||
public static final short HOST_CHANGE = 5;
|
||||
public static final short EXPIRE = 10;
|
||||
}
|
||||
|
||||
private final short type;
|
||||
private final User user;
|
||||
private final String contents;
|
||||
|
||||
public SystemMessage(long id, Topic topic, short type, User user, String contents, LocalDateTime postTime) {
|
||||
super(id, topic, postTime);
|
||||
this.type = type;
|
||||
this.user = user;
|
||||
this.contents = contents;
|
||||
}
|
||||
|
||||
public SystemMessage(long id, Topic topic, short type, User user, String contents) {
|
||||
this(id, topic, type, user, contents, LocalDateTime.now());
|
||||
}
|
||||
|
||||
public short getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public String getContents() {
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,9 @@ public class Topic {
|
||||
private short color;
|
||||
|
||||
private final List<Message> messages = Collections.synchronizedList(new ArrayList<>());
|
||||
private final Map<Long, Message> messageByIDs = new ConcurrentHashMap<>();
|
||||
|
||||
private long messageTrackerID = 1;
|
||||
|
||||
public Topic(long id, String name, String description, User host, short color) {
|
||||
this.id = id;
|
||||
@ -93,10 +96,19 @@ public class Topic {
|
||||
|
||||
public void addMessage(Message message) {
|
||||
messages.add(message);
|
||||
messageByIDs.put(message.getId(), message);
|
||||
|
||||
this.changeSupport.firePropertyChange("messageAdd", null, message);
|
||||
}
|
||||
|
||||
public Message getMessageByID(long messageID) {
|
||||
return messageByIDs.getOrDefault(messageID, null);
|
||||
}
|
||||
|
||||
public long getNextMessageID() {
|
||||
return messageTrackerID++;
|
||||
}
|
||||
|
||||
public void addChangeListener(PropertyChangeListener listener) {
|
||||
this.changeSupport.addPropertyChangeListener(listener);
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
package dev.wiing.gossip.lib.models;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
public class UserMessage extends Message {
|
||||
private final User author;
|
||||
private final String contents;
|
||||
|
||||
public UserMessage(long id, User author, Topic topic, String contents, LocalDateTime postTime) {
|
||||
super(id, topic, postTime);
|
||||
this.author = author;
|
||||
this.contents = contents;
|
||||
}
|
||||
|
||||
public UserMessage(long id, User author, Topic topic, String contents) {
|
||||
this(id, author, topic, contents, LocalDateTime.now());
|
||||
}
|
||||
|
||||
public User getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public String getContents() {
|
||||
return contents;
|
||||
}
|
||||
}
|
||||
@ -7,8 +7,9 @@ import java.nio.ByteBuffer;
|
||||
public class MessageCreatedPacket extends Packet {
|
||||
|
||||
public static final short TYPE = 0x32;
|
||||
public static final int LENGTH = 0x014;
|
||||
public static final int LENGTH = 0x01C;
|
||||
|
||||
private long messageID;
|
||||
private long authorID;
|
||||
private long topicID;
|
||||
private final StringData contents = new StringData();
|
||||
@ -17,6 +18,14 @@ public class MessageCreatedPacket extends Packet {
|
||||
super(TYPE, LENGTH);
|
||||
}
|
||||
|
||||
public long getMessageID() {
|
||||
return messageID;
|
||||
}
|
||||
|
||||
public void setMessageID(long messageID) {
|
||||
this.messageID = messageID;
|
||||
}
|
||||
|
||||
public long getAuthorID() {
|
||||
return authorID;
|
||||
}
|
||||
@ -39,7 +48,7 @@ public class MessageCreatedPacket extends Packet {
|
||||
|
||||
public void setContents(String contents) {
|
||||
this.contents.setValue(contents);
|
||||
setLength(16 + this.contents.getLength());
|
||||
setLength(24 + this.contents.getLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -47,6 +56,7 @@ public class MessageCreatedPacket extends Packet {
|
||||
MessageCreatedPacket packet = new MessageCreatedPacket();
|
||||
packet.setLength(size);
|
||||
|
||||
packet.messageID = buffer.getLong();
|
||||
packet.authorID = buffer.getLong();
|
||||
packet.topicID = buffer.getLong();
|
||||
packet.contents.setBytes(buffer);
|
||||
@ -56,6 +66,7 @@ public class MessageCreatedPacket extends Packet {
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer buffer) {
|
||||
buffer.putLong(messageID);
|
||||
buffer.putLong(authorID);
|
||||
buffer.putLong(topicID);
|
||||
buffer.put(contents.getBytes());
|
||||
|
||||
@ -0,0 +1,151 @@
|
||||
package dev.wiing.gossip.lib.packets;
|
||||
|
||||
import dev.wiing.gossip.lib.data.StringData;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class MessageDataPacket extends Packet {
|
||||
|
||||
public static final short TYPE = 0x37;
|
||||
public static final int LENGTH = 0x000;
|
||||
|
||||
public static class MessageType {
|
||||
public static final byte USER = 1;
|
||||
public static final byte SYSTEM = 2;
|
||||
}
|
||||
|
||||
private long messageID;
|
||||
private long topicID;
|
||||
|
||||
private byte messageType;
|
||||
|
||||
// USER TYPE
|
||||
private long userAuthorID;
|
||||
private final StringData userContents = new StringData();
|
||||
|
||||
// SYSTEM TYPE
|
||||
private short systemType;
|
||||
private long systemUserID = 0;
|
||||
private final StringData systemContents = new StringData();
|
||||
|
||||
public MessageDataPacket() {
|
||||
super(TYPE, LENGTH);
|
||||
}
|
||||
|
||||
private void updateLength() {
|
||||
setLength(17 +
|
||||
(isUserMessage() ? (8 + userContents.getLength()) : 0) +
|
||||
(isSystemMessage() ? (16 + systemContents.getLength()) : 0));
|
||||
}
|
||||
|
||||
public boolean isUserMessage() {
|
||||
return messageType == MessageType.USER;
|
||||
}
|
||||
|
||||
public boolean isSystemMessage() {
|
||||
return messageType == MessageType.SYSTEM;
|
||||
}
|
||||
|
||||
public long getMessageID() {
|
||||
return messageID;
|
||||
}
|
||||
|
||||
public void setMessageID(long messageID) {
|
||||
this.messageID = messageID;
|
||||
}
|
||||
|
||||
public long getTopicID() {
|
||||
return topicID;
|
||||
}
|
||||
|
||||
public void setTopicID(long topicID) {
|
||||
this.topicID = topicID;
|
||||
}
|
||||
|
||||
public byte getMessageType() {
|
||||
return messageType;
|
||||
}
|
||||
|
||||
public void setMessageType(byte messageType) {
|
||||
this.messageType = messageType;
|
||||
}
|
||||
|
||||
public long getUserAuthorID() {
|
||||
return userAuthorID;
|
||||
}
|
||||
|
||||
public void setUserAuthorID(long userAuthorID) {
|
||||
this.userAuthorID = userAuthorID;
|
||||
}
|
||||
|
||||
public String getUserContents() {
|
||||
return userContents.getValue();
|
||||
}
|
||||
|
||||
public void setUserContents(String userContents) {
|
||||
this.userContents.setValue(userContents);
|
||||
updateLength();
|
||||
}
|
||||
|
||||
public short getSystemType() {
|
||||
return systemType;
|
||||
}
|
||||
|
||||
public void setSystemType(short systemType) {
|
||||
this.systemType = systemType;
|
||||
}
|
||||
|
||||
public long getSystemUserID() {
|
||||
return systemUserID;
|
||||
}
|
||||
|
||||
public void setSystemUserID(long systemUserID) {
|
||||
this.systemUserID = systemUserID;
|
||||
}
|
||||
|
||||
public String getSystemContents() {
|
||||
return systemContents.getValue();
|
||||
}
|
||||
|
||||
public void setSystemContents(String systemContents) {
|
||||
this.systemContents.setValue(systemContents);
|
||||
updateLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet readBytes(ByteBuffer buffer, int size) {
|
||||
MessageDataPacket packet = new MessageDataPacket();
|
||||
packet.setLength(size);
|
||||
|
||||
packet.messageID = buffer.getLong();
|
||||
packet.topicID = buffer.getLong();
|
||||
packet.messageType = buffer.get();
|
||||
|
||||
if (packet.isUserMessage()) {
|
||||
packet.userAuthorID = buffer.getLong();
|
||||
packet.userContents.setBytes(buffer);
|
||||
} else if (packet.isSystemMessage()) {
|
||||
packet.systemType = buffer.getShort();
|
||||
packet.systemUserID = buffer.getLong();
|
||||
packet.systemContents.setBytes(buffer);
|
||||
}
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer buffer) {
|
||||
buffer.putLong(messageID);
|
||||
buffer.putLong(topicID);
|
||||
buffer.put(messageType);
|
||||
|
||||
if (isUserMessage()) {
|
||||
buffer.putLong(userAuthorID);
|
||||
buffer.put(userContents.getBytes());
|
||||
} else if (isSystemMessage()) {
|
||||
buffer.putShort(systemType);
|
||||
buffer.putLong(systemUserID);
|
||||
buffer.put(systemContents.getBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package dev.wiing.gossip.lib.packets;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class MessageFetchPacket extends Packet {
|
||||
|
||||
public static final short TYPE = 0x36;
|
||||
public static final int LENGTH = 0x010;
|
||||
|
||||
private long topicID;
|
||||
private long messageID;
|
||||
|
||||
public MessageFetchPacket() {
|
||||
super(TYPE, LENGTH);
|
||||
}
|
||||
|
||||
public long getTopicID() {
|
||||
return topicID;
|
||||
}
|
||||
|
||||
public void setTopicID(long topicID) {
|
||||
this.topicID = topicID;
|
||||
}
|
||||
|
||||
public long getMessageID() {
|
||||
return messageID;
|
||||
}
|
||||
|
||||
public void setMessageID(long messageID) {
|
||||
this.messageID = messageID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet readBytes(ByteBuffer buffer, int size) {
|
||||
MessageFetchPacket packet = new MessageFetchPacket();
|
||||
|
||||
packet.topicID = buffer.getLong();
|
||||
packet.messageID = buffer.getLong();
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer buffer) {
|
||||
buffer.putLong(topicID);
|
||||
buffer.putLong(messageID);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,59 @@
|
||||
package dev.wiing.gossip.lib.packets;
|
||||
|
||||
import dev.wiing.gossip.lib.data.ListData;
|
||||
import dev.wiing.gossip.lib.data.LongData;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
public class MessageListDataPacket extends Packet {
|
||||
|
||||
public static final short TYPE = 0x35;
|
||||
public static final int LENGTH = 0x00C;
|
||||
|
||||
private long topicID;
|
||||
private final ListData<LongData> messageIDs = new ListData<>(LongData::new);
|
||||
|
||||
public MessageListDataPacket() {
|
||||
super(TYPE, LENGTH);
|
||||
}
|
||||
|
||||
private void updateLength() {
|
||||
setLength(8 + messageIDs.getLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
updateLength();
|
||||
return super.getLength();
|
||||
}
|
||||
|
||||
public long getTopicID() {
|
||||
return topicID;
|
||||
}
|
||||
|
||||
public void setTopicID(long topicID) {
|
||||
this.topicID = topicID;
|
||||
}
|
||||
|
||||
public List<LongData> getMessageIDs() {
|
||||
return messageIDs.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet readBytes(ByteBuffer buffer, int size) {
|
||||
MessageListDataPacket packet = new MessageListDataPacket();
|
||||
packet.setLength(size);
|
||||
|
||||
packet.topicID = buffer.getLong();
|
||||
packet.messageIDs.setBytes(buffer);
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer buffer) {
|
||||
buffer.putLong(topicID);
|
||||
buffer.put(messageIDs.getBytes());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package dev.wiing.gossip.lib.packets;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class MessageListFetchPacket extends Packet {
|
||||
|
||||
public static final short TYPE = 0x34;
|
||||
public static final int LENGTH = 0x008;
|
||||
|
||||
private long topicID;
|
||||
|
||||
public MessageListFetchPacket() {
|
||||
super(TYPE, LENGTH);
|
||||
}
|
||||
|
||||
public long getTopicID() {
|
||||
return topicID;
|
||||
}
|
||||
|
||||
public void setTopicID(long topicID) {
|
||||
this.topicID = topicID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet readBytes(ByteBuffer buffer, int size) {
|
||||
MessageListFetchPacket packet = new MessageListFetchPacket();
|
||||
|
||||
packet.topicID = buffer.getLong();
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer buffer) {
|
||||
buffer.putLong(topicID);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
package dev.wiing.gossip.lib.packets;
|
||||
|
||||
import dev.wiing.gossip.lib.data.StringData;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MessageSystemPacket extends Packet {
|
||||
|
||||
public static final short TYPE = 0x33;
|
||||
public static final int LENGTH = 0x01E;
|
||||
|
||||
private long messageID;
|
||||
private long topicID;
|
||||
private short systemType = 0;
|
||||
private long userID = 0;
|
||||
private final StringData content = new StringData();
|
||||
|
||||
public MessageSystemPacket() {
|
||||
super(TYPE, LENGTH);
|
||||
}
|
||||
|
||||
public long getMessageID() {
|
||||
return messageID;
|
||||
}
|
||||
|
||||
public void setMessageID(long messageID) {
|
||||
this.messageID = messageID;
|
||||
}
|
||||
|
||||
public long getTopicID() {
|
||||
return topicID;
|
||||
}
|
||||
|
||||
public void setTopicID(long topicID) {
|
||||
this.topicID = topicID;
|
||||
}
|
||||
|
||||
public short getSystemType() {
|
||||
return systemType;
|
||||
}
|
||||
|
||||
public void setSystemType(short systemType) {
|
||||
this.systemType = systemType;
|
||||
}
|
||||
|
||||
public long getUserID() {
|
||||
return userID;
|
||||
}
|
||||
|
||||
public void setUserID(long userID) {
|
||||
this.userID = userID;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content.getValue();
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content.setValue(content);
|
||||
setLength(26 + this.content.getLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet readBytes(ByteBuffer buffer, int size) {
|
||||
MessageSystemPacket packet = new MessageSystemPacket();
|
||||
packet.setLength(size);
|
||||
|
||||
packet.messageID = buffer.getLong();
|
||||
packet.topicID = buffer.getLong();
|
||||
packet.systemType = buffer.getShort();
|
||||
packet.userID = buffer.getLong();
|
||||
packet.content.setBytes(buffer);
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer buffer) {
|
||||
buffer.putLong(messageID);
|
||||
buffer.putLong(topicID);
|
||||
buffer.putShort(systemType);
|
||||
buffer.putLong(userID);
|
||||
buffer.put(content.getBytes());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
package dev.wiing.gossip.lib.packets;
|
||||
|
||||
import dev.wiing.gossip.lib.data.ListData;
|
||||
import dev.wiing.gossip.lib.data.LongData;
|
||||
import dev.wiing.gossip.lib.data.StringData;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
public class TopicDataPacket extends Packet {
|
||||
|
||||
public static final short TYPE = 0x18;
|
||||
public static final int LENGTH = 0x01E;
|
||||
|
||||
private long topicID;
|
||||
private long hostID;
|
||||
private final StringData topicName = new StringData();
|
||||
private final StringData topicDescription = new StringData();
|
||||
private short topicColor;
|
||||
private final ListData<LongData> userIDs = new ListData<>(LongData::new);
|
||||
|
||||
public TopicDataPacket() {
|
||||
super(TYPE, LENGTH);
|
||||
}
|
||||
|
||||
private void updateLength() {
|
||||
super.setLength(18 +
|
||||
topicName.getLength() +
|
||||
topicDescription.getLength() +
|
||||
userIDs.getLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
updateLength();
|
||||
return super.getLength();
|
||||
}
|
||||
|
||||
public long getTopicID() {
|
||||
return topicID;
|
||||
}
|
||||
|
||||
public void setTopicID(long topicID) {
|
||||
this.topicID = topicID;
|
||||
}
|
||||
|
||||
public long getHostID() {
|
||||
return hostID;
|
||||
}
|
||||
|
||||
public void setHostID(long hostID) {
|
||||
this.hostID = hostID;
|
||||
}
|
||||
|
||||
public String getTopicName() {
|
||||
return topicName.getValue();
|
||||
}
|
||||
|
||||
public void setTopicName(String topicName) {
|
||||
this.topicName.setValue(topicName);
|
||||
updateLength();
|
||||
}
|
||||
|
||||
public String getTopicDescription() {
|
||||
return topicDescription.getValue();
|
||||
}
|
||||
|
||||
public void setTopicDescription(String topicDescription) {
|
||||
this.topicDescription.setValue(topicDescription);
|
||||
updateLength();
|
||||
}
|
||||
|
||||
public short getTopicColor() {
|
||||
return topicColor;
|
||||
}
|
||||
|
||||
public void setTopicColor(short topicColor) {
|
||||
this.topicColor = topicColor;
|
||||
}
|
||||
|
||||
public List<LongData> getUserIDs() {
|
||||
return userIDs.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet readBytes(ByteBuffer buffer, int size) {
|
||||
TopicDataPacket packet = new TopicDataPacket();
|
||||
packet.setLength(size);
|
||||
|
||||
packet.topicID = buffer.getLong();
|
||||
packet.hostID = buffer.getLong();
|
||||
packet.topicName.setBytes(buffer);
|
||||
packet.topicDescription.setBytes(buffer);
|
||||
packet.topicColor = buffer.getShort();
|
||||
packet.userIDs.setBytes(buffer);
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer buffer) {
|
||||
buffer.putLong(topicID);
|
||||
buffer.putLong(hostID);
|
||||
buffer.put(topicName.getBytes());
|
||||
buffer.put(topicDescription.getBytes());
|
||||
buffer.putShort(topicColor);
|
||||
buffer.put(userIDs.getBytes());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
package dev.wiing.gossip.lib.packets;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class TopicFetchPacket extends Packet {
|
||||
|
||||
public static final short TYPE = 0x17;
|
||||
public static final int LENGTH = 8;
|
||||
|
||||
private long topicID;
|
||||
|
||||
public TopicFetchPacket() {
|
||||
super(TYPE, LENGTH);
|
||||
}
|
||||
|
||||
public long getTopicID() {
|
||||
return topicID;
|
||||
}
|
||||
|
||||
public void setTopicID(long topicID) {
|
||||
this.topicID = topicID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet readBytes(ByteBuffer buffer, int size) {
|
||||
TopicFetchPacket packet = new TopicFetchPacket();
|
||||
|
||||
packet.topicID = buffer.getLong();
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer buffer) {
|
||||
buffer.putLong(topicID);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package dev.wiing.gossip.lib.packets;
|
||||
|
||||
import dev.wiing.gossip.lib.data.ListData;
|
||||
import dev.wiing.gossip.lib.data.LongData;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
public class TopicListDataPacket extends Packet {
|
||||
|
||||
public static final short TYPE = 0x16;
|
||||
public static final int LENGTH = 0x004;
|
||||
|
||||
private final ListData<LongData> topicIDs = new ListData<>(LongData::new);
|
||||
|
||||
public TopicListDataPacket() {
|
||||
super(TYPE, LENGTH);
|
||||
}
|
||||
|
||||
private void updateLength() {
|
||||
setLength(this.topicIDs.getLength());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
updateLength();
|
||||
return super.getLength();
|
||||
}
|
||||
|
||||
public List<LongData> getTopicIDs() {
|
||||
return topicIDs.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet readBytes(ByteBuffer buffer, int size) {
|
||||
TopicListDataPacket packet = new TopicListDataPacket();
|
||||
packet.setLength(size);
|
||||
|
||||
packet.topicIDs.setBytes(buffer);
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer buffer) {
|
||||
buffer.put(topicIDs.getBytes());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
package dev.wiing.gossip.lib.packets;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class TopicListFetchPacket extends Packet {
|
||||
|
||||
public static final short TYPE = 0x15;
|
||||
public static final int LENGTH = 0x000;
|
||||
|
||||
public TopicListFetchPacket() {
|
||||
super(TYPE, LENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet readBytes(ByteBuffer buffer, int size) {
|
||||
TopicListFetchPacket packet = new TopicListFetchPacket();
|
||||
packet.setLength(size);
|
||||
|
||||
return packet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeBytes(ByteBuffer buffer) {
|
||||
|
||||
}
|
||||
}
|
||||
@ -134,4 +134,8 @@ public class Database {
|
||||
|
||||
logger.info("Topic removed: \"{}\" (#{})", topic.getName(), topic.getId());
|
||||
}
|
||||
|
||||
public List<Topic> getAllTopicsReadOnly() {
|
||||
return Collections.unmodifiableList(topics.values().stream().toList());
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,15 @@
|
||||
package dev.wiing.gossip.server;
|
||||
|
||||
import dev.wiing.gossip.lib.data.LongData;
|
||||
import dev.wiing.gossip.lib.models.Message;
|
||||
import dev.wiing.gossip.lib.models.SecretUser;
|
||||
import dev.wiing.gossip.lib.models.Topic;
|
||||
import dev.wiing.gossip.lib.models.User;
|
||||
import dev.wiing.gossip.lib.models.*;
|
||||
import dev.wiing.gossip.lib.packets.*;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.util.List;
|
||||
|
||||
public record UserSocket(Socket socket) implements Runnable {
|
||||
|
||||
@ -33,7 +30,7 @@ public record UserSocket(Socket socket) implements Runnable {
|
||||
if (!socket.isConnected())
|
||||
break;
|
||||
|
||||
Packet packet = Globals.getPacketManager().readPacket(new BufferedInputStream(socket.getInputStream()));
|
||||
Packet packet = Globals.getPacketManager().readPacket(socket.getInputStream());
|
||||
|
||||
if (packet == null) continue;
|
||||
|
||||
@ -52,6 +49,14 @@ public record UserSocket(Socket socket) implements Runnable {
|
||||
onUserJoinTopic((TopicJoinPacket) packet);
|
||||
break;
|
||||
|
||||
case TopicListFetchPacket.TYPE:
|
||||
onTopicListFetch((TopicListFetchPacket) packet);
|
||||
break;
|
||||
|
||||
case TopicFetchPacket.TYPE:
|
||||
onFetchTopic((TopicFetchPacket) packet);
|
||||
break;
|
||||
|
||||
case UserFetchPacket.TYPE:
|
||||
onFetchUser((UserFetchPacket) packet);
|
||||
break;
|
||||
@ -59,6 +64,14 @@ public record UserSocket(Socket socket) implements Runnable {
|
||||
case MessagePushPacket.TYPE:
|
||||
onUserMessage((MessagePushPacket) packet);
|
||||
break;
|
||||
|
||||
case MessageListFetchPacket.TYPE:
|
||||
onMessageListFetch((MessageListFetchPacket) packet);
|
||||
break;
|
||||
|
||||
case MessageFetchPacket.TYPE:
|
||||
onFetchMessage((MessageFetchPacket) packet);
|
||||
break;
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
loop = false;
|
||||
@ -120,10 +133,13 @@ public record UserSocket(Socket socket) implements Runnable {
|
||||
if (requester == null) return;
|
||||
if (topic == null) return;
|
||||
|
||||
if (!topic.hasUser(requester)) {
|
||||
if (topic.hasUser(requester)) return;
|
||||
|
||||
info("\"{}\" joined topic \"{}\" (#{})", topic.getHost().getUsername().toUpperCase(), topic.getName().toUpperCase(), topic.getId());
|
||||
topic.addUser(requester);
|
||||
}
|
||||
|
||||
SystemMessage message = new SystemMessage(topic.getNextMessageID(), topic, SystemMessage.SystemType.USER_JOIN, requester, "");
|
||||
topic.addMessage(message);
|
||||
|
||||
AckPacket resp = new AckPacket();
|
||||
resp.setAcknowledgement(packet);
|
||||
@ -138,17 +154,62 @@ public record UserSocket(Socket socket) implements Runnable {
|
||||
updatePacket.setTopicID(topic.getId());
|
||||
updatePacket.getUsersJoined().add(new LongData().setValue(requester.getUserID()));
|
||||
|
||||
MessageSystemPacket systemPacket = new MessageSystemPacket();
|
||||
systemPacket.setTopicID(topic.getId());
|
||||
systemPacket.setSystemType(message.getType());
|
||||
systemPacket.setUserID(message.getUser().getUserID());
|
||||
|
||||
for (User user : Database.getInstance().getUsers()) {
|
||||
Socket socket = Database.getInstance().getUserSocket(user.getUserID());
|
||||
|
||||
try {
|
||||
Globals.getPacketManager().writePacket(socket.getOutputStream(), updatePacket);
|
||||
Globals.getPacketManager().writeAllPackets(socket.getOutputStream(), updatePacket, systemPacket);
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void onTopicListFetch(TopicListFetchPacket packet) {
|
||||
TopicListDataPacket result = new TopicListDataPacket();
|
||||
|
||||
info("Requested Topic list");
|
||||
|
||||
for (Topic topic : Database.getInstance().getAllTopicsReadOnly()) {
|
||||
result.getTopicIDs().add(new LongData().setValue(topic.getId()));
|
||||
}
|
||||
|
||||
try {
|
||||
Globals.getPacketManager().replyPacket(packet, result);
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void onFetchTopic(TopicFetchPacket packet) {
|
||||
Topic topic = Database.getInstance().getTopic(packet.getTopicID());
|
||||
|
||||
if (topic == null) return;
|
||||
|
||||
info("Requested topic #{}", topic.getId());
|
||||
|
||||
TopicDataPacket resp = new TopicDataPacket();
|
||||
resp.setTopicID(topic.getId());
|
||||
resp.setHostID(topic.getHost().getUserID());
|
||||
resp.setTopicName(topic.getName());
|
||||
resp.setTopicDescription(topic.getDescription());
|
||||
resp.setTopicColor(topic.getColor());
|
||||
for (User value : topic.getUsersReadOnly().values()) {
|
||||
resp.getUserIDs().add(new LongData().setValue(value.getUserID()));
|
||||
}
|
||||
|
||||
try {
|
||||
Globals.getPacketManager().replyPacket(packet, resp);
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void onFetchUser(UserFetchPacket packet) {
|
||||
User user = Database.getInstance().getUserByID(packet.getUserID());
|
||||
|
||||
@ -175,9 +236,9 @@ public record UserSocket(Socket socket) implements Runnable {
|
||||
if (user == null) return;
|
||||
if (topic == null) return;
|
||||
|
||||
Message message = new Message(user, topic, packet.getMessage());
|
||||
UserMessage userMessage = new UserMessage(topic.getNextMessageID(), user, topic, packet.getMessage());
|
||||
|
||||
topic.addMessage(message);
|
||||
topic.addMessage(userMessage);
|
||||
|
||||
info("\"{}\" in \"{}\" sends \"{}\"", user.getUsername().toUpperCase(), topic.getName().toUpperCase(), packet.getMessage());
|
||||
|
||||
@ -193,7 +254,7 @@ public record UserSocket(Socket socket) implements Runnable {
|
||||
MessageCreatedPacket messageCreated = new MessageCreatedPacket();
|
||||
messageCreated.setAuthorID(user.getUserID());
|
||||
messageCreated.setTopicID(topic.getId());
|
||||
messageCreated.setContents(message.getContents());
|
||||
messageCreated.setContents(userMessage.getContents());
|
||||
|
||||
for (User babbler : topic.getUsersReadOnly().values()) {
|
||||
Socket userSocket = Database.getInstance().getUserSocket(babbler.getUserID());
|
||||
@ -206,4 +267,58 @@ public record UserSocket(Socket socket) implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void onMessageListFetch(MessageListFetchPacket packet) {
|
||||
Topic topic = Database.getInstance().getTopic(packet.getTopicID());
|
||||
|
||||
if (topic == null) return;
|
||||
|
||||
info("Requested Message list on #{}", topic.getId());
|
||||
|
||||
MessageListDataPacket result = new MessageListDataPacket();
|
||||
|
||||
for (Message message : topic.getMessagesReadOnly()) {
|
||||
result.getMessageIDs().add(new LongData().setValue(message.getId()));
|
||||
}
|
||||
|
||||
try {
|
||||
Globals.getPacketManager().replyPacket(packet, result);
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void onFetchMessage(MessageFetchPacket packet) {
|
||||
Topic topic = Database.getInstance().getTopic(packet.getTopicID());
|
||||
|
||||
if (topic == null) return;
|
||||
|
||||
Message message = topic.getMessageByID(packet.getMessageID());
|
||||
|
||||
if (message == null) return;
|
||||
|
||||
info("Requested message #{} on #{}", message.getId(), topic.getId());
|
||||
|
||||
MessageDataPacket resp = new MessageDataPacket();
|
||||
resp.setMessageID(message.getId());
|
||||
resp.setTopicID(message.getTopic().getId());
|
||||
|
||||
if (message instanceof UserMessage userMessage) {
|
||||
resp.setMessageType(MessageDataPacket.MessageType.USER);
|
||||
resp.setUserAuthorID(userMessage.getAuthor().getUserID());
|
||||
resp.setUserContents(userMessage.getContents());
|
||||
} else if (message instanceof SystemMessage systemMessage) {
|
||||
resp.setMessageType(MessageDataPacket.MessageType.SYSTEM);
|
||||
resp.setSystemType(systemMessage.getType());
|
||||
if (systemMessage.getUser() != null)
|
||||
resp.setSystemUserID(systemMessage.getUser().getUserID());
|
||||
resp.setSystemContents(systemMessage.getContents());
|
||||
}
|
||||
|
||||
try {
|
||||
Globals.getPacketManager().replyPacket(packet, resp);
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user