From 4dff067faad244c82c7299e21f46a7224b435b92 Mon Sep 17 00:00:00 2001 From: OnlyBMan <27742182+OnlyBMan@users.noreply.github.com> Date: Wed, 5 Feb 2020 21:10:34 -0500 Subject: [PATCH 1/2] Add biomes --- .../network/session/GeyserSession.java | 21 ++++++++++- .../network/translators/BiomeTranslator.java | 35 ++++++++++++++++++ .../java/world/JavaChunkDataTranslator.java | 5 ++- .../geysermc/connector/utils/ChunkUtils.java | 1 - .../resources/bedrock/biome_definitions.dat | Bin 3544 -> 27359 bytes 5 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 53fecf79c..b873db90f 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -41,6 +41,8 @@ import com.nukkitx.math.vector.Vector2f; import com.nukkitx.math.vector.Vector2i; import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3i; +import com.nukkitx.nbt.NbtUtils; +import com.nukkitx.nbt.stream.NBTInputStream; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.data.GamePublishSetting; @@ -53,6 +55,7 @@ import org.geysermc.api.RemoteServer; import org.geysermc.api.session.AuthData; import org.geysermc.api.window.FormWindow; import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.console.GeyserLogger; import org.geysermc.connector.entity.PlayerEntity; import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.session.cache.*; @@ -60,6 +63,7 @@ import org.geysermc.connector.network.translators.Registry; import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.utils.Toolbox; +import java.io.InputStream; import java.net.InetSocketAddress; import java.util.UUID; @@ -131,7 +135,22 @@ public class GeyserSession implements Player { ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 0, false); BiomeDefinitionListPacket biomePacket = new BiomeDefinitionListPacket(); - biomePacket.setTag(CompoundTag.EMPTY); + InputStream stream = GeyserConnector.class.getClassLoader().getResourceAsStream("bedrock/biome_definitions.dat"); + if (stream == null) { + throw new AssertionError("Unable to find bedrock/biome_definitions.dat"); + } + + CompoundTag biomesTag; + + NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream); + try { + biomesTag = (CompoundTag) nbtInputStream.readTag(); + biomePacket.setTag(biomesTag); + nbtInputStream.close(); + } catch (Exception ex) { + GeyserLogger.DEFAULT.warning("Failed to get biomes from biome definitions, is there something wrong with the file?"); + throw new AssertionError(ex); + } upstream.sendPacket(biomePacket); AvailableEntityIdentifiersPacket entityPacket = new AvailableEntityIdentifiersPacket(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java new file mode 100644 index 000000000..122788412 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/BiomeTranslator.java @@ -0,0 +1,35 @@ +package org.geysermc.connector.network.translators; +import java.util.Arrays; + +//Based off of ProtocolSupport's LegacyBiomeData.java https://github.com/ProtocolSupport/ProtocolSupport/blob/b2cad35977f3fcb65bee57b9e14fc9c975f71d32/src/protocolsupport/protocol/typeremapper/legacy/LegacyBiomeData.java +//Array index formula by https://wiki.vg/Chunk_Format + +public class BiomeTranslator { + + public static byte[] toBedrockBiome(int[] biomeData) { + byte[] bedrockData = new byte[256]; + if(biomeData == null) { + return bedrockData; + } + + for (int z = 0; z < 16; z += 4) { + for (int x = 0; x < 16; x += 4) { + byte biomeId = biomeID(biomeData, x, z); + fillArray(z, x, bedrockData, biomeId); + fillArray(z + 1, x, bedrockData, biomeId); + fillArray(z + 2, x, bedrockData, biomeId); + fillArray(z + 3, x, bedrockData, biomeId); + } + } + return bedrockData; + } + + protected static void fillArray(int z, int x, byte[] legacyBiomeData, int biomeId) { + int offset = (z << 4) | x; + Arrays.fill(legacyBiomeData, offset, offset + 4, (byte) biomeId); + } + + protected static byte biomeID(int[] biomeData, int x, int z) { + return (byte) biomeData[((z >> 2) & 3) << 2 | ((x >> 2) & 3)]; + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java index 1a9230e6d..d74995993 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaChunkDataTranslator.java @@ -35,6 +35,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.geysermc.api.Geyser; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.BiomeTranslator; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.utils.ChunkUtils; import org.geysermc.connector.world.chunk.ChunkSection; @@ -74,7 +75,9 @@ public class JavaChunkDataTranslator extends PacketTranslator#JTC=TP{R>H)1TY2x@*)_rHV=t_$UZ=T93U_ny)(VLW6yLix@WXe z3>{JasXdIIz=v$BAeA@k?djhPOoGnV?SvnHjBmj`RZeln?%Wzsw~g) zd3sh>dA&|on{~F%=i@u;e07;u*?LpuCnqPLjVJT+syNG*%Xe@8_*wE`wJ7pgm7T3$ z%$AE43<->g4oBhia#YEYXR-grPXGc*N2a*1Ll^ooPukywD z#rj|}K3$Zn+?X>ud|Y3En);1-q85@16{kvDHB4lxSWg>8A?3QOMdeOVonxt^!&aFi zp|~iyUvG-DWqAe5zFcODq9$4t8*6U!+m|6p+z}{AqP7_Y!u{1E#f=1DfU8Y?0Xw`( z7xgkL=Bd;%k?id3%#bXKz8!FX{nLkc!IcTu9^YS;C0UYQ^;j+rEO{}@eR}|V8|gh5 z){>9Ts`9USkxIJ;mTFxX%Q=HV$u`t76=^N!)1Y7KmFRl<_i&;{x$k~3gI^`&!#W_{Pnby(YdUqFFt)btv9D%=Ck$m z#j~f=HH7i$i|IvHr!s)05O=3fr?0Z*CWoIl3z&ZM^!lHW!9{){D_-v^Pm>2Md0-hm zmL$w&rw>R^*y#(a{5;$31C2rL^o`R+HM^L8^9B5$+ z-fI(Hoi2)X>1Mn;%EpC3g0qB@z{!bi_UKQT1mfm{b}sPd`Y1V88LBZ1k_UzaA`?1~ zEu87}iHt|@8FuJ7d&W&ECo^uw7&i~X`z(?XO-;DZlaUY>HE3gxD7n49$WsV%WG~&% zg$&IdfdU-h3{f(=$d^ldqR)xkL5qfotP$-*agoDfswg>{=XGAKQyDsLY`#g{Of#0# zpoUG`d(bY%?0hM<=K(RH^HyM@`7}*z}Nr7qh|xHJh&U zx~=?noxRG6A|s{^#!LfJ#4&9i>b<8X6c~M-XB$55ZAU7I$c)5o0XParVt3)_NfWE= z(%ym^1UGenIngQvKT?74YAt46ER$LT?1S;b6$DqAD4cF!bTn$W&Ww_Wa#ko`&NDA= zhlzgBA@beZaNX;UK+*214UieJ563Z<@9wbibb5!!?uFfFvm0J7Ey3?GS{0fU(ly_Ii`s;tT(NGK-9Tau9IJtPxK zW@UpOYZMFev~&)yEU{LM%0xN`)#(DB`=V?Ieneyj88ykq3b1VE1)#mdtTLA#`$d({ zugY?6&fYqCFgLoQ;i54Csoc{*DzK{a4Ar2m3Uf{iS(KF#EeN(%Ye6LC0k!Z`3uf^( z;EIJBKz!-0_qJM}#zK!yv(;%?ri$@!ZNMcr7^~lNdh#r3r#vn&+fE;ld%4pW_MDzN z@e@=wdKcE}apO5ne6a{V9buy6PFHjV2ezYY;84*W;RvNTL%H{^|6{!S8KD>eY;VLd zNS-^#VTOPr;xb(SI?M?h5q{hyH$QBKNf^q%SS5^?hDmf5y~%>*Po!SC?(v5-M^PQ@ z!jLONVx>anF`ENL_>9973MKmS4h93@RZi05ViDu;HxL zOT(l#`-CLdEz$dtBS1n~3mD8}e0~{8`=L6c@rd*-8_}5j+$bv2$7FE7a^28(P_M26P_LN%pu-(H2DfPUkt{HqjIP9}=^!0g$uM>P*xF%bu`_d>6*Gpf+r5Qde9 zNU4$0A^p!Wp$LtZ25;YVKdjs|;#mg@J)0Zw9GXD(e&0~X8efS1?EzM$=uje1KfQPk zYWl6nU&!?P#=u(99a6*Wx9B_Ajd8}?GLd2Ke?J(+1eywGn1vEM>bHfWUuh>HS{vAf z*|&P%37`-t*8-t|6DxNFW?)1%$c$-7GnR1{ZU|{^k4WJXnjBceqaTeqyEsUl9M%0e zw9J+%#Gf}Pl$|8V+^jrpWQiaaa<$g(#8w&@J}md)gEZW@Q?s?{8_H7ZFs(NY_)!%R z+PF=zN691AwfI4_>zkadU+-X!6^df0 zG(<$o6EN?@G3#7k^Uj_hpEhyVN~Jqvx_%!}xtPF#eqY!(-*}pDux?k)Hx|35F+`Mn zL^uYy9ay$m{%LbBp%XQixxyHR$K-@npm#d9hLb4qG9x!8FEW)xURL0Pd%)`Ymp?4q z*T+IS1$6Q`L6#Bf6fb}=#ggsAL}Biy8E}z*KJhnti{QFlIi9xve$|6K1K+i+M_sl9 z<#W4uq4f!FYn)cEXE_@>$UO>Q@^Lo~Z6cOmK#MTF-mG4T70@)iKc(VbmEUJl`C@>d zpy`*+WjfmZQjTfhJ>1lHiW~Mo*J;oLF%SFBxJ-W}ts7e$l8KA?VR`>nMA!2d9=fuh zCGVlF`8pDH$Y23XUCQh$N0$mVlq-iaHW*F8;j_$_iNx}}^(Hp|6D49*iw zokt=uIZ$n9jwAB(_TKOT{du1QSXX@*=(=f2r2XLiFmjQ}4~U23DX_>;hnA!l7pn^$ zf{~$c53jb^kKhVJh@GlTj6jv4AtOFRp}aj0NcPf4mWXWdZHqJF*!Fw4kFA%C7wyEm zN!}X*ACar9&8rc9L$T|i&^~~2Iw~i6l@fPBn+CQ+M@eHOmeL)Iy>39!4yr@EiM5P52DO8ew}H?clZjPVYFp1mN1? zz-R8sfpI{$zhd9Ktl0I?l&XX|7fSii_kWa;U^cUPESwoD+Bh}ZKN(oUxEOYeo+LO+%NCF9o~69sENEo+B~hwW-2>|2dg}HNvOEd zmZwpnwQp8T7h-5Kq&`WWxT`w;H}-b>KW!>7&D!tE2o&pvtntoiTx?|=8~`N{L=^s(XJ zUgMjee)4SR9!k$snGnK~YiAmIiRAhqO$CR-2#7D$#n%)MA6Fs1>QC7x$@XIA&-kI8S9AY!-;B*VENveN7V z%KzIhm?d+|$urV}yJ}P=rU#2&dsvjI`Q{@$ld5Zqxc!Y760>;s`VSf;4EuPEnMZ@Q z09d~z2(DY1kj#p%9YNKEZ-e=;_q(^>8I}ny$6)O35hw_j1So_DeJfF-WZScC#LC^* zL_+npI|2o~Pk(1h1L>fE(Qmq;$o@kHiS8gIc<)u(Y8(vIs_TzI3lW>AO;!8}*FDk( z-`=Hc`mSyg7X5?5B8`Rmof8j#hh&#~4c*veNCZS4Mdza)tC@}&eOtmZ?nPMs-)%1m pOW3QtsmzNMZf~xBPDamt zwN2JCiauW7-cKCY-O4l;$^)5@)4Sd7u5nubb=PwEm1DRGs!vu8U4`a6*(w9I*TEbrPp$h1;J(EcD7E{dq@~VP+WI-`C$x* zsKV9dNYh>mZQAm{aAd>uK)G73WV}*Jm_F!cK_!?jnA$*L)n6MK45(MsP@Aa81UjrG z3~wv9CV}wFm;bU=KC5ThCJm7Iw`BXk2iS-~1|Ibte{XCAu=sc)#+62d1YVt`QL}7Z zHbE=QsPt&fG`xV6r0H67+59r%vgnjE>iUA>W`}E;kYEBxL@Y+(>JY1(u9n56!|Jomu=>Bp0 z=I!AkurThq+ABvYDadkg+ORn}-y-1A-UDacxc{P(g1=SDH>288D>E05{+pIB4keV zB~iStqZLRmXdk?9%zKP0H>f%J03iX`$J~d9M$caVxpBST5AaogTnIQV5CXFZyr%7} psb%|9r>Gwnysi8&8g<`K)SUSy8dtNClx%UwwCY^8=x$Rv{{YL+hwuOZ From 0bb18d26b053fe96e554f444f26fe467b7adecad Mon Sep 17 00:00:00 2001 From: OnlyBMan <27742182+OnlyBMan@users.noreply.github.com> Date: Wed, 5 Feb 2020 22:02:23 -0500 Subject: [PATCH 2/2] Load biome definitions only once instead of everytime a new player joins --- .../network/session/GeyserSession.java | 21 +++---------------- .../org/geysermc/connector/utils/Toolbox.java | 18 ++++++++++++++++ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index b873db90f..f4835863c 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -134,24 +134,9 @@ public class GeyserSession implements Player { ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 0, false); - BiomeDefinitionListPacket biomePacket = new BiomeDefinitionListPacket(); - InputStream stream = GeyserConnector.class.getClassLoader().getResourceAsStream("bedrock/biome_definitions.dat"); - if (stream == null) { - throw new AssertionError("Unable to find bedrock/biome_definitions.dat"); - } - - CompoundTag biomesTag; - - NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream); - try { - biomesTag = (CompoundTag) nbtInputStream.readTag(); - biomePacket.setTag(biomesTag); - nbtInputStream.close(); - } catch (Exception ex) { - GeyserLogger.DEFAULT.warning("Failed to get biomes from biome definitions, is there something wrong with the file?"); - throw new AssertionError(ex); - } - upstream.sendPacket(biomePacket); + BiomeDefinitionListPacket biomeDefinitionListPacket = new BiomeDefinitionListPacket(); + biomeDefinitionListPacket.setTag(Toolbox.BIOMES); + upstream.sendPacket(biomeDefinitionListPacket); AvailableEntityIdentifiersPacket entityPacket = new AvailableEntityIdentifiersPacket(); entityPacket.setTag(CompoundTag.EMPTY); diff --git a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java index b90aa2352..d2beb8074 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java +++ b/connector/src/main/java/org/geysermc/connector/utils/Toolbox.java @@ -31,6 +31,7 @@ import com.nukkitx.nbt.stream.NBTInputStream; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.nbt.tag.ListTag; import com.nukkitx.nbt.tag.Tag; +import com.nukkitx.protocol.bedrock.packet.BiomeDefinitionListPacket; import com.nukkitx.protocol.bedrock.packet.StartGamePacket; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -47,11 +48,27 @@ public class Toolbox { public static final Collection ITEMS = new ArrayList<>(); public static ListTag BLOCKS; + public static CompoundTag BIOMES; public static final Int2ObjectMap ITEM_ENTRIES = new Int2ObjectOpenHashMap<>(); public static final Int2ObjectMap BLOCK_ENTRIES = new Int2ObjectOpenHashMap<>(); public static void init() { + InputStream biomestream = GeyserConnector.class.getClassLoader().getResourceAsStream("bedrock/biome_definitions.dat"); + if (biomestream == null) { + throw new AssertionError("Unable to find bedrock/biome_definitions.dat"); + } + + CompoundTag biomesTag; + + try (NBTInputStream biomenbtInputStream = NbtUtils.createNetworkReader(biomestream)){ + biomesTag = (CompoundTag) biomenbtInputStream.readTag(); + BIOMES = biomesTag; + } catch (Exception ex) { + GeyserLogger.DEFAULT.warning("Failed to get biomes from biome definitions, is there something wrong with the file?"); + throw new AssertionError(ex); + } + InputStream stream = GeyserConnector.class.getClassLoader().getResourceAsStream("bedrock/runtime_block_states.dat"); if (stream == null) { throw new AssertionError("Unable to find bedrock/runtime_block_states.dat"); @@ -69,6 +86,7 @@ public class Toolbox { } BLOCKS = blocksTag; + InputStream stream2 = Toolbox.class.getClassLoader().getResourceAsStream("bedrock/items.json"); if (stream2 == null) { throw new AssertionError("Items Table not found");