21w20a support

This commit is contained in:
Camotoy 2021-05-19 22:24:11 -04:00
parent 024655f008
commit b5307ab3ed
No known key found for this signature in database
GPG Key ID: 7EEFB66FE798081F
87 changed files with 314 additions and 577 deletions

View File

@ -18,7 +18,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!
### Currently supporting Minecraft Bedrock v1.16.100 - v1.16.220 and Minecraft Java v1.16.4 - v1.16.5.
### Currently supporting Minecraft Bedrock v1.16.220.52 and Minecraft Java 21w20a.
## Setting Up
Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set up Geyser.
@ -39,6 +39,8 @@ Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set
- Some Entity Flags
- Structure block UI
Extended height features can be "supported", but require additional work.
## What can't be fixed
The following things cannot be fixed without changes to Bedrock. As of now, they are not fixable in Geyser.

View File

@ -150,11 +150,6 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
if (isLegacy)
geyserLogger.debug("Legacy version of Minecraft (1.12.2 or older) detected; falling back to ViaVersion for block state retrieval.");
boolean use3dBiomes = isCompatible(Bukkit.getServer().getVersion(), "1.16.0");
if (!use3dBiomes) {
geyserLogger.debug("Legacy version of Minecraft (1.15.2 or older) detected; not using 3D biomes.");
}
boolean isPre1_12 = !isCompatible(Bukkit.getServer().getVersion(), "1.12.0");
// Set if we need to use a different method for getting a player's locale
SpigotCommandSender.setUseLegacyLocaleMethod(isPre1_12);
@ -170,11 +165,11 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
this.geyserWorldManager = new GeyserSpigot1_12NativeWorldManager(this);
} else {
// Post-1.13
this.geyserWorldManager = new GeyserSpigotLegacyNativeWorldManager(this, use3dBiomes);
this.geyserWorldManager = new GeyserSpigotLegacyNativeWorldManager(this);
}
} else {
// No ViaVersion
this.geyserWorldManager = new GeyserSpigotNativeWorldManager(this, use3dBiomes);
this.geyserWorldManager = new GeyserSpigotNativeWorldManager(this);
}
geyserLogger.debug("Using NMS adapter: " + this.geyserWorldManager.getClass() + ", " + nmsVersion);
} catch (Exception e) {
@ -196,7 +191,7 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
this.geyserWorldManager = new GeyserSpigotFallbackWorldManager(this);
} else {
// Post-1.13
this.geyserWorldManager = new GeyserSpigotWorldManager(this, use3dBiomes);
this.geyserWorldManager = new GeyserSpigotWorldManager(this);
}
geyserLogger.debug("Using default world manager: " + this.geyserWorldManager.getClass());
}

View File

@ -25,9 +25,7 @@
package org.geysermc.platform.spigot.world.manager;
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
@ -63,7 +61,7 @@ public class GeyserSpigot1_12WorldManager extends GeyserSpigotWorldManager {
private final List<Pair<Integer, Protocol>> protocolList;
public GeyserSpigot1_12WorldManager(Plugin plugin) {
super(plugin, false);
super(plugin);
this.mappingData1_12to1_13 = ProtocolRegistry.getProtocol(Protocol1_13To1_12_2.class).getMappingData();
this.protocolList = ProtocolRegistry.getProtocolPath(CLIENT_PROTOCOL_VERSION,
ProtocolVersion.v1_13.getVersion());
@ -117,28 +115,6 @@ public class GeyserSpigot1_12WorldManager extends GeyserSpigotWorldManager {
return blockId;
}
@SuppressWarnings("deprecation")
@Override
public void getBlocksInSection(GeyserSession session, int x, int y, int z, Chunk chunk) {
Player player = Bukkit.getPlayer(session.getPlayerEntity().getUsername());
if (player == null) {
return;
}
World world = player.getWorld();
// Get block entity storage
BlockStorage storage = Via.getManager().getConnection(player.getUniqueId()).get(BlockStorage.class);
for (int blockY = 0; blockY < 16; blockY++) { // Cache-friendly iteration order
for (int blockZ = 0; blockZ < 16; blockZ++) {
for (int blockX = 0; blockX < 16; blockX++) {
Block block = world.getBlockAt((x << 4) + blockX, (y << 4) + blockY, (z << 4) + blockZ);
// Black magic that gets the old block state ID
int blockId = (block.getType().getId() << 4) | (block.getData() & 0xF);
chunk.set(blockX, blockY, blockZ, getLegacyBlock(storage, blockId, (x << 4) + blockX, (y << 4) + blockY, (z << 4) + blockZ));
}
}
}
}
@Override
public boolean isLegacy() {
return true;

View File

@ -25,7 +25,6 @@
package org.geysermc.platform.spigot.world.manager;
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
import org.bukkit.plugin.Plugin;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
@ -37,8 +36,7 @@ import org.geysermc.connector.network.translators.world.block.BlockTranslator;
*/
public class GeyserSpigotFallbackWorldManager extends GeyserSpigotWorldManager {
public GeyserSpigotFallbackWorldManager(Plugin plugin) {
// Since this is pre-1.13 (and thus pre-1.15), there will never be 3D biomes.
super(plugin, false);
super(plugin);
}
@Override
@ -46,11 +44,6 @@ public class GeyserSpigotFallbackWorldManager extends GeyserSpigotWorldManager {
return BlockTranslator.JAVA_AIR_ID;
}
@Override
public void getBlocksInSection(GeyserSession session, int x, int y, int z, Chunk chunk) {
// Do nothing, since we can't do anything with the chunk
}
@Override
public boolean hasOwnChunkCache() {
return false;

View File

@ -46,8 +46,8 @@ public class GeyserSpigotLegacyNativeWorldManager extends GeyserSpigotNativeWorl
private final Int2IntMap oldToNewBlockId;
public GeyserSpigotLegacyNativeWorldManager(GeyserSpigotPlugin plugin, boolean use3dBiomes) {
super(plugin, use3dBiomes);
public GeyserSpigotLegacyNativeWorldManager(GeyserSpigotPlugin plugin) {
super(plugin);
IntList allBlockStates = adapter.getAllBlockStates();
oldToNewBlockId = new Int2IntOpenHashMap(allBlockStates.size());
ProtocolVersion serverVersion = plugin.getServerProtocolVersion();

View File

@ -36,8 +36,8 @@ import org.geysermc.geyser.adapters.spigot.SpigotWorldAdapter;
public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
protected final SpigotWorldAdapter adapter;
public GeyserSpigotNativeWorldManager(Plugin plugin, boolean use3dBiomes) {
super(plugin, use3dBiomes);
public GeyserSpigotNativeWorldManager(Plugin plugin) {
super(plugin);
adapter = SpigotAdapters.getWorldAdapter();
}

View File

@ -25,18 +25,13 @@
package org.geysermc.platform.spigot.world.manager;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.steveice10.mc.protocol.MinecraftConstants;
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.block.Lectern;
import org.bukkit.block.data.BlockData;
@ -44,17 +39,13 @@ import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.plugin.Plugin;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.inventory.translators.LecternInventoryTranslator;
import org.geysermc.connector.network.translators.world.GeyserWorldManager;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.utils.BlockEntityUtils;
import org.geysermc.connector.utils.FileUtils;
import org.geysermc.connector.utils.GameRule;
import org.geysermc.connector.utils.LanguageUtils;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
@ -67,48 +58,10 @@ public class GeyserSpigotWorldManager extends GeyserWorldManager {
*/
protected static final int CLIENT_PROTOCOL_VERSION = MinecraftConstants.PROTOCOL_VERSION;
/**
* Whether the server is pre-1.16 and therefore does not support 3D biomes on an API level guaranteed.
*/
private final boolean use3dBiomes;
/**
* Stores a list of {@link Biome} ordinal numbers to Minecraft biome numeric IDs.
*
* Working with the Biome enum in Spigot poses two problems:
* 1: The Biome enum values change in both order and names over the years.
* 2: There is no way to get the Minecraft biome ID from the name itself with Spigot.
* To solve both of these problems, we store a JSON file of every Biome enum that has existed,
* along with its 1.16 biome number.
*
* The key is the Spigot Biome ordinal; the value is the Minecraft Java biome numerical ID
*/
private final Int2IntMap biomeToIdMap = new Int2IntOpenHashMap(Biome.values().length);
private final Plugin plugin;
public GeyserSpigotWorldManager(Plugin plugin, boolean use3dBiomes) {
this.use3dBiomes = use3dBiomes;
public GeyserSpigotWorldManager(Plugin plugin) {
this.plugin = plugin;
// Load the values into the biome-to-ID map
InputStream biomeStream = FileUtils.getResource("biomes.json");
JsonNode biomes;
try {
biomes = GeyserConnector.JSON_MAPPER.readTree(biomeStream);
} catch (Exception e) {
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.runtime_java"), e);
}
// Only load in the biomes that are present in this version of Minecraft
for (Biome enumBiome : Biome.values()) {
JsonNode biome = biomes.get(enumBiome.toString());
if (biome != null) {
biomeToIdMap.put(enumBiome.ordinal(), biome.intValue());
} else {
GeyserConnector.getInstance().getLogger().debug("No biome mapping found for " + enumBiome.toString() +
", defaulting to 0");
biomeToIdMap.put(enumBiome.ordinal(), 0);
}
}
}
@Override
@ -121,64 +74,11 @@ public class GeyserSpigotWorldManager extends GeyserWorldManager {
return BlockTranslator.getJavaIdBlockMap().getOrDefault(world.getBlockAt(x, y, z).getBlockData().getAsString(), BlockTranslator.JAVA_AIR_ID);
}
@Override
public void getBlocksInSection(GeyserSession session, int x, int y, int z, Chunk chunk) {
Player bukkitPlayer;
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUsername())) == null) {
return;
}
World world = bukkitPlayer.getWorld();
for (int blockY = 0; blockY < 16; blockY++) { // Cache-friendly iteration order
for (int blockZ = 0; blockZ < 16; blockZ++) {
for (int blockX = 0; blockX < 16; blockX++) {
Block block = world.getBlockAt((x << 4) + blockX, (y << 4) + blockY, (z << 4) + blockZ);
int id = BlockTranslator.getJavaIdBlockMap().getOrDefault(block.getBlockData().getAsString(), BlockTranslator.JAVA_AIR_ID);
chunk.set(blockX, blockY, blockZ, id);
}
}
}
}
@Override
public boolean hasOwnChunkCache() {
return true;
}
@Override
@SuppressWarnings("deprecation")
public int[] getBiomeDataAt(GeyserSession session, int x, int z) {
int[] biomeData = new int[1024];
World world = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld();
int chunkX = x << 4;
int chunkZ = z << 4;
int chunkXmax = chunkX + 16;
int chunkZmax = chunkZ + 16;
// 3D biomes didn't exist until 1.15
if (use3dBiomes) {
for (int localX = chunkX; localX < chunkXmax; localX += 4) {
for (int localY = 0; localY < 255; localY += + 4) {
for (int localZ = chunkZ; localZ < chunkZmax; localZ += 4) {
// Index is based on wiki.vg's index requirements
final int i = ((localY >> 2) & 63) << 4 | ((localZ >> 2) & 3) << 2 | ((localX >> 2) & 3);
biomeData[i] = biomeToIdMap.getOrDefault(world.getBiome(localX, localY, localZ).ordinal(), 0);
}
}
}
} else {
// Looks like the same code, but we're not checking the Y coordinate here
for (int localX = chunkX; localX < chunkXmax; localX += 4) {
for (int localY = 0; localY < 255; localY += + 4) {
for (int localZ = chunkZ; localZ < chunkZmax; localZ += 4) {
// Index is based on wiki.vg's index requirements
final int i = ((localY >> 2) & 63) << 4 | ((localZ >> 2) & 3) << 2 | ((localX >> 2) & 3);
biomeData[i] = biomeToIdMap.getOrDefault(world.getBiome(localX, localZ).ordinal(), 0);
}
}
}
}
return biomeData;
}
@Override
public NbtMap getLecternDataAt(GeyserSession session, int x, int y, int z, boolean isChunkLoad) {
// Run as a task to prevent async issues

View File

@ -1,155 +0,0 @@
{
"MUTATED_ICE_FLATS" : 140,
"MUTATED_TAIGA" : 133,
"SAVANNA_PLATEAU_MOUNTAINS" : 164,
"DEEP_WARM_OCEAN" : 47,
"REDWOOD_TAIGA_HILLS" : 33,
"THE_VOID" : 127,
"COLD_TAIGA_MOUNTAINS" : 158,
"BAMBOO_JUNGLE_HILLS" : 169,
"MOUNTAINS" : 3,
"MESA_PLATEAU" : 39,
"SNOWY_TAIGA_HILLS" : 31,
"DEEP_FROZEN_OCEAN" : 50,
"EXTREME_HILLS" : 3,
"BIRCH_FOREST_MOUNTAINS" : 155,
"FOREST" : 4,
"BIRCH_FOREST" : 27,
"SNOWY_TUNDRA" : 12,
"ICE_SPIKES" : 140,
"FROZEN_OCEAN" : 10,
"WARPED_FOREST" : 172,
"WOODED_BADLANDS_PLATEAU" : 38,
"BADLANDS_PLATEAU" : 39,
"ICE_PLAINS_SPIKES" : 140,
"MEGA_TAIGA" : 32,
"MUTATED_SAVANNA_ROCK" : 164,
"SAVANNA_PLATEAU" : 36,
"DARK_FOREST_HILLS" : 157,
"END_MIDLANDS" : 41,
"SHATTERED_SAVANNA_PLATEAU" : 164,
"SAVANNA" : 35,
"MUSHROOM_ISLAND_SHORE" : 15,
"SWAMP" : 6,
"ICE_MOUNTAINS" : 13,
"BEACH" : 16,
"MUTATED_MESA_CLEAR_ROCK" : 167,
"END_HIGHLANDS" : 42,
"COLD_BEACH" : 26,
"JUNGLE" : 21,
"MUTATED_TAIGA_COLD" : 158,
"TALL_BIRCH_HILLS" : 156,
"DARK_FOREST" : 29,
"WOODED_HILLS" : 18,
"HELL" : 8,
"MUTATED_REDWOOD_TAIGA" : 160,
"MESA_PLATEAU_FOREST" : 38,
"MUSHROOM_ISLAND" : 14,
"BADLANDS" : 37,
"END_BARRENS" : 43,
"MUTATED_EXTREME_HILLS_WITH_TREES" : 162,
"MUTATED_JUNGLE_EDGE" : 151,
"MODIFIED_BADLANDS_PLATEAU" : 167,
"ROOFED_FOREST_MOUNTAINS" : 157,
"SOUL_SAND_VALLEY" : 170,
"DESERT" : 2,
"MUTATED_PLAINS" : 129,
"MUTATED_BIRCH_FOREST" : 155,
"WOODED_MOUNTAINS" : 34,
"TAIGA_HILLS" : 19,
"BAMBOO_JUNGLE" : 168,
"SWAMPLAND_MOUNTAINS" : 134,
"DESERT_MOUNTAINS" : 130,
"REDWOOD_TAIGA" : 32,
"MUSHROOM_FIELDS" : 14,
"GIANT_TREE_TAIGA_HILLS" : 33,
"PLAINS" : 1,
"JUNGLE_EDGE" : 23,
"SAVANNA_MOUNTAINS" : 163,
"DEEP_COLD_OCEAN" : 49,
"DESERT_LAKES" : 130,
"MOUNTAIN_EDGE" : 20,
"SNOWY_MOUNTAINS" : 13,
"MESA_PLATEAU_MOUNTAINS" : 167,
"JUNGLE_MOUNTAINS" : 149,
"SMALLER_EXTREME_HILLS" : 20,
"MESA_PLATEAU_FOREST_MOUNTAINS" : 166,
"NETHER_WASTES" : 8,
"BIRCH_FOREST_HILLS_MOUNTAINS" : 156,
"MUTATED_JUNGLE" : 149,
"WARM_OCEAN" : 44,
"DEEP_OCEAN" : 24,
"STONE_BEACH" : 25,
"MODIFIED_JUNGLE" : 149,
"MUTATED_SAVANNA" : 163,
"TAIGA_COLD_HILLS" : 31,
"OCEAN" : 0,
"SMALL_END_ISLANDS" : 40,
"MUSHROOM_FIELD_SHORE" : 15,
"GRAVELLY_MOUNTAINS" : 131,
"FROZEN_RIVER" : 11,
"TAIGA_COLD" : 30,
"BASALT_DELTAS" : 173,
"EXTREME_HILLS_WITH_TREES" : 34,
"MEGA_TAIGA_HILLS" : 33,
"MUTATED_FOREST" : 132,
"MUTATED_BIRCH_FOREST_HILLS" : 156,
"SKY" : 9,
"LUKEWARM_OCEAN" : 45,
"EXTREME_HILLS_MOUNTAINS" : 131,
"COLD_TAIGA_HILLS" : 31,
"THE_END" : 9,
"SUNFLOWER_PLAINS" : 129,
"SAVANNA_ROCK" : 36,
"ERODED_BADLANDS" : 165,
"STONE_SHORE" : 25,
"EXTREME_HILLS_PLUS_MOUNTAINS" : 162,
"CRIMSON_FOREST" : 171,
"VOID" : 127,
"SNOWY_TAIGA" : 30,
"SNOWY_TAIGA_MOUNTAINS" : 158,
"FLOWER_FOREST" : 132,
"COLD_OCEAN" : 46,
"BEACHES" : 16,
"MESA" : 37,
"MUSHROOM_SHORE" : 15,
"MESA_CLEAR_ROCK" : 39,
"NETHER" : 8,
"ICE_PLAINS" : 12,
"SHATTERED_SAVANNA" : 163,
"ROOFED_FOREST" : 29,
"GIANT_SPRUCE_TAIGA_HILLS" : 161,
"SNOWY_BEACH" : 26,
"MESA_BRYCE" : 165,
"JUNGLE_EDGE_MOUNTAINS" : 151,
"MUTATED_DESERT" : 130,
"MODIFIED_GRAVELLY_MOUNTAINS" : 158,
"MEGA_SPRUCE_TAIGA" : 160,
"TAIGA_MOUNTAINS" : 133,
"SMALL_MOUNTAINS" : 20,
"EXTREME_HILLS_PLUS" : 34,
"GIANT_SPRUCE_TAIGA" : 160,
"FOREST_HILLS" : 18,
"DESERT_HILLS" : 17,
"MUTATED_REDWOOD_TAIGA_HILLS" : 161,
"MEGA_SPRUCE_TAIGA_HILLS" : 161,
"RIVER" : 7,
"GIANT_TREE_TAIGA" : 32,
"SWAMPLAND" : 6,
"JUNGLE_HILLS" : 22,
"TALL_BIRCH_FOREST" : 155,
"DEEP_LUKEWARM_OCEAN" : 48,
"MESA_ROCK" : 38,
"SWAMP_HILLS" : 134,
"MODIFIED_WOODED_BADLANDS_PLATEAU" : 166,
"MODIFIED_JUNGLE_EDGE" : 151,
"BIRCH_FOREST_HILLS" : 28,
"COLD_TAIGA" : 30,
"TAIGA" : 5,
"MUTATED_MESA_ROCK" : 166,
"MUTATED_SWAMPLAND" : 134,
"ICE_FLATS" : 12,
"MUTATED_ROOFED_FOREST" : 157,
"MUTATED_MESA" : 165,
"MUTATED_EXTREME_HILLS" : 131
}

View File

@ -122,7 +122,7 @@
<dependency>
<groupId>com.github.steveice10</groupId>
<artifactId>mcprotocollib</artifactId>
<version>21w17a-SNAPSHOT</version>
<version>21w20a-SNAPSHOT</version>
<scope>compile</scope>
<exclusions>
<exclusion>

View File

@ -44,7 +44,7 @@ public class AbstractArrowEntity extends Entity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 7) {
if (entityMetadata.getId() == 8) {
byte data = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.CRITICAL, (data & 0x01) == 0x01);

View File

@ -52,12 +52,12 @@ public class AreaEffectCloudEntity extends Entity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 7) {
if (entityMetadata.getId() == 8) {
metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, entityMetadata.getValue());
metadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * (float) entityMetadata.getValue());
} else if (entityMetadata.getId() == 8) {
} else if (entityMetadata.getId() == 9) {
metadata.put(EntityData.EFFECT_COLOR, entityMetadata.getValue());
} else if (entityMetadata.getId() == 10) {
} else if (entityMetadata.getId() == 11) {
Particle particle = (Particle) entityMetadata.getValue();
int particleId = EffectRegistry.getParticleId(particle.getType());
if (particleId != -1) {

View File

@ -87,24 +87,24 @@ public class BoatEntity extends Entity {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
// Time since last hit
if (entityMetadata.getId() == 7) {
if (entityMetadata.getId() == 8) {
metadata.put(EntityData.HURT_TIME, entityMetadata.getValue());
}
// Rocking direction
if (entityMetadata.getId() == 8) {
if (entityMetadata.getId() == 9) {
metadata.put(EntityData.HURT_DIRECTION, entityMetadata.getValue());
}
// 'Health' in Bedrock, damage taken in Java
if (entityMetadata.getId() == 9) {
if (entityMetadata.getId() == 10) {
// Not exactly health but it makes motion in Bedrock
metadata.put(EntityData.HEALTH, 40 - ((int) (float) entityMetadata.getValue()));
}
if (entityMetadata.getId() == 10) {
if (entityMetadata.getId() == 11) {
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
} else if (entityMetadata.getId() == 11) {
} else if (entityMetadata.getId() == 12) {
isPaddlingLeft = (boolean) entityMetadata.getValue();
if (isPaddlingLeft) {
// Java sends simply "true" and "false" (is_paddling_left), Bedrock keeps sending packets as you're rowing
@ -124,7 +124,7 @@ public class BoatEntity extends Entity {
metadata.put(EntityData.ROW_TIME_LEFT, 0.0f);
}
}
else if (entityMetadata.getId() == 12) {
else if (entityMetadata.getId() == 13) {
isPaddlingRight = (boolean) entityMetadata.getValue();
if (isPaddlingRight) {
paddleTimeRight = 0f;
@ -139,7 +139,7 @@ public class BoatEntity extends Entity {
} else {
metadata.put(EntityData.ROW_TIME_RIGHT, 0.0f);
}
} else if (entityMetadata.getId() == 13) {
} else if (entityMetadata.getId() == 14) {
// Possibly - I don't think this does anything?
metadata.put(EntityData.BOAT_BUBBLE_TIME, entityMetadata.getValue());
}

View File

@ -46,10 +46,10 @@ public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 13) {
if (entityMetadata.getId() == 14) {
metadata.put(EntityData.COMMAND_BLOCK_COMMAND, entityMetadata.getValue());
}
if (entityMetadata.getId() == 14) {
if (entityMetadata.getId() == 15) {
metadata.put(EntityData.COMMAND_BLOCK_LAST_OUTPUT, MessageTranslator.convertMessage((Component) entityMetadata.getValue()));
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -56,7 +56,7 @@ public class DefaultBlockMinecartEntity extends MinecartEntity {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
// Custom block
if (entityMetadata.getId() == 10) {
if (entityMetadata.getId() == 11) {
customBlock = (int) entityMetadata.getValue();
if (showCustomBlock) {
@ -65,7 +65,7 @@ public class DefaultBlockMinecartEntity extends MinecartEntity {
}
// Custom block offset
if (entityMetadata.getId() == 11) {
if (entityMetadata.getId() == 12) {
customBlockOffset = (int) entityMetadata.getValue();
if (showCustomBlock) {
@ -74,7 +74,7 @@ public class DefaultBlockMinecartEntity extends MinecartEntity {
}
// If the custom block should be enabled
if (entityMetadata.getId() == 12) {
if (entityMetadata.getId() == 13) {
if ((boolean) entityMetadata.getValue()) {
showCustomBlock = true;
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockTranslator().getBedrockBlockId(customBlock));

View File

@ -47,7 +47,7 @@ public class EnderCrystalEntity extends Entity {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
// Show beam
// Usually performed client-side on Bedrock except for Ender Dragon respawn event
if (entityMetadata.getId() == 7) {
if (entityMetadata.getId() == 8) {
if (entityMetadata.getValue() instanceof Position) {
Position pos = (Position) entityMetadata.getValue();
metadata.put(EntityData.BLOCK_TARGET, Vector3i.from(pos.getX(), pos.getY(), pos.getZ()));
@ -56,7 +56,7 @@ public class EnderCrystalEntity extends Entity {
}
}
// There is a base located on the ender crystal
if (entityMetadata.getId() == 8) {
if (entityMetadata.getId() == 9) {
metadata.getFlags().setFlag(EntityFlag.SHOW_BOTTOM, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -329,6 +329,10 @@ public class Entity {
metadata.put(EntityData.BOUNDING_BOX_WIDTH, width);
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, height);
break;
case 7:
//TODO check
metadata.put(EntityData.FREEZING_EFFECT_STRENGTH, entityMetadata.getValue());
break;
}
}

View File

@ -32,7 +32,7 @@ import org.geysermc.connector.network.session.GeyserSession;
public class ExpOrbEntity extends Entity {
private int amount;
private final int amount;
public ExpOrbEntity(int amount, long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
super(entityId, geyserId, entityType, position, motion, rotation);

View File

@ -55,7 +55,7 @@ public class FireworkEntity extends Entity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 7) {
if (entityMetadata.getId() == 8) {
ItemStack item = (ItemStack) entityMetadata.getValue();
if (item == null) {
return;
@ -134,7 +134,7 @@ public class FireworkEntity extends Entity {
NbtMapBuilder builder = NbtMap.builder();
builder.put("Fireworks", fireworksBuilder.build());
metadata.put(EntityData.DISPLAY_ITEM, builder.build());
} else if (entityMetadata.getId() == 8 && !entityMetadata.getValue().equals(OptionalInt.empty()) && ((OptionalInt) entityMetadata.getValue()).getAsInt() == session.getPlayerEntity().getEntityId()) {
} else if (entityMetadata.getId() == 9 && !entityMetadata.getValue().equals(OptionalInt.empty()) && ((OptionalInt) entityMetadata.getValue()).getAsInt() == session.getPlayerEntity().getEntityId()) {
//Checks if the firework has an entity ID (used when a player is gliding) and checks to make sure the player that is gliding is the one getting sent the packet or else every player near the gliding player will boost too.
PlayerEntity entity = session.getPlayerEntity();
float yaw = entity.getRotation().getX();

View File

@ -67,7 +67,7 @@ public class FishingHookEntity extends ThrowableEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 7) { // Hooked entity
if (entityMetadata.getId() == 8) { // Hooked entity
int hookedEntityId = (int) entityMetadata.getValue() - 1;
Entity entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
if (entity == null && session.getPlayerEntity().getEntityId() == hookedEntityId) {

View File

@ -42,7 +42,7 @@ public class FurnaceMinecartEntity extends DefaultBlockMinecartEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 13 && !showCustomBlock) {
if (entityMetadata.getId() == 14 && !showCustomBlock) {
hasFuel = (boolean) entityMetadata.getValue();
updateDefaultBlockMetadata(session);
}

View File

@ -54,7 +54,7 @@ public class ItemEntity extends Entity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 7) {
if (entityMetadata.getId() == 8) {
AddItemEntityPacket itemPacket = new AddItemEntityPacket();
itemPacket.setRuntimeEntityId(geyserId);
itemPacket.setPosition(position.add(0d, this.entityType.getOffset(), 0d));

View File

@ -105,7 +105,7 @@ public class ItemFrameEntity extends Entity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 7 && entityMetadata.getValue() != null) {
if (entityMetadata.getId() == 8 && entityMetadata.getValue() != null) {
this.heldItem = (ItemStack) entityMetadata.getValue();
ItemData itemData = ItemTranslator.translateToBedrock(session, heldItem);
ItemEntry itemEntry = ItemRegistry.getItem((ItemStack) entityMetadata.getValue());
@ -124,11 +124,11 @@ public class ItemFrameEntity extends Entity {
cachedTag = tag.build();
updateBlock(session);
}
else if (entityMetadata.getId() == 7 && entityMetadata.getValue() == null && cachedTag != null) {
else if (entityMetadata.getId() == 8 && entityMetadata.getValue() == null && cachedTag != null) {
cachedTag = getDefaultTag();
updateBlock(session);
}
else if (entityMetadata.getId() == 8) {
else if (entityMetadata.getId() == 9) {
rotation = ((int) entityMetadata.getValue()) * 45;
if (cachedTag == null) {
updateBlock(session);

View File

@ -68,7 +68,7 @@ public class LivingEntity extends Entity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
switch (entityMetadata.getId()) {
case 7: // blocking
case 8: // blocking
byte xd = (byte) entityMetadata.getValue();
//blocking gets triggered when using a bow, but if we set USING_ITEM for all items, it may look like
@ -81,16 +81,16 @@ public class LivingEntity extends Entity {
// Riptide spin attack
metadata.getFlags().setFlag(EntityFlag.DAMAGE_NEARBY_MOBS, (xd & 0x04) == 0x04);
break;
case 8:
case 9:
metadata.put(EntityData.HEALTH, entityMetadata.getValue());
break;
case 9:
case 10:
metadata.put(EntityData.EFFECT_COLOR, entityMetadata.getValue());
break;
case 10:
case 11:
metadata.put(EntityData.EFFECT_AMBIENT, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0));
break;
case 13: // Bed Position
case 14: // Bed Position
Position bedPosition = (Position) entityMetadata.getValue();
if (bedPosition != null) {
metadata.put(EntityData.BED_POSITION, Vector3i.from(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ()));

View File

@ -40,33 +40,33 @@ public class MinecartEntity extends Entity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 7) {
if (entityMetadata.getId() == 8) {
metadata.put(EntityData.HEALTH, entityMetadata.getValue());
}
// Direction in which the minecart is shaking
if (entityMetadata.getId() == 8) {
if (entityMetadata.getId() == 9) {
metadata.put(EntityData.HURT_DIRECTION, entityMetadata.getValue());
}
// Power in Java, time in Bedrock
if (entityMetadata.getId() == 9) {
if (entityMetadata.getId() == 10) {
metadata.put(EntityData.HURT_TIME, Math.min((int) (float) entityMetadata.getValue(), 15));
}
if (!(this instanceof DefaultBlockMinecartEntity)) { // Handled in the DefaultBlockMinecartEntity class
// Custom block
if (entityMetadata.getId() == 10) {
if (entityMetadata.getId() == 11) {
metadata.put(EntityData.DISPLAY_ITEM, session.getBlockTranslator().getBedrockBlockId((int) entityMetadata.getValue()));
}
// Custom block offset
if (entityMetadata.getId() == 11) {
if (entityMetadata.getId() == 12) {
metadata.put(EntityData.DISPLAY_OFFSET, entityMetadata.getValue());
}
// If the custom block should be enabled
if (entityMetadata.getId() == 12) {
if (entityMetadata.getId() == 13) {
// Needs a byte based off of Java's boolean
metadata.put(EntityData.CUSTOM_DISPLAY, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0));
}

View File

@ -45,7 +45,7 @@ public class TNTEntity extends Entity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 7) {
if (entityMetadata.getId() == 8) {
currentTick = (int) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.IGNITED, true);
metadata.put(EntityData.FUSE_LENGTH, currentTick);

View File

@ -167,10 +167,8 @@ public class ThrowableEntity extends Entity implements Tickable {
*/
protected boolean isInWater(GeyserSession session) {
if (session.getConnector().getConfig().isCacheChunks()) {
if (0 <= position.getFloorY() && position.getFloorY() <= 255) {
int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
return BlockStateValues.getWaterLevel(block) != -1;
}
int block = session.getConnector().getWorldManager().getBlockAt(session, position.toInt());
return BlockStateValues.getWaterLevel(block) != -1;
}
return false;
}

View File

@ -51,7 +51,7 @@ public class ThrownPotionEntity extends ThrowableEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 7 && entityMetadata.getType() == MetadataType.ITEM) {
if (entityMetadata.getId() == 8 && entityMetadata.getType() == MetadataType.ITEM) {
ItemStack itemStack = (ItemStack) entityMetadata.getValue();
ItemEntry itemEntry = ItemRegistry.getItem(itemStack);
if (itemEntry.getJavaIdentifier().endsWith("potion") && itemStack.getNbt() != null) {

View File

@ -44,17 +44,17 @@ public class TippedArrowEntity extends AbstractArrowEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
// Arrow potion effect color
if (entityMetadata.getId() == 9) {
if (entityMetadata.getId() == 10) {
int potionColor = (int) entityMetadata.getValue();
// -1 means no color
if (potionColor == -1) {
metadata.remove(EntityData.CUSTOM_DISPLAY);
metadata.put(EntityData.CUSTOM_DISPLAY, 0);
} else {
TippedArrowPotion potion = TippedArrowPotion.getByJavaColor(potionColor);
if (potion != null && potion.getJavaColor() != -1) {
metadata.put(EntityData.CUSTOM_DISPLAY, (byte) potion.getBedrockId());
} else {
metadata.remove(EntityData.CUSTOM_DISPLAY);
metadata.put(EntityData.CUSTOM_DISPLAY, 0);
}
}
}

View File

@ -39,7 +39,7 @@ public class TridentEntity extends AbstractArrowEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 10) {
if (entityMetadata.getId() == 11) {
metadata.getFlags().setFlag(EntityFlag.ENCHANTED, (boolean) entityMetadata.getValue());
}

View File

@ -46,7 +46,7 @@ public class WitherSkullEntity extends ItemedFireballEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 7) {
if (entityMetadata.getId() == 8) {
boolean newIsCharged = (boolean) entityMetadata.getValue();
if (newIsCharged != isCharged) {
isCharged = newIsCharged;

View File

@ -40,7 +40,7 @@ public class AgeableEntity extends CreatureEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
boolean isBaby = (boolean) entityMetadata.getValue();
metadata.put(EntityData.SCALE, isBaby ? .55f : 1f);
metadata.getFlags().setFlag(EntityFlag.BABY, isBaby);

View File

@ -126,7 +126,7 @@ public class ArmorStandEntity extends LivingEntity {
}
} else if (entityMetadata.getId() == 2) {
updateSecondEntityStatus(false);
} else if (entityMetadata.getId() == 14 && entityMetadata.getType() == MetadataType.BYTE) {
} else if (entityMetadata.getId() == 15 && entityMetadata.getType() == MetadataType.BYTE) {
byte xd = (byte) entityMetadata.getValue();
// isSmall
@ -169,37 +169,37 @@ public class ArmorStandEntity extends LivingEntity {
EntityFlag negativeYToggle = null;
EntityFlag negativeZToggle = null;
switch (entityMetadata.getId()) {
case 15: // Head
case 16: // Head
dataLeech = EntityData.MARK_VARIANT;
negativeXToggle = EntityFlag.INTERESTED;
negativeYToggle = EntityFlag.CHARGED;
negativeZToggle = EntityFlag.POWERED;
break;
case 16: // Body
case 17: // Body
dataLeech = EntityData.VARIANT;
negativeXToggle = EntityFlag.IN_LOVE;
negativeYToggle = EntityFlag.CELEBRATING;
negativeZToggle = EntityFlag.CELEBRATING_SPECIAL;
break;
case 17: // Left arm
case 18: // Left arm
dataLeech = EntityData.TRADE_TIER;
negativeXToggle = EntityFlag.CHARGING;
negativeYToggle = EntityFlag.CRITICAL;
negativeZToggle = EntityFlag.DANCING;
break;
case 18: // Right arm
case 19: // Right arm
dataLeech = EntityData.MAX_TRADE_TIER;
negativeXToggle = EntityFlag.ELDER;
negativeYToggle = EntityFlag.EMOTING;
negativeZToggle = EntityFlag.IDLING;
break;
case 19: // Left leg
case 20: // Left leg
dataLeech = EntityData.SKIN_ID;
negativeXToggle = EntityFlag.IS_ILLAGER_CAPTAIN;
negativeYToggle = EntityFlag.IS_IN_UI;
negativeZToggle = EntityFlag.LINGERING;
break;
case 20: // Right leg
case 21: // Right leg
dataLeech = EntityData.HURT_DIRECTION;
negativeXToggle = EntityFlag.IS_PREGNANT;
negativeYToggle = EntityFlag.SHEARED;

View File

@ -39,7 +39,7 @@ public class BatEntity extends AmbientEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.RESTING, (xd & 0x01) == 0x01);
}

View File

@ -41,7 +41,7 @@ public class InsentientEntity extends LivingEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 14 && entityMetadata.getType() == MetadataType.BYTE) {
if (entityMetadata.getId() == 15 && entityMetadata.getType() == MetadataType.BYTE) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.NO_AI, (xd & 0x01) == 0x01);
}

View File

@ -53,7 +53,7 @@ public class IronGolemEntity extends GolemEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
super.updateBedrockMetadata(entityMetadata, session);
if (entityMetadata.getId() == 8) {
if (entityMetadata.getId() == 9) {
// Required so the resource pack sees the entity health
attributes.put(AttributeType.HEALTH, AttributeType.HEALTH.getAttribute(metadata.getFloat(EntityData.HEALTH), 100f));
updateBedrockAttributes(session);

View File

@ -39,7 +39,7 @@ public class SlimeEntity extends InsentientEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
this.metadata.put(EntityData.SCALE, 0.10f + (int) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -39,7 +39,7 @@ public class SnowGolemEntity extends GolemEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
byte xd = (byte) entityMetadata.getValue();
// Handle the visibility of the pumpkin
metadata.getFlags().setFlag(EntityFlag.SHEARED, (xd & 0x10) != 0x10);

View File

@ -43,7 +43,7 @@ public class BeeEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
byte xd = (byte) entityMetadata.getValue();
// Bee is performing sting attack; trigger animation
if ((xd & 0x02) == 0x02) {
@ -58,7 +58,7 @@ public class BeeEntity extends AnimalEntity {
// If the bee has nectar or not
metadata.getFlags().setFlag(EntityFlag.POWERED, (xd & 0x08) == 0x08);
}
if (entityMetadata.getId() == 17) {
if (entityMetadata.getId() == 18) {
// Converting "anger time" to a boolean
metadata.getFlags().setFlag(EntityFlag.ANGRY, (int) entityMetadata.getValue() > 0);
}

View File

@ -41,10 +41,10 @@ public class FoxEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
}
if (entityMetadata.getId() == 17) {
if (entityMetadata.getId() == 18) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01);
metadata.getFlags().setFlag(EntityFlag.SNEAKING, (xd & 0x04) == 0x04);
@ -56,6 +56,6 @@ public class FoxEntity extends AnimalEntity {
@Override
public boolean canEat(GeyserSession session, String javaIdentifierStripped, ItemEntry itemEntry) {
return javaIdentifierStripped.equals("sweet_berries");
return session.getTagCache().isFoxFood(itemEntry);
}
}

View File

@ -41,7 +41,7 @@ public class HoglinEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
// Immune to zombification?
// Apply shaking effect if not in the nether and zombification is possible
metadata.getFlags().setFlag(EntityFlag.SHAKING, !((boolean) entityMetadata.getValue()) && !session.getDimension().equals(DimensionUtils.NETHER));

View File

@ -39,7 +39,7 @@ public class MooshroomEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
metadata.put(EntityData.VARIANT, entityMetadata.getValue().equals("brown") ? 1 : 0);
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -40,7 +40,7 @@ public class OcelotEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
metadata.getFlags().setFlag(EntityFlag.TRUSTING, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -47,7 +47,7 @@ public class PandaEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 18) {
if (entityMetadata.getId() == 19) {
metadata.getFlags().setFlag(EntityFlag.EATING, (int) entityMetadata.getValue() > 0);
metadata.put(EntityData.EATING_COUNTER, entityMetadata.getValue());
if ((int) entityMetadata.getValue() != 0) {
@ -59,15 +59,15 @@ public class PandaEntity extends AnimalEntity {
session.sendUpstreamPacket(packet);
}
}
if (entityMetadata.getId() == 19) {
if (entityMetadata.getId() == 20) {
mainGene = (int) (byte) entityMetadata.getValue();
updateAppearance();
}
if (entityMetadata.getId() == 20) {
if (entityMetadata.getId() == 21) {
hiddenGene = (int) (byte) entityMetadata.getValue();
updateAppearance();
}
if (entityMetadata.getId() == 21) {
if (entityMetadata.getId() == 22) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.SNEEZING, (xd & 0x02) == 0x02);
metadata.getFlags().setFlag(EntityFlag.ROLLING, (xd & 0x04) == 0x04);

View File

@ -40,8 +40,7 @@ public class PigEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
metadata.getFlags().setFlag(EntityFlag.SADDLED, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -40,7 +40,7 @@ public class PolarBearEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
metadata.getFlags().setFlag(EntityFlag.STANDING, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -40,10 +40,11 @@ public class PufferFishEntity extends AbstractFishEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
// Transfers correctly but doesn't apply on the client
//TODO check - probably because we didn't set PUFFERFISH_SIZE as a byte
int puffsize = (int) entityMetadata.getValue();
metadata.put(EntityData.PUFFERFISH_SIZE, puffsize);
metadata.put(EntityData.PUFFERFISH_SIZE, (byte) puffsize);
metadata.put(EntityData.VARIANT, puffsize);
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -42,14 +42,14 @@ public class RabbitEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
super.updateBedrockMetadata(entityMetadata, session);
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
metadata.put(EntityData.SCALE, .55f);
boolean isBaby = (boolean) entityMetadata.getValue();
if (isBaby) {
metadata.put(EntityData.SCALE, .35f);
metadata.getFlags().setFlag(EntityFlag.BABY, true);
}
} else if (entityMetadata.getId() == 16) {
} else if (entityMetadata.getId() == 17) {
int variant = (int) entityMetadata.getValue();
// Change the killer bunny to display as white since it only exists on Java Edition

View File

@ -40,7 +40,7 @@ public class SheepEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.SHEARED, (xd & 0x10) == 0x10);
metadata.put(EntityData.COLOR, xd);

View File

@ -46,10 +46,10 @@ public class StriderEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 17) {
if (entityMetadata.getId() == 18) {
shaking = (boolean) entityMetadata.getValue();
}
if (entityMetadata.getId() == 18) {
if (entityMetadata.getId() == 19) {
metadata.getFlags().setFlag(EntityFlag.SADDLED, (boolean) entityMetadata.getValue());
}

View File

@ -28,8 +28,6 @@ package org.geysermc.connector.entity.living.animal;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.geysermc.connector.entity.living.AbstractFishEntity;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
@ -42,34 +40,14 @@ public class TropicalFishEntity extends AbstractFishEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
TropicalFishVariant variant = TropicalFishVariant.fromVariantNumber((int) entityMetadata.getValue());
if (entityMetadata.getId() == 17) {
int varNumber = (int) entityMetadata.getValue();
metadata.put(EntityData.VARIANT, variant.getShape()); // Shape 0-1
metadata.put(EntityData.MARK_VARIANT, variant.getPattern()); // Pattern 0-5
metadata.put(EntityData.COLOR, variant.getBaseColor()); // Base color 0-15
metadata.put(EntityData.COLOR_2, variant.getPatternColor()); // Pattern color 0-15
metadata.put(EntityData.VARIANT, varNumber & 0xFF); // Shape 0-1
metadata.put(EntityData.MARK_VARIANT, (varNumber >> 8) & 0xFF); // Pattern 0-5
metadata.put(EntityData.COLOR, (byte) ((varNumber >> 16) & 0xFF)); // Base color 0-15
metadata.put(EntityData.COLOR_2, (byte) ((varNumber >> 24) & 0xFF)); // Pattern color 0-15
}
super.updateBedrockMetadata(entityMetadata, session);
}
@Getter
@AllArgsConstructor
private static class TropicalFishVariant {
private int shape;
private int pattern;
private byte baseColor;
private byte patternColor;
/**
* Convert the variant number from Java into separate values
*
* @param varNumber Variant number from Java edition
*
* @return The variant converted into TropicalFishVariant
*/
public static TropicalFishVariant fromVariantNumber(int varNumber) {
return new TropicalFishVariant((varNumber & 0xFF), ((varNumber >> 8) & 0xFF), (byte) ((varNumber >> 16) & 0xFF), (byte) ((varNumber >> 24) & 0xFF));
}
}
}

View File

@ -40,9 +40,9 @@ public class TurtleEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 17) {
if (entityMetadata.getId() == 18) {
metadata.getFlags().setFlag(EntityFlag.IS_PREGNANT, (boolean) entityMetadata.getValue());
} else if (entityMetadata.getId() == 18) {
} else if (entityMetadata.getId() == 19) {
metadata.getFlags().setFlag(EntityFlag.LAYING_EGG, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -64,7 +64,7 @@ public class AbstractHorseEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.TAMED, (xd & 0x02) == 0x02);
metadata.getFlags().setFlag(EntityFlag.SADDLED, (xd & 0x04) == 0x04);
@ -106,7 +106,7 @@ public class AbstractHorseEntity extends AnimalEntity {
super.updateBedrockMetadata(entityMetadata, session);
if (entityMetadata.getId() == 8) {
if (entityMetadata.getId() == 9) {
// Update the health attribute
updateBedrockAttributes(session);
}

View File

@ -42,7 +42,7 @@ public class ChestedHorseEntity extends AbstractHorseEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 18) {
if (entityMetadata.getId() == 19) {
metadata.getFlags().setFlag(EntityFlag.CHESTED, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -39,7 +39,7 @@ public class HorseEntity extends AbstractHorseEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 18) {
if (entityMetadata.getId() == 19) {
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
metadata.put(EntityData.MARK_VARIANT, (((int) entityMetadata.getValue()) >> 8) % 5);
}

View File

@ -46,11 +46,11 @@ public class LlamaEntity extends ChestedHorseEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
// Strength
if (entityMetadata.getId() == 19) {
if (entityMetadata.getId() == 20) {
metadata.put(EntityData.STRENGTH, entityMetadata.getValue());
}
// Color equipped on the llama
if (entityMetadata.getId() == 20) {
if (entityMetadata.getId() == 21) {
// Bedrock treats llama decoration as armor
MobArmorEquipmentPacket equipmentPacket = new MobArmorEquipmentPacket();
equipmentPacket.setRuntimeEntityId(geyserId);
@ -71,7 +71,7 @@ public class LlamaEntity extends ChestedHorseEntity {
session.sendUpstreamPacket(equipmentPacket);
}
// Color of the llama
if (entityMetadata.getId() == 21) {
if (entityMetadata.getId() == 22) {
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -49,13 +49,13 @@ public class CatEntity extends TameableEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
super.updateBedrockMetadata(entityMetadata, session);
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
// Update collar color if tamed
if (metadata.getFlags().getFlag(EntityFlag.TAMED)) {
metadata.put(EntityData.COLOR, collarColor);
}
}
if (entityMetadata.getId() == 18) {
if (entityMetadata.getId() == 19) {
// Different colors in Java and Bedrock for some reason
int variantColor;
switch ((int) entityMetadata.getValue()) {
@ -76,7 +76,7 @@ public class CatEntity extends TameableEntity {
}
metadata.put(EntityData.VARIANT, variantColor);
}
if (entityMetadata.getId() == 21) {
if (entityMetadata.getId() == 22) {
collarColor = (byte) (int) entityMetadata.getValue();
// Needed or else wild cats are a red color
if (metadata.getFlags().getFlag(EntityFlag.TAMED)) {

View File

@ -41,7 +41,7 @@ public class ParrotEntity extends TameableEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
// Parrot color
if (entityMetadata.getId() == 18) {
if (entityMetadata.getId() == 19) {
metadata.put(EntityData.VARIANT, entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -44,7 +44,7 @@ public class TameableEntity extends AnimalEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.SITTING, (xd & 0x01) == 0x01);
metadata.getFlags().setFlag(EntityFlag.ANGRY, (xd & 0x02) == 0x02);
@ -52,7 +52,7 @@ public class TameableEntity extends AnimalEntity {
}
// Note: Must be set for wolf collar color to work
if (entityMetadata.getId() == 17) {
if (entityMetadata.getId() == 18) {
if (entityMetadata.getValue() != null) {
// Owner UUID of entity
Entity entity = session.getEntityCache().getPlayerEntity((UUID) entityMetadata.getValue());

View File

@ -54,7 +54,7 @@ public class WolfEntity extends TameableEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
//Reset wolf color
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
byte xd = (byte) entityMetadata.getValue();
boolean angry = (xd & 0x02) == 0x02;
if (angry) {
@ -63,13 +63,13 @@ public class WolfEntity extends TameableEntity {
}
// "Begging" on wiki.vg, "Interested" in Nukkit - the tilt of the head
if (entityMetadata.getId() == 18) {
if (entityMetadata.getId() == 19) {
metadata.getFlags().setFlag(EntityFlag.INTERESTED, (boolean) entityMetadata.getValue());
}
// Wolf collar color
// Relies on EntityData.OWNER_EID being set in TameableEntity.java
if (entityMetadata.getId() == 19 && !metadata.getFlags().getFlag(EntityFlag.ANGRY)) {
if (entityMetadata.getId() == 20 && !metadata.getFlags().getFlag(EntityFlag.ANGRY)) {
metadata.put(EntityData.COLOR, collarColor = (byte) (int) entityMetadata.getValue());
if (!metadata.containsKey(EntityData.OWNER_EID)) {
// If a color is set and there is no owner entity ID, set one.
@ -79,7 +79,7 @@ public class WolfEntity extends TameableEntity {
}
// Wolf anger (1.16+)
if (entityMetadata.getId() == 20) {
if (entityMetadata.getId() == 21) {
metadata.getFlags().setFlag(EntityFlag.ANGRY, (int) entityMetadata.getValue() != 0);
metadata.put(EntityData.COLOR, (int) entityMetadata.getValue() != 0 ? (byte) 0 : collarColor);
}

View File

@ -85,7 +85,7 @@ public class VillagerEntity extends AbstractMerchantEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 17) {
if (entityMetadata.getId() == 18) {
VillagerData villagerData = (VillagerData) entityMetadata.getValue();
// Profession
metadata.put(EntityData.VARIANT, VILLAGER_VARIANTS.get(villagerData.getProfession()));

View File

@ -39,7 +39,7 @@ public class AbstractSkeletonEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 14) {
if (entityMetadata.getId() == 15) {
byte xd = (byte) entityMetadata.getValue();
// A bit of a loophole so the hands get raised - set the target ID to its own ID
metadata.put(EntityData.TARGET_EID, ((xd & 4) == 4) ? geyserId : 0);

View File

@ -40,7 +40,7 @@ public class BasePiglinEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
// Immune to zombification?
// Apply shaking effect if not in the nether and zombification is possible
metadata.getFlags().setFlag(EntityFlag.SHAKING, !((boolean) entityMetadata.getValue()) && !session.getDimension().equals(DimensionUtils.NETHER));

View File

@ -39,7 +39,7 @@ public class BlazeEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.ON_FIRE, (xd & 0x01) == 0x01);
}

View File

@ -45,15 +45,15 @@ public class CreeperEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
if (!ignitedByFlintAndSteel) {
metadata.getFlags().setFlag(EntityFlag.IGNITED, (int) entityMetadata.getValue() == 1);
}
}
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
metadata.getFlags().setFlag(EntityFlag.POWERED, (boolean) entityMetadata.getValue());
}
if (entityMetadata.getId() == 17) {
if (entityMetadata.getId() == 18) {
ignitedByFlintAndSteel = (boolean) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.IGNITED, ignitedByFlintAndSteel);
}

View File

@ -92,7 +92,7 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) { // Phase
if (entityMetadata.getId() == 16) { // Phase
phase = (int) entityMetadata.getValue();
phaseTicks = 0;
metadata.getFlags().setFlag(EntityFlag.SITTING, isSitting());
@ -100,7 +100,7 @@ public class EnderDragonEntity extends InsentientEntity implements Tickable {
super.updateBedrockMetadata(entityMetadata, session);
if (entityMetadata.getId() == 8) { // Health
if (entityMetadata.getId() == 9) { // Health
// Update the health attribute, so that the death animation gets played
// Round health up, so that Bedrock doesn't consider the dragon to be dead when health is between 0 and 1
float health = (float) Math.ceil(metadata.getFloat(EntityData.HEALTH));

View File

@ -43,11 +43,11 @@ public class EndermanEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
// Held block
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
metadata.put(EntityData.CARRIED_BLOCK, session.getBlockTranslator().getBedrockBlockId((int) entityMetadata.getValue()));
}
// "Is screaming" - controls sound
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
if ((boolean) entityMetadata.getValue()) {
LevelSoundEvent2Packet packet = new LevelSoundEvent2Packet();
packet.setSound(SoundEvent.STARE);
@ -58,7 +58,7 @@ public class EndermanEntity extends MonsterEntity {
}
}
// "Is staring/provoked" - controls visuals
if (entityMetadata.getId() == 17) {
if (entityMetadata.getId() == 18) {
metadata.getFlags().setFlag(EntityFlag.ANGRY, (boolean) entityMetadata.getValue());
}
super.updateBedrockMetadata(entityMetadata, session);

View File

@ -40,7 +40,7 @@ public class GhastEntity extends FlyingEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
// If the ghast is attacking
metadata.put(EntityData.CHARGE_AMOUNT, (byte) ((boolean) entityMetadata.getValue() ? 1 : 0));
}

View File

@ -40,7 +40,7 @@ public class GuardianEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
Entity entity = session.getEntityCache().getEntityByJavaId((int) entityMetadata.getValue());
if (entity == null && session.getPlayerEntity().getEntityId() == (Integer) entityMetadata.getValue()) {
entity = session.getPlayerEntity();

View File

@ -41,17 +41,17 @@ public class PiglinEntity extends BasePiglinEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
boolean isBaby = (boolean) entityMetadata.getValue();
if (isBaby) {
metadata.put(EntityData.SCALE, .55f);
metadata.getFlags().setFlag(EntityFlag.BABY, true);
}
}
if (entityMetadata.getId() == 17) {
if (entityMetadata.getId() == 18) {
metadata.getFlags().setFlag(EntityFlag.CHARGING, (boolean) entityMetadata.getValue());
}
if (entityMetadata.getId() == 18) {
if (entityMetadata.getId() == 19) {
metadata.getFlags().setFlag(EntityFlag.DANCING, (boolean) entityMetadata.getValue());
}

View File

@ -26,10 +26,8 @@
package org.geysermc.connector.entity.living.monster;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.connector.entity.living.GolemEntity;
@ -46,16 +44,17 @@ public class ShulkerEntity extends GolemEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
BlockFace blockFace = (BlockFace) entityMetadata.getValue();
metadata.put(EntityData.SHULKER_ATTACH_FACE, (byte) blockFace.ordinal());
}
if (entityMetadata.getId() == 16) {
Position position = (Position) entityMetadata.getValue();
if (position != null) {
metadata.put(EntityData.SHULKER_ATTACH_POS, Vector3i.from(position.getX(), position.getY(), position.getZ()));
}
}
//TODO - this was removed on Java Edition, but does Bedrock Edition still need it??
// if (entityMetadata.getId() == 16) {
// Position position = (Position) entityMetadata.getValue();
// if (position != null) {
// metadata.put(EntityData.SHULKER_ATTACH_POS, Vector3i.from(position.getX(), position.getY(), position.getZ()));
// }
// }
if (entityMetadata.getId() == 17) {
int height = (byte) entityMetadata.getValue();

View File

@ -39,7 +39,7 @@ public class SpiderEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.WALL_CLIMBING, (xd & 0x01) == 0x01);
}

View File

@ -39,7 +39,7 @@ public class VexEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
byte xd = (byte) entityMetadata.getValue();
// Set the target to the player to force the attack animation
// even if the player isn't the target as we dont get the target on Java

View File

@ -44,7 +44,7 @@ public class WitherEntity extends MonsterEntity {
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
long targetID = 0;
if (entityMetadata.getId() >= 15 && entityMetadata.getId() <= 17) {
if (entityMetadata.getId() >= 16 && entityMetadata.getId() <= 18) {
Entity entity = session.getEntityCache().getEntityByJavaId((int) entityMetadata.getValue());
if (entity == null && session.getPlayerEntity().getEntityId() == (int) entityMetadata.getValue()) {
entity = session.getPlayerEntity();
@ -55,13 +55,13 @@ public class WitherEntity extends MonsterEntity {
}
}
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
metadata.put(EntityData.WITHER_TARGET_1, targetID);
} else if (entityMetadata.getId() == 16) {
metadata.put(EntityData.WITHER_TARGET_2, targetID);
} else if (entityMetadata.getId() == 17) {
metadata.put(EntityData.WITHER_TARGET_3, targetID);
metadata.put(EntityData.WITHER_TARGET_2, targetID);
} else if (entityMetadata.getId() == 18) {
metadata.put(EntityData.WITHER_TARGET_3, targetID);
} else if (entityMetadata.getId() == 19) {
metadata.put(EntityData.WITHER_INVULNERABLE_TICKS, entityMetadata.getValue());
// Show the shield for the first few seconds of spawning (like Java)

View File

@ -40,7 +40,7 @@ public class ZoglinEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
boolean isBaby = (boolean) entityMetadata.getValue();
if (isBaby) {
metadata.put(EntityData.SCALE, .55f);

View File

@ -40,7 +40,7 @@ public class ZombieEntity extends MonsterEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 15) {
if (entityMetadata.getId() == 16) {
boolean isBaby = (boolean) entityMetadata.getValue();
if (isBaby) {
metadata.put(EntityData.SCALE, .55f);

View File

@ -42,11 +42,11 @@ public class ZombieVillagerEntity extends ZombieEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 18) {
if (entityMetadata.getId() == 19) {
metadata.getFlags().setFlag(EntityFlag.IS_TRANSFORMING, (boolean) entityMetadata.getValue());
metadata.getFlags().setFlag(EntityFlag.SHAKING, (boolean) entityMetadata.getValue());
}
if (entityMetadata.getId() == 19) {
if (entityMetadata.getId() == 20) {
VillagerData villagerData = (VillagerData) entityMetadata.getValue();
// Region - only one used on Bedrock
metadata.put(EntityData.MARK_VARIANT, VillagerEntity.VILLAGER_REGIONS.get(villagerData.getType()));

View File

@ -45,7 +45,7 @@ public class SpellcasterIllagerEntity extends AbstractIllagerEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
int spellType = (int) (byte) entityMetadata.getValue();
// Summon vex, attack, or wololo
metadata.getFlags().setFlag(EntityFlag.CASTING, spellType == 1 || spellType == 2 || spellType == 3);

View File

@ -40,7 +40,7 @@ public class VindicatorEntity extends AbstractIllagerEntity {
@Override
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
// Allow the axe to be shown if necessary
if (entityMetadata.getId() == 14) {
if (entityMetadata.getId() == 15) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.ANGRY, (xd & 4) == 4);
}

View File

@ -273,7 +273,7 @@ public class PlayerEntity extends LivingEntity {
}
// Extra hearts - is not metadata but an attribute on Bedrock
if (entityMetadata.getId() == 14) {
if (entityMetadata.getId() == 15) {
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
attributesPacket.setRuntimeEntityId(geyserId);
List<AttributeData> attributes = new ArrayList<>();
@ -283,7 +283,7 @@ public class PlayerEntity extends LivingEntity {
session.sendUpstreamPacket(attributesPacket);
}
if (entityMetadata.getId() == 16) {
if (entityMetadata.getId() == 17) {
// OptionalPack usage for toggling skin bits
// In Java Edition, a bit being set means that part should be enabled
// However, to ensure that the pack still works on other servers, we invert the bit so all values by default
@ -292,10 +292,10 @@ public class PlayerEntity extends LivingEntity {
}
// Parrot occupying shoulder
if (entityMetadata.getId() == 18 || entityMetadata.getId() == 19) {
if (entityMetadata.getId() == 19 || entityMetadata.getId() == 20) {
CompoundTag tag = (CompoundTag) entityMetadata.getValue();
if (tag != null && !tag.isEmpty()) {
if ((entityMetadata.getId() == 18 && leftParrot != null) || (entityMetadata.getId() == 19 && rightParrot != null)) {
if ((entityMetadata.getId() == 19 && leftParrot != null) || (entityMetadata.getId() == 20 && rightParrot != null)) {
// No need to update a parrot's data when it already exists
return;
}
@ -321,10 +321,10 @@ public class PlayerEntity extends LivingEntity {
rightParrot = parrot;
}
} else {
Entity parrot = (entityMetadata.getId() == 18 ? leftParrot : rightParrot);
Entity parrot = (entityMetadata.getId() == 19 ? leftParrot : rightParrot);
if (parrot != null) {
parrot.despawnEntity(session);
if (entityMetadata.getId() == 18) {
if (entityMetadata.getId() == 19) {
leftParrot = null;
} else {
rightParrot = null;

View File

@ -29,17 +29,18 @@ import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
import com.github.steveice10.mc.protocol.data.game.chunk.Column;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import lombok.Setter;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.utils.MathUtils;
public class ChunkCache {
private static final int MINIMUM_WORLD_HEIGHT = 0;
private final boolean cache;
private final Long2ObjectMap<Column> chunks;
@Setter
private int minY;
public ChunkCache(GeyserSession session) {
if (session.getConnector().getWorldManager().hasOwnChunkCache()) {
this.cache = false; // To prevent Spigot from initializing
@ -87,7 +88,7 @@ public class ChunkCache {
return;
}
if (y < MINIMUM_WORLD_HEIGHT || (y >> 4) > column.getChunks().length - 1) {
if (y < minY || (y >> 4) > column.getChunks().length - 1) {
// Y likely goes above or below the height limit of this world
return;
}
@ -108,7 +109,7 @@ public class ChunkCache {
return BlockTranslator.JAVA_AIR_ID;
}
if (y < MINIMUM_WORLD_HEIGHT || (y >> 4) > column.getChunks().length - 1) {
if (y < minY || (y >> 4) > column.getChunks().length - 1) {
// Y likely goes above or below the height limit of this world
return BlockTranslator.JAVA_AIR_ID;
}

View File

@ -39,24 +39,51 @@ import java.util.Map;
*/
public class TagCache {
/* Blocks */
private IntList wool = IntLists.emptyList();
private IntList leaves;
private IntList wool;
private IntList axeEffective;
private IntList hoeEffective;
private IntList pickaxeEffective;
private IntList shovelEffective;
/* Items */
private IntList flowers = IntLists.emptyList();
private IntList piglinLoved = IntLists.emptyList();
private IntList flowers;
private IntList foxFood;
private IntList piglinLoved;
public TagCache() {
// Ensure all lists are non-null
clear();
}
public void loadPacket(ServerDeclareTagsPacket packet) {
Map<String, int[]> blockTags = packet.getBlockTags();
Map<String, int[]> blockTags = packet.getTags().get("minecraft:block");
this.leaves = IntList.of(blockTags.get("minecraft:leaves"));
this.wool = IntList.of(blockTags.get("minecraft:wool"));
Map<String, int[]> itemTags = packet.getItemTags();
this.axeEffective = IntList.of(blockTags.get("minecraft:mineable/axe"));
this.hoeEffective = IntList.of(blockTags.get("minecraft:mineable/hoe"));
this.pickaxeEffective = IntList.of(blockTags.get("minecraft:mineable/pickaxe"));
this.shovelEffective = IntList.of(blockTags.get("minecraft:mineable/shovel"));
Map<String, int[]> itemTags = packet.getTags().get("minecraft:item");
this.flowers = IntList.of(itemTags.get("minecraft:flowers"));
this.foxFood = IntList.of(itemTags.get("minecraft:fox_food"));
this.piglinLoved = IntList.of(itemTags.get("minecraft:piglin_loved"));
}
public void clear() {
this.leaves = IntLists.emptyList();
this.wool = IntLists.emptyList();
this.axeEffective = IntLists.emptyList();
this.hoeEffective = IntLists.emptyList();
this.pickaxeEffective = IntLists.emptyList();
this.shovelEffective = IntLists.emptyList();
this.flowers = IntLists.emptyList();
this.foxFood = IntLists.emptyList();
this.piglinLoved = IntLists.emptyList();
}
@ -64,11 +91,32 @@ public class TagCache {
return flowers.contains(itemEntry.getJavaId());
}
public boolean isFoxFood(ItemEntry itemEntry) {
return foxFood.contains(itemEntry.getJavaId());
}
public boolean shouldPiglinAdmire(ItemEntry itemEntry) {
return piglinLoved.contains(itemEntry.getJavaId());
}
public boolean isWool(BlockMapping blockMapping) {
return wool.contains(blockMapping.getJavaBlockId());
public boolean isAxeEffective(BlockMapping blockMapping) {
return axeEffective.contains(blockMapping.getJavaBlockId());
}
public boolean isHoeEffective(BlockMapping blockMapping) {
return hoeEffective.contains(blockMapping.getJavaBlockId());
}
public boolean isPickaxeEffective(BlockMapping blockMapping) {
return pickaxeEffective.contains(blockMapping.getJavaBlockId());
}
public boolean isShovelEffective(BlockMapping blockMapping) {
return shovelEffective.contains(blockMapping.getJavaBlockId());
}
public boolean isShearsEffective(BlockMapping blockMapping) {
int javaBlockId = blockMapping.getJavaBlockId();
return leaves.contains(javaBlockId) || wool.contains(javaBlockId);
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.connector.network.translators.java;
import com.github.steveice10.mc.protocol.packet.ingame.client.ClientPongPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPingPacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
// Why does this packet exist? Whatever, we better implement it
@Translator(packet = ServerPingPacket.class)
public class JavaPingPacket extends PacketTranslator<ServerPingPacket> {
@Override
public void translate(ServerPingPacket packet, GeyserSession session) {
session.sendDownstreamPacket(new ClientPongPacket(packet.getId()));
}
}

View File

@ -25,8 +25,6 @@
package org.geysermc.connector.network.translators.world;
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
import com.github.steveice10.mc.protocol.data.game.chunk.Column;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
import com.github.steveice10.mc.protocol.packet.ingame.client.ClientChatPacket;
@ -53,45 +51,12 @@ public class GeyserWorldManager extends WorldManager {
return BlockTranslator.JAVA_AIR_ID;
}
@Override
public void getBlocksInSection(GeyserSession session, int x, int y, int z, Chunk chunk) {
ChunkCache chunkCache = session.getChunkCache();
Column cachedColumn;
Chunk cachedChunk;
if (chunkCache == null || (cachedColumn = chunkCache.getChunk(x, z)) == null || (cachedChunk = cachedColumn.getChunks()[y]) == null) {
return;
}
// Copy state IDs from cached chunk to output chunk
for (int blockY = 0; blockY < 16; blockY++) { // Cache-friendly iteration order
for (int blockZ = 0; blockZ < 16; blockZ++) {
for (int blockX = 0; blockX < 16; blockX++) {
chunk.set(blockX, blockY, blockZ, cachedChunk.get(blockX, blockY, blockZ));
}
}
}
}
@Override
public boolean hasOwnChunkCache() {
// This implementation can only fetch data from the session chunk cache
return false;
}
@Override
public int[] getBiomeDataAt(GeyserSession session, int x, int z) {
if (session.getConnector().getConfig().isCacheChunks()) {
ChunkCache chunkCache = session.getChunkCache();
if (chunkCache != null) { // Chunk cache can be null if the session is closed asynchronously
Column column = chunkCache.getChunk(x, z);
if (column != null) { // Column can be null if the server sent a partial chunk update before the first ground-up-continuous one
return column.getBiomeData();
}
}
}
return new int[1024];
}
@Override
public NbtMap getLecternDataAt(GeyserSession session, int x, int y, int z, boolean isChunkLoad) {
// Without direct server access, we can't get lectern information on-the-fly.

View File

@ -25,7 +25,6 @@
package org.geysermc.connector.network.translators.world;
import com.github.steveice10.mc.protocol.data.game.chunk.Chunk;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
@ -76,17 +75,6 @@ public abstract class WorldManager {
*/
public abstract int getBlockAt(GeyserSession session, int x, int y, int z);
/**
* Gets all block states in the specified chunk section.
*
* @param session the session
* @param x the chunk's X coordinate
* @param y the chunk's Y coordinate
* @param z the chunk's Z coordinate
* @param section the chunk section to store the block data in
*/
public abstract void getBlocksInSection(GeyserSession session, int x, int y, int z, Chunk section);
/**
* Checks whether or not this world manager requires a separate chunk cache/has access to more block data than the chunk cache.
* <p>
@ -97,16 +85,6 @@ public abstract class WorldManager {
*/
public abstract boolean hasOwnChunkCache();
/**
* Gets the Java biome data for the specified chunk.
*
* @param session the session of the player
* @param x the chunk's X coordinate
* @param z the chunk's Z coordinate
* @return the biome data for the specified region with a length of 1024.
*/
public abstract int[] getBiomeDataAt(GeyserSession session, int x, int z);
/**
* Sigh. <br>
*

View File

@ -143,12 +143,7 @@ public abstract class BlockTranslator {
builder.canBreakWithHand(false);
}
JsonNode toolTypeNode = entry.getValue().get("tool_type");
if (toolTypeNode != null) {
builder.toolType(toolTypeNode.textValue());
} else {
builder.toolType("");
}
builder.toolType(""); //TODO
JsonNode collisionIndexNode = entry.getValue().get("collision_index");
if (hardnessNode != null) {
@ -225,7 +220,7 @@ public abstract class BlockTranslator {
throw new AssertionError("Unable to find Java water in palette");
}
JAVA_WATER_ID = waterRuntimeId;
BlockMapping.AIR = JAVA_RUNTIME_ID_TO_BLOCK_MAPPING.get(JAVA_AIR_ID);
BlockTranslator1_16_210.init();

View File

@ -41,16 +41,28 @@ public class BlockUtils {
*/
public static final Position POSITION_ZERO = new Position(0, 0, 0);
private static boolean correctTool(String blockToolType, String itemToolType) {
return (blockToolType.equals("sword") && itemToolType.equals("sword")) ||
(blockToolType.equals("shovel") && itemToolType.equals("shovel")) ||
(blockToolType.equals("pickaxe") && itemToolType.equals("pickaxe")) ||
(blockToolType.equals("axe") && itemToolType.equals("axe")) ||
(blockToolType.equals("shears") && itemToolType.equals("shears"));
private static boolean correctTool(GeyserSession session, BlockMapping blockMapping, String itemToolType) {
switch (itemToolType) {
case "axe":
return session.getTagCache().isAxeEffective(blockMapping);
case "hoe":
return session.getTagCache().isHoeEffective(blockMapping);
case "pickaxe":
return session.getTagCache().isPickaxeEffective(blockMapping);
case "shears":
return session.getTagCache().isShearsEffective(blockMapping);
case "shovel":
return session.getTagCache().isShovelEffective(blockMapping);
case "sword":
return blockMapping.getJavaBlockId() == BlockTranslator.JAVA_COBWEB_BLOCK_ID;
default:
session.getConnector().getLogger().warning("Unknown tool type: " + itemToolType);
return false;
}
}
private static double toolBreakTimeBonus(String toolType, String toolTier, boolean isWoolBlock) {
if (toolType.equals("shears")) return isWoolBlock ? 5.0 : 15.0;
private static double toolBreakTimeBonus(String toolType, String toolTier, boolean isShearsEffective) {
if (toolType.equals("shears")) return isShearsEffective ? 5.0 : 15.0;
if (toolType.equals("")) return 1.0;
switch (toolTier) {
// https://minecraft.gamepedia.com/Breaking#Speed
@ -73,16 +85,14 @@ public class BlockUtils {
//http://minecraft.gamepedia.com/Breaking
private static double calculateBreakTime(double blockHardness, String toolTier, boolean canHarvestWithHand, boolean correctTool,
String toolType, boolean isWoolBlock, boolean isCobweb, int toolEfficiencyLevel, int hasteLevel, int miningFatigueLevel,
String toolType, boolean isShearsEffective, int toolEfficiencyLevel, int hasteLevel, int miningFatigueLevel,
boolean insideOfWaterWithoutAquaAffinity, boolean outOfWaterButNotOnGround, boolean insideWaterAndNotOnGround) {
double baseTime = ((correctTool || canHarvestWithHand) ? 1.5 : 5.0) * blockHardness;
double speed = 1.0 / baseTime;
if (correctTool) {
speed *= toolBreakTimeBonus(toolType, toolTier, isWoolBlock);
speed *= toolBreakTimeBonus(toolType, toolTier, isShearsEffective);
speed += toolEfficiencyLevel == 0 ? 0 : toolEfficiencyLevel * toolEfficiencyLevel + 1;
} else if (toolType.equals("sword")) {
speed*= (isCobweb ? 15.0 : 1.5);
}
speed *= 1.0 + (0.2 * hasteLevel);
@ -110,9 +120,7 @@ public class BlockUtils {
}
public static double getBreakTime(GeyserSession session, BlockMapping blockMapping, ItemEntry item, CompoundTag nbtData, boolean isSessionPlayer) {
boolean isWoolBlock = session.getTagCache().isWool(blockMapping);
boolean isCobweb = blockMapping.getJavaBlockId() == BlockTranslator.JAVA_COBWEB_BLOCK_ID;
String blockToolType = blockMapping.getToolType();
boolean isShearsEffective = session.getTagCache().isShearsEffective(blockMapping); //TODO called twice
boolean canHarvestWithHand = blockMapping.isCanBreakWithHand();
String toolType = "";
String toolTier = "";
@ -121,7 +129,7 @@ public class BlockUtils {
ToolItemEntry toolItem = (ToolItemEntry) item;
toolType = toolItem.getToolType();
toolTier = toolItem.getToolTier();
correctTool = correctTool(blockToolType, toolType);
correctTool = correctTool(session, blockMapping, toolType);
}
int toolEfficiencyLevel = ItemUtils.getEnchantmentLevel(nbtData, "minecraft:efficiency");
int hasteLevel = 0;
@ -129,8 +137,8 @@ public class BlockUtils {
if (!isSessionPlayer) {
// Another entity is currently mining; we have all the information we know
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock,
isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false,
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolType, isShearsEffective,
toolEfficiencyLevel, hasteLevel, miningFatigueLevel, false,
false, false);
}
@ -144,8 +152,8 @@ public class BlockUtils {
boolean outOfWaterButNotOnGround = (!isInWater) && (!session.getPlayerEntity().isOnGround());
boolean insideWaterNotOnGround = isInWater && !session.getPlayerEntity().isOnGround();
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolType, isWoolBlock,
isCobweb, toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity,
return calculateBreakTime(blockMapping.getHardness(), toolTier, canHarvestWithHand, correctTool, toolType, isShearsEffective,
toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity,
outOfWaterButNotOnGround, insideWaterNotOnGround);
}

View File

@ -82,7 +82,17 @@ public class ChunkUtils {
public static ChunkData translateToBedrock(GeyserSession session, Column column) {
Chunk[] javaSections = column.getChunks();
ChunkSection[] sections = new ChunkSection[javaSections.length];
//FIXME TEMPORARY UNTIL THE CAVES AND CLIFFS EXPERIMENTAL DATA IS REMOVED UNLESS IT'S NOT REMOVED THEN HMMMM
int sectionYOffset;
if (session.getDimension().equals(DimensionUtils.OVERWORLD)) {
sectionYOffset = 4;
} else {
sectionYOffset = 0;
}
//FIXME END
ChunkSection[] sections = new ChunkSection[javaSections.length + sectionYOffset];
// Temporarily stores compound tags of Bedrock-only block entities
List<NbtMap> bedrockOnlyBlockEntities = new ArrayList<>();
@ -195,7 +205,7 @@ public class ChunkUtils {
layers = new BlockStorage[]{ layer0, new BlockStorage(BitArrayVersion.V1.createArray(BlockStorage.SIZE, layer1Data), layer1Palette) };
}
sections[sectionY] = new ChunkSection(layers);
sections[sectionY + sectionYOffset] = new ChunkSection(layers);
}
CompoundTag[] blockEntities = column.getTileEntities();