Skip to content

Commit

Permalink
feat: add support for 1.20 and bedrock obfuscation (#291)
Browse files Browse the repository at this point in the history
* chore: update to java 17, protocollib 5.0.0

* chore: update README

* feat: add support for 1.20 and bedrock obfuscation

* feat: added bedrock obfuscation

---------

Co-authored-by: Nils Gereke <[email protected]>
  • Loading branch information
Ingrim4 and NgLoader authored Jun 7, 2023
1 parent 3f664ec commit ef153ac
Show file tree
Hide file tree
Showing 30 changed files with 958 additions and 32 deletions.
29 changes: 15 additions & 14 deletions .github/workflows/buildtools.sh
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
#!/bin/bash

build () {
JAVA_PATH=$"JAVA_HOME_$2_X64"
export JAVA_HOME=${!JAVA_PATH}
JAVA_PATH=$"JAVA_HOME_$2_X64"
export JAVA_HOME=${!JAVA_PATH}

echo "Building v$1 with java-$2 ($JAVA_HOME)"
echo "Building v$1 with java-$2 ($JAVA_HOME)"

rm -rf $1
mkdir $1
cd $1
rm -rf $1
mkdir $1
cd $1

curl -o BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
"$JAVA_HOME/bin/java" -jar BuildTools.jar --rev $1 --remapped
curl -o BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar
"$JAVA_HOME/bin/java" -jar BuildTools.jar --rev $1 --remapped

cd ..
cd ..
}

checkVersion () {
echo Checking version $1
echo Checking version $1

if [ ! -d ~/.m2/repository/org/spigotmc/spigot/$1-R0.1-SNAPSHOT ]; then
build $1 $2
fi
if [ ! -d ~/.m2/repository/org/spigotmc/spigot/$1-R0.1-SNAPSHOT ]; then
build $1 $2
fi
}

checkVersion "1.9.4" "8"
Expand All @@ -40,4 +40,5 @@ checkVersion "1.18.1" "17"
checkVersion "1.18.2" "17"
checkVersion "1.19.2" "17"
checkVersion "1.19.3" "17"
checkVersion "1.19.4" "17"
checkVersion "1.19.4" "17"
checkVersion "1.20" "17"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Orebfuscator is plugin for Spigot based Minecraft Servers that modifies packets
### 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) 4.0 or higher
- [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997) 5.0.0 or higher

### Installation
1. Download [ProtocolLib](https://github.com/dmulloy2/ProtocolLib/releases)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public interface BlockFlags {
public static final int FLAG_BLOCK_ENTITY = 2;
public static final int FLAG_PROXIMITY = 4;
public static final int FLAG_USE_BLOCK_BELOW = 8;
public static final int FLAG_ALLOW_FOR_USE_BLOCK_BELOW = 16;

public static boolean isEmpty(int mask) {
return (mask & 0xFF) == 0;
Expand All @@ -31,6 +32,10 @@ public static boolean isUseBlockBelowBitSet(int mask) {
return isBitSet(mask, FLAG_USE_BLOCK_BELOW);
}

public static boolean isAllowForUseBlockBelowBitSet(int mask) {
return isBitSet(mask, FLAG_ALLOW_FOR_USE_BLOCK_BELOW);
}

int flags(int blockState);

int flags(int blockState, int y);
Expand Down
2 changes: 1 addition & 1 deletion orebfuscator-nms/orebfuscator-nms-v1_18_R1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib-API</artifactId>
<artifactId>ProtocolLib</artifactId>
<version>${dependency.protocollib.version}</version>
<scope>provided</scope>
</dependency>
Expand Down
66 changes: 66 additions & 0 deletions orebfuscator-nms/orebfuscator-nms-v1_20_R1/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>net.imprex</groupId>
<artifactId>orebfuscator-nms</artifactId>
<version>${revision}</version>
</parent>

<artifactId>orebfuscator-nms-v1_20_R1</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>net.imprex</groupId>
<artifactId>orebfuscator-nms-api</artifactId>
<version>${revision}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.20-R0.1-SNAPSHOT</version>
<classifier>remapped-mojang</classifier>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>net.md-5</groupId>
<artifactId>specialsource-maven-plugin</artifactId>
<version>${plugin.specialsource.version}</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-obf</id>
<configuration>
<srgIn>org.spigotmc:minecraft-server:1.20-R0.1-SNAPSHOT:txt:maps-mojang</srgIn>
<reverse>true</reverse>
<remappedDependencies>org.spigotmc:spigot:1.20-R0.1-SNAPSHOT:jar:remapped-mojang</remappedDependencies>
<remappedArtifactAttached>true</remappedArtifactAttached>
<remappedClassifierName>remapped-obf</remappedClassifierName>
</configuration>
</execution>
<execution>
<phase>package</phase>
<goals>
<goal>remap</goal>
</goals>
<id>remap-spigot</id>
<configuration>
<inputFile>${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar</inputFile>
<srgIn>org.spigotmc:minecraft-server:1.20-R0.1-SNAPSHOT:csrg:maps-spigot</srgIn>
<remappedDependencies>org.spigotmc:spigot:1.20-R0.1-SNAPSHOT:jar:remapped-obf</remappedDependencies>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package net.imprex.orebfuscator.nms.v1_20_R1;

import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;

import net.imprex.orebfuscator.nms.AbstractBlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;

public class BlockStateWrapper extends AbstractBlockState<BlockState> {

public BlockStateWrapper(int x, int y, int z, World world, BlockState state) {
super(x, y, z, world, state);
}

@Override
public int getBlockId() {
return Block.getId(this.state);
}

@Override
public void notifyBlockChange() {
ServerLevel serverLevel = ((CraftWorld) this.world).getHandle();
serverLevel.getChunkSource().blockChanged(new BlockPos(this.getX(), this.getY(), this.getZ()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package net.imprex.orebfuscator.nms.v1_20_R1;

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

import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
import org.bukkit.entity.Player;

import com.google.common.collect.ImmutableList;

import net.imprex.orebfuscator.config.CacheConfig;
import net.imprex.orebfuscator.config.Config;
import net.imprex.orebfuscator.nms.AbstractBlockState;
import net.imprex.orebfuscator.nms.AbstractNmsManager;
import net.imprex.orebfuscator.nms.AbstractRegionFileCache;
import net.imprex.orebfuscator.nms.ReadOnlyChunk;
import net.imprex.orebfuscator.util.BlockProperties;
import net.imprex.orebfuscator.util.BlockStateProperties;
import net.imprex.orebfuscator.util.NamespacedKey;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;

public class NmsManager extends AbstractNmsManager {

private static ServerLevel level(World world) {
return ((CraftWorld) world).getHandle();
}

private static ServerPlayer player(Player player) {
return ((CraftPlayer) player).getHandle();
}

private static boolean isChunkLoaded(ServerLevel level, int chunkX, int chunkZ) {
return level.getChunkSource().isChunkLoaded(chunkX, chunkZ);
}

private static BlockState getBlockState(World world, int x, int y, int z, boolean loadChunk) {
ServerLevel level = level(world);
ServerChunkCache serverChunkCache = level.getChunkSource();

if (isChunkLoaded(level, x >> 4, z >> 4) || loadChunk) {
// will load chunk if not loaded already
LevelChunk chunk = serverChunkCache.getChunk(x >> 4, z >> 4, true);
return chunk != null ? chunk.getBlockState(new BlockPos(x, y, z)) : null;
}
return null;
}

public NmsManager(Config config) {
super(config);

for (Map.Entry<ResourceKey<Block>, Block> entry : BuiltInRegistries.BLOCK.entrySet()) {
NamespacedKey namespacedKey = NamespacedKey.fromString(entry.getKey().location().toString());
Block block = entry.getValue();

ImmutableList<BlockState> possibleBlockStates = block.getStateDefinition().getPossibleStates();
List<BlockStateProperties> possibleBlockStateProperties = new ArrayList<>();

for (BlockState blockState : possibleBlockStates) {
Material material = CraftBlockData.fromData(blockState).getMaterial();

BlockStateProperties properties = BlockStateProperties.builder(Block.getId(blockState))
.withIsAir(blockState.isAir())
// check if material is occluding and use blockData check for rare edge cases like barrier, spawner, slime_block, ...
.withIsOccluding(material.isOccluding() && blockState.canOcclude())
.withIsBlockEntity(blockState.hasBlockEntity())
.build();

possibleBlockStateProperties.add(properties);
this.registerBlockStateProperties(properties);
}

int defaultBlockStateId = Block.getId(block.defaultBlockState());
BlockStateProperties defaultBlockState = getBlockStateProperties(defaultBlockStateId);

BlockProperties blockProperties = BlockProperties.builder(namespacedKey)
.withDefaultBlockState(defaultBlockState)
.withPossibleBlockStates(ImmutableList.copyOf(possibleBlockStateProperties))
.build();

this.registerBlockProperties(blockProperties);
}
}

@Override
protected AbstractRegionFileCache<?> createRegionFileCache(CacheConfig cacheConfig) {
return new RegionFileCache(cacheConfig);
}

@Override
public int getMaxBitsPerBlock() {
return Mth.ceillog2(Block.BLOCK_STATE_REGISTRY.size());
}

@Override
public int getTotalBlockCount() {
return Block.BLOCK_STATE_REGISTRY.size();
}

@Override
public ReadOnlyChunk getReadOnlyChunk(World world, int chunkX, int chunkZ) {
ServerChunkCache serverChunkCache = level(world).getChunkSource();
LevelChunk chunk = serverChunkCache.getChunk(chunkX, chunkZ, true);
return new ReadOnlyChunkWrapper(chunk);
}

@Override
public AbstractBlockState<?> getBlockState(World world, int x, int y, int z) {
BlockState blockData = getBlockState(world, x, y, z, false);
return blockData != null ? new BlockStateWrapper(x, y, z, world, blockData) : null;
}

@Override
public boolean sendBlockChange(Player player, int x, int y, int z) {
ServerPlayer serverPlayer = player(player);
ServerLevel level = serverPlayer.serverLevel();
if (!isChunkLoaded(level, x >> 4, z >> 4)) {
return false;
}

BlockPos position = new BlockPos(x, y, z);
ClientboundBlockUpdatePacket packet = new ClientboundBlockUpdatePacket(level, position);
serverPlayer.connection.send(packet);
updateBlockEntity(serverPlayer, position, packet.blockState);

return true;
}

private void updateBlockEntity(ServerPlayer player, BlockPos position, BlockState blockData) {
if (blockData.hasBlockEntity()) {
ServerLevel serverLevel = player.serverLevel();
BlockEntity blockEntity = serverLevel.getBlockEntity(position);
if (blockEntity != null) {
player.connection.send(blockEntity.getUpdatePacket());
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package net.imprex.orebfuscator.nms.v1_20_R1;

import net.imprex.orebfuscator.nms.ReadOnlyChunk;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;

public class ReadOnlyChunkWrapper implements ReadOnlyChunk {

private final LevelChunk chunk;

ReadOnlyChunkWrapper(LevelChunk chunk) {
this.chunk = chunk;
}

private BlockState getState(int x, int y, int z) {
int sectionIndex = chunk.getSectionIndex(y);
LevelChunkSection[] sections = chunk.getSections();
if (sectionIndex >= 0 && sectionIndex < sections.length) {
LevelChunkSection section = sections[sectionIndex];
if (sections != null && !section.hasOnlyAir()) {
return section.getBlockState(x & 0xF, y & 0xF, z & 0xF);
}
}
return Blocks.AIR.defaultBlockState();
}

@Override
public int getBlockState(int x, int y, int z) {
return Block.getId(getState(x, y, z));
}
}
Loading

0 comments on commit ef153ac

Please sign in to comment.