9
0
mirror of https://github.com/Samsuik/Sakura.git synced 2026-01-04 15:31:43 +00:00
Files
SakuraMC/patches/server/0012-Slice-Packet-obfuscation-and-reduction.patch
2024-01-21 23:16:08 +00:00

257 lines
11 KiB
Diff

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] (Slice) 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:
# This reduces the amount of health packet updates as well which is great for players in combat.
# 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
diff --git a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
index ff7ba7a161cfed7521354bc6e3f21ba0f17f3760..bced07e0b6075cf0fa10f5498451ec53600ce02f 100644
--- a/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
+++ b/src/main/java/net/minecraft/network/syncher/SynchedEntityData.java
@@ -34,6 +34,7 @@ public class SynchedEntityData {
private final Int2ObjectMap<SynchedEntityData.DataItem<?>> itemsById = new Int2ObjectOpenHashMap();
// private final ReadWriteLock lock = new ReentrantReadWriteLock(); // Spigot - not required
private boolean isDirty;
+ private boolean isForeignDirty; // Slice
public SynchedEntityData(Entity trackedEntity) {
this.entity = trackedEntity;
@@ -139,6 +140,16 @@ public class SynchedEntityData {
}
public <T> void set(EntityDataAccessor<T> key, T value, boolean force) {
+ // Slice start
+ this.set(key, value, null, force);
+ }
+
+ public <T> void set(EntityDataAccessor<T> key, T value, T foreignValue) {
+ this.set(key, value, foreignValue, false);
+ }
+
+ public <T> void set(EntityDataAccessor<T> key, T value, T foreignValue, boolean force) {
+ // Slice end
SynchedEntityData.DataItem<T> datawatcher_item = this.getItem(key);
if (force || ObjectUtils.notEqual(value, datawatcher_item.getValue())) {
@@ -148,6 +159,12 @@ public class SynchedEntityData {
this.isDirty = true;
}
+ // Slice start
+ if (foreignValue != null && ObjectUtils.notEqual(foreignValue, datawatcher_item.getForeignValue())) {
+ datawatcher_item.setForeignValue(foreignValue);
+ this.isForeignDirty = true;
+ }
+ // Slice end
}
// CraftBukkit start - add method from above
@@ -157,6 +174,12 @@ public class SynchedEntityData {
}
// CraftBukkit end
+ // Slice start
+ public boolean isForeignDirty() {
+ return this.isForeignDirty;
+ }
+ // Slice end
+
public boolean isDirty() {
return this.isDirty;
}
@@ -189,6 +212,29 @@ public class SynchedEntityData {
return list;
}
+ // Slice start
+ @Nullable
+ public List<SynchedEntityData.DataValue<?>> packForeignDirty(List<DataValue<?>> unpackedData) {
+ List<SynchedEntityData.DataValue<?>> list = null;
+
+ for (DataValue<?> dataItem : unpackedData) {
+ DataItem<?> item = itemsById.get(dataItem.id());
+ if (item.isDirty(true)) {
+ item.setForeignDirty(false);
+
+ if (list == null) {
+ list = new ArrayList<>();
+ }
+
+ list.add(item.copy(true));
+ }
+ }
+
+ this.isForeignDirty = false;
+ return list;
+ }
+ // Slice end
+
@Nullable
public List<SynchedEntityData.DataValue<?>> getNonDefaultValues() {
List<SynchedEntityData.DataValue<?>> list = null;
@@ -296,11 +342,14 @@ public class SynchedEntityData {
T value;
private final T initialValue;
private boolean dirty;
+ @Nullable T foreignValue = null; // Slice
+ private boolean foreignDirty; // Slice
public DataItem(EntityDataAccessor<T> data, T value) {
this.accessor = data;
this.initialValue = value;
this.value = value;
+ this.foreignDirty = true; // Slice
}
public EntityDataAccessor<T> getAccessor() {
@@ -327,6 +376,35 @@ public class SynchedEntityData {
return this.initialValue.equals(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.DataValue<T> copy(boolean foreign) {
+ return SynchedEntityData.DataValue.create(this.accessor, this.accessor.getSerializer().copy((foreign && this.foreignValue != null ? this.foreignValue : this.value)));
+ }
+ // Slice end
+
public SynchedEntityData.DataValue<T> value() {
return SynchedEntityData.DataValue.create(this.accessor, this.value);
}
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 2028e0371e933852635bbebc660e1555ba6a59dc..18c5473923f8ce53be59b2496f347b31934ecc92 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -149,7 +149,7 @@ public class ServerEntity {
}
}
- if (this.tickCount % this.updateInterval == 0 || this.entity.hasImpulse || this.entity.getEntityData().isDirty()) {
+ if (this.tickCount % this.updateInterval == 0 || this.entity.hasImpulse || this.entity.getEntityData().isForeignDirty()) { // Slice
int i;
int j;
@@ -420,11 +420,23 @@ public class ServerEntity {
}
// Sakura start - visibility api
- private void broadcastEntityData(List<SynchedEntityData.DataValue<?>> packedValues) {
+ private void broadcastEntityData(SynchedEntityData datawatcher, List<SynchedEntityData.DataValue<?>> packedValues) {
Packet<?> packet0 = new ClientboundSetEntityDataPacket(this.entity.getId(), packedValues);
Packet<?> packet1 = null;
- if (this.entity.isPrimedTNT) {
+ // Slice start
+ if (this.entity instanceof ServerPlayer serverPlayer) {
+ serverPlayer.connection.send(packet0);
+ }
+
+ packedValues = datawatcher.packForeignDirty(packedValues);
+
+ if (packedValues != null) {
+ packet0 = new ClientboundSetEntityDataPacket(this.entity.getId(), packedValues);
+ }
+
+ if (packedValues != null && this.entity.isPrimedTNT) {
+ // Slice end
var copyOfDirtyItems = Lists.newArrayList(packedValues);
copyOfDirtyItems.removeIf((data) -> data.id() == 8);
@@ -451,7 +463,7 @@ public class ServerEntity {
if (list != null) {
this.trackedDataValues = datawatcher.getNonDefaultValues();
- this.broadcastEntityData(list); // Sakura - visibility api
+ this.broadcastEntityData(datawatcher, list); // Sakura - visibility api
}
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 f6f9f101899121afcf9df1426b56e49011a5bbcd..7e2a9c3b356e2ac46c1a0badb82c444def901045 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -3149,7 +3149,7 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
this.entityData.markDirty(Entity.DATA_AIR_SUPPLY_ID);
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/item/FallingBlockEntity.java b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
index 0bab2d4397dd4f24755a38e4c14320bbfda62425..aa88218a06366ade96797d370ef08baafb9dfa61 100644
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -108,7 +108,7 @@ public class FallingBlockEntity extends Entity {
}
public void setStartPos(BlockPos pos) {
- this.entityData.set(FallingBlockEntity.DATA_START_POS, pos);
+ this.entityData.set(FallingBlockEntity.DATA_START_POS, pos, BlockPos.ZERO); // Slice
}
public BlockPos getStartPos() {
diff --git a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
index 6e842da33ca43c8e22f35c59afd41ddff629c28c..6097d495252c9c7ee54f7017ca2b39d42e5046fe 100644
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
@@ -171,7 +171,7 @@ public class PrimedTnt extends Entity implements TraceableEntity {
}
public void setFuse(int fuse) {
- this.entityData.set(PrimedTnt.DATA_FUSE_ID, fuse);
+ this.entityData.set(PrimedTnt.DATA_FUSE_ID, fuse, (fuse / 10) * 10); // Slice
}
public int getFuse() {
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 0629c471d38a77c44fc1c86ccdfcb0690f61ca17..c125c963c1f0266fccf7a83ccd01641d5ea2a980 100644
--- a/src/main/java/net/minecraft/world/entity/player/Player.java
+++ b/src/main/java/net/minecraft/world/entity/player/Player.java
@@ -641,7 +641,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
}
public void startAutoSpinAttack(int riptideTicks) {