From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Samsuik Date: Tue, 21 Sep 2021 23:54:25 +0100 Subject: [PATCH] Visibility API and Command diff --git a/src/main/java/me/samsuik/sakura/command/SakuraCommands.java b/src/main/java/me/samsuik/sakura/command/SakuraCommands.java index 3e85c19db0655034c203eaab8d2e6b5504da5da8..9b550fad76a45fb6ea8d07f75c2ff901d56ae514 100644 --- a/src/main/java/me/samsuik/sakura/command/SakuraCommands.java +++ b/src/main/java/me/samsuik/sakura/command/SakuraCommands.java @@ -1,6 +1,9 @@ package me.samsuik.sakura.command; import me.samsuik.sakura.command.subcommands.ConfigCommand; +import me.samsuik.sakura.command.subcommands.FPSCommand; +import me.samsuik.sakura.command.subcommands.VisualCommand; +import me.samsuik.sakura.player.visibility.Visibility; import net.minecraft.server.MinecraftServer; import org.bukkit.command.Command; @@ -12,6 +15,10 @@ public final class SakuraCommands { static { COMMANDS.put("sakura", new SakuraCommand("sakura")); COMMANDS.put("config", new ConfigCommand("config")); + COMMANDS.put("fps", new FPSCommand("fps")); + COMMANDS.put("tntvisibility", new VisualCommand(Visibility.Setting.TNT_VISIBILITY, "tnttoggle")); + COMMANDS.put("sandvisibility", new VisualCommand(Visibility.Setting.SAND_VISIBILITY, "sandtoggle")); + COMMANDS.put("minimal", new VisualCommand(Visibility.Setting.MINIMAL, "minimaltnt", "tntlag")); } public static void registerCommands(MinecraftServer server) { diff --git a/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java b/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..65f7f7dee78e352bdc88ff42714d10585aa25e21 --- /dev/null +++ b/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java @@ -0,0 +1,24 @@ +package me.samsuik.sakura.command.subcommands; + +import me.samsuik.sakura.command.BaseSubCommand; +import me.samsuik.sakura.player.visibility.VisibilityGUI; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; + +@DefaultQualifier(NonNull.class) +public final class FPSCommand extends BaseSubCommand { + private final VisibilityGUI gui = new VisibilityGUI(); + + public FPSCommand(String name) { + super(name); + } + + @Override + public void execute(CommandSender sender, String[] args) { + if (sender instanceof Player player) { + this.gui.showTo(player); + } + } +} diff --git a/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java b/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java new file mode 100644 index 0000000000000000000000000000000000000000..edb3733a15687fadbf25e6f69274fab6b91508c3 --- /dev/null +++ b/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java @@ -0,0 +1,43 @@ +package me.samsuik.sakura.command.subcommands; + +import me.samsuik.sakura.command.BaseSubCommand; +import me.samsuik.sakura.configuration.GlobalConfiguration; +import me.samsuik.sakura.player.visibility.Visibility; +import net.kyori.adventure.text.minimessage.MiniMessage; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.framework.qual.DefaultQualifier; + +import java.util.Arrays; + +@DefaultQualifier(NonNull.class) +public final class VisualCommand extends BaseSubCommand { + private final Visibility.Setting type; + + public VisualCommand(Visibility.Setting type, String... aliases) { + super(type.basicName()); + this.setAliases(Arrays.asList(aliases)); + this.type = type; + } + + @Override + public void execute(CommandSender sender, String[] args) { + if (!(sender instanceof Player player)) { + return; + } + + Visibility visibility = player.getVisibility(); + + // Toggle clicked setting visibility + visibility.toggle(this.type); + + // Send message to player + String state = visibility.isEnabled(this.type) ? "Enabled" : "Disabled"; + player.sendRichMessage(GlobalConfiguration.get().fps.message, + Placeholder.unparsed("name", this.type.friendlyName()), + Placeholder.unparsed("state", state) + ); + } +} diff --git a/src/main/java/me/samsuik/sakura/player/visibility/VisibilityGUI.java b/src/main/java/me/samsuik/sakura/player/visibility/VisibilityGUI.java new file mode 100644 index 0000000000000000000000000000000000000000..6f74429456e78f17fa3e4426d9d9b5f008d8df42 --- /dev/null +++ b/src/main/java/me/samsuik/sakura/player/visibility/VisibilityGUI.java @@ -0,0 +1,123 @@ +package me.samsuik.sakura.player.visibility; + +import me.samsuik.sakura.configuration.GlobalConfiguration; +import me.samsuik.sakura.player.gui.ItemIcon; +import me.samsuik.sakura.player.gui.PlayerGUI; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.function.BiFunction; + +public final class VisibilityGUI extends PlayerGUI { + + private static final BiFunction CREATE_INVENTORY = (player, holder) -> { + Inventory inventory = Bukkit.createInventory(holder, 45, Component.text("FPS GUI")); + + for (int i = 0; i < inventory.getSize(); ++i) { + int column = i % 9; + int row = (i + 1) / 9; + + Material background = column > 0 && column < 8 ? (row > 0 && row < 4 || column > 1 && column < 7) + ? Material.matchMaterial(GlobalConfiguration.get().fps.material) + : Material.WHITE_STAINED_GLASS_PANE + : Material.BLACK_STAINED_GLASS_PANE; + + ItemStack itemstack = new ItemStack(background); + ItemMeta meta = itemstack.getItemMeta(); + meta.displayName(Component.space()); + itemstack.setItemMeta(meta); + + inventory.setItem(i, itemstack); + } + + return inventory; + }; + + public VisibilityGUI() { + super(CREATE_INVENTORY); + } + + @Override + protected void register() { + registerFPSIcon(Visibility.Setting.TNT_VISIBILITY, 12); + registerFPSIcon(Visibility.Setting.SAND_VISIBILITY, 14); + registerFPSIcon(Visibility.Setting.MINIMAL, 13); + registerFPSIcon(Visibility.Setting.SPAWNERS, 20); + // ...22 + registerFPSIcon(Visibility.Setting.EXPLOSIONS, 24); + registerFPSIcon(Visibility.Setting.PISTONS, 30); + registerFPSIcon(Visibility.Setting.REDSTONE, 31); + registerFPSIcon(Visibility.Setting.ENCHANTMENT_GLINT, 32); + + registerIcon(new ItemIcon(player -> { + Visibility.State state = player.getVisibility().getState(); + ItemStack itemstack = new ItemStack(state.material()); + + itemstack.editMeta(meta -> { + Component title = Component.text("Toggle all", state.colour()); + + // italic is default + title = title.decoration(TextDecoration.ITALIC, false); + + meta.displayName(title.append(Component.space()) + .append(Component.text(state.title(), NamedTextColor.GRAY))); + }); + + return itemstack; + }, player -> { + player.getVisibility().toggleAll(); + // refresh icons after toggling + this.refresh(player); + }, 26)); + } + + private void registerFPSIcon(Visibility.Setting setting, int slot) { + registerIcon(new ItemIcon(player -> { + Visibility visibility = player.getVisibility(); + ItemStack itemstack = new ItemStack(setting.material()); + + itemstack.editMeta(meta -> { + // Get the current state as a string + String state = visibility.isEnabled(setting) ? "Enabled" : "Disabled"; + + // Friendly name as a component + Component title = Component.text(setting.friendlyName(), setting.colour()); + + // Display names are italic by default + title = title.decoration(TextDecoration.ITALIC, false); + + // Set the display name + meta.displayName(title.append(Component.space()) + .append(Component.text(state, NamedTextColor.GRAY))); + }); + + return itemstack; + }, player -> { + Visibility visibility = player.getVisibility(); + + // Toggle clicked setting visibility + visibility.toggle(setting); + + // Get the current state as a string + String state = visibility.isEnabled(setting) ? "Enabled" : "Disabled"; + + // Send message to player + player.sendRichMessage(GlobalConfiguration.get().fps.message, + Placeholder.unparsed("name", setting.friendlyName()), + Placeholder.unparsed("state", state) + ); + + // Update toggle all icon + this.refreshSlot(player, 26); + }, slot)); + } + +} diff --git a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java index 1a37654aff9a9c86c9f7af10a1cf721371f0c5ec..82644b34a77dc5e5af38260b7b07b3ec9aceae33 100644 --- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java +++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java @@ -19,7 +19,7 @@ public class ClientboundSectionBlocksUpdatePacket implements Packet public public ClientboundSectionBlocksUpdatePacket(SectionPos sectionPos, ShortSet positions, LevelChunkSection section) { this.sectionPos = sectionPos; diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java index af8cb316ac169aa8d98a88765b85bb013b9ba961..76d4b7e9dad6536c100e5940f9f528ba2561e3b8 100644 --- a/src/main/java/net/minecraft/server/level/ChunkMap.java +++ b/src/main/java/net/minecraft/server/level/ChunkMap.java @@ -172,6 +172,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider return null; // Paper - rewrite chunk system } // Paper end + private final it.unimi.dsi.fastutil.longs.Long2IntMap minimalEntities = new it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap(); // Sakura - visibility api public ChunkMap(ServerLevel world, LevelStorageSource.LevelStorageAccess session, DataFixer dataFixer, StructureTemplateManager structureTemplateManager, Executor executor, BlockableEventLoop mainThreadExecutor, LightChunkGetter chunkProvider, ChunkGenerator chunkGenerator, ChunkProgressListener worldGenerationProgressListener, ChunkStatusUpdateListener chunkStatusChangeListener, Supplier persistentStateManagerFactory, int viewDistance, boolean dsync) { super(new RegionStorageInfo(session.getLevelId(), world.dimension(), "chunk"), session.getDimensionPath(world.dimension()).resolve("region"), dataFixer, dsync); @@ -943,6 +944,8 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } ((ca.spottedleaf.moonrise.patches.entity_tracker.EntityTrackerTrackedEntity)tracker).moonrise$clearPlayers(); } + + this.minimalEntities.clear(); // Sakura - visibility api and command } // Paper end - optimise entity tracker @@ -1179,6 +1182,29 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } // Paper end - optimise entity tracker + // Sakura start - visibility api and command + private boolean checkEntityVisibility(ServerPlayer player) { + if (player.visibility.isModified() || !(this.entity.isPrimedTNT || this.entity.isFallingBlock)) { + return true; + } + if (this.entity.isPrimedTNT && player.visibility.isToggled(me.samsuik.sakura.player.visibility.Visibility.Setting.TNT_VISIBILITY)) { + return false; + } + if (this.entity.isFallingBlock && player.visibility.isToggled(me.samsuik.sakura.player.visibility.Visibility.Setting.SAND_VISIBILITY)) { + return false; + } + if (player.visibility.isToggled(me.samsuik.sakura.player.visibility.Visibility.Setting.MINIMAL)) { + final long key = this.entity.blockPosition().asLong() ^ this.entity.getType().hashCode(); + final long visibleEntity = ChunkMap.this.minimalEntities.get(key); + if (visibleEntity != Integer.MIN_VALUE) { + return this.entity.getId() == visibleEntity; + } else { + ChunkMap.this.minimalEntities.put(key, this.entity.getId()); + } + } + return true; + } + // Sakura end - visibility api and command public TrackedEntity(final Entity entity, final int i, final int j, final boolean flag) { this.serverEntity = new ServerEntity(ChunkMap.this.level, entity, j, flag, this::broadcast, this.seenBy); // CraftBukkit @@ -1256,6 +1282,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 - visibility api and command // CraftBukkit start - respect vanish API if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index fb2e895aa658175329708828de3e1030bf28620b..07f36cd0dea417459e7022fe7e73a5177fc7c67a 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -1791,7 +1791,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ca.spottedleaf. while (iterator.hasNext()) { ServerPlayer entityplayer = (ServerPlayer) iterator.next(); - if (entityplayer.distanceToSqr(x, y, z) < 4096.0D) { + if (entityplayer.distanceToSqr(x, y, z) < 4096.0D && !entityplayer.visibility.isToggled(me.samsuik.sakura.player.visibility.Visibility.Setting.EXPLOSIONS)) { // Sakura - visibility api entityplayer.connection.send(new ClientboundExplodePacket(x, y, z, power, explosion.getToBlow(), (Vec3) explosion.getHitPlayers().get(entityplayer), explosion.getBlockInteraction(), explosion.getSmallExplosionParticles(), explosion.getLargeExplosionParticles(), explosion.getExplosionSound())); } } diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java index c396580a9cfd86ff261bed439bb4662ae88010b5..007bc568d3fb23f08790044aa3171727996927dc 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -282,6 +282,7 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper // Paper end - Optional per player mob spawns public final int[] mobBackoffCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper - per player mob count backoff + public final me.samsuik.sakura.player.visibility.Visibility visibility = new me.samsuik.sakura.player.visibility.Visibility(); // Sakura - visiblity api // CraftBukkit start public CraftPlayer.TransferCookieConnection transferCookieConnection; @@ -586,6 +587,15 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple this.respawnDimension = (ResourceKey) dataresult1.resultOrPartial(logger1::error).orElse(Level.OVERWORLD); } } + // Sakura start - visibility api + CompoundTag tag = nbt.getCompound("Sakura.Visuals"); + + for (me.samsuik.sakura.player.visibility.Visibility.Setting setting : me.samsuik.sakura.player.visibility.Visibility.Setting.values()) { + if (tag.getBoolean(setting.name())) { + visibility.toggle(setting); + } + } + // Sakura end - visibility api this.spawnExtraParticlesOnFall = nbt.getBoolean("spawn_extra_particles_on_fall"); Tag nbtbase = nbt.get("raid_omen_position"); @@ -664,6 +674,13 @@ public class ServerPlayer extends net.minecraft.world.entity.player.Player imple }); } this.getBukkitEntity().setExtraData(nbt); // CraftBukkit + // Sakura start - visibility api + CompoundTag tag = new CompoundTag(); + for (me.samsuik.sakura.player.visibility.Visibility.Setting setting : me.samsuik.sakura.player.visibility.Visibility.Setting.values()) { + tag.putBoolean(setting.name(), visibility.isToggled(setting)); + } + nbt.put("Sakura.Visuals", tag); + // Sakura end - visibility api nbt.putBoolean("spawn_extra_particles_on_fall", this.spawnExtraParticlesOnFall); if (this.raidOmenPosition != null) { diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java index 6998f32f8d79dbdb6b31ffaa126602fc4a428616..65ed367fe5b4a19ecbd0fe0193dcf0d4c5d2521d 100644 --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java @@ -43,6 +43,23 @@ import org.bukkit.craftbukkit.util.CraftLocation; import org.bukkit.craftbukkit.util.Waitable; import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerResourcePackStatusEvent; +// Sakura start +import com.mojang.datafixers.util.Pair; +import me.samsuik.sakura.player.visibility.Visibility.Setting; +import net.minecraft.core.component.DataComponents; +import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.network.protocol.game.ClientboundBlockEventPacket; +import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.DiodeBlock; +import net.minecraft.world.level.block.RedStoneWireBlock; +import net.minecraft.world.level.block.piston.PistonBaseBlock; +import net.minecraft.world.level.block.piston.PistonHeadBlock; +// Sakura end public abstract class ServerCommonPacketListenerImpl implements ServerCommonPacketListener, CraftPlayer.TransferCookieConnection { @@ -100,6 +117,65 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack protected final org.bukkit.craftbukkit.CraftServer cserver; public boolean processedDisconnect; + // Sakura start - visibility api + private @Nullable Packet recreatePacket(Packet packet) { + me.samsuik.sakura.player.visibility.Visibility visibility = this.player.visibility; + if (packet instanceof ClientboundSetEquipmentPacket equipment && visibility.isToggled(Setting.ENCHANTMENT_GLINT)) { + java.util.List> slots = new java.util.ArrayList<>(); + + for (int i = 0; i < equipment.getSlots().size(); i++) { + Pair pair = equipment.getSlots().get(i); + ItemStack itemstack = pair.getSecond(); + + if (itemstack.isEnchanted()) { + ItemStack copy = itemstack.copy(); + copy.remove(DataComponents.ENCHANTMENTS); + itemstack = copy; + } + + slots.add(new Pair<>(pair.getFirst(), itemstack)); + } + + packet = new ClientboundSetEquipmentPacket(equipment.getEntity(), slots); + } else if (packet instanceof ClientboundBlockEntityDataPacket blockdata + && visibility.isToggled(Setting.SPAWNERS) + && this.player.level().getBlockIfLoaded(blockdata.getPos()) == Blocks.SPAWNER) { + packet = new ClientboundBlockUpdatePacket(blockdata.getPos(), Blocks.BLACK_STAINED_GLASS.defaultBlockState()); + } else if (packet instanceof ClientboundBlockUpdatePacket updatePacket) { + if (visibility.isToggled(Setting.SPAWNERS) && updatePacket.blockState.getBlock() == Blocks.SPAWNER) { + packet = new ClientboundBlockUpdatePacket(updatePacket.getPos(), Blocks.BLACK_STAINED_GLASS.defaultBlockState()); + } else if (visibility.isToggled(Setting.REDSTONE) + && (updatePacket.blockState.getBlock() instanceof DiodeBlock + || updatePacket.blockState.getBlock() instanceof RedStoneWireBlock)) { + return null; + } else if (visibility.isToggled(Setting.PISTONS) + && (updatePacket.blockState.getBlock() instanceof PistonBaseBlock + || updatePacket.blockState.getBlock() instanceof PistonHeadBlock)) { + return null; + } + } else if (packet instanceof ClientboundSectionBlocksUpdatePacket sectionPacket) { + for (net.minecraft.world.level.block.state.BlockState state : sectionPacket.states) { + if (visibility.isToggled(Setting.REDSTONE) + && (state.getBlock() instanceof DiodeBlock + || state.getBlock() instanceof RedStoneWireBlock)) { + return null; + } else if (visibility.isToggled(Setting.PISTONS) + && (state.getBlock() instanceof PistonBaseBlock + || state.getBlock() instanceof PistonHeadBlock)) { + return null; + } + } + } else if (packet instanceof ClientboundBlockEventPacket blockevent + && visibility.isToggled(Setting.PISTONS) + && (blockevent.getBlock() instanceof PistonBaseBlock + || blockevent.getBlock() instanceof PistonHeadBlock)) { + return null; + } + + return packet; + } + // Sakura end - visibility api + public CraftPlayer getCraftPlayer() { return (this.player == null) ? null : (CraftPlayer) this.player.getBukkitEntity(); // CraftBukkit end @@ -306,6 +382,12 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack ClientboundSetDefaultSpawnPositionPacket packet6 = (ClientboundSetDefaultSpawnPositionPacket) packet; this.player.compassTarget = CraftLocation.toBukkit(packet6.pos, this.getCraftPlayer().getWorld()); } + // Sakura start - visibility api + if (this.player.visibility.isModified()) { + packet = this.recreatePacket(packet); + if (packet == null) return; + } + // Sakura end - visibility api // CraftBukkit end if (packet.isTerminal()) { this.close(); @@ -319,8 +401,11 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack CrashReport crashreport = CrashReport.forThrowable(throwable, "Sending packet"); CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Packet being sent"); + // Sakura start - this has to be effectively final as we're modifying the packet above + var packetFinal = packet; crashreportsystemdetails.setDetail("Packet class", () -> { - return packet.getClass().getCanonicalName(); + return packetFinal.getClass().getCanonicalName(); + // Sakura end }); throw new ReportedException(crashreport); } diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java index fcccf989c25f0a259b160c4ff7873f7009e64d14..5f066ffa28b6eb6560c4645ce52f7cbc36c7d3f5 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -3213,6 +3213,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl event.setCancelled(cancelled); AbstractContainerMenu oldContainer = this.player.containerMenu; // SPIGOT-1224 + me.samsuik.sakura.player.gui.PlayerGUI.onWindowClick(event); // Sakura - visibility gui this.cserver.getPluginManager().callEvent(event); if (this.player.containerMenu != oldContainer) { return; diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index 9f68c0fda7f5526eb97619f1a35ed3b78d1b3751..26a144e56cf906e1eb0ad52d217bcc0ef5bbd30d 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -549,6 +549,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } } // Paper end - optimise entity tracker + // Sakura start - visibility api and command + public boolean isPrimedTNT; + public boolean isFallingBlock; + // Sakura end - visibility api and command public Entity(EntityType type, Level world) { this.id = Entity.ENTITY_COUNTER.incrementAndGet(); 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 b83be9bbb9f348da83c0fd1ecc7f65c8a58b45b9..1bfdebe6c1057ee19fb96d8f0f571c9d20d14cc6 100644 --- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java +++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java @@ -78,6 +78,7 @@ public class FallingBlockEntity extends Entity { this.blockState = Blocks.SAND.defaultBlockState(); this.dropItem = true; this.fallDamageMax = 40; + this.isFallingBlock = true; // Sakura } public FallingBlockEntity(Level world, double x, double y, double z, BlockState block) { 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 42bd2d9a1528b6210e4dfb56233062fd97c9743b..28a15f612239614c6c56974da5855ce3bfd7c89e 100644 --- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java +++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java @@ -57,6 +57,7 @@ public class PrimedTnt extends Entity implements TraceableEntity { public PrimedTnt(EntityType type, Level world) { super(type, world); this.blocksBuilding = true; + this.isPrimedTNT = true; // Sakura } public PrimedTnt(Level world, double x, double y, double z, @Nullable LivingEntity igniter) { diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index ad740739437be632fc7fedec488a7d0c49534688..ff8580ca3e74e7e28afbfa8c2e566b98ced2dbff 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -547,6 +547,13 @@ public class CraftPlayer extends CraftHumanEntity implements Player { this.getHandle().displayName = name == null ? this.getName() : name; } + // Sakura start - visiblity api + @Override + public me.samsuik.sakura.player.visibility.Visibility getVisibility() { + return getHandle().visibility; + } + // Sakura end + // Paper start @Override public void playerListName(net.kyori.adventure.text.Component name) {