From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Samsuik Date: Tue, 21 Sep 2021 23:54:25 +0100 Subject: [PATCH] Client Visibility Settings diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java index dff3cc7456fe69ebd735aa950f79ce0dfed7e25e..07d8bb89ed0f9cea6353905939ba9f91c6fb64a5 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 6fa053b317fa51d0bf25a6d3f48addc55452257e..c5fffb6ca4ef4d447e4eb668e8980fe0885d99da 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -561,6 +561,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, @@ -671,6 +686,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 @@ -1876,7 +1892,18 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe for (ServerPlayer serverPlayer : this.players) { if (serverPlayer.distanceToSqr(vec3) < 4096.0) { Optional 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 531336f7c09e74ed60f7c697c26a9639a9ea489c..5c7bb1ff36fe9d91958eda88a2631b7d60659fb2 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -451,6 +451,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, level.getSharedSpawnPos(), level.getSharedSpawnAngle(), gameProfile); diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java index 186393485396cfe9b1baef29586198356e2d2600..a06f5a9b577cd9cc2cb948b2801b0aec31db8836 100644 --- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java @@ -51,6 +51,21 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack public final java.util.Map packCallbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - adventure resource pack callbacks private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit protected static final net.minecraft.resources.ResourceLocation MINECRAFT_BRAND = net.minecraft.resources.ResourceLocation.withDefaultNamespace("brand"); // Paper - Brand support + // Sakura start - client visibility settings + private @Nullable Packet recreatePacket(final Packet packet) { + final me.samsuik.sakura.player.visibility.VisibilitySettings settings = this.player.visibilitySettings; + if (packet instanceof net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket bedPacket) { + if (settings.isToggled(me.samsuik.sakura.player.visibility.VisibilityTypes.SPAWNERS) && bedPacket.getType() == net.minecraft.world.level.block.entity.BlockEntityType.MOB_SPAWNER) { + return null; + } + } else if (packet instanceof net.minecraft.network.protocol.game.ClientboundBlockEventPacket bePacket) { + if (settings.isToggled(me.samsuik.sakura.player.visibility.VisibilityTypes.PISTONS) && bePacket.getBlock() instanceof net.minecraft.world.level.block.piston.PistonBaseBlock) { + return null; + } + } + return packet; + } + // Sakura end - client visibility settings public ServerCommonPacketListenerImpl(MinecraftServer server, Connection connection, CommonListenerCookie cookie, net.minecraft.server.level.ServerPlayer player) { // CraftBukkit this.server = server; @@ -291,6 +306,12 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } else if (packet instanceof net.minecraft.network.protocol.game.ClientboundSetDefaultSpawnPositionPacket defaultSpawnPositionPacket) { this.player.compassTarget = org.bukkit.craftbukkit.util.CraftLocation.toBukkit(defaultSpawnPositionPacket.getPos(), this.getCraftPlayer().getWorld()); } + // Sakura start - client visibility settings + if (this.player.visibilitySettings.playerModified()) { + packet = this.recreatePacket(packet); + if (packet == null) return; + } + // Sakura end - client visibility settings // CraftBukkit end if (packet.isTerminal()) { this.close(); @@ -303,7 +324,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack } catch (Throwable var7) { CrashReport crashReport = CrashReport.forThrowable(var7, "Sending packet"); CrashReportCategory crashReportCategory = crashReport.addCategory("Packet being sent"); - crashReportCategory.setDetail("Packet class", () -> packet.getClass().getCanonicalName()); + // Sakura start - client visibility settings; packet has to be effectively final + final Packet packetFinal = packet; + crashReportCategory.setDetail("Packet class", () -> packetFinal.getClass().getCanonicalName()); + // Sakura end - client visibility settings; packet has to be effectively final throw new ReportedException(crashReport); } } diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java index 9041830c19e2899479e1519488faba5c416ccd88..2708d162c24e1d446485cd49f7b47abc0bcd5054 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -3192,6 +3192,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) { return; diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java index d96d493b3d14cf84a7ecf0d531aa35d41a801601..92fd4bb2b2473a0630cd5edf8d301dc7c60b2998 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -516,6 +516,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 5b036edf61c53596528bf722c46673b47c01f51d..6660e6c78303db5585a06d6836b035d0e8582922 100644 --- a/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/net/minecraft/world/entity/item/FallingBlockEntity.java @@ -76,6 +76,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 deb5e9e4cdd235311ff4e51ffb2f02f35d580645..7e3d7d5b47557e57bf661aa8d3eefcb416cb408b 100644 --- a/net/minecraft/world/entity/item/PrimedTnt.java +++ b/net/minecraft/world/entity/item/PrimedTnt.java @@ -64,6 +64,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { public PrimedTnt(EntityType 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) {