9
0
mirror of https://github.com/Samsuik/Sakura.git synced 2025-12-19 14:59:30 +00:00
Files
SakuraMC/sakura-server/minecraft-patches/features/0002-Client-Visibility-Settings.patch
2025-07-20 21:43:04 +01:00

306 lines
19 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Samsuik <kfian294ma4@gmail.com>
Date: Tue, 21 Sep 2021 23:54:25 +0100
Subject: [PATCH] Client Visibility Settings
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
index 9f6d7c5dc0e591488a8a3763d8a1f1b3671d5299..0f5383dcec940db15205afbb65f1f8aa5899edf4 100644
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
@@ -31,7 +31,7 @@ public class ClientboundLevelChunkPacketData {
private static final int TWO_MEGABYTES = 2097152;
private final Map<Heightmap.Types, long[]> heightmaps;
private final byte[] buffer;
- private final List<ClientboundLevelChunkPacketData.BlockEntityInfo> blockEntitiesData;
+ public final List<ClientboundLevelChunkPacketData.BlockEntityInfo> blockEntitiesData; // Sakura - client visibility settings; private -> public; ATs for some reason don't work here
// Paper start - Handle oversized block entities in chunks
private final java.util.List<net.minecraft.network.protocol.Packet<?>> extraPackets = new java.util.ArrayList<>();
private static final int BLOCK_ENTITY_LIMIT = Integer.getInteger("Paper.excessiveTELimit", 750);
@@ -153,7 +153,7 @@ public class ClientboundLevelChunkPacketData {
return this.heightmaps;
}
- static class BlockEntityInfo {
+ public static class BlockEntityInfo { // Sakura - client visibility settings; package-protected -> public; ATs for some reason don't work here
public static final StreamCodec<RegistryFriendlyByteBuf, ClientboundLevelChunkPacketData.BlockEntityInfo> STREAM_CODEC = StreamCodec.ofMember(
ClientboundLevelChunkPacketData.BlockEntityInfo::write, ClientboundLevelChunkPacketData.BlockEntityInfo::new
);
@@ -162,7 +162,7 @@ public class ClientboundLevelChunkPacketData {
);
final int packedXZ;
final int y;
- final BlockEntityType<?> type;
+ public final BlockEntityType<?> type; // Sakura - client visibility settings; private -> public; ATs for some reason don't work here
@Nullable
final CompoundTag tag;
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index df822f0e7c358d74737c749d6ba61ec31846a569..a88184f63f3cb539569942c5c982193973183984 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -173,6 +173,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
this.handleLegacyStructureIndex(pos);
}
// Paper end - rewrite chunk system
+ private final it.unimi.dsi.fastutil.longs.Long2IntMap minimalEntities; // Sakura - client visibility settings; minimal tnt/sand
public ChunkMap(
ServerLevel level,
@@ -237,6 +238,10 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
);
this.setServerViewDistance(serverViewDistance);
this.worldGenContext = new WorldGenContext(level, generator, structureManager, this.lightEngine, null, this::setChunkUnsaved); // Paper - rewrite chunk system
+ // Sakura start - client visibility settings; minimal tnt/sand
+ this.minimalEntities = new it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap();
+ this.minimalEntities.defaultReturnValue(Integer.MIN_VALUE);
+ // Sakura end - client visibility settings; minimal tnt/sand
}
private void setChunkUnsaved(ChunkPos chunkPos) {
@@ -1016,6 +1021,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
tracker.serverEntity.sendChanges();
}
}
+
+ this.minimalEntities.clear(); // Sakura - client visibility settings; minimal tnt/sand
}
// Paper end - optimise entity tracker
@@ -1226,6 +1233,32 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
return !this.seenBy.isEmpty();
}
// Paper end - optimise entity tracker
+ // Sakura start - client visibility settings; entity visibility
+ private boolean checkEntityVisibility(final ServerPlayer player) {
+ final Entity entity = this.entity;
+ final me.samsuik.sakura.player.visibility.VisibilitySettings settings = player.visibilitySettings;
+ if (!settings.playerModified() || !(entity.isPrimedTNT || entity.isFallingBlock)) {
+ return true;
+ }
+ final me.samsuik.sakura.player.visibility.VisibilityType type;
+ if (entity.isPrimedTNT) {
+ type = me.samsuik.sakura.player.visibility.VisibilityTypes.TNT;
+ } else {
+ type = me.samsuik.sakura.player.visibility.VisibilityTypes.SAND;
+ }
+ final me.samsuik.sakura.player.visibility.VisibilityState state = settings.get(type);
+ if (state == me.samsuik.sakura.player.visibility.VisibilityState.MINIMAL) {
+ final long key = entity.blockPosition().asLong() ^ entity.getType().hashCode();
+ final long visibleEntity = ChunkMap.this.minimalEntities.get(key);
+ if (visibleEntity != Integer.MIN_VALUE) {
+ return entity.getId() == visibleEntity;
+ } else {
+ ChunkMap.this.minimalEntities.put(key, entity.getId());
+ }
+ }
+ return state != me.samsuik.sakura.player.visibility.VisibilityState.OFF;
+ }
+ // Sakura end - client visibility settings; entity visibility
public TrackedEntity(final Entity entity, final int range, final int updateInterval, final boolean trackDelta) {
this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, updateInterval, trackDelta, this::broadcast, this::broadcastIgnorePlayers, this.seenBy); // Paper
@@ -1304,6 +1337,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
flag = flag && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
// Paper end - Configurable entity tracking range by Y
+ flag = flag && this.checkEntityVisibility(player); // Sakura start - client visibility settings; entity visibility
// CraftBukkit start - respect vanish API
if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits
flag = false;
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 03a157f6c96b0f39effa24ae278eeac689c83ee8..5f38281763419123a0611cbb34d9a02a0e0302ea 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -564,6 +564,21 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.playerTickingChunks.remove((LevelChunk)chunkHolder.getCurrentChunk());
}
// Paper end - chunk tick iteration
+ // Sakura start - client visibility settings
+ public final LongSet explosionPositions = new it.unimi.dsi.fastutil.longs.LongOpenHashSet();
+
+ public final boolean checkExplosionVisibility(final Vec3 position, final ServerPlayer player) {
+ final me.samsuik.sakura.player.visibility.VisibilitySettings settings = player.visibilitySettings;
+ if (settings.isDisabled(me.samsuik.sakura.player.visibility.VisibilityTypes.EXPLOSIONS)) {
+ return false;
+ } else if (settings.isToggled(me.samsuik.sakura.player.visibility.VisibilityTypes.EXPLOSIONS)) {
+ final BlockPos blockPosition = BlockPos.containing(position);
+ final long encodedPosition = blockPosition.asLong();
+ return this.explosionPositions.add(encodedPosition);
+ }
+ return true;
+ }
+ // Sakura end - client visibility settings
public ServerLevel(
MinecraftServer server,
@@ -675,6 +690,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler);
// Paper end - rewrite chunk system
this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit
+ this.levelTickScheduler.registerNewTask(this.explosionPositions::clear, 0); // Sakura - client visibility settings
}
// Paper start
@@ -1898,7 +1914,18 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
for (ServerPlayer serverPlayer : this.players) {
if (serverPlayer.distanceToSqr(vec3) < 4096.0) {
Optional<Vec3> optional = Optional.ofNullable(serverExplosion.getHitPlayers().get(serverPlayer));
- serverPlayer.connection.send(new ClientboundExplodePacket(vec3, optional, particleOptions, explosionSound));
+ // Sakura start - client visibility settings; let players toggle explosion particles
+ ParticleOptions particle = particleOptions;
+ Vec3 position = vec3;
+ // In 1.22 and later this should be replaced with sending the motion through a PlayerPositionPacket.
+ // The problem here is SetEntityMotion is capped to 3.9 b/pt and the only other alternate mean was
+ // implemented in 1.21.3. I believe it's best to just wait on this issue and deal with this hack.
+ if (!this.checkExplosionVisibility(vec3, serverPlayer)) {
+ position = new Vec3(0.0, -1024.0, 0.0);
+ particle = net.minecraft.core.particles.ParticleTypes.SMOKE;
+ }
+ serverPlayer.connection.send(new ClientboundExplodePacket(position, optional, particle, explosionSound));
+ // Sakura end - client visibility settings; let players toggle explosion particles
}
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index f3723436b65f64866af695209983b0ca4ad4f716..a7d71e5bd99a02aa156e1301dc5169e2c35f046d 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -460,6 +460,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
return this.viewDistanceHolder;
}
// Paper end - rewrite chunk system
+ public final me.samsuik.sakura.player.visibility.PlayerVisibilitySettings visibilitySettings = new me.samsuik.sakura.player.visibility.PlayerVisibilitySettings(); // Sakura - client visibility settings
public ServerPlayer(MinecraftServer server, ServerLevel level, GameProfile gameProfile, ClientInformation clientInformation) {
super(level, gameProfile);
diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index 08c59d603fca038fc2dde36384eea1b6c971e659..c1c432b5732b1e85aca5597be75e0149a333de0d 100644
--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -57,6 +57,60 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
public @Nullable String playerBrand;
public final java.util.Set<String> pluginMessagerChannels;
// Paper end - retain certain values
+ // Sakura start - client visibility settings
+ private boolean filterExtraPackets(final Packet<?> packet, final net.minecraft.server.level.ServerPlayer player) {
+ final me.samsuik.sakura.player.visibility.VisibilitySettings settings = player.visibilitySettings;
+ if (settings.isToggled(me.samsuik.sakura.player.visibility.VisibilityTypes.SPAWNERS)) {
+ if (packet instanceof net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket bedPacket) {
+ return bedPacket.getType() == net.minecraft.world.level.block.entity.BlockEntityType.MOB_SPAWNER;
+ }
+ }
+ return false;
+ }
+
+ private boolean filterOrModifyPacket(final Packet<?> packet, final net.minecraft.server.level.ServerPlayer player) {
+ final me.samsuik.sakura.player.visibility.VisibilitySettings settings = player.visibilitySettings;
+ final java.util.List<Packet<?>> extraPackets = packet.getExtraPackets();
+ if (extraPackets != null) {
+ // block entity data is sent as an extra packet
+ extraPackets.removeIf(extraPacket -> this.filterExtraPackets(extraPacket, player));
+ }
+
+ if (settings.isToggled(me.samsuik.sakura.player.visibility.VisibilityTypes.SPAWNERS)) {
+ net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData chunkData = null;
+
+ if (packet instanceof net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket chunkPacket) {
+ chunkData = chunkPacket.getChunkData();
+ } else if (packet instanceof net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData chunkPacket) {
+ chunkData = chunkPacket;
+ }
+
+ if (chunkData != null) {
+ chunkData.blockEntitiesData.removeIf(blockEntityInfo -> blockEntityInfo.type == net.minecraft.world.level.block.entity.BlockEntityType.MOB_SPAWNER);
+ }
+
+ if (packet instanceof net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket bedPacket && bedPacket.getType() == net.minecraft.world.level.block.entity.BlockEntityType.MOB_SPAWNER) {
+ return true;
+ }
+ }
+
+ if (packet instanceof net.minecraft.network.protocol.game.ClientboundBlockEventPacket bePacket) {
+ if (settings.isToggled(me.samsuik.sakura.player.visibility.VisibilityTypes.PISTONS)) {
+ return bePacket.getBlock() instanceof net.minecraft.world.level.block.piston.PistonBaseBlock;
+ }
+ }
+
+ return false;
+ }
+
+ private net.minecraft.server.level.ServerPlayer getPlayer() {
+ if (this instanceof ServerGamePacketListenerImpl gamePacketListener) {
+ return gamePacketListener.getPlayer();
+ } else {
+ return this.connection.getPlayer();
+ }
+ }
+ // Sakura end - client visibility settings
public ServerCommonPacketListenerImpl(MinecraftServer server, Connection connection, CommonListenerCookie cookie) {
this.server = server;
@@ -317,6 +371,12 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
} else if (packet instanceof net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket defaultSpawnPositionPacket && this instanceof ServerGamePacketListenerImpl serverGamePacketListener) {
serverGamePacketListener.player.compassTarget = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(defaultSpawnPositionPacket.getPos(), serverGamePacketListener.getCraftPlayer().getWorld());
}
+ // Sakura start - client visibility settings
+ final net.minecraft.server.level.ServerPlayer player = this.getPlayer();
+ if (player != null && player.visibilitySettings.playerModified() && this.filterOrModifyPacket(packet, player)) {
+ return;
+ }
+ // Sakura end - client visibility settings
// CraftBukkit end
if (packet.isTerminal()) {
this.close();
diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 5bba860a5f913d3a83c1d469f0f4854b6e063a49..ce8ea023bbf09178507f324634c11353cf204c8c 100644
--- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3204,6 +3204,7 @@ public class ServerGamePacketListenerImpl
event.setCancelled(cancelled);
net.minecraft.world.inventory.AbstractContainerMenu oldContainer = this.player.containerMenu; // SPIGOT-1224
+ me.samsuik.sakura.player.gui.FeatureGui.clickEvent(event); // Sakura - client visibility settings
this.cserver.getPluginManager().callEvent(event);
if (this.player.containerMenu != oldContainer) {
this.player.containerMenu.resumeRemoteUpdates();
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index d0727a05addee3e13fc65c2a2337565288f7cf98..ef6f91f35d8725fa3df81b23d86adc900a5df5ce 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -533,6 +533,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
// Paper end - optimise entity tracker
public boolean pushedByFluid = true; // Sakura - entity pushed by fluid api
+ // Sakura start - client visibility settings
+ public boolean isPrimedTNT;
+ public boolean isFallingBlock;
+ // Sakura end - client visibility settings
public Entity(EntityType<?> entityType, Level level) {
this.type = entityType;
diff --git a/net/minecraft/world/entity/item/FallingBlockEntity.java b/net/minecraft/world/entity/item/FallingBlockEntity.java
index ae1f7a8b9cc6db4dd8dd3d6593a952166d35cc68..f7663d07a71582c332b38871211e648cffcf13c2 100644
--- a/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -79,6 +79,7 @@ public class FallingBlockEntity extends Entity {
super(entityType, level);
this.dropItem = level.sakuraConfig().cannons.sand.dropItems; // Sakura - configure falling blocks dropping items
this.heightParity = level.sakuraConfig().cannons.mechanics.fallingBlockParity; // Sakura - configure cannon mechanics
+ this.isFallingBlock = true; // Sakura - client visibility settings
}
public FallingBlockEntity(Level level, double x, double y, double z, BlockState state) {
diff --git a/net/minecraft/world/entity/item/PrimedTnt.java b/net/minecraft/world/entity/item/PrimedTnt.java
index dc9c8bdc81dec07a8e457431bbd35a54236b03ef..8755c76b679adcacbdd8e2faec363745fd583e48 100644
--- a/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/net/minecraft/world/entity/item/PrimedTnt.java
@@ -63,6 +63,7 @@ public class PrimedTnt extends Entity implements TraceableEntity {
public PrimedTnt(EntityType<? extends PrimedTnt> entityType, Level level) {
super(entityType, level);
this.blocksBuilding = true;
+ this.isPrimedTNT = true; // Sakura - client visibility settings
}
public PrimedTnt(Level level, double x, double y, double z, @Nullable LivingEntity owner) {