9
0
mirror of https://github.com/Samsuik/Sakura.git synced 2025-12-19 14:59:30 +00:00
Files
SakuraMC/patches/server/0006-Visibility-API-and-Command.patch
Samsuik 70571388cf Updated Upstream (Paper)
Upstream has released updates that appear to apply and compile correctly

Paper Changes:
PaperMC/Paper@f9edc4b Update paperweight to 1.5.11
PaperMC/Paper@2f92d4e Updated Upstream (Bukkit/CraftBukkit)
PaperMC/Paper@8d8eb3b optimise explosion damage further
PaperMC/Paper@7606e6d fixup tests and add missing API detected by those tests
PaperMC/Paper@f17622c more cleanup and resource pack api fixes
PaperMC/Paper@9051fc3 remove redundant patch
PaperMC/Paper@abfb6b2 more work on adventure codecs
PaperMC/Paper@b42a1da Use uuid param in setResourcePack
PaperMC/Paper@bcbe5dc Fix `PlayerInteractEvent#getClickedBlock()` returning wrong block in adventure mode (#10019)
2023-12-10 13:33:09 +00:00

631 lines
32 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] 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 c2651cac1dcf85fb67fe981b97efee4e56431de2..d7d0c49cc5d576c594dee16ddba037cd147e11fa 100644
--- a/src/main/java/me/samsuik/sakura/command/SakuraCommands.java
+++ b/src/main/java/me/samsuik/sakura/command/SakuraCommands.java
@@ -2,6 +2,9 @@ package me.samsuik.sakura.command;
import io.papermc.paper.command.PaperPluginsCommand;
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;
@@ -14,6 +17,10 @@ public 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(final 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..1dc2a98123d671c945e85b97a898f56e527a81f5
--- /dev/null
+++ b/src/main/java/me/samsuik/sakura/command/subcommands/FPSCommand.java
@@ -0,0 +1,26 @@
+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 class FPSCommand extends BaseSubCommand {
+
+ private final VisibilityGUI VISIBILITY_GUI = new VisibilityGUI();
+
+ public FPSCommand(String name) {
+ super(name);
+ }
+
+ @Override
+ public void execute(CommandSender sender, String[] args) {
+ if (sender instanceof Player player) {
+ VISIBILITY_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..6027e4741e2de7c6d3bd7b094c196a212e34e2f5
--- /dev/null
+++ b/src/main/java/me/samsuik/sakura/command/subcommands/VisualCommand.java
@@ -0,0 +1,45 @@
+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 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;
+ }
+
+ var visibility = player.getVisibility();
+
+ // Toggle clicked setting visibility
+ visibility.toggle(type);
+
+ // Send message to player
+ var state = visibility.isEnabled(type) ? "Enabled" : "Disabled";
+ player.sendMessage(MiniMessage.miniMessage().deserialize(GlobalConfiguration.get().fps.message,
+ Placeholder.unparsed("name", 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..d5bd47426a219a3825deaa0b62386c88d17b4aac
--- /dev/null
+++ b/src/main/java/me/samsuik/sakura/player/visibility/VisibilityGUI.java
@@ -0,0 +1,119 @@
+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.TextColor;
+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 class VisibilityGUI extends PlayerGUI {
+
+ private static final BiFunction<Player, Holder, Inventory> 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, Material.TNT, NamedTextColor.RED, 12);
+ registerFPSIcon(Visibility.Setting.SAND_VISIBILITY, Material.SAND, NamedTextColor.YELLOW, 14);
+ registerFPSIcon(Visibility.Setting.MINIMAL, Material.NETHER_BRICK_SLAB, NamedTextColor.GOLD, 13);
+ registerFPSIcon(Visibility.Setting.SPAWNERS, Material.SPAWNER, NamedTextColor.DARK_GRAY, 20);
+ registerFPSIcon(Visibility.Setting.FLASHING_TNT, Material.REDSTONE_LAMP, NamedTextColor.RED, 22);
+ registerFPSIcon(Visibility.Setting.EXPLOSIONS, Material.COBWEB, NamedTextColor.WHITE, 24);
+ registerFPSIcon(Visibility.Setting.PISTONS, Material.PISTON, NamedTextColor.GOLD, 30);
+ registerFPSIcon(Visibility.Setting.REDSTONE, Material.REDSTONE, NamedTextColor.DARK_RED, 31);
+ registerFPSIcon(Visibility.Setting.ENCHANTMENT_GLINT, Material.ENCHANTED_BOOK, NamedTextColor.DARK_PURPLE, 32);
+
+ registerIcon(new ItemIcon(
+ (player) -> {
+ ItemStack itemstack = new ItemStack(Material.GREEN_STAINED_GLASS_PANE);
+ Component title = Component.text("Toggle all", NamedTextColor.GREEN);
+
+ itemstack.editMeta(meta -> meta.displayName(title.decoration(TextDecoration.ITALIC, false)));
+ return itemstack;
+ },
+ (player) -> {
+ player.getVisibility().toggleAll();
+
+ // refresh icons after toggling
+ this.refresh(player);
+ },
+ 26
+ ));
+ }
+
+ private void registerFPSIcon(Visibility.Setting setting, Material material, TextColor colour, int slot) {
+ registerIcon(new ItemIcon((player) -> {
+ Visibility visibility = player.getVisibility();
+ ItemStack itemstack = new ItemStack(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(), 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)
+ );
+ },
+ 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 e3f355c85eb7cc8c1683e3009502c10a5ed32daa..349e56d5caad3fc38e83eac6ffff83e2fb30eaa7 100644
--- a/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
+++ b/src/main/java/net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket.java
@@ -16,7 +16,7 @@ public class ClientboundSectionBlocksUpdatePacket implements Packet<ClientGamePa
private static final int POS_IN_SECTION_BITS = 12;
private final SectionPos sectionPos;
private final short[] positions;
- private final BlockState[] states;
+ public final BlockState[] states; // Sakura - private -> public
public ClientboundSectionBlocksUpdatePacket(SectionPos sectionPos, ShortSet positions, LevelChunkSection section) {
this.sectionPos = sectionPos;
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index b5e2ae560431cd3ecfc780deb25488016c0ad0e7..73dc4f245039805b635f9e89438104e3b7a93e7b 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1745,6 +1745,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.profiler.pop();
worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions
worldserver.localConfig().expire(currentTickLong); // Sakura
+ worldserver.minimalTNT.clear(); // Sakura - visibility api
}
this.isIteratingOverLevels = false; // Paper
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index caa73632aee15583c6b6ed12a668c8f49b794708..7e205ccdc7c6691581eb7423d01a383b87f0d2af 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -1435,6 +1435,22 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
}
// Paper end - check Y
+ // Sakura start - visibility api
+ if (this.entity.isPrimedTNT && player.visibility.isToggled(me.samsuik.sakura.player.visibility.Visibility.Setting.TNT_VISIBILITY)
+ || this.entity.isFallingBlock && player.visibility.isToggled(me.samsuik.sakura.player.visibility.Visibility.Setting.SAND_VISIBILITY)) {
+ flag = false;
+ }
+
+ if (flag && (this.entity.isPrimedTNT || this.entity.isFallingBlock) && player.visibility.isToggled(me.samsuik.sakura.player.visibility.Visibility.Setting.MINIMAL)) {
+ long key = entity.blockPosition().asLong();
+
+ if (level.minimalTNT.containsKey(key)) {
+ flag = level.minimalTNT.get(key) == entity.getId();
+ } else {
+ level.minimalTNT.put(key, entity.getId());
+ }
+ }
+ // Sakura end
// CraftBukkit start - respect vanish API
if (flag && !player.getBukkitEntity().canSee(this.entity.getBukkitEntity())) { // Paper - only consider hits
flag = false;
diff --git a/src/main/java/net/minecraft/server/level/ServerEntity.java b/src/main/java/net/minecraft/server/level/ServerEntity.java
index 35674f92a67f93382103c2766df4b678ba5c862f..83c4639c2bdca4dc4281d9f5eca104af3063bfa5 100644
--- a/src/main/java/net/minecraft/server/level/ServerEntity.java
+++ b/src/main/java/net/minecraft/server/level/ServerEntity.java
@@ -47,6 +47,13 @@ import net.minecraft.util.Mth;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerVelocityEvent;
// CraftBukkit end
+// Sakura start
+import me.samsuik.sakura.player.visibility.Visibility;
+import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
+import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.level.block.Block;
+import net.minecraft.world.level.block.Blocks;
+// Sakura end
public class ServerEntity {
@@ -284,6 +291,18 @@ public class ServerEntity {
this.entity.startSeenByPlayer(player);
}
+ // Sakura start - visibility api
+ protected Packet<ClientGamePacketListener> createEntityPacket(Entity entity, ServerPlayer entityplayer) {
+ if (entity.isPrimedTNT && entityplayer.visibility.isToggled(Visibility.Setting.FLASHING_TNT)) {
+ return new ClientboundAddEntityPacket(entity.getId(), entity.getUUID(),
+ entity.getX(), entity.getY(), entity.getZ(), 0, 0, EntityType.FALLING_BLOCK,
+ Block.getId(Blocks.TNT.defaultBlockState()), entity.getDeltaMovement(), entity.getYHeadRot());
+ } else {
+ return entity.getAddEntityPacket();
+ }
+ }
+ // Sakura end
+
public void sendPairingData(ServerPlayer player, Consumer<Packet<ClientGamePacketListener>> sender) {
if (this.entity.isRemoved()) {
// CraftBukkit start - Remove useless error spam, just return
@@ -292,12 +311,19 @@ public class ServerEntity {
// CraftBukkit end
}
- Packet<ClientGamePacketListener> packet = this.entity.getAddEntityPacket();
+ Packet<ClientGamePacketListener> packet = this.createEntityPacket(this.entity, player); // Sakura - visibility api
this.yHeadRotp = Mth.floor(this.entity.getYHeadRot() * 256.0F / 360.0F);
sender.accept(packet);
if (this.trackedDataValues != null) {
- sender.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), this.trackedDataValues));
+ // Sakura start - visibility api
+ if (this.entity.isPrimedTNT && player.visibility.isToggled(Visibility.Setting.FLASHING_TNT)) {
+ // Could modifying this break something elsewhere?
+ trackedDataValues.removeIf((data) -> data.id() == 8);
+ }
+
+ sender.accept(new ClientboundSetEntityDataPacket(this.entity.getId(), trackedDataValues));
+ // Sakura end
}
boolean flag = this.trackDelta;
@@ -367,6 +393,32 @@ public class ServerEntity {
}
}
+
+ // Sakura start - visibility api
+ private void broadcastEntityData(List<SynchedEntityData.DataValue<?>> packedValues) {
+ Packet<?> packet0 = new ClientboundSetEntityDataPacket(this.entity.getId(), packedValues);
+ Packet<?> packet1 = null;
+
+ if (this.entity.isPrimedTNT) {
+ var copyOfDirtyItems = Lists.newArrayList(packedValues);
+ copyOfDirtyItems.removeIf((data) -> data.id() == 8);
+
+ if (!copyOfDirtyItems.isEmpty()) {
+ packet1 = new ClientboundSetEntityDataPacket(this.entity.getId(), copyOfDirtyItems);
+ }
+ }
+
+ for (var connection : trackedPlayers) {
+ var player = connection.getPlayer();
+
+ if (!this.entity.isPrimedTNT || !player.visibility.isToggled(Visibility.Setting.FLASHING_TNT)) {
+ connection.send(packet0);
+ } else if (packet1 != null) {
+ connection.send(packet1);
+ }
+ }
+ }
+ // Sakura end
private void sendDirtyEntityData() {
SynchedEntityData datawatcher = this.entity.getEntityData();
@@ -374,7 +426,7 @@ public class ServerEntity {
if (list != null) {
this.trackedDataValues = datawatcher.getNonDefaultValues();
- this.broadcastAndSend(new ClientboundSetEntityDataPacket(this.entity.getId(), list));
+ this.broadcastEntityData(list); // Sakura - visibility api
}
if (this.entity instanceof LivingEntity) {
diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java
index 1f36015d2e9c433cfe2de079b8eba144f0dad4cf..c33c9cb3a0e574e5284e48ffaf8d0945061ea388 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1956,7 +1956,7 @@ public class ServerLevel extends Level implements WorldGenLevel {
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 8efbbd379244e3ed54d4aba199037cc20ccd096a..3ef738c817c10a9233b930296ce5df6e6dc0a58b 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -261,6 +261,7 @@ public class ServerPlayer extends Player {
public final int[] mobCounts = new int[MOBCATEGORY_TOTAL_ENUMS]; // Paper
// Paper end - mob spawning rework
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 String displayName;
@@ -567,6 +568,15 @@ public class ServerPlayer extends Player {
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
}
@@ -633,6 +643,13 @@ public class ServerPlayer extends Player {
});
}
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
}
diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
index 4a712f5fc4f0b4a4434ae808c989113bee8d8634..c59db7ea7d4dafc6df030c2c4d5f51395fe1c363 100644
--- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java
@@ -40,6 +40,23 @@ import org.bukkit.craftbukkit.util.Waitable;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerResourcePackStatusEvent;
// CraftBukkit end
+// Sakura start
+import com.mojang.datafixers.util.Pair;
+import me.samsuik.sakura.player.visibility.Visibility.Setting;
+import net.minecraft.world.level.block.Blocks;
+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.ClientboundLevelChunkPacketData;
+import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData.BlockEntityTagOutput;
+import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket;
+import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket;
+import net.minecraft.world.level.block.DiodeBlock;
+import net.minecraft.world.level.block.entity.BlockEntityType;
+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 {
@@ -234,6 +251,61 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack
} else if (packet instanceof ClientboundSetDefaultSpawnPositionPacket) {
ClientboundSetDefaultSpawnPositionPacket packet6 = (ClientboundSetDefaultSpawnPositionPacket) packet;
this.player.compassTarget = CraftLocation.toBukkit(packet6.pos, this.getCraftPlayer().getWorld());
+ // Sakura start - visibility api
+ } else if (!player.visibility.isModified()) {
+ // Skip players that haven't modified their settings
+ } else if (packet instanceof ClientboundSetEquipmentPacket equipment
+ && player.visibility.isToggled(Setting.ENCHANTMENT_GLINT)) {
+ var slots = new java.util.ArrayList<Pair<net.minecraft.world.entity.EquipmentSlot, net.minecraft.world.item.ItemStack>>();
+
+ for (int i = 0; i < equipment.getSlots().size(); i++) {
+ var pair = equipment.getSlots().get(i);
+ var itemstack = pair.getSecond();
+
+ if (itemstack.isEnchanted()) {
+ var copy = itemstack.copy();
+ copy.getTag().remove("ench");
+ itemstack = copy;
+ }
+
+ slots.add(new Pair<>(pair.getFirst(), itemstack));
+ }
+
+ packet = new ClientboundSetEquipmentPacket(equipment.getEntity(), slots);
+ } else if (packet instanceof ClientboundBlockEntityDataPacket blockdata
+ && player.visibility.isToggled(Setting.SPAWNERS)
+ && player.level().getBlockIfLoaded(blockdata.getPos()) == Blocks.SPAWNER) {
+ packet = new ClientboundBlockUpdatePacket(blockdata.getPos(), Blocks.BLACK_STAINED_GLASS.defaultBlockState());
+ } else if (packet instanceof ClientboundBlockUpdatePacket updatePacket) {
+ if (player.visibility.isToggled(Setting.SPAWNERS) && updatePacket.blockState.getBlock() == Blocks.SPAWNER) {
+ packet = new ClientboundBlockUpdatePacket(updatePacket.getPos(), Blocks.BLACK_STAINED_GLASS.defaultBlockState());
+ } else if (player.visibility.isToggled(Setting.REDSTONE)
+ && (updatePacket.blockState.getBlock() instanceof DiodeBlock
+ || updatePacket.blockState.getBlock() instanceof RedStoneWireBlock)) {
+ return;
+ } else if (player.visibility.isToggled(Setting.PISTONS)
+ && (updatePacket.blockState.getBlock() instanceof PistonBaseBlock
+ || updatePacket.blockState.getBlock() instanceof PistonHeadBlock)) {
+ return;
+ }
+ } else if (packet instanceof ClientboundSectionBlocksUpdatePacket sectionPacket) {
+ for (var state : sectionPacket.states) {
+ if (player.visibility.isToggled(Setting.REDSTONE)
+ && (state.getBlock() instanceof DiodeBlock
+ || state.getBlock() instanceof RedStoneWireBlock)) {
+ return;
+ } else if (player.visibility.isToggled(Setting.PISTONS)
+ && (state.getBlock() instanceof PistonBaseBlock
+ || state.getBlock() instanceof PistonHeadBlock)) {
+ return;
+ }
+ }
+ } else if (packet instanceof ClientboundBlockEventPacket blockevent
+ && player.visibility.isToggled(Setting.PISTONS)
+ && (blockevent.getBlock() instanceof PistonBaseBlock
+ || blockevent.getBlock() instanceof PistonHeadBlock)) {
+ return;
+ // Sakura end
}
// CraftBukkit end
boolean flag = !this.suspendFlushingOnServerThread || !this.server.isSameThread();
@@ -244,8 +316,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 30ccbab1586a656e0ae41d7406525fb02d9e025b..187ba90c50256aaa0514f4b2bd79bf30bc04b0af 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3107,6 +3107,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 9abe817ae202edaa2d88cd59ae5c7db0b1c634be..f3b02609297b663559b82984dcd93db186e645f5 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -536,6 +536,8 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
this.teleportTo(worldserver, null);
}
// Paper end - make end portalling safe
+ public boolean isPrimedTNT; // Sakura
+ public boolean isFallingBlock; // Sakura
public boolean isLegacyTrackingEntity = false;
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 45c07733f03b5c11f6d8e820f65dc950c70d9a67..3ec931c9aa9e2857e0c24eeb47c1048ace05f6fe 100644
--- a/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
+++ b/src/main/java/net/minecraft/world/entity/item/FallingBlockEntity.java
@@ -73,6 +73,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 c3e47426382296d650fa00ce0bc1a82bf23c7877..62a3cd512d473d5ed673386d5c15091a09426945 100644
--- a/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
+++ b/src/main/java/net/minecraft/world/entity/item/PrimedTnt.java
@@ -38,6 +38,7 @@ public class PrimedTnt extends Entity implements TraceableEntity {
public PrimedTnt(EntityType<? extends PrimedTnt> 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/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index 512088b5457e5afbc29d2937051fc4dcc4c5aed6..8fd4d63fdbff9c454d903f4797ec9281df7266fc 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -226,6 +226,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
public abstract ResourceKey<LevelStem> getTypeKey();
+ public final it.unimi.dsi.fastutil.longs.Long2IntMap minimalTNT = new it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap(); // Sakura - visibility api
+
protected Level(WritableLevelData worlddatamutable, ResourceKey<Level> resourcekey, RegistryAccess iregistrycustom, Holder<DimensionType> holder, Supplier<ProfilerFiller> supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function<org.spigotmc.SpigotWorldConfig, io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, Supplier<me.samsuik.sakura.configuration.WorldConfiguration> sakuraWorldConfigCreator, java.util.concurrent.Executor executor) { // Sakura // Paper - Async-Anti-Xray - Pass executor
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index fd84786f3e72875e79df46416f47f3403876cef3..044033eb34581849ecb0463164ca05bf19466c76 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -497,6 +497,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) {