Packet obfuscation and reduction

This commit is contained in:
Cryptite
2021-10-06 11:12:18 -05:00
parent 0df155a60a
commit a7a96a6b6e
5 changed files with 233 additions and 16 deletions

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Build Changes
diff --git a/build.gradle.kts b/build.gradle.kts diff --git a/build.gradle.kts b/build.gradle.kts
index d80cfcb94db51440b5d0aa589a9a3d8a4189a9aa..9dbad4407dcf1a7070d5c5a692473cf57a4543e7 100644 index cb1a931417073908be5c7aa1af710477775b3dbd..0c3c936990f161eb3de9a33f8983e4da571befac 100644
--- a/build.gradle.kts --- a/build.gradle.kts
+++ b/build.gradle.kts +++ b/build.gradle.kts
@@ -29,8 +29,8 @@ repositories { @@ -28,8 +28,8 @@ repositories {
} }
dependencies { dependencies {
@@ -19,7 +19,7 @@ index d80cfcb94db51440b5d0aa589a9a3d8a4189a9aa..9dbad4407dcf1a7070d5c5a692473cf5
// Paper start // Paper start
implementation("org.jline:jline-terminal-jansi:3.12.1") implementation("org.jline:jline-terminal-jansi:3.12.1")
implementation("net.minecrell:terminalconsoleappender:1.2.0") implementation("net.minecrell:terminalconsoleappender:1.2.0")
@@ -82,7 +82,7 @@ tasks.jar { @@ -81,7 +81,7 @@ tasks.jar {
attributes( attributes(
"Main-Class" to "org.bukkit.craftbukkit.Main", "Main-Class" to "org.bukkit.craftbukkit.Main",
"Implementation-Title" to "CraftBukkit", "Implementation-Title" to "CraftBukkit",
@@ -28,7 +28,7 @@ index d80cfcb94db51440b5d0aa589a9a3d8a4189a9aa..9dbad4407dcf1a7070d5c5a692473cf5
"Implementation-Vendor" to date, // Paper "Implementation-Vendor" to date, // Paper
"Specification-Title" to "Bukkit", "Specification-Title" to "Bukkit",
"Specification-Version" to project.version, "Specification-Version" to project.version,
@@ -207,7 +207,7 @@ tasks.test { @@ -206,7 +206,7 @@ tasks.test {
fun TaskContainer.registerRunTask( fun TaskContainer.registerRunTask(
name: String, block: JavaExec.() -> Unit name: String, block: JavaExec.() -> Unit
): TaskProvider<JavaExec> = register<JavaExec>(name) { ): TaskProvider<JavaExec> = register<JavaExec>(name) {
@@ -51,10 +51,10 @@ index fe6d5051b139cd6079e288ffdf20e30fdd46fdda..c3c2b44c998ccb73594e4f33a571508a
public SystemReport fillSystemReport(SystemReport details) { public SystemReport fillSystemReport(SystemReport details) {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index f925130552cb4ff2f813b1ddae9ac2f915e17bd5..7df81489dd9d3c7ed84b3b6bdf2b724903fbcdc4 100644 index 0adb686d690e1be0c5540625efbecc46bac5d045..d32b296d63e8f16ad4ba6e5e8da259d2905098ef 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -249,7 +249,7 @@ import javax.annotation.Nullable; // Paper @@ -251,7 +251,7 @@ import javax.annotation.Nullable; // Paper
import javax.annotation.Nonnull; // Paper import javax.annotation.Nonnull; // Paper
public final class CraftServer implements Server { public final class CraftServer implements Server {

View File

@@ -27,10 +27,10 @@ index 21d1e0c9c471e9e556b5bd70166a769b46105c7a..d46dc12001bd46596c3bb2e24144bbe4
return false; return false;
} else { } else {
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index b93056b91e7ebd49e6ddb53ccb6c05c056088df9..a9315b7acec3c2ccaf879e0f1d45c062d8e201b1 100644 index f936e9f9a9fa655fa997d6862b5ed54c04169d35..465a1e179f6ae43d253d692255c8fe144179efe3 100644
--- a/src/main/java/net/minecraft/world/level/Level.java --- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -550,12 +550,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -552,12 +552,12 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
} }
@Override @Override
@@ -46,7 +46,7 @@ index b93056b91e7ebd49e6ddb53ccb6c05c056088df9..a9315b7acec3c2ccaf879e0f1d45c062
// CraftBukkit start - tree generation // CraftBukkit start - tree generation
if (this.captureTreeGeneration) { if (this.captureTreeGeneration) {
// Paper start // Paper start
@@ -602,7 +602,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -604,7 +604,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
} else { } else {
BlockState iblockdata2 = this.getBlockState(pos); BlockState iblockdata2 = this.getBlockState(pos);
@@ -55,7 +55,7 @@ index b93056b91e7ebd49e6ddb53ccb6c05c056088df9..a9315b7acec3c2ccaf879e0f1d45c062
this.getProfiler().push("queueCheckLight"); this.getProfiler().push("queueCheckLight");
this.getChunkSource().getLightEngine().checkBlock(pos); this.getChunkSource().getLightEngine().checkBlock(pos);
this.getProfiler().pop(); this.getProfiler().pop();
@@ -749,7 +749,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -751,7 +751,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
Block.dropResources(iblockdata, this, pos, tileentity, breakingEntity, ItemStack.EMPTY); Block.dropResources(iblockdata, this, pos, tileentity, breakingEntity, ItemStack.EMPTY);
} }

View File

@@ -37,10 +37,10 @@ index 3e5e358e24bd84a05785a9391526f316475e95ff..9914a92040a63b6102eb6171f058ea1c
CompoundTag newData = this.getTagClone(); CompoundTag newData = this.getTagClone();
int newCount = this.getCount(); int newCount = this.getCount();
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index a9315b7acec3c2ccaf879e0f1d45c062d8e201b1..7dec61b831860e372f1785c2ae838cb3ad2fc623 100644 index 465a1e179f6ae43d253d692255c8fe144179efe3..46a1b0519aaccc2b5625104d42168254bfb27cd9 100644
--- a/src/main/java/net/minecraft/world/level/Level.java --- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -175,6 +175,27 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -176,6 +176,27 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here public java.util.ArrayDeque<net.minecraft.world.level.block.RedstoneTorchBlock.Toggle> redstoneUpdateInfos; // Paper - Move from Map in BlockRedstoneTorch to here
@@ -68,7 +68,7 @@ index a9315b7acec3c2ccaf879e0f1d45c062d8e201b1..7dec61b831860e372f1785c2ae838cb3
// Paper start - fix and optimise world upgrading // Paper start - fix and optimise world upgrading
// copied from below // copied from below
public static ResourceKey<DimensionType> getDimensionKey(DimensionType manager) { public static ResourceKey<DimensionType> getDimensionKey(DimensionType manager) {
@@ -704,6 +725,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -706,6 +727,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
if (!this.preventPoiUpdated) { if (!this.preventPoiUpdated) {
this.onBlockStateChange(blockposition, iblockdata1, iblockdata2); this.onBlockStateChange(blockposition, iblockdata1, iblockdata2);
} }
@@ -76,7 +76,7 @@ index a9315b7acec3c2ccaf879e0f1d45c062d8e201b1..7dec61b831860e372f1785c2ae838cb3
// CraftBukkit end // CraftBukkit end
} }
} }
@@ -809,8 +831,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -811,8 +833,20 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public void neighborChanged(BlockPos pos, Block sourceBlock, BlockPos neighborPos) { public void neighborChanged(BlockPos pos, Block sourceBlock, BlockPos neighborPos) {
if (!this.isClientSide) { if (!this.isClientSide) {
BlockState iblockdata = this.getBlockState(pos); BlockState iblockdata = this.getBlockState(pos);

View File

@@ -5,10 +5,10 @@ Subject: [PATCH] Add BlockDestroyedByNeighborEvent
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 7dec61b831860e372f1785c2ae838cb3ad2fc623..9b704693ea8d8677d3c25d5a3c08d4ef26aa1fc3 100644 index 46a1b0519aaccc2b5625104d42168254bfb27cd9..5e87676aa9dfa26ac052aa0c1fce35b8822e7a50 100644
--- a/src/main/java/net/minecraft/world/level/Level.java --- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java +++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -747,6 +747,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable { @@ -749,6 +749,17 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
if (iblockdata.isAir()) { if (iblockdata.isAir()) {
return false; return false;
} else { } else {

View File

@@ -0,0 +1,217 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Cryptite <cryptite@gmail.com>
Date: Wed, 6 Oct 2021 11:03:01 -0500
Subject: [PATCH] Packet obfuscation and reduction
Minecraft is overzealous about packet updates for Entities. In Loka's case, we want to reduce as many unnecessary
packet updates as possible. This patch is likely to be updated over and over in terms of reducing packet sends.
In summary, this patch creates the concept of a "foreignValue" of a packet's data. We treat packets in two ways:
1) The packet sent to the player itself (the normal way). This always has all of the values as usual.
2) The packet data as seen by any other (foreign) players.
This patch adds the ability to set a "foreignValue" for an entity value so as to obfuscate data received by other players.
The current packets modified/obfuscated are the following:
- Health - Foreign Players will only receive packets that say the player is "alive or dead (max health or 0 health).
-- This reduces the amount of health packet updates as well which is great for players in combat.
- Air Level - Foreign players will only ever see a player as having full oxygen
-- Air level packets are sent PER-TICK, and as such a player with any change in air level will only spam themselves
with packets instead of every single player within tracking distance
- Score - Foreign players will only see a player's score as 0 and will not update due to gathering xp orbs, etc.
diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java
index 3e17f6131bf590d7c4a16b79c1c145cb4f565bc9..e1233fa58d068448d0accef7a7f6725fcb902848 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSetEntityDataPacket.java
@@ -22,6 +22,13 @@ public class ClientboundSetEntityDataPacket implements Packet<ClientGamePacketLi
}
+ // Slice start
+ public ClientboundSetEntityDataPacket(int id, List<SynchedEntityData.DataItem<?>> packedItems) {
+ this.id = id;
+ this.packedItems = packedItems;
+ }
+ // Slice end
+
public ClientboundSetEntityDataPacket(FriendlyByteBuf buf) {
this.id = buf.readVarInt();
this.packedItems = SynchedEntityData.unpack(buf);
diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
index 4df12454001f0de5f358c88d876e34c35a736c42..72c74d2369a36b14f1103aa74b096f50e7990f4d 100644
--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
+++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
@@ -136,6 +136,11 @@ public class SynchedEntityData {
}
public <T> void set(EntityDataAccessor<T> key, T value) {
+ //Slice start
+ set(key, value, null);
+ }
+
+ public <T> void set(EntityDataAccessor<T> key, T value, @Nullable T foreignValue) { // Slice end
SynchedEntityData.DataItem<T> datawatcher_item = this.getItem(key);
if (ObjectUtils.notEqual(value, datawatcher_item.getValue())) {
@@ -145,6 +150,11 @@ public class SynchedEntityData {
this.isDirty = true;
}
+ // Slice start
+ if (foreignValue != null && ObjectUtils.notEqual(foreignValue, datawatcher_item.getForeignValue())) {
+ datawatcher_item.setForeignValue(foreignValue);
+ }
+ // Slice end
}
// CraftBukkit start - add method from above
@@ -200,6 +210,28 @@ public class SynchedEntityData {
return list;
}
+ // Slice start
+ @Nullable
+ public List<SynchedEntityData.DataItem<?>> packForeignDirty(List<DataItem<?>> unpackedData) {
+ List<SynchedEntityData.DataItem<?>> list = null;
+
+ for (DataItem<?> dataItem : unpackedData) {
+ DataItem<?> item = itemsById.get(dataItem.accessor.getId());
+ if (item.isDirty(true)) {
+ item.setForeignDirty(false);
+
+ if (list == null) {
+ list = Lists.newArrayList();
+ }
+
+ list.add(item.copy(true));
+ }
+ }
+
+ return list;
+ }
+ // Slice end
+
@Nullable
public List<SynchedEntityData.DataItem<?>> getAll() {
List<SynchedEntityData.DataItem<?>> list = null;
@@ -313,11 +345,14 @@ public class SynchedEntityData {
final EntityDataAccessor<T> accessor;
T value;
private boolean dirty;
+ @Nullable T foreignValue = null; // Slice
+ private boolean foreignDirty; // Slice
public DataItem(EntityDataAccessor<T> data, T value) {
this.accessor = data;
this.value = value;
this.dirty = true;
+ this.foreignDirty = true; // Slice
}
public EntityDataAccessor<T> getAccessor() {
@@ -343,5 +378,34 @@ public class SynchedEntityData {
public SynchedEntityData.DataItem<T> copy() {
return new SynchedEntityData.DataItem<>(this.accessor, this.accessor.getSerializer().copy(this.value));
}
+
+ // Slice start
+ public void setForeignValue(T foreignValue) {
+ this.foreignValue = foreignValue;
+ this.foreignDirty = true;
+ }
+
+ public @Nullable T getForeignValue() {
+ return foreignValue;
+ }
+
+ public boolean isDirty(boolean foreign) {
+ if (foreign) {
+ //There must be a foreign value in order for this to be dirty, otherwise we consider this a normal
+ //value and check the normal dirty flag.
+ return foreignValue == null || this.foreignDirty;
+ }
+
+ return this.dirty;
+ }
+
+ public void setForeignDirty(boolean dirty) {
+ this.foreignDirty = dirty;
+ }
+
+ public SynchedEntityData.DataItem<T> copy(boolean foreign) {
+ return new SynchedEntityData.DataItem<>(this.accessor, this.accessor.getSerializer().copy((foreign && this.foreignValue != null ? this.foreignValue : this.value)));
+ }
+ // Slice end
}
}
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index b7c9294fdd3d799d410afba4a1118aa371c98533..b5205bfc6f9834dc811df71bfb96494448c8dfed 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -368,7 +368,21 @@ public class ServerEntity {
SynchedEntityData datawatcher = this.entity.getEntityData();
if (datawatcher.isDirty()) {
- this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), datawatcher, false));
+ // Slice start
+ ClientboundSetEntityDataPacket dataPacket = new ClientboundSetEntityDataPacket(this.entity.getId(), datawatcher, false);
+ if (this.entity instanceof ServerPlayer serverPlayer) {
+ serverPlayer.connection.send(dataPacket);
+
+ //Get the packedData that the original packet has, and then determine if any of those are changed in
+ //the foreign version. If null, nothing to notify foreign trackers about.
+ List<SynchedEntityData.DataItem<?>> dirtyItems = datawatcher.packForeignDirty(dataPacket.getUnpackedData());
+ if (dirtyItems != null) {
+ this.broadcast(new ClientboundSetEntityDataPacket(this.entity.getId(), dirtyItems));
+ }
+ } else {
+ this.broadcastAndSend(dataPacket);
+ }
+ // Slice end
}
if (this.entity instanceof LivingEntity) {
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
index 049a9ba9cc96880513e681f7d29bd5f9681fbb0e..37836b6f9b39ab1dcbfa1e4dea90e4d12fc9e5b9 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -2944,7 +2944,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, n
if (event.isCancelled()) {
return;
}
- this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, event.getAmount());
+ this.entityData.set(Entity.DATA_AIR_SUPPLY_ID, event.getAmount(), getMaxAirSupply()); // Slice
// CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java
index 4a35056b01b947c57f7ca06c974463008fc4bbef..80a8ea35b47cc649f435856cad19a80d69da8425 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -633,7 +633,7 @@ public abstract class Player extends LivingEntity {
public void increaseScore(int score) {
int j = this.getScore();
- this.entityData.set(Player.DATA_SCORE_ID, j + score);
+ this.entityData.set(Player.DATA_SCORE_ID, j + score, 0); // Slice
}
@Override
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index c64911651f3d736c83cc83996de04920b091cc57..cf8d4edba400d5f21737c0af52a1193f69386fa9 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -1997,7 +1997,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
this.sendHealthUpdate();
}
}
- this.getHandle().getEntityData().set(LivingEntity.DATA_HEALTH_ID, (float) this.getScaledHealth());
+ this.getHandle().getEntityData().set(LivingEntity.DATA_HEALTH_ID, (float) this.getScaledHealth(), isDead() ? 0f : 20f); // Slice
this.getHandle().maxHealthCache = getMaxHealth();
}