diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e26e25d0..e1348729 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -23,13 +23,14 @@ jobs:
key: ${{ runner.os }}-maven-${{ secrets.CACHE_VERSION }}-${{ hashFiles('./.github/workflows/buildtools.sh') }}
restore-keys: |
${{ runner.os }}-maven-${{ secrets.CACHE_VERSION }}-
- - name: Set up JDK 8/17
+ - name: Set up JDK 8/17/21
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: |
8
17
+ 21
- name: Run BuildTools
run: |
bash ./.github/workflows/buildtools.sh
diff --git a/.github/workflows/buildtools.sh b/.github/workflows/buildtools.sh
index 41ea07d7..bbfad0c2 100644
--- a/.github/workflows/buildtools.sh
+++ b/.github/workflows/buildtools.sh
@@ -44,3 +44,4 @@ checkVersion "1.19.4" "17"
checkVersion "1.20.1" "17"
checkVersion "1.20.2" "17"
checkVersion "1.20.4" "17"
+checkVersion "1.20.5" "21"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 1354f151..56dd1350 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,13 +23,14 @@ jobs:
key: ${{ runner.os }}-maven-${{ secrets.CACHE_VERSION }}-${{ hashFiles('./.github/workflows/buildtools.sh') }}
restore-keys: |
${{ runner.os }}-maven-${{ secrets.CACHE_VERSION }}-
- - name: Set up JDK 8/17
+ - name: Set up JDK 8/17/21
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: |
8
17
+ 21
- name: Run BuildTools
run: |
bash ./.github/workflows/buildtools.sh
diff --git a/orebfuscator-nms/orebfuscator-nms-v1_20_R4/pom.xml b/orebfuscator-nms/orebfuscator-nms-v1_20_R4/pom.xml
new file mode 100644
index 00000000..d5bb3333
--- /dev/null
+++ b/orebfuscator-nms/orebfuscator-nms-v1_20_R4/pom.xml
@@ -0,0 +1,81 @@
+
+ 4.0.0
+
+
+ net.imprex
+ orebfuscator-nms
+ ${revision}
+
+
+ orebfuscator-nms-v1_20_R4
+ jar
+
+
+
+ net.imprex
+ orebfuscator-nms-api
+ ${revision}
+ provided
+
+
+ org.spigotmc
+ spigot
+ 1.20.5-R0.1-SNAPSHOT
+ remapped-mojang
+ provided
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+ true
+ mojang-mapped
+
+
+ net.imprex.orebfuscator.nms.v1_20_R4
+ net.imprex.orebfuscator.nms.v1_20_R4_mojang
+
+
+
+
+
+ net.md-5
+ specialsource-maven-plugin
+ ${plugin.specialsource.version}
+
+
+ package
+
+ remap
+
+ remap-obf
+
+ org.spigotmc:minecraft-server:1.20.5-R0.1-SNAPSHOT:txt:maps-mojang
+ true
+ org.spigotmc:spigot:1.20.5-R0.1-SNAPSHOT:jar:remapped-mojang
+ true
+ remapped-obf
+
+
+
+ package
+
+ remap
+
+ remap-spigot
+
+ ${project.build.directory}/${project.artifactId}-${project.version}-remapped-obf.jar
+ org.spigotmc:minecraft-server:1.20.5-R0.1-SNAPSHOT:csrg:maps-spigot
+ org.spigotmc:spigot:1.20.5-R0.1-SNAPSHOT:jar:remapped-obf
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/orebfuscator-nms/orebfuscator-nms-v1_20_R4/src/main/java/net/imprex/orebfuscator/nms/v1_20_R4/NmsManager.java b/orebfuscator-nms/orebfuscator-nms-v1_20_R4/src/main/java/net/imprex/orebfuscator/nms/v1_20_R4/NmsManager.java
new file mode 100644
index 00000000..f37d98f8
--- /dev/null
+++ b/orebfuscator-nms/orebfuscator-nms-v1_20_R4/src/main/java/net/imprex/orebfuscator/nms/v1_20_R4/NmsManager.java
@@ -0,0 +1,176 @@
+package net.imprex.orebfuscator.nms.v1_20_R4;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.craftbukkit.v1_20_R4.CraftWorld;
+import org.bukkit.craftbukkit.v1_20_R4.block.data.CraftBlockData;
+import org.bukkit.craftbukkit.v1_20_R4.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+
+import com.google.common.collect.ImmutableList;
+
+import it.unimi.dsi.fastutil.shorts.Short2ObjectLinkedOpenHashMap;
+import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
+import net.imprex.orebfuscator.config.Config;
+import net.imprex.orebfuscator.nms.AbstractNmsManager;
+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.SectionPos;
+import net.minecraft.core.registries.BuiltInRegistries;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.ClientGamePacketListener;
+import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
+import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket;
+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.world.level.block.Block;
+import net.minecraft.world.level.block.Blocks;
+import net.minecraft.world.level.block.entity.BlockEntity;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.chunk.LevelChunk;
+import net.minecraft.world.level.chunk.LevelChunkSection;
+
+public class NmsManager extends AbstractNmsManager {
+
+ private static final int BLOCK_ID_AIR = Block.getId(Blocks.AIR.defaultBlockState());
+
+ static int getBlockState(LevelChunk chunk, int x, int y, int z) {
+ LevelChunkSection[] sections = chunk.getSections();
+
+ int sectionIndex = chunk.getSectionIndex(y);
+ if (sectionIndex >= 0 && sectionIndex < sections.length) {
+ LevelChunkSection section = sections[sectionIndex];
+ if (section != null && !section.hasOnlyAir()) {
+ return Block.getId(section.getBlockState(x & 0xF, y & 0xF, z & 0xF));
+ }
+ }
+
+ return BLOCK_ID_AIR;
+ }
+
+ private static ServerLevel level(World world) {
+ return ((CraftWorld) world).getHandle();
+ }
+
+ private static ServerPlayer player(Player player) {
+ return ((CraftPlayer) player).getHandle();
+ }
+
+ public NmsManager(Config config) {
+ super(Block.BLOCK_STATE_REGISTRY.size(), new RegionFileCache(config.cache()));
+
+ for (Map.Entry, Block> entry : BuiltInRegistries.BLOCK.entrySet()) {
+ NamespacedKey namespacedKey = NamespacedKey.fromString(entry.getKey().location().toString());
+ Block block = entry.getValue();
+
+ ImmutableList possibleBlockStates = block.getStateDefinition().getPossibleStates();
+ BlockProperties.Builder builder = BlockProperties.builder(namespacedKey);
+
+ 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())
+ .withIsDefaultState(Objects.equals(block.defaultBlockState(), blockState))
+ .build();
+
+ builder.withBlockState(properties);
+ }
+
+ this.registerBlockProperties(builder.build());
+ }
+ }
+
+ @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 int getBlockState(World world, int x, int y, int z) {
+ ServerChunkCache serverChunkCache = level(world).getChunkSource();
+ if (!serverChunkCache.isChunkLoaded(x >> 4, z >> 4)) {
+ return BLOCK_ID_AIR;
+ }
+
+ LevelChunk chunk = serverChunkCache.getChunk(x >> 4, z >> 4, true);
+ if (chunk == null) {
+ return BLOCK_ID_AIR;
+ }
+
+ return getBlockState(chunk, x, y, z);
+ }
+
+ @Override
+ public void sendBlockUpdates(World world, Iterable iterable) {
+ ServerChunkCache serverChunkCache = level(world).getChunkSource();
+ BlockPos.MutableBlockPos position = new BlockPos.MutableBlockPos();
+
+ for (net.imprex.orebfuscator.util.BlockPos pos : iterable) {
+ position.set(pos.x, pos.y, pos.z);
+ serverChunkCache.blockChanged(position);
+ }
+ }
+
+ @Override
+ public void sendBlockUpdates(Player player, Iterable iterable) {
+ ServerPlayer serverPlayer = player(player);
+ ServerLevel level = serverPlayer.serverLevel();
+ ServerChunkCache serverChunkCache = level.getChunkSource();
+
+ BlockPos.MutableBlockPos position = new BlockPos.MutableBlockPos();
+ Map> sectionPackets = new HashMap<>();
+ List> blockEntityPackets = new ArrayList<>();
+
+ for (net.imprex.orebfuscator.util.BlockPos pos : iterable) {
+ if (!serverChunkCache.isChunkLoaded(pos.x >> 4, pos.z >> 4)) {
+ continue;
+ }
+
+ position.set(pos.x, pos.y, pos.z);
+ BlockState blockState = level.getBlockState(position);
+
+ sectionPackets.computeIfAbsent(SectionPos.of(position), key -> new Short2ObjectLinkedOpenHashMap<>())
+ .put(SectionPos.sectionRelativePos(position), blockState);
+
+ if (blockState.hasBlockEntity()) {
+ BlockEntity blockEntity = level.getBlockEntity(position);
+ if (blockEntity != null) {
+ blockEntityPackets.add(blockEntity.getUpdatePacket());
+ }
+ }
+ }
+
+ for (Map.Entry> entry : sectionPackets.entrySet()) {
+ Short2ObjectMap blockStates = entry.getValue();
+ if (blockStates.size() == 1) {
+ Short2ObjectMap.Entry blockEntry = blockStates.short2ObjectEntrySet().iterator().next();
+ BlockPos blockPosition = entry.getKey().relativeToBlockPos(blockEntry.getShortKey());
+ serverPlayer.connection.send(new ClientboundBlockUpdatePacket(blockPosition, blockEntry.getValue()));
+ } else {
+ serverPlayer.connection.send(new ClientboundSectionBlocksUpdatePacket(entry.getKey(),
+ blockStates.keySet(), blockStates.values().toArray(BlockState[]::new)));
+ }
+ }
+
+ for (Packet packet : blockEntityPackets) {
+ serverPlayer.connection.send(packet);
+ }
+ }
+}
diff --git a/orebfuscator-nms/orebfuscator-nms-v1_20_R4/src/main/java/net/imprex/orebfuscator/nms/v1_20_R4/ReadOnlyChunkWrapper.java b/orebfuscator-nms/orebfuscator-nms-v1_20_R4/src/main/java/net/imprex/orebfuscator/nms/v1_20_R4/ReadOnlyChunkWrapper.java
new file mode 100644
index 00000000..d09fbff6
--- /dev/null
+++ b/orebfuscator-nms/orebfuscator-nms-v1_20_R4/src/main/java/net/imprex/orebfuscator/nms/v1_20_R4/ReadOnlyChunkWrapper.java
@@ -0,0 +1,18 @@
+package net.imprex.orebfuscator.nms.v1_20_R4;
+
+import net.imprex.orebfuscator.nms.ReadOnlyChunk;
+import net.minecraft.world.level.chunk.LevelChunk;
+
+public class ReadOnlyChunkWrapper implements ReadOnlyChunk {
+
+ private final LevelChunk chunk;
+
+ ReadOnlyChunkWrapper(LevelChunk chunk) {
+ this.chunk = chunk;
+ }
+
+ @Override
+ public int getBlockState(int x, int y, int z) {
+ return NmsManager.getBlockState(chunk, x, y, z);
+ }
+}
diff --git a/orebfuscator-nms/orebfuscator-nms-v1_20_R4/src/main/java/net/imprex/orebfuscator/nms/v1_20_R4/RegionFileCache.java b/orebfuscator-nms/orebfuscator-nms-v1_20_R4/src/main/java/net/imprex/orebfuscator/nms/v1_20_R4/RegionFileCache.java
new file mode 100644
index 00000000..81d74cde
--- /dev/null
+++ b/orebfuscator-nms/orebfuscator-nms-v1_20_R4/src/main/java/net/imprex/orebfuscator/nms/v1_20_R4/RegionFileCache.java
@@ -0,0 +1,44 @@
+package net.imprex.orebfuscator.nms.v1_20_R4;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+
+import org.bukkit.Bukkit;
+import org.bukkit.craftbukkit.v1_20_R4.CraftServer;
+
+import net.imprex.orebfuscator.config.CacheConfig;
+import net.imprex.orebfuscator.nms.AbstractRegionFileCache;
+import net.imprex.orebfuscator.util.ChunkPosition;
+import net.minecraft.world.level.ChunkPos;
+import net.minecraft.world.level.chunk.storage.RegionFile;
+import net.minecraft.world.level.chunk.storage.RegionFileVersion;
+
+public class RegionFileCache extends AbstractRegionFileCache {
+
+ RegionFileCache(CacheConfig cacheConfig) {
+ super(cacheConfig);
+ }
+
+ @Override
+ protected RegionFile createRegionFile(Path path) throws IOException {
+ boolean isSyncChunkWrites = ((CraftServer) Bukkit.getServer()).getServer().forceSynchronousWrites();
+ return new RegionFile(null, path, path.getParent(), RegionFileVersion.VERSION_DEFLATE, isSyncChunkWrites);
+ }
+
+ @Override
+ protected void closeRegionFile(RegionFile t) throws IOException {
+ t.close();
+ }
+
+ @Override
+ protected DataInputStream createInputStream(RegionFile t, ChunkPosition key) throws IOException {
+ return t.getChunkDataInputStream(new ChunkPos(key.x, key.z));
+ }
+
+ @Override
+ protected DataOutputStream createOutputStream(RegionFile t, ChunkPosition key) throws IOException {
+ return t.getChunkDataOutputStream(new ChunkPos(key.x, key.z));
+ }
+}
\ No newline at end of file
diff --git a/orebfuscator-nms/pom.xml b/orebfuscator-nms/pom.xml
index 5eaebebf..23fe8399 100644
--- a/orebfuscator-nms/pom.xml
+++ b/orebfuscator-nms/pom.xml
@@ -34,5 +34,6 @@
orebfuscator-nms-v1_20_R1
orebfuscator-nms-v1_20_R2
orebfuscator-nms-v1_20_R3
+ orebfuscator-nms-v1_20_R4
\ No newline at end of file
diff --git a/orebfuscator-plugin/pom.xml b/orebfuscator-plugin/pom.xml
index 96ed2fb0..ed7b4fe1 100644
--- a/orebfuscator-plugin/pom.xml
+++ b/orebfuscator-plugin/pom.xml
@@ -295,5 +295,18 @@
${revision}
compile
+
+ net.imprex
+ orebfuscator-nms-v1_20_R4
+ ${revision}
+ mojang-mapped
+ compile
+
+
+ net.imprex
+ orebfuscator-nms-v1_20_R4
+ ${revision}
+ compile
+
\ No newline at end of file
diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java
index 5ff78d23..2ba8b68a 100644
--- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java
+++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java
@@ -1,5 +1,7 @@
package net.imprex.orebfuscator;
+import java.util.logging.Level;
+
import org.bukkit.Bukkit;
import org.bukkit.event.Event;
import org.bukkit.event.EventPriority;
@@ -17,6 +19,7 @@
import net.imprex.orebfuscator.player.OrebfuscatorPlayerMap;
import net.imprex.orebfuscator.proximity.ProximityDirectorThread;
import net.imprex.orebfuscator.proximity.ProximityPacketListener;
+import net.imprex.orebfuscator.util.ConsoleUtil;
import net.imprex.orebfuscator.util.HeightAccessor;
import net.imprex.orebfuscator.util.OFCLogger;
@@ -42,6 +45,12 @@ public void onLoad() {
@Override
public void onEnable() {
try {
+ ConsoleUtil.printBox(Level.SEVERE,
+ "WARNING",
+ "REMOVAL OF SUPPORT FOR JAVA VERSIONS BEFORE 17 AND MINECRAFT VERSIONS BEFORE 1.16",
+ "",
+ "https://github.com/Imprex-Development/orebfuscator/discussions/367");
+
// Check if protocolLib is enabled
Plugin protocolLib = getServer().getPluginManager().getPlugin("ProtocolLib");
if (protocolLib == null || !protocolLib.isEnabled()) {
diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/util/ConsoleUtil.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/util/ConsoleUtil.java
index 14736a68..209c99b1 100644
--- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/util/ConsoleUtil.java
+++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/util/ConsoleUtil.java
@@ -8,7 +8,7 @@
public final class ConsoleUtil {
private static final int BOX_PADDING = 3;
- private static final int BOX_MAX_WIDTH = 48;
+ private static final int BOX_PREFERRED_WIDTH = 48;
private ConsoleUtil() {
}
@@ -28,12 +28,12 @@ public static Iterable createBox(String...lines) {
for (String line : lines) {
line = line.trim();
- while (line.length() > BOX_MAX_WIDTH) {
+ while (line.length() > BOX_PREFERRED_WIDTH) {
int splitLength = 0;
for (int i = 0; i < line.length(); i++) {
if (Character.isWhitespace(line.charAt(i))) {
- if (i <= BOX_MAX_WIDTH) {
+ if (i <= BOX_PREFERRED_WIDTH) {
splitLength = i;
} else {
break;
@@ -41,6 +41,11 @@ public static Iterable createBox(String...lines) {
}
}
+ // can't split line no whitespace character found
+ if (splitLength == 0) {
+ break;
+ }
+
// split line at latest word that fit length
wrappedLines.add(line.substring(0, splitLength));
line = line.substring(splitLength, line.length()).trim();
diff --git a/pom.xml b/pom.xml
index 761a9165..c41acc1b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,16 +23,16 @@
1.20.1-R0.1-SNAPSHOT
1.20.1-R0.1-SNAPSHOT
3.0.2
- 5.10.0
- 4.1.68.Final
+ 5.10.2
+ 4.1.90.Final
5.0.0
1.10.5
- 3.11.0
- 3.5.0
- 3.1.2
- 1.5.0
- 1.2.5
+ 3.13.0
+ 3.5.2
+ 3.2.5
+ 1.6.0
+ 2.0.2
UTF-8