Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use multi block update packets where possible #317

Merged
merged 16 commits into from
Sep 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ body:
id: dump
attributes:
label: Orebfuscator Dump
description: Please provide an Orebfuscator dump file (use `/orebfuscator dump`) or if Orebfuscator didn't start provide a ProtocolLib dump (use `/protocol dump`). You should use https://gist.github.com/ to upload, then include the link below.
description: Please provide an Orebfuscator dump file (use `/orebfuscator dump`) or if Orebfuscator didn't start provide a ProtocolLib dump (use `/protocol dump`). You should use https://gist.github.com/ to upload, then include the link below. If you don't provide a dump file or a good reason why you didn't then this issue can get closed without futher notice.
placeholder: https://gist.github.com/HelpfulBugReporter/ThisIsAVeryUsefulLogOutput
validations:
required: true
Expand Down
32 changes: 18 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,40 @@
# Orebfuscator - Anti X-Ray
[![Release Status](https://github.com/Imprex-Development/Orebfuscator/workflows/Releases/badge.svg)](https://github.com/Imprex-Development/Orebfuscator/releases/latest) [![Build Status](https://github.com/Imprex-Development/Orebfuscator/workflows/Build/badge.svg)](https://github.com/Imprex-Development/Orebfuscator/actions?query=workflow%3ABuild)

Orebfuscator is plugin for Spigot based Minecraft Servers that modifies packets in order to hide blocks of interest from X-Ray Clients and Texture Packs. Thus it doesn't modify your world and is safe to use.
Orebfuscator empowers server owners to protect their server from X-Ray Clients and Texture Packs, all while offering a high degree of configurability. This is achieved through modifying network packets without altering your game world, guaranteeing a secure and reliable experience for users. With Orebfuscator, you can tailor the settings to suit your server's needs, ensuring precise control over the visibility of specific blocks. This means that not only does Orebfuscator safeguard your world's integrity, but it also empowers you to fine-tune your Anti-X-Ray measures for the best gameplay experience.

### Features
* Plug & Play
* Highly configurable config
* Support for Spigot based servers 1.9.4+ (only tested on spigot)
* Obfuscate non-visible blocks
* Hide block entities like Chests and Furnaces
* Make blocks in a players proximity visible based on their distance an
* Seamless Integration: Plug & Play functionality for effortless use.
* Extensive Configuration: Highly customizable settings to tailor the experience to your liking.
* Server Compatibility: Designed for Spigot-based servers 1.9.4 and newer (primarily tested on Spigot).
* Block Obfuscation: Conceal non-visible blocks from players' view.
* Block-Entity Support: Hide block entities such as Chests and Furnaces.
* Dynamic Block Visibility: Adjust block visibility based on player proximity and distance.

### Requirements
- Java 17 or higher
- Spigot and (proably) any other fork of Spigot (1.9.4 or higher)
- [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997) 5.0.0 or higher
* Java 11 or higher
* Spigot or compatible forks (1.9.4 or newer)
* [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997) 5.0.0 or later

### Installation
1. Download [ProtocolLib](https://github.com/dmulloy2/ProtocolLib/releases)
2. Download [Orebfuscator](https://github.com/Imprex-Development/Orebfuscator/releases)
3. Put both in your *plugins* directory
4. Start your server and [configure](https://github.com/Imprex-Development/Orebfuscator/wiki/Config) orebfuscator to your liking
3. Place both plugins in your _plugins_ directory
4. Start your server and [configure Orebfuscator](https://github.com/Imprex-Development/Orebfuscator/wiki/Config) to your liking

Still having trouble getting Orebfuscator to run check out our [common issues](https://github.com/Imprex-Development/Orebfuscator/wiki/Common-Issues).

### Maven
```maven

To include the API in your Maven project, add the following configuration to your `pom.xml`:

```xml
<repositories>
<repository>
<id>codemc-repo</id>
<url>https://repo.codemc.io/repository/maven-public/</url>
</repository>
...
<!-- Additional repositories can be added here if needed -->
</repositories>

<dependencies>
Expand All @@ -42,6 +45,7 @@ Still having trouble getting Orebfuscator to run check out our [common issues](h
<artifactId>orebfuscator-api</artifactId>
<version>5.2.4</version>
</dependency>
<!-- Add other dependencies as required -->
</dependencies>
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

import org.bukkit.plugin.Plugin;

import com.google.common.base.Preconditions;

/**
* Represents a String based key which consists of two components - a namespace
* and a key.
Expand Down Expand Up @@ -82,15 +80,19 @@ private static boolean isValidKey(String key) {
*/
@Deprecated
public NamespacedKey(String namespace, String key) {
Preconditions.checkArgument(namespace != null && isValidNamespace(namespace),
"Invalid namespace. Must be [a-z0-9._-]: %s", namespace);
Preconditions.checkArgument(key != null && isValidKey(key), "Invalid key. Must be [a-z0-9/._-]: %s", key);
if (namespace == null || !isValidNamespace(namespace)) {
throw new IllegalArgumentException(String.format("Invalid namespace. Must be [a-z0-9._-]: %s", namespace));
} else if (key == null || !isValidKey(key)) {
throw new IllegalArgumentException(String.format("Invalid key. Must be [a-z0-9/._-]: %s", key));
}

this.namespace = namespace;
this.key = key;

String string = toString();
Preconditions.checkArgument(string.length() < 256, "NamespacedKey must be less than 256 characters", string);
if (string.length() >= 256) {
throw new IllegalArgumentException(String.format("NamespacedKey must be less than 256 characters (%s)", string));
}
}

/**
Expand All @@ -106,20 +108,26 @@ public NamespacedKey(String namespace, String key) {
* @param key the key to create
*/
public NamespacedKey(Plugin plugin, String key) {
Preconditions.checkArgument(plugin != null, "Plugin cannot be null");
Preconditions.checkArgument(key != null, "Key cannot be null");
if (plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null");
} else if (key == null) {
throw new IllegalArgumentException("Key cannot be null");
}

this.namespace = plugin.getName().toLowerCase(Locale.ROOT);
this.key = key.toLowerCase(Locale.ROOT);

// Check validity after normalization
Preconditions.checkArgument(isValidNamespace(this.namespace), "Invalid namespace. Must be [a-z0-9._-]: %s",
this.namespace);
Preconditions.checkArgument(isValidKey(this.key), "Invalid key. Must be [a-z0-9/._-]: %s", this.key);
if (!isValidNamespace(this.namespace)) {
throw new IllegalArgumentException(String.format("Invalid namespace. Must be [a-z0-9._-]: %s", this.namespace));
} else if (!isValidKey(this.key)) {
throw new IllegalArgumentException(String.format("Invalid key. Must be [a-z0-9/._-]: %s", this.key));
}

String string = toString();
Preconditions.checkArgument(string.length() < 256, "NamespacedKey must be less than 256 characters (%s)",
string);
if (string.length() >= 256) {
throw new IllegalArgumentException(String.format("NamespacedKey must be less than 256 characters (%s)", string));
}
}

public String getNamespace() {
Expand Down Expand Up @@ -202,7 +210,9 @@ public static NamespacedKey minecraft(String key) {
* @see #fromString(String)
*/
public static NamespacedKey fromString(String string, Plugin defaultNamespace) {
Preconditions.checkArgument(string != null && !string.isEmpty(), "Input string must not be empty or null");
if (string == null || string.isEmpty()) {
throw new IllegalArgumentException("Input string must not be empty or null");
}

String[] components = string.split(":", 3);
if (components.length > 2) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.bukkit.World;
import org.bukkit.entity.Player;

import net.imprex.orebfuscator.util.BlockPos;
import net.imprex.orebfuscator.util.BlockProperties;
import net.imprex.orebfuscator.util.NamespacedKey;

Expand All @@ -26,7 +27,7 @@ public interface NmsManager {

BlockStateHolder getBlockState(World world, int x, int y, int z);

boolean sendBlockChange(Player player, int x, int y, int z);
void sendBlockUpdates(Player player, Iterable<BlockPos> iterable);

void close();
}
6 changes: 6 additions & 0 deletions orebfuscator-nms/orebfuscator-nms-v1_10_R1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
<version>${revision}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>${dependency.protocollib.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package net.imprex.orebfuscator.nms.v1_10_R1;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.bukkit.Material;
import org.bukkit.World;
Expand All @@ -10,6 +12,11 @@
import org.bukkit.craftbukkit.v1_10_R1.util.CraftMagicNumbers;
import org.bukkit.entity.Player;

import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.ChunkCoordIntPair;
import com.comphenix.protocol.wrappers.MultiBlockChangeInfo;
import com.comphenix.protocol.wrappers.WrappedBlockData;
import com.google.common.collect.ImmutableList;

import net.imprex.orebfuscator.config.CacheConfig;
Expand All @@ -18,6 +25,7 @@
import net.imprex.orebfuscator.nms.AbstractNmsManager;
import net.imprex.orebfuscator.nms.AbstractRegionFileCache;
import net.imprex.orebfuscator.nms.ReadOnlyChunk;
import net.imprex.orebfuscator.util.BlockPos;
import net.imprex.orebfuscator.util.BlockProperties;
import net.imprex.orebfuscator.util.BlockStateProperties;
import net.imprex.orebfuscator.util.NamespacedKey;
Expand All @@ -30,7 +38,8 @@
import net.minecraft.server.v1_10_R1.IBlockData;
import net.minecraft.server.v1_10_R1.MathHelper;
import net.minecraft.server.v1_10_R1.MinecraftKey;
import net.minecraft.server.v1_10_R1.PacketPlayOutBlockChange;
import net.minecraft.server.v1_10_R1.Packet;
import net.minecraft.server.v1_10_R1.PacketListenerPlayOut;
import net.minecraft.server.v1_10_R1.TileEntity;
import net.minecraft.server.v1_10_R1.WorldServer;

Expand Down Expand Up @@ -135,28 +144,57 @@ public AbstractBlockState<?> getBlockState(World world, int x, int y, int z) {
}

@Override
public boolean sendBlockChange(Player player, int x, int y, int z) {
EntityPlayer entityPlayer = player(player);
WorldServer world = entityPlayer.x();
if (!isChunkLoaded(world, x >> 4, z >> 4)) {
return false;
}
public void sendBlockUpdates(Player player, Iterable<BlockPos> iterable) {
EntityPlayer serverPlayer = player(player);
WorldServer level = serverPlayer.x();

BlockPosition position = new BlockPosition(x, y, z);
PacketPlayOutBlockChange packet = new PacketPlayOutBlockChange(world, position);
entityPlayer.playerConnection.sendPacket(packet);
updateTileEntity(entityPlayer, position, packet.block);
BlockPosition.MutableBlockPosition position = new BlockPosition.MutableBlockPosition();
Map<ChunkCoordIntPair, List<MultiBlockChangeInfo>> sectionPackets = new HashMap<>();
List<Packet<PacketListenerPlayOut>> blockEntityPackets = new ArrayList<>();

return true;
}
for (net.imprex.orebfuscator.util.BlockPos pos : iterable) {
if (!isChunkLoaded(level, pos.x >> 4, pos.z >> 4)) {
continue;
}

position.c(pos.x, pos.y, pos.z);
IBlockData blockState = level.getType(position);

ChunkCoordIntPair chunkCoord = new ChunkCoordIntPair(pos.x >> 4, pos.z >> 4);
short location = (short) ((pos.x & 0xF) << 12 | (pos.z & 0xF) << 8 | pos.y);

sectionPackets.computeIfAbsent(chunkCoord, key -> new ArrayList<>())
.add(new MultiBlockChangeInfo(location, WrappedBlockData.fromHandle(blockState), chunkCoord));

private void updateTileEntity(EntityPlayer player, BlockPosition position, IBlockData blockData) {
if (blockData.getBlock().isTileEntity()) {
WorldServer worldServer = player.x();
TileEntity tileEntity = worldServer.getTileEntity(position);
if (tileEntity != null) {
player.playerConnection.sendPacket(tileEntity.getUpdatePacket());
if (blockState.getBlock().isTileEntity()) {
TileEntity blockEntity = level.getTileEntity(position);
if (blockEntity != null) {
blockEntityPackets.add(blockEntity.getUpdatePacket());
}
}
}

for (Map.Entry<ChunkCoordIntPair, List<MultiBlockChangeInfo>> entry : sectionPackets.entrySet()) {
List<MultiBlockChangeInfo> blockStates = entry.getValue();
if (blockStates.size() == 1) {
MultiBlockChangeInfo blockEntry = blockStates.get(0);
var blockPosition = new com.comphenix.protocol.wrappers.BlockPosition(
blockEntry.getAbsoluteX(), blockEntry.getY(), blockEntry.getAbsoluteZ());

PacketContainer packet = new PacketContainer(PacketType.Play.Server.BLOCK_CHANGE);
packet.getBlockPositionModifier().write(0, blockPosition);
packet.getBlockData().write(0, blockEntry.getData());
serverPlayer.playerConnection.sendPacket((Packet<?>) packet.getHandle());
} else {
PacketContainer packet = new PacketContainer(PacketType.Play.Server.MULTI_BLOCK_CHANGE);
packet.getChunkCoordIntPairs().write(0, entry.getKey());
packet.getMultiBlockChangeInfoArrays().write(0, blockStates.toArray(MultiBlockChangeInfo[]::new));
serverPlayer.playerConnection.sendPacket((Packet<?>) packet.getHandle());
}
}

for (Packet<PacketListenerPlayOut> packet : blockEntityPackets) {
serverPlayer.playerConnection.sendPacket(packet);
}
}
}
6 changes: 6 additions & 0 deletions orebfuscator-nms/orebfuscator-nms-v1_11_R1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
<version>${revision}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>${dependency.protocollib.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
Expand Down
Loading