Skip to content

Commit 32db2b4

Browse files
authored
Merge pull request #10 from TWME-TW/fix-bug-0105
Fix unexpected multiple clipboard transfers to proxy when copying large areas.
2 parents c6f6b4c + db373ef commit 32db2b4

File tree

10 files changed

+91
-30
lines changed

10 files changed

+91
-30
lines changed

src/main/java/dev/twme/worldeditsync/bungeecord/clipboard/ClipboardManager.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ public class ClipboardManager {
1717
private final WorldEditSyncBungee plugin;
1818
private final Map<UUID, ClipboardData> clipboardStorage;
1919
private final Map<String, TransferSession> transferSessions;
20+
private final Map<UUID, Boolean> playerTransferStatus;
2021

2122
public ClipboardManager(WorldEditSyncBungee plugin) {
2223
this.plugin = plugin;
2324
this.clipboardStorage = new ConcurrentHashMap<>();
2425
this.transferSessions = new ConcurrentHashMap<>();
26+
this.playerTransferStatus = new ConcurrentHashMap<>();
2527
}
2628

2729
public void storeClipboard(UUID playerUuid, byte[] data, String hash) {
@@ -52,7 +54,7 @@ public void addChunk(String sessionId, int index, byte[] data) {
5254
plugin.getLogger().warning("Failed to assemble data: " + sessionId);
5355
return;
5456
}
55-
plugin.getLogger().info("Finished transferring clipboard data: " + sessionId);
57+
plugin.getLogger().info("Finished receiving clipboard data: " + sessionId);
5658
// 儲存剪貼簿
5759
storeClipboard(playerUuid, fullData, hash);
5860

@@ -132,4 +134,12 @@ public long getTimestamp() {
132134
return timestamp;
133135
}
134136
}
137+
138+
public boolean isPlayerTransferring(UUID playerUuid) {
139+
return playerTransferStatus.getOrDefault(playerUuid, false);
140+
}
141+
142+
public void setPlayerTransferring(UUID playerUuid, boolean transferring) {
143+
playerTransferStatus.put(playerUuid, transferring);
144+
}
135145
}

src/main/java/dev/twme/worldeditsync/bungeecord/listener/MessageListener.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,18 @@ private void handleClipboardUpload(ByteArrayDataInput in) {
5858

5959
clipboardManager.createTransferSession(sessionId,
6060
UUID.fromString(playerUuid), totalChunks, chunkSize);
61-
62-
plugin.getLogger().info("Created transfer session: " + sessionId);
6361
}
6462

6563
private void handleClipboardDownload(ByteArrayDataInput in, ProxiedPlayer player) {
6664
String playerUuid = in.readUTF();
6765
ClipboardManager.ClipboardData clipboardData = clipboardManager.getClipboard(UUID.fromString(playerUuid));
68-
plugin.getLogger().info("Received download request from player: " + player.getName() + " UUID: " + playerUuid);
66+
6967
if (clipboardData != null) {
70-
plugin.getLogger().info("Sending clipboard data to player: " + player.getName());
68+
if (clipboardManager.isPlayerTransferring(player.getUniqueId())) {
69+
// 如果玩家正在傳輸剪貼簿,則不允許下載
70+
return;
71+
}
72+
clipboardManager.setPlayerTransferring(player.getUniqueId(), true);
7173
sendClipboardData(player, clipboardData.getData());
7274
}
7375
}
@@ -135,6 +137,7 @@ private void sendClipboardData(ProxiedPlayer player, byte[] data) {
135137

136138
player.getServer().getInfo().sendData(Constants.CHANNEL, chunkOut.toByteArray());
137139
}
140+
clipboardManager.setPlayerTransferring(player.getUniqueId(), false);
138141
plugin.getLogger().info("Finished sending clipboard data to player: " + player.getName() +" Session: " + sessionId);
139142
});
140143
}

src/main/java/dev/twme/worldeditsync/bungeecord/listener/PlayerListener.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public void onServerSwitch(ServerSwitchEvent event) {
3131
private void handleServerUpdate(ProxiedPlayer player) {
3232
ClipboardManager.ClipboardData clipboardData =
3333
clipboardManager.getClipboard(player.getUniqueId());
34+
clipboardManager.setPlayerTransferring(player.getUniqueId(), false);
3435

3536
plugin.getProxy().getScheduler().schedule(plugin, () -> {
3637
if (clipboardData != null) {

src/main/java/dev/twme/worldeditsync/paper/WorldEditSyncPaper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public void onEnable() {
3737
this.getServer().getMessenger().registerIncomingPluginChannel(this, Constants.CHANNEL, messageHandler);
3838

3939
// 啟動剪貼簿監視器
40-
clipboardWatcher.runTaskTimerAsynchronously(this, 40L, 20L);
40+
clipboardWatcher.runTaskTimer(this, 40L, 20L);
4141

4242
// 註冊監聽器
4343
getServer().getPluginManager().registerEvents(playerListener, this);

src/main/java/dev/twme/worldeditsync/paper/clipboard/ClipboardManager.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ public class ClipboardManager {
1818
private final Map<UUID, ClipboardData> clipboardCache;
1919
private final Map<String, TransferSession> activeSessions;
2020
private final Set<UUID> firstCheck = new HashSet<>();
21+
private Map<UUID, Boolean> playerTransferStatus;
2122
private final MiniMessage mm = MiniMessage.miniMessage();
2223

2324
public ClipboardManager(WorldEditSyncPaper plugin) {
2425
this.plugin = plugin;
2526
this.clipboardCache = new ConcurrentHashMap<>();
2627
this.activeSessions = new HashMap<>();
28+
this.playerTransferStatus = new ConcurrentHashMap<>();
2729
}
2830

2931
/**
@@ -54,7 +56,6 @@ public byte[] getLocalData(UUID playerUuid) {
5456
*/
5557
public String calculateClipboardHash(Clipboard clipboard) {
5658
if (clipboard == null) return "";
57-
5859
return String.valueOf(clipboard.hashCode());
5960
}
6061

@@ -157,6 +158,8 @@ public void uploadClipboard(Player player, byte[] data) {
157158
return;
158159
}
159160

161+
plugin.getClipboardManager().setPlayerTransferring(player.getUniqueId(), true);
162+
160163
// 發送上傳開始訊息
161164
ByteArrayDataOutput out = ByteStreams.newDataOutput();
162165
out.writeUTF("ClipboardUpload");
@@ -185,7 +188,7 @@ public void uploadClipboard(Player player, byte[] data) {
185188
private void sendChunks(Player player, String sessionId, byte[] data, int totalChunks) {
186189
//wait 10ms
187190
try {
188-
Thread.sleep(10);
191+
Thread.sleep(Constants.THREAD_DELAY_MS);
189192
} catch (InterruptedException e) {
190193
e.fillInStackTrace();
191194
}
@@ -214,6 +217,7 @@ private void sendChunks(Player player, String sessionId, byte[] data, int totalC
214217
if (i + 1 < totalChunks) {
215218
player.sendActionBar(mm.deserialize("<blue>Uploading clipboard... <gray>(" + (i + 1) + "</gray>/<yellow>" + totalChunks + "</yellow>)</blue>"));
216219
} else {
220+
setPlayerTransferring(player.getUniqueId(), false);
217221
player.sendActionBar(mm.deserialize("<green>Clipboard uploaded!</green>"));
218222
}
219223
}
@@ -248,10 +252,10 @@ public boolean hasClipboardChanged(Player player, Clipboard currentClipboard) {
248252
// 獲取儲存的雜湊值
249253
String storedHash = getLocalHash(player.getUniqueId());
250254

251-
// 如果任一雜湊值為空,視為有變化
252-
if (currentHash.isEmpty() || storedHash.isEmpty()) {
253-
return true;
254-
}
255+
// // 如果儲存的雜湊值為空,視為有變化
256+
// if (storedHash.isEmpty()) {
257+
// return true;
258+
// }
255259

256260
return !currentHash.equals(storedHash);
257261

@@ -393,10 +397,21 @@ public void uncheck(UUID playerUuid) {
393397
public void startUploadClipboard(Player player) {
394398
Clipboard clipboard = plugin.getWorldEditHelper().getPlayerClipboard(player);
395399
byte[] serializedClipboard = plugin.getWorldEditHelper().serializeClipboard(clipboard);
400+
396401
if (serializedClipboard != null) {
397-
String hash = plugin.getClipboardManager().calculateClipboardHash(clipboard);
398-
plugin.getClipboardManager().setLocalClipboard(player.getUniqueId(), serializedClipboard, hash);
399-
plugin.getClipboardManager().uploadClipboard(player, serializedClipboard);
402+
String hash = calculateClipboardHash(clipboard);
403+
setLocalClipboard(player.getUniqueId(), serializedClipboard, hash);
404+
setPlayerTransferring(player.getUniqueId(), true);
405+
406+
uploadClipboard(player, serializedClipboard);
400407
}
401408
}
409+
410+
public void setPlayerTransferring(UUID playerUuid, boolean transferring) {
411+
playerTransferStatus.put(playerUuid, transferring);
412+
}
413+
414+
public boolean isPlayerTransferring(UUID playerUuid) {
415+
return playerTransferStatus.getOrDefault(playerUuid, false);
416+
}
402417
}

src/main/java/dev/twme/worldeditsync/paper/clipboard/ClipboardWatcher.java

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,31 +24,38 @@ public void run() {
2424
if (!(player.hasPermission("worldeditsync.sync"))) {
2525
continue;
2626
}
27-
2827
if (!clipboardManager.isChecked(player.getUniqueId())) {
2928
continue;
3029
}
3130

32-
checkAndUploadPlayerClipboard(player);
31+
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> checkAndUploadPlayerClipboard(player));
3332
}
3433
}
3534

3635
private void checkAndUploadPlayerClipboard(Player player) {
36+
if (plugin.getClipboardManager().isPlayerTransferring(player.getUniqueId())) return;
37+
3738
Clipboard clipboard = plugin.getWorldEditHelper().getPlayerClipboard(player);
3839
if (clipboard == null) {
3940
return;
4041
}
4142

42-
// 使用新的判斷方法
43-
if (clipboardManager.hasClipboardChanged(player, clipboard)) {
44-
player.sendActionBar(mm.deserialize("<green>Detect clipboard change, uploading...</green>"));
45-
// 序列化並上傳
46-
byte[] serializedClipboard = plugin.getWorldEditHelper().serializeClipboard(clipboard);
47-
if (serializedClipboard != null) {
48-
String hash = clipboardManager.calculateClipboardHash(clipboard);
49-
clipboardManager.setLocalClipboard(player.getUniqueId(), serializedClipboard, hash);
50-
clipboardManager.uploadClipboard(player, serializedClipboard);
51-
}
43+
if (!clipboardManager.hasClipboardChanged(player, clipboard)) {
44+
return;
5245
}
46+
plugin.getClipboardManager().setPlayerTransferring(player.getUniqueId(), true);
47+
48+
player.sendActionBar(mm.deserialize("<green>Detect clipboard change, uploading...</green>"));
49+
// 序列化並上傳
50+
51+
52+
// if (plugin.getClipboardManager().isPlayerTransferring(player.getUniqueId())) return;
53+
54+
byte[] serializedClipboard = plugin.getWorldEditHelper().serializeClipboard(clipboard);
55+
56+
String hash = clipboardManager.calculateClipboardHash(clipboard);
57+
clipboardManager.setLocalClipboard(player.getUniqueId(), serializedClipboard, hash);
58+
clipboardManager.uploadClipboard(player, serializedClipboard);
59+
5360
}
5461
}

src/main/java/dev/twme/worldeditsync/paper/listener/PlayerListener.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,19 @@ public PlayerListener(WorldEditSyncPaper plugin) {
1515
this.plugin = plugin;
1616
}
1717

18+
@EventHandler
19+
public void onPlayerJoin(PlayerQuitEvent event) {
20+
Player player = event.getPlayer();
21+
22+
plugin.getClipboardManager().setPlayerTransferring(player.getUniqueId(), false);
23+
plugin.getClipboardManager().uncheck(player.getUniqueId());
24+
}
25+
1826
@EventHandler
1927
public void onPlayerQuit(PlayerQuitEvent event) {
2028
Player player = event.getPlayer();
2129

30+
plugin.getClipboardManager().setPlayerTransferring(player.getUniqueId(), false);
2231
plugin.getClipboardManager().uncheck(player.getUniqueId());
2332
}
2433

@@ -29,6 +38,7 @@ public void onPlayerCommand(PlayerCommandPreprocessEvent event) {
2938
String[] args = message.split(" ");
3039

3140
if (args[0].equalsIgnoreCase("//copy") || args[0].equalsIgnoreCase("//cut")) {
41+
plugin.getClipboardManager().setPlayerTransferring(player.getUniqueId(), false);
3242
plugin.getClipboardManager().check(player.getUniqueId());
3343
}
3444
}

src/main/java/dev/twme/worldeditsync/velocity/clipboard/ClipboardManager.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ public class ClipboardManager {
1616
private final WorldEditSyncVelocity plugin;
1717
private final Map<UUID, ClipboardData> clipboardStorage;
1818
private final Map<String, TransferSession> transferSessions;
19+
private final Map<UUID, Boolean> playerTransferStatus;
1920

2021
public ClipboardManager(WorldEditSyncVelocity plugin) {
2122
this.plugin = plugin;
2223
this.clipboardStorage = new ConcurrentHashMap<>();
2324
this.transferSessions = new ConcurrentHashMap<>();
25+
this.playerTransferStatus = new ConcurrentHashMap<>();
2426
}
2527

2628
public void storeClipboard(UUID playerUuid, byte[] data, String hash) {
@@ -53,7 +55,7 @@ public void addChunk(String sessionId, int index, byte[] data) {
5355
plugin.getLogger().warn("Failed to assemble data: {}", sessionId);
5456
return;
5557
}
56-
plugin.getLogger().info("Finished transferring clipboard data: {}", sessionId);
58+
plugin.getLogger().info("Finished receiving clipboard data: {}", sessionId);
5759
// 儲存剪貼簿
5860
storeClipboard(playerUuid, fullData, hash);
5961

@@ -137,4 +139,12 @@ public long getTimestamp() {
137139
return timestamp;
138140
}
139141
}
142+
143+
public boolean isPlayerTransferring(UUID playerUuid) {
144+
return playerTransferStatus.getOrDefault(playerUuid, false);
145+
}
146+
147+
public void setPlayerTransferring(UUID playerUuid, boolean transferring) {
148+
playerTransferStatus.put(playerUuid, transferring);
149+
}
140150
}

src/main/java/dev/twme/worldeditsync/velocity/listener/MessageListener.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,11 @@ private void handleClipboardDownload(ByteArrayDataInput in, PluginMessageEvent e
8989
ClipboardManager.ClipboardData clipboardData = clipboardManager.getClipboard(UUID.fromString(playerUuid));
9090

9191
if (clipboardData != null) {
92-
92+
if (clipboardManager.isPlayerTransferring(player.getUniqueId())) {
93+
// 如果玩家正在傳輸剪貼簿,則不允許下載
94+
return;
95+
}
96+
clipboardManager.setPlayerTransferring(player.getUniqueId(), true);
9397
sendClipboardData(player, clipboardData.getData());
9498
}
9599
}
@@ -183,7 +187,7 @@ private void sendClipboardData(Player player, byte[] data) {
183187
);
184188
}
185189
plugin.getLogger().info("Finished sending clipboard data to player: {} Session: {}", player.getUsername(), sessionId);
186-
190+
clipboardManager.setPlayerTransferring(player.getUniqueId(), false);
187191
}).schedule();
188192
}
189193

src/main/java/dev/twme/worldeditsync/velocity/listener/PlayerListener.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public void onServerConnected(ServerConnectedEvent event) {
2626
// 當玩家連接到新服務器時,檢查是否有可用的剪貼簿數據
2727
ClipboardManager.ClipboardData clipboardData =
2828
clipboardManager.getClipboard(event.getPlayer().getUniqueId());
29+
clipboardManager.setPlayerTransferring(event.getPlayer().getUniqueId(), false);
2930

3031
plugin.getServer().getScheduler().buildTask(plugin, () -> {
3132
if (clipboardData != null) {

0 commit comments

Comments
 (0)