From 4b3c6d74a91488e1aae0914d30670f97b07335ea Mon Sep 17 00:00:00 2001 From: MaXFeeD Date: Sat, 23 Dec 2023 00:45:02 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=9D=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE?= =?UTF-8?q?=D0=B4=D0=BD=D0=B5=D0=B5=20=D1=81=D0=BE=D0=B1=D1=8B=D1=82=D0=B8?= =?UTF-8?q?=D0=B5,=20=D0=BE=D0=B6=D0=B8=D0=B4=D0=B0=D0=B5=D0=BC=20=D0=BE?= =?UTF-8?q?=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81?= =?UTF-8?q?=D0=B5=D1=80=D0=B2=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/reider745/Main.java | 3 +- ...AndroidSdkHooks.java => AndroidHooks.java} | 4 +- .../reider745/hooks/SnowfallEverywhere.java | 108 ++++++++++++++++++ 3 files changed, 112 insertions(+), 3 deletions(-) rename src/main/java/com/reider745/hooks/{AndroidSdkHooks.java => AndroidHooks.java} (99%) create mode 100644 src/main/java/com/reider745/hooks/SnowfallEverywhere.java diff --git a/src/main/java/com/reider745/Main.java b/src/main/java/com/reider745/Main.java index 879c4f979..07988d4f2 100644 --- a/src/main/java/com/reider745/Main.java +++ b/src/main/java/com/reider745/Main.java @@ -82,7 +82,8 @@ public static void main(String[] args) throws Throwable { loader.registerHooksInitializationForClass(BlocksHooks.class); loader.registerHooksInitializationForClass(LevelHooks.class); loader.registerHooksInitializationForClass(ItemUtils.class); - loader.registerHooksInitializationForClass(AndroidSdkHooks.class); + loader.registerHooksInitializationForClass(AndroidHooks.class); + loader.registerHooksInitializationForClass(SnowfallEverywhere.class); loader.init(); loader.run("cn.nukkit.Nukkit", args); diff --git a/src/main/java/com/reider745/hooks/AndroidSdkHooks.java b/src/main/java/com/reider745/hooks/AndroidHooks.java similarity index 99% rename from src/main/java/com/reider745/hooks/AndroidSdkHooks.java rename to src/main/java/com/reider745/hooks/AndroidHooks.java index 9a4b2c41a..5768b1e9c 100644 --- a/src/main/java/com/reider745/hooks/AndroidSdkHooks.java +++ b/src/main/java/com/reider745/hooks/AndroidHooks.java @@ -12,7 +12,7 @@ import java.util.Locale; @Hooks -public class AndroidSdkHooks implements HookClass { +public class AndroidHooks implements HookClass { @FieldPatched(className = "android.os.Build.VERSION") public static final String INCREMENTAL = "1661782216865"; @FieldPatched(className = "android.os.Build.VERSION") @@ -276,6 +276,6 @@ public static int argb(float alpha, float red, float green, float blue) { sColorNameMap.put("teal", 0xFF008080); } - private AndroidSdkHooks() { + private AndroidHooks() { } } diff --git a/src/main/java/com/reider745/hooks/SnowfallEverywhere.java b/src/main/java/com/reider745/hooks/SnowfallEverywhere.java new file mode 100644 index 000000000..799d663d4 --- /dev/null +++ b/src/main/java/com/reider745/hooks/SnowfallEverywhere.java @@ -0,0 +1,108 @@ +package com.reider745.hooks; + +import java.io.IOException; +import java.util.List; +import java.util.function.Consumer; + +import com.reider745.api.hooks.HookClass; +import com.reider745.api.hooks.annotation.Hooks; +import com.reider745.api.hooks.annotation.Inject; + +import cn.nukkit.blockentity.BlockEntity; +import cn.nukkit.blockentity.BlockEntitySpawnable; +import cn.nukkit.level.DimensionData; +import cn.nukkit.level.biome.Biome; +import cn.nukkit.level.format.ChunkSection; +import cn.nukkit.level.format.generic.BaseChunk; +import cn.nukkit.level.format.generic.serializer.NetworkChunkSerializer; +import cn.nukkit.nbt.NBTIO; +import cn.nukkit.nbt.tag.CompoundTag; +import cn.nukkit.utils.BinaryStream; +import cn.nukkit.utils.ThreadCache; + +import java.nio.ByteOrder; +import it.unimi.dsi.fastutil.ints.IntSet; +import it.unimi.dsi.fastutil.objects.ObjectArrayList; + +/** + * Special christmas adaptation, do not use anywhere else. + */ +@Hooks +public class SnowfallEverywhere implements HookClass { + + @Inject(className = "cn.nukkit.level.format.generic.serializer.NetworkChunkSerializer") + public static void serialize(IntSet protocols, BaseChunk chunk, + Consumer callback, DimensionData dimensionData) { + for (int protocolId : protocols) { + byte[] blockEntities; + if (chunk.getBlockEntities().isEmpty()) { + blockEntities = new byte[0]; + } else { + blockEntities = serializeEntities(chunk, protocolId); + } + + int subChunkCount = 0; + ChunkSection[] sections = chunk.getSections(); + for (int i = sections.length - 1; i >= 0; i--) { + if (!sections[i].isEmpty()) { + subChunkCount = i + 1; + break; + } + } + + BinaryStream stream = ThreadCache.binaryStream.get().reset(); + for (int i = 0; i < subChunkCount; i++) { + sections[i].writeTo(protocolId, stream); + } + + stream.put(toSnowfallBiomeIdArray(chunk.getBiomeIdArray())); + // Border blocks + stream.putByte((byte) 0); + stream.put(blockEntities); + + callback.accept( + new NetworkChunkSerializer.NetworkChunkSerializerCallback(protocolId, stream, subChunkCount)); + } + } + + private static byte[] toSnowfallBiomeIdArray(byte[] biomes) { + for (int i = 0, l = biomes.length; i < l; i++) { + Biome biome = Biome.getBiome(biomes[i] & 0xFF); + if (biome.isFreezing() || !biome.canRain()) { + continue; + } + biomes[i] = (byte) switch (biomes[i] & 0xFF) { + case 0, 24 -> 10; // OCEAN, DEEP_OCEAN -> FROZEN_OCEAN + case 7 -> 11; // RIVER -> FROZEN_RIVER + case 14, 15, 16, 25 -> 26; // MUSHROOM_ISLAND, MUSHROOM_ISLAND_SHORE, BEACH, STONE_BEACH -> COLD_BEACH + // PLAINS, FOREST, SWAMP, JUNGLE, BIRCH_FOREST, ROOFED_FOREST, SUNFLOWER_PLAINS, + // FLOWER_FOREST, SWAMPLAND_M, JUNGLE_M, JUNGLE_EDGE_M, BIRCH_FOREST_M, + // BIRCH_FOREST_HILLS_M, ROOFED_FOREST_M, EXTREME_HILLS_PLUS_M -> ICE_PLAINS + case 1, 4, 6, 21, 27, 29, 34, 131, 132, 134, 149, 151, 155, 156, 157, 162 -> 12; + // EXTREME_HILLS, FOREST_HILLS, EXTREME_HILLS_EDGE, JUNGLE_HILLS, JUNGLE_EDGE, + // BIRCH_FOREST_HILLS, EXTREME_HILLS_PLUS, EXTREME_HILLS_M -> ICE_PLAINS_SPIKES + case 3, 18, 20, 22, 23, 28, 129 -> 140; + case 5, 32, 160 -> 30; // TAIGA, MEGA_TAIGA, MEGA_SPRUCE_TAIGA -> COLD_TAIGA + case 133 -> 158; // TAIGA_M -> COLD_TAIGA_M + case 19, 33 -> 32; // TAIGA_HILLS, MEGA_TAIGA_HILLS -> COLD_TAIGA_HILLS + default -> 10; // FROZEN_OCEAN + }; + } + return biomes; + } + + private static byte[] serializeEntities(BaseChunk chunk, int protocol) { + List tagList = new ObjectArrayList<>(); + for (BlockEntity blockEntity : chunk.getBlockEntities().values()) { + if (blockEntity instanceof BlockEntitySpawnable) { + tagList.add(((BlockEntitySpawnable) blockEntity).getSpawnCompound(protocol)); + } + } + + try { + return NBTIO.write(tagList, ByteOrder.LITTLE_ENDIAN, true); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +}