Skip to content

Commit 6903480

Browse files
committed
Don't spam the user with packets
1 parent 5e7ebe8 commit 6903480

File tree

14 files changed

+463
-3
lines changed

14 files changed

+463
-3
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2015 Techcable
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package net.techcable.spawnshield.nms;
24+
25+
import lombok.Getter;
26+
import lombok.RequiredArgsConstructor;
27+
import net.techcable.spawnshield.compat.BlockPos;
28+
import net.techcable.spawnshield.compat.ChunkPos;
29+
import org.bukkit.Material;
30+
31+
/**
32+
* Created by Nicholas Schlabach on 5/19/2015.
33+
*/
34+
@Getter
35+
@RequiredArgsConstructor
36+
public class BlockChange {
37+
private final BlockPos pos;
38+
private final Material newMaterial;
39+
private final byte newData;
40+
41+
public short encodePos() {
42+
int chunkX = pos.getChunkPos().getX();
43+
int chunkZ = pos.getChunkPos().getZ();
44+
return (short) ((pos.getX() - (chunkX << 4)) << 12 | (pos.getZ() - (chunkZ << 4)) << 8 | pos.getY());
45+
}
46+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2015 Techcable
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package net.techcable.spawnshield.nms;
24+
25+
import net.techcable.spawnshield.compat.ChunkPos;
26+
import org.bukkit.entity.Player;
27+
28+
import java.util.Collection;
29+
30+
public interface NMS {
31+
public void sendMultiBlockChange(Player player, ChunkPos chunkPos, Collection<BlockChange> changes);
32+
}

base/pom.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,21 @@
3131
<artifactId>worldguard6</artifactId>
3232
<version>${project.parent.version}</version>
3333
</dependency>
34+
<!-- NMS Version Compatibility -->
35+
<dependency>
36+
<groupId>net.techcable.spawnshield</groupId>
37+
<artifactId>nms-v1_8_R1</artifactId>
38+
<version>${parent.version}</version>
39+
</dependency>
40+
<dependency>
41+
<groupId>net.techcable.spawnshield</groupId>
42+
<artifactId>nms-v1_8_R2</artifactId>
43+
<version>${parent.version}</version>
44+
</dependency>
45+
<dependency>
46+
<groupId>net.techcable.spawnshield</groupId>
47+
<artifactId>nms-v1_8_R3</artifactId>
48+
<version>${parent.version}</version>
49+
</dependency>
3450
</dependencies>
3551
</project>

base/src/main/java/net/techcable/spawnshield/SpawnShieldPlayer.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.google.common.collect.Maps;
2626
import com.google.common.collect.Sets;
2727
import lombok.*;
28+
import net.techcable.spawnshield.change.BlockChangeTracker;
2829
import net.techcable.spawnshield.compat.BlockPos;
2930
import net.techcable.techutils.entity.TechPlayer;
3031
import org.bukkit.Location;

base/src/main/java/net/techcable/spawnshield/Utils.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,48 @@
2525
import com.google.common.base.Preconditions;
2626
import lombok.AccessLevel;
2727
import lombok.NoArgsConstructor;
28+
import net.techcable.spawnshield.compat.ChunkPos;
29+
import net.techcable.spawnshield.nms.BlockChange;
30+
import net.techcable.spawnshield.nms.NMS;
31+
import net.techcable.techutils.Reflection;
2832
import org.bukkit.Bukkit;
33+
import org.bukkit.entity.Player;
34+
35+
import java.lang.reflect.Constructor;
36+
import java.util.Collection;
2937

3038
@NoArgsConstructor(access = AccessLevel.PRIVATE)
3139
public class Utils {
3240

41+
private static NMS nms;
42+
private static final Object nmsInitLock = new Object();
43+
public static NMS getNms() {
44+
if (nms == null) {
45+
synchronized (nmsInitLock) {
46+
if (nms == null) {
47+
String className = "net.techcable.spawnshield.nms.versions." + Reflection.getVersion() + ".NMSImpl";
48+
Class<?> nmsClazz = Reflection.getClass(className);
49+
Constructor constructor = nmsClazz == null ? null : Reflection.makeConstructor(nmsClazz);
50+
if (constructor == null) {
51+
warning("This version of minecraft is unsupported");
52+
warning("Forcefields will be less efficient, and players will be spammed with packets");
53+
nms = new NMS() {
54+
@Override
55+
public void sendMultiBlockChange(Player player, ChunkPos chunkPos, Collection<BlockChange> changes) {
56+
for (BlockChange change : changes) {
57+
player.sendBlockChange(change.getPos().toLocation(), change.getNewMaterial(), change.getNewData());
58+
}
59+
}
60+
};
61+
} else {
62+
nms = (NMS) Reflection.callConstructor(constructor);
63+
}
64+
}
65+
}
66+
}
67+
return nms;
68+
}
69+
3370
public static void severe(String error) {
3471
Bukkit.getLogger().severe("[SpawnShield] " + error);
3572
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2015 Techcable
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package net.techcable.spawnshield.change;
24+
25+
import com.google.common.collect.*;
26+
import lombok.*;
27+
import net.techcable.spawnshield.Utils;
28+
import net.techcable.spawnshield.compat.BlockPos;
29+
import net.techcable.spawnshield.compat.ChunkPos;
30+
import net.techcable.spawnshield.nms.BlockChange;
31+
import net.techcable.spawnshield.nms.NMS;
32+
import org.bukkit.Material;
33+
import org.bukkit.entity.Player;
34+
35+
import java.util.Collection;
36+
37+
/**
38+
* Tracks block changes and puts them all into a set of multi-block change packets
39+
*/
40+
@RequiredArgsConstructor
41+
@Getter
42+
public class BlockChangeTracker {
43+
private final Player player;
44+
private final Multimap<ChunkPos, BlockChange> changes = HashMultimap.create();
45+
46+
public void addBlockChange(BlockPos pos, Material material, int data) {
47+
BlockChange change = new BlockChange(pos, material, (byte)data);
48+
changes.put(pos.getChunkPos(), change);
49+
}
50+
51+
public void flush() {
52+
for (ChunkPos chunk : changes.keySet()) {
53+
Collection<BlockChange> changeList = changes.get(chunk);
54+
NMS nms = Utils.getNms();
55+
nms.sendMultiBlockChange(player, chunk, changeList);
56+
}
57+
this.changes.clear();
58+
}
59+
}

base/src/main/java/net/techcable/spawnshield/tasks/ForceFieldUpdateTask.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@
2525
import com.google.common.collect.*;
2626
import com.google.common.util.concurrent.ListeningExecutorService;
2727
import com.google.common.util.concurrent.MoreExecutors;
28-
import com.google.common.util.concurrent.ThreadFactoryBuilder;
2928
import lombok.RequiredArgsConstructor;
3029
import net.techcable.spawnshield.Utils;
30+
import net.techcable.spawnshield.change.BlockChangeTracker;
3131
import net.techcable.spawnshield.compat.BlockPos;
3232
import net.techcable.spawnshield.compat.Region;
3333
import net.techcable.spawnshield.forcefield.BorderFinder;
@@ -93,6 +93,7 @@ public void run() {
9393
public void runRequest(ForceFieldUpdateRequest request) {
9494
Set<BlockPos> shownBlocks = new HashSet<>();
9595
BlockPos center = request.getPosition();
96+
BlockChangeTracker tracker = new BlockChangeTracker(request.getPlayerEntity());
9697
int radius = request.getUpdateRadius();
9798
for (Region region : request.getRegionsToUpdate()) {
9899
for (BlockPos borderPoint : getBorders(region)) {
@@ -105,12 +106,13 @@ public void runRequest(ForceFieldUpdateRequest request) {
105106
if (lastShown == null) lastShown = new HashSet<>();
106107
for (BlockPos noLongerShown : lastShown) {
107108
if (shownBlocks.contains(noLongerShown)) continue; //We will show
108-
request.getPlayerEntity().sendBlockChange(noLongerShown.toLocation(), noLongerShown.getTypeAt().getId(), noLongerShown.getDataAt());
109+
tracker.addBlockChange(noLongerShown, noLongerShown.getTypeAt(), noLongerShown.getDataAt());
109110
}
110111
for (BlockPos toShow : shownBlocks) {
111112
if (toShow.getTypeAt().isSolid()) continue;
112-
request.getPlayerEntity().sendBlockChange(toShow.toLocation(), Material.STAINED_GLASS, (byte) 14);
113+
tracker.addBlockChange(toShow, Material.STAINED_GLASS, 14);
113114
}
115+
tracker.flush();
114116
request.getPlayer().setLastShownBlocks(shownBlocks);
115117
}
116118

nms-v1_8_R1/pom.xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<project>
2+
<modelVersion>4.0.0</modelVersion>
3+
<parent>
4+
<groupId>net.techcable.spawnshield</groupId>
5+
<artifactId>parent</artifactId>
6+
<version>1.1.1-SNAPSHOT</version>
7+
<relativePath>../pom.xml</relativePath>
8+
</parent>
9+
<artifactId>nms-v1_8_R1</artifactId>
10+
<dependencies>
11+
<dependency>
12+
<groupId>net.techcable.spawnshield</groupId>
13+
<artifactId>api</artifactId>
14+
<version>${parent.version}</version>
15+
<scope>provided</scope>
16+
</dependency>
17+
<dependency>
18+
<groupId>net.techcable</groupId>
19+
<artifactId>techutils</artifactId>
20+
<version>1.1.0-SNAPSHOT</version>
21+
</dependency>
22+
<dependency>
23+
<groupId>org.bukkit</groupId>
24+
<artifactId>craftbukkit</artifactId>
25+
<version>1.8-R0.1-SNAPSHOT</version>
26+
<scope>provided</scope>
27+
</dependency>
28+
</dependencies>
29+
</project>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* The MIT License
3+
* Copyright (c) 2015 Techcable
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a copy
6+
* of this software and associated documentation files (the "Software"), to deal
7+
* in the Software without restriction, including without limitation the rights
8+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
* copies of the Software, and to permit persons to whom the Software is
10+
* furnished to do so, subject to the following conditions:
11+
*
12+
* The above copyright notice and this permission notice shall be included in
13+
* all copies or substantial portions of the Software.
14+
*
15+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
* THE SOFTWARE.
22+
*/
23+
package net.techcable.spawnshield.nms.versions.v1_8_R1;
24+
25+
26+
import net.minecraft.server.v1_8_R1.*;
27+
import net.techcable.spawnshield.compat.ChunkPos;
28+
import net.techcable.spawnshield.nms.BlockChange;
29+
import net.techcable.spawnshield.nms.NMS;
30+
import net.techcable.techutils.Reflection;
31+
import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer;
32+
import org.bukkit.entity.Player;
33+
34+
import java.lang.reflect.Field;
35+
import java.util.Collection;
36+
37+
public class NMSImpl implements NMS {
38+
39+
private final Field chunkCoordField = PacketPlayOutMultiBlockChange.class.getDeclaredFields()[0];
40+
private final Field dataArray = PacketPlayOutMultiBlockChange.class.getDeclaredFields()[1];
41+
@Override
42+
public void sendMultiBlockChange(Player player, ChunkPos chunkPos, Collection<BlockChange> changes) {
43+
PacketPlayOutMultiBlockChange packet = new PacketPlayOutMultiBlockChange();
44+
MultiBlockChangeInfo[] changeArray = new MultiBlockChangeInfo[changes.size()];
45+
int i = 0;
46+
for (BlockChange change : changes) {
47+
IBlockData data = Block.getById(change.getNewMaterial().getId()).fromLegacyData(change.getNewData());
48+
MultiBlockChangeInfo info = new MultiBlockChangeInfo(packet, change.encodePos(), data);
49+
changeArray[i] = info;
50+
i++;
51+
}
52+
ChunkCoordIntPair chunkCoord = new ChunkCoordIntPair(chunkPos.getX(), chunkPos.getZ());
53+
Reflection.setField(chunkCoordField, packet, chunkCoord);
54+
Reflection.setField(dataArray, packet, changeArray);
55+
EntityPlayer handle = ((CraftPlayer)player).getHandle();
56+
handle.playerConnection.sendPacket(packet);
57+
}
58+
}

nms-v1_8_R2/pom.xml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<project>
2+
<modelVersion>4.0.0</modelVersion>
3+
<parent>
4+
<groupId>net.techcable.spawnshield</groupId>
5+
<artifactId>parent</artifactId>
6+
<version>1.1.1-SNAPSHOT</version>
7+
<relativePath>../pom.xml</relativePath>
8+
</parent>
9+
<artifactId>nms-v1_8_R2</artifactId>
10+
<dependencies>
11+
<dependency>
12+
<groupId>net.techcable.spawnshield</groupId>
13+
<artifactId>api</artifactId>
14+
<version>${parent.version}</version>
15+
<scope>provided</scope>
16+
</dependency>
17+
<dependency>
18+
<groupId>net.techcable</groupId>
19+
<artifactId>techutils</artifactId>
20+
<version>1.1.0-SNAPSHOT</version>
21+
</dependency>
22+
<dependency>
23+
<groupId>org.bukkit</groupId>
24+
<artifactId>craftbukkit</artifactId>
25+
<version>1.8.3-R0.1-SNAPSHOT</version>
26+
<scope>provided</scope>
27+
</dependency>
28+
</dependencies>
29+
</project>

0 commit comments

Comments
 (0)