mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Merge remote-tracking branch 'upstream/master' into JE-1.19.3
This commit is contained in:
commit
92aa2059d2
31 changed files with 1174 additions and 10937 deletions
|
@ -17,7 +17,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 1.19.0 - 1.19.40 and Minecraft Java 1.19.1/1.19.2.
|
||||
### Currently supporting Minecraft Bedrock 1.19.20 - 1.19.50 and Minecraft Java 1.19.1/1.19.2.
|
||||
|
||||
## Setting Up
|
||||
Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser.
|
||||
|
|
|
@ -16,7 +16,7 @@ dependencies {
|
|||
|
||||
// Within the gradle plugin classpath, there is a version conflict between loom and some other
|
||||
// plugin for databind. This fixes it: minimum 2.13.2 is required by loom.
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.13.3")
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.14.0")
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
|
|
|
@ -111,6 +111,8 @@ public interface GeyserConfiguration {
|
|||
|
||||
boolean isNotifyOnNewBedrockUpdate();
|
||||
|
||||
String getUnusableSpaceBlock();
|
||||
|
||||
IMetricsInfo getMetrics();
|
||||
|
||||
int getPendingAuthenticationTimeout();
|
||||
|
|
|
@ -154,6 +154,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
|
|||
@JsonProperty("notify-on-new-bedrock-update")
|
||||
private boolean notifyOnNewBedrockUpdate = true;
|
||||
|
||||
@JsonProperty("unusable-space-block")
|
||||
private String unusableSpaceBlock = "minecraft:barrier";
|
||||
|
||||
private MetricsInfo metrics = new MetricsInfo();
|
||||
|
||||
@JsonProperty("pending-authentication-timeout")
|
||||
|
|
|
@ -44,6 +44,8 @@ import lombok.Setter;
|
|||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.GeyserDirtyMetadata;
|
||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
|
@ -355,6 +357,7 @@ public class Entity {
|
|||
setFlag(EntityFlag.ON_FIRE, ((xd & 0x01) == 0x01) && !getFlag(EntityFlag.FIRE_IMMUNE)); // Otherwise immune entities sometimes flicker onfire
|
||||
setFlag(EntityFlag.SNEAKING, (xd & 0x02) == 0x02);
|
||||
setFlag(EntityFlag.SPRINTING, (xd & 0x08) == 0x08);
|
||||
|
||||
// Swimming is ignored here and instead we rely on the pose
|
||||
setFlag(EntityFlag.GLIDING, (xd & 0x80) == 0x80);
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class AnvilContainer extends Container {
|
|||
String originalName = ItemUtils.getCustomName(getInput().getNbt());
|
||||
|
||||
String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.locale());
|
||||
String plainNewName = MessageTranslator.convertToPlainText(rename, session.locale());
|
||||
String plainNewName = MessageTranslator.convertToPlainText(rename);
|
||||
if (!plainOriginalName.equals(plainNewName)) {
|
||||
// Strip out formatting since Java Edition does not allow it
|
||||
correctRename = plainNewName;
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
package org.geysermc.geyser.inventory.holder;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
|
@ -35,11 +34,11 @@ import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
|||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
@ -50,8 +49,6 @@ import java.util.Set;
|
|||
* This class will attempt to use a real block first, if possible.
|
||||
*/
|
||||
public class BlockInventoryHolder extends InventoryHolder {
|
||||
private static final int FAKE_BLOCK_DISTANCE = 1;
|
||||
|
||||
/**
|
||||
* The default Java block ID to translate as a fake block
|
||||
*/
|
||||
|
@ -66,7 +63,7 @@ public class BlockInventoryHolder extends InventoryHolder {
|
|||
Set<String> validBlocksTemp = new HashSet<>(validBlocks.length + 1);
|
||||
Collections.addAll(validBlocksTemp, validBlocks);
|
||||
validBlocksTemp.add(BlockUtils.getCleanIdentifier(javaBlockIdentifier));
|
||||
this.validBlocks = ImmutableSet.copyOf(validBlocksTemp);
|
||||
this.validBlocks = Set.copyOf(validBlocksTemp);
|
||||
} else {
|
||||
this.validBlocks = Collections.singleton(BlockUtils.getCleanIdentifier(javaBlockIdentifier));
|
||||
}
|
||||
|
@ -91,20 +88,10 @@ public class BlockInventoryHolder extends InventoryHolder {
|
|||
}
|
||||
}
|
||||
|
||||
// Check if a fake block can be placed, either above the player or beneath.
|
||||
BedrockDimension dimension = session.getChunkCache().getBedrockDimension();
|
||||
int minY = dimension.minY(), maxY = minY + dimension.height();
|
||||
Vector3i flatPlayerPosition = session.getPlayerEntity().getPosition().toInt();
|
||||
Vector3i position = flatPlayerPosition.add(Vector3i.UP);
|
||||
if (position.getY() < minY) {
|
||||
Vector3i position = InventoryUtils.findAvailableWorldSpace(session);
|
||||
if (position == null) {
|
||||
return false;
|
||||
}
|
||||
if (position.getY() >= maxY) {
|
||||
position = flatPlayerPosition.sub(0, 4, 0);
|
||||
if (position.getY() >= maxY) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||
blockPacket.setDataLayer(0);
|
||||
|
|
|
@ -28,12 +28,11 @@ package org.geysermc.geyser.network;
|
|||
import com.github.steveice10.mc.protocol.codec.MinecraftCodec;
|
||||
import com.github.steveice10.mc.protocol.codec.PacketCodec;
|
||||
import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
|
||||
import com.nukkitx.protocol.bedrock.v527.Bedrock_v527;
|
||||
import com.nukkitx.protocol.bedrock.v534.Bedrock_v534;
|
||||
import com.nukkitx.protocol.bedrock.v544.Bedrock_v544;
|
||||
import com.nukkitx.protocol.bedrock.v545.Bedrock_v545;
|
||||
import com.nukkitx.protocol.bedrock.v554.Bedrock_v554;
|
||||
import com.nukkitx.protocol.bedrock.v557.Bedrock_v557;
|
||||
import com.nukkitx.protocol.bedrock.v560.Bedrock_v560;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -48,7 +47,7 @@ public final class GameProtocol {
|
|||
* Default Bedrock codec that should act as a fallback. Should represent the latest available
|
||||
* release of the game that Geyser supports.
|
||||
*/
|
||||
public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v557.V557_CODEC;
|
||||
public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v560.V560_CODEC;
|
||||
/**
|
||||
* A list of all supported Bedrock versions that can join Geyser
|
||||
*/
|
||||
|
@ -61,12 +60,6 @@ public final class GameProtocol {
|
|||
private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC;
|
||||
|
||||
static {
|
||||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v527.V527_CODEC.toBuilder()
|
||||
.minecraftVersion("1.19.0/1.19.2")
|
||||
.build());
|
||||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v534.V534_CODEC.toBuilder()
|
||||
.minecraftVersion("1.19.10/1.19.11")
|
||||
.build());
|
||||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v544.V544_CODEC);
|
||||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v545.V545_CODEC.toBuilder()
|
||||
.minecraftVersion("1.19.21/1.19.22")
|
||||
|
@ -74,6 +67,7 @@ public final class GameProtocol {
|
|||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v554.V554_CODEC.toBuilder()
|
||||
.minecraftVersion("1.19.30/1.19.31")
|
||||
.build());
|
||||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v557.V557_CODEC);
|
||||
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
|
||||
}
|
||||
|
||||
|
@ -93,14 +87,14 @@ public final class GameProtocol {
|
|||
|
||||
/* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */
|
||||
|
||||
public static boolean supports1_19_10(GeyserSession session) {
|
||||
return session.getUpstream().getProtocolVersion() >= Bedrock_v534.V534_CODEC.getProtocolVersion();
|
||||
}
|
||||
|
||||
public static boolean supports1_19_30(GeyserSession session) {
|
||||
return session.getUpstream().getProtocolVersion() >= Bedrock_v554.V554_CODEC.getProtocolVersion();
|
||||
}
|
||||
|
||||
public static boolean supports1_19_50(GeyserSession session) {
|
||||
return session.getUpstream().getProtocolVersion() >= Bedrock_v560.V560_CODEC.getProtocolVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link PacketCodec} for Minecraft: Java Edition.
|
||||
*
|
||||
|
|
|
@ -46,9 +46,13 @@ import org.geysermc.geyser.util.MathUtils;
|
|||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
public class UpstreamPacketHandler extends LoggingPacketHandler {
|
||||
|
||||
private Deque<String> packsToSent = new ArrayDeque<>();
|
||||
|
||||
public UpstreamPacketHandler(GeyserImpl geyser, GeyserSession session) {
|
||||
super(geyser, session);
|
||||
}
|
||||
|
@ -161,24 +165,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||
break;
|
||||
|
||||
case SEND_PACKS:
|
||||
for(String id : packet.getPackIds()) {
|
||||
ResourcePackDataInfoPacket data = new ResourcePackDataInfoPacket();
|
||||
String[] packID = id.split("_");
|
||||
ResourcePack pack = ResourcePack.PACKS.get(packID[0]);
|
||||
ResourcePackManifest.Header header = pack.getManifest().getHeader();
|
||||
|
||||
data.setPackId(header.getUuid());
|
||||
int chunkCount = (int) Math.ceil((int) pack.getFile().length() / (double) ResourcePack.CHUNK_SIZE);
|
||||
data.setChunkCount(chunkCount);
|
||||
data.setCompressedPackSize(pack.getFile().length());
|
||||
data.setMaxChunkSize(ResourcePack.CHUNK_SIZE);
|
||||
data.setHash(pack.getSha256());
|
||||
data.setPackVersion(packID[1]);
|
||||
data.setPremium(false);
|
||||
data.setType(ResourcePackType.RESOURCE);
|
||||
|
||||
session.sendUpstreamPacket(data);
|
||||
}
|
||||
packsToSent.addAll(packet.getPackIds());
|
||||
sendPackDataInfo(packsToSent.pop());
|
||||
break;
|
||||
|
||||
case HAVE_ALL_PACKS:
|
||||
|
@ -271,7 +259,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||
data.setPackId(packet.getPackId());
|
||||
|
||||
int offset = packet.getChunkIndex() * ResourcePack.CHUNK_SIZE;
|
||||
byte[] packData = new byte[(int) MathUtils.constrain(pack.getFile().length() - offset, 0, ResourcePack.CHUNK_SIZE)];
|
||||
long remainingSize = pack.getFile().length() - offset;
|
||||
byte[] packData = new byte[(int) MathUtils.constrain(remainingSize, 0, ResourcePack.CHUNK_SIZE)];
|
||||
|
||||
try (InputStream inputStream = new FileInputStream(pack.getFile())) {
|
||||
inputStream.skip(offset);
|
||||
|
@ -283,6 +272,31 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||
data.setData(packData);
|
||||
|
||||
session.sendUpstreamPacket(data);
|
||||
|
||||
// Check if it is the last chunk and send next pack in queue when available.
|
||||
if (remainingSize <= ResourcePack.CHUNK_SIZE && !packsToSent.isEmpty()) {
|
||||
sendPackDataInfo(packsToSent.pop());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sendPackDataInfo(String id) {
|
||||
ResourcePackDataInfoPacket data = new ResourcePackDataInfoPacket();
|
||||
String[] packID = id.split("_");
|
||||
ResourcePack pack = ResourcePack.PACKS.get(packID[0]);
|
||||
ResourcePackManifest.Header header = pack.getManifest().getHeader();
|
||||
|
||||
data.setPackId(header.getUuid());
|
||||
int chunkCount = (int) Math.ceil((int) pack.getFile().length() / (double) ResourcePack.CHUNK_SIZE);
|
||||
data.setChunkCount(chunkCount);
|
||||
data.setCompressedPackSize(pack.getFile().length());
|
||||
data.setMaxChunkSize(ResourcePack.CHUNK_SIZE);
|
||||
data.setHash(pack.getSha256());
|
||||
data.setPackVersion(packID[1]);
|
||||
data.setPremium(false);
|
||||
data.setType(ResourcePackType.RESOURCE);
|
||||
|
||||
session.sendUpstreamPacket(data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import com.google.common.collect.ImmutableMap;
|
|||
import com.nukkitx.nbt.*;
|
||||
import com.nukkitx.protocol.bedrock.v527.Bedrock_v527;
|
||||
import com.nukkitx.protocol.bedrock.v544.Bedrock_v544;
|
||||
import com.nukkitx.protocol.bedrock.v560.Bedrock_v560;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
|
@ -73,13 +74,9 @@ public final class BlockRegistryPopulator {
|
|||
private static void registerBedrockBlocks() {
|
||||
BiFunction<String, NbtMapBuilder, String> emptyMapper = (bedrockIdentifier, statesBuilder) -> null;
|
||||
ImmutableMap<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> blockMappers = ImmutableMap.<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>>builder()
|
||||
.put(ObjectIntPair.of("1_19_0", Bedrock_v527.V527_CODEC.getProtocolVersion()), (bedrockIdentifier, statesBuilder) -> {
|
||||
if (bedrockIdentifier.equals("minecraft:muddy_mangrove_roots")) {
|
||||
statesBuilder.remove("pillar_axis");
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.put(ObjectIntPair.of("1_19_20", Bedrock_v544.V544_CODEC.getProtocolVersion()), emptyMapper).build();
|
||||
.put(ObjectIntPair.of("1_19_20", Bedrock_v544.V544_CODEC.getProtocolVersion()), emptyMapper)
|
||||
.put(ObjectIntPair.of("1_19_50", Bedrock_v560.V560_CODEC.getProtocolVersion()), emptyMapper)
|
||||
.build();
|
||||
|
||||
for (Map.Entry<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> palette : blockMappers.entrySet()) {
|
||||
NbtList<NbtMap> blocksTag;
|
||||
|
|
|
@ -37,6 +37,7 @@ import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
|||
import com.nukkitx.protocol.bedrock.data.inventory.ComponentItemData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
||||
import com.nukkitx.protocol.bedrock.v560.Bedrock_v560;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import com.nukkitx.protocol.bedrock.v527.Bedrock_v527;
|
||||
import com.nukkitx.protocol.bedrock.v534.Bedrock_v534;
|
||||
|
@ -76,10 +77,8 @@ public class ItemRegistryPopulator {
|
|||
|
||||
public static void populate() {
|
||||
Map<String, PaletteVersion> paletteVersions = new Object2ObjectOpenHashMap<>();
|
||||
paletteVersions.put("1_19_0", new PaletteVersion(Bedrock_v527.V527_CODEC.getProtocolVersion(),
|
||||
Collections.singletonMap("minecraft:trader_llama_spawn_egg", "minecraft:llama_spawn_egg")));
|
||||
paletteVersions.put("1_19_10", new PaletteVersion(Bedrock_v534.V534_CODEC.getProtocolVersion(), Collections.emptyMap()));
|
||||
paletteVersions.put("1_19_20", new PaletteVersion(Bedrock_v544.V544_CODEC.getProtocolVersion(), Collections.emptyMap()));
|
||||
paletteVersions.put("1_19_50", new PaletteVersion(Bedrock_v560.V560_CODEC.getProtocolVersion(), Collections.emptyMap()));
|
||||
|
||||
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
|
||||
|
||||
|
|
|
@ -58,19 +58,55 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.Server
|
|||
import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryPacket;
|
||||
import com.github.steveice10.packetlib.BuiltinFlags;
|
||||
import com.github.steveice10.packetlib.Session;
|
||||
import com.github.steveice10.packetlib.event.session.*;
|
||||
import com.github.steveice10.packetlib.event.session.ConnectedEvent;
|
||||
import com.github.steveice10.packetlib.event.session.DisconnectedEvent;
|
||||
import com.github.steveice10.packetlib.event.session.PacketErrorEvent;
|
||||
import com.github.steveice10.packetlib.event.session.PacketSendingEvent;
|
||||
import com.github.steveice10.packetlib.event.session.SessionAdapter;
|
||||
import com.github.steveice10.packetlib.packet.Packet;
|
||||
import com.github.steveice10.packetlib.tcp.TcpClientSession;
|
||||
import com.github.steveice10.packetlib.tcp.TcpSession;
|
||||
import com.nukkitx.math.GenericMath;
|
||||
import com.nukkitx.math.vector.*;
|
||||
import com.nukkitx.math.vector.Vector2f;
|
||||
import com.nukkitx.math.vector.Vector2i;
|
||||
import com.nukkitx.math.vector.Vector3d;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.protocol.bedrock.BedrockPacket;
|
||||
import com.nukkitx.protocol.bedrock.BedrockServerSession;
|
||||
import com.nukkitx.protocol.bedrock.data.*;
|
||||
import com.nukkitx.protocol.bedrock.data.Ability;
|
||||
import com.nukkitx.protocol.bedrock.data.AbilityLayer;
|
||||
import com.nukkitx.protocol.bedrock.data.AttributeData;
|
||||
import com.nukkitx.protocol.bedrock.data.AuthoritativeMovementMode;
|
||||
import com.nukkitx.protocol.bedrock.data.ChatRestrictionLevel;
|
||||
import com.nukkitx.protocol.bedrock.data.GamePublishSetting;
|
||||
import com.nukkitx.protocol.bedrock.data.GameRuleData;
|
||||
import com.nukkitx.protocol.bedrock.data.GameType;
|
||||
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.data.SyncedPlayerMovementSettings;
|
||||
import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.*;
|
||||
import com.nukkitx.protocol.bedrock.packet.AvailableEntityIdentifiersPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.BiomeDefinitionListPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.ClientboundMapItemDataPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.CreativeContentPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.EmoteListPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.GameRulesChangedPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.ItemComponentPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.LevelSoundEvent2Packet;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlayerFogPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetTimePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.TextPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.TransferPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.UpdateAbilitiesPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.UpdateAdventureSettingsPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.EventLoop;
|
||||
import it.unimi.dsi.fastutil.bytes.ByteArrays;
|
||||
|
@ -127,7 +163,20 @@ import org.geysermc.geyser.registry.type.ItemMapping;
|
|||
import org.geysermc.geyser.registry.type.ItemMappings;
|
||||
import org.geysermc.geyser.session.auth.AuthData;
|
||||
import org.geysermc.geyser.session.auth.BedrockClientData;
|
||||
import org.geysermc.geyser.session.cache.*;
|
||||
import org.geysermc.geyser.session.cache.AdvancementsCache;
|
||||
import org.geysermc.geyser.session.cache.BookEditCache;
|
||||
import org.geysermc.geyser.session.cache.ChunkCache;
|
||||
import org.geysermc.geyser.session.cache.EntityCache;
|
||||
import org.geysermc.geyser.session.cache.EntityEffectCache;
|
||||
import org.geysermc.geyser.session.cache.FormCache;
|
||||
import org.geysermc.geyser.session.cache.LodestoneCache;
|
||||
import org.geysermc.geyser.session.cache.PistonCache;
|
||||
import org.geysermc.geyser.session.cache.PreferencesCache;
|
||||
import org.geysermc.geyser.session.cache.SkullCache;
|
||||
import org.geysermc.geyser.session.cache.TagCache;
|
||||
import org.geysermc.geyser.session.cache.TeleportCache;
|
||||
import org.geysermc.geyser.session.cache.WorldBorder;
|
||||
import org.geysermc.geyser.session.cache.WorldCache;
|
||||
import org.geysermc.geyser.skin.FloodgateSkinUploader;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.text.MinecraftLocale;
|
||||
|
@ -143,7 +192,14 @@ import java.net.ConnectException;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -1630,7 +1686,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
boolean spectator = gameMode == GameMode.SPECTATOR;
|
||||
boolean worldImmutable = gameMode == GameMode.ADVENTURE || spectator;
|
||||
|
||||
if (GameProtocol.supports1_19_10(this)) {
|
||||
UpdateAdventureSettingsPacket adventureSettingsPacket = new UpdateAdventureSettingsPacket();
|
||||
adventureSettingsPacket.setNoMvP(false);
|
||||
adventureSettingsPacket.setNoPvM(false);
|
||||
|
@ -1689,40 +1744,6 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||
|
||||
updateAbilitiesPacket.getAbilityLayers().add(abilityLayer);
|
||||
sendUpstreamPacket(updateAbilitiesPacket);
|
||||
return;
|
||||
}
|
||||
|
||||
AdventureSettingsPacket adventureSettingsPacket = new AdventureSettingsPacket();
|
||||
adventureSettingsPacket.setUniqueEntityId(bedrockId);
|
||||
adventureSettingsPacket.setCommandPermission(commandPermission);
|
||||
adventureSettingsPacket.setPlayerPermission(playerPermission);
|
||||
|
||||
Set<AdventureSetting> flags = adventureSettingsPacket.getSettings();
|
||||
if (canFly || spectator) {
|
||||
flags.add(AdventureSetting.MAY_FLY);
|
||||
}
|
||||
|
||||
if (flying || spectator) {
|
||||
if (spectator && !flying) {
|
||||
// We're "flying locked" in this gamemode
|
||||
flying = true;
|
||||
ServerboundPlayerAbilitiesPacket abilitiesPacket = new ServerboundPlayerAbilitiesPacket(true);
|
||||
sendDownstreamPacket(abilitiesPacket);
|
||||
}
|
||||
flags.add(AdventureSetting.FLYING);
|
||||
}
|
||||
|
||||
if (worldImmutable) {
|
||||
flags.add(AdventureSetting.WORLD_IMMUTABLE);
|
||||
}
|
||||
|
||||
if (spectator) {
|
||||
flags.add(AdventureSetting.NO_CLIP);
|
||||
}
|
||||
|
||||
flags.add(AdventureSetting.AUTO_JUMP);
|
||||
|
||||
sendUpstreamPacket(adventureSettingsPacket);
|
||||
}
|
||||
|
||||
private int getRenderDistance() {
|
||||
|
|
|
@ -59,11 +59,13 @@ public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator {
|
|||
CraftRecipeOptionalStackRequestActionData data = (CraftRecipeOptionalStackRequestActionData) request.getActions()[0];
|
||||
AnvilContainer container = (AnvilContainer) inventory;
|
||||
|
||||
if (request.getFilterStrings().length != 0) {
|
||||
// Required as of 1.18.30 - FilterTextPackets no longer appear to be sent
|
||||
String name = request.getFilterStrings()[data.getFilteredStringIndex()];
|
||||
if (!Objects.equals(name, container.getNewName())) {
|
||||
if (!Objects.equals(name, container.getNewName())) { // TODO is this still necessary after pre-1.19.50 support is dropped?
|
||||
container.checkForRename(session, name);
|
||||
}
|
||||
}
|
||||
|
||||
return super.translateRequest(session, inventory, request);
|
||||
}
|
||||
|
|
|
@ -35,12 +35,12 @@ import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
|||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.block.DoubleChestValue;
|
||||
import org.geysermc.geyser.translator.level.block.entity.DoubleChestBlockEntityTranslator;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.level.block.entity.DoubleChestBlockEntityTranslator;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
|
||||
public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
||||
private final int defaultJavaBlockState;
|
||||
|
@ -82,19 +82,10 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||
}
|
||||
}
|
||||
|
||||
// Check if a fake block can be placed, either above the player or beneath.
|
||||
BedrockDimension dimension = session.getChunkCache().getBedrockDimension();
|
||||
int minY = dimension.minY(), maxY = minY + dimension.height();
|
||||
Vector3i position = session.getPlayerEntity().getPosition().toInt().add(0, 5, 0);
|
||||
if (position.getY() < minY) {
|
||||
Vector3i position = InventoryUtils.findAvailableWorldSpace(session);
|
||||
if (position == null) {
|
||||
return false;
|
||||
}
|
||||
if (position.getY() >= maxY) {
|
||||
position = session.getPlayerEntity().getPosition().toInt().sub(0, 5, 0);
|
||||
if (position.getY() >= maxY) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3i pairPosition = position.add(Vector3i.UNIT_X);
|
||||
int bedrockBlockId = session.getBlockMappings().getBedrockBlockId(defaultJavaBlockState);
|
||||
|
|
|
@ -29,6 +29,7 @@ import com.nukkitx.protocol.bedrock.packet.CommandRequestPacket;
|
|||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
|
@ -38,16 +39,14 @@ public class BedrockCommandRequestTranslator extends PacketTranslator<CommandReq
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, CommandRequestPacket packet) {
|
||||
String command = packet.getCommand().replace("/", "");
|
||||
String command = MessageTranslator.convertToPlainText(packet.getCommand());
|
||||
if (!(session.getGeyser().getPlatformType() == PlatformType.STANDALONE
|
||||
&& GeyserImpl.getInstance().commandManager().runCommand(session, command))) {
|
||||
String message = packet.getCommand().trim();
|
||||
|
||||
if (MessageTranslator.isTooLong(message, session)) {
|
||||
&& GeyserImpl.getInstance().commandManager().runCommand(session, command.substring(1)))) {
|
||||
if (MessageTranslator.isTooLong(command, session)) {
|
||||
return;
|
||||
}
|
||||
|
||||
session.sendCommand(message.substring(1));
|
||||
session.sendCommand(command.substring(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,12 +32,21 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
|||
import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.*;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundSwingPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemOnPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket;
|
||||
import com.nukkitx.math.vector.Vector3d;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.*;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.InventorySource;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.LegacySetItemSlotData;
|
||||
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
|
||||
|
@ -54,7 +63,6 @@ import org.geysermc.geyser.inventory.Inventory;
|
|||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.inventory.click.Click;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.registry.type.ItemMappings;
|
||||
|
@ -63,7 +71,11 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
|||
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.util.*;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
import org.geysermc.geyser.util.CooldownUtils;
|
||||
import org.geysermc.geyser.util.EntityUtils;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -464,12 +476,10 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
InteractAction.ATTACK, session.isSneaking());
|
||||
session.sendDownstreamPacket(attackPacket);
|
||||
|
||||
if (GameProtocol.supports1_19_10(session)) {
|
||||
// Since 1.19.10, LevelSoundEventPackets are no longer sent by the client when attacking entities
|
||||
CooldownUtils.sendCooldown(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,21 +37,7 @@ public class BedrockTextTranslator extends PacketTranslator<TextPacket> {
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, TextPacket packet) {
|
||||
String message = packet.getMessage();
|
||||
|
||||
// The order here is important - strip out illegal characters first, then check if it's blank
|
||||
// (in case the message is blank after removing)
|
||||
if (message.indexOf(ChatColor.ESCAPE) != -1) {
|
||||
// Filter out all escape characters - Java doesn't let you type these
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < message.length(); i++) {
|
||||
char c = message.charAt(i);
|
||||
if (c != ChatColor.ESCAPE) {
|
||||
builder.append(c);
|
||||
}
|
||||
}
|
||||
message = builder.toString();
|
||||
}
|
||||
String message = MessageTranslator.convertToPlainText(packet.getMessage());
|
||||
|
||||
if (message.isBlank()) {
|
||||
// Java Edition (as of 1.17.1) just doesn't pass on these messages, so... we won't either!
|
||||
|
|
|
@ -39,7 +39,7 @@ public class JavaPlayerCombatKillTranslator extends PacketTranslator<Clientbound
|
|||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundPlayerCombatKillPacket packet) {
|
||||
if (packet.getPlayerId() == session.getPlayerEntity().getEntityId() && GameProtocol.supports1_19_10(session)) {
|
||||
if (packet.getPlayerId() == session.getPlayerEntity().getEntityId()) {
|
||||
Component deathMessage = packet.getMessage();
|
||||
// TODO - could inject score in, but as of 1.19.10 newlines don't center and start at the left of the first text
|
||||
DeathInfoPacket deathInfoPacket = new DeathInfoPacket();
|
||||
|
|
|
@ -51,6 +51,8 @@ public class JavaMapItemDataTranslator extends PacketTranslator<ClientboundMapIt
|
|||
mapItemDataPacket.setLocked(packet.isLocked());
|
||||
mapItemDataPacket.setOrigin(Vector3i.ZERO); // Required since 1.19.20
|
||||
mapItemDataPacket.setScale(packet.getScale());
|
||||
// Required as of 1.19.50
|
||||
mapItemDataPacket.getTrackedEntityIds().add(packet.getMapId());
|
||||
|
||||
MapData data = packet.getData();
|
||||
if (data != null) {
|
||||
|
|
|
@ -201,6 +201,28 @@ public class MessageTranslator {
|
|||
return GSON_SERIALIZER.serialize(component);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert legacy format message to plain text
|
||||
*
|
||||
* @param message Message to convert
|
||||
* @return The plain text of the message
|
||||
*/
|
||||
public static String convertToPlainText(String message) {
|
||||
char[] input = message.toCharArray();
|
||||
char[] output = new char[input.length];
|
||||
int outputSize = 0;
|
||||
for (int i = 0, inputLength = input.length; i < inputLength; i++) {
|
||||
char c = input[i];
|
||||
if (c == ChatColor.ESCAPE) {
|
||||
i++;
|
||||
} else {
|
||||
output[outputSize++] = c;
|
||||
}
|
||||
}
|
||||
return new String(output, 0, outputSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert JSON and legacy format message to plain text
|
||||
*
|
||||
|
|
|
@ -27,12 +27,16 @@ package org.geysermc.geyser.util;
|
|||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.Effect;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.data.PlayerActionType;
|
||||
import com.nukkitx.protocol.bedrock.packet.ChangeDimensionPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.MobEffectPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.StopSoundPacket;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import java.util.Set;
|
||||
|
@ -94,8 +98,10 @@ public class DimensionUtils {
|
|||
changeDimensionPacket.setRespawn(true);
|
||||
changeDimensionPacket.setPosition(pos);
|
||||
session.sendUpstreamPacket(changeDimensionPacket);
|
||||
|
||||
session.setDimension(javaDimension);
|
||||
setBedrockDimension(session, javaDimension);
|
||||
|
||||
player.setPosition(pos);
|
||||
session.setSpawned(false);
|
||||
session.setLastChunkPosition(null);
|
||||
|
@ -117,6 +123,19 @@ public class DimensionUtils {
|
|||
stopSoundPacket.setSoundName("");
|
||||
session.sendUpstreamPacket(stopSoundPacket);
|
||||
|
||||
// Kind of silly but Bedrock 1.19.50 requires an acknowledgement after the
|
||||
// initial chunks are sent, prior to the client acknowledgement
|
||||
if (GameProtocol.supports1_19_50(session)) {
|
||||
// Note: send this before chunks are sent. Fixed https://github.com/GeyserMC/Geyser/issues/3421
|
||||
PlayerActionPacket ackPacket = new PlayerActionPacket();
|
||||
ackPacket.setRuntimeEntityId(player.getGeyserId());
|
||||
ackPacket.setAction(PlayerActionType.DIMENSION_CHANGE_SUCCESS);
|
||||
ackPacket.setBlockPosition(Vector3i.ZERO);
|
||||
ackPacket.setResultPosition(Vector3i.ZERO);
|
||||
ackPacket.setFace(0);
|
||||
session.sendUpstreamPacket(ackPacket);
|
||||
}
|
||||
|
||||
// TODO - fix this hack of a fix by sending the final dimension switching logic after sections have been sent.
|
||||
// The client wants sections sent to it before it can successfully respawn.
|
||||
ChunkUtils.sendEmptyChunks(session, player.getPosition().toInt(), 3, true);
|
||||
|
|
|
@ -31,6 +31,7 @@ import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
|
|||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundPickItemPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import com.nukkitx.nbt.NbtType;
|
||||
|
@ -38,6 +39,7 @@ import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
|
|||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlayerHotbarPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
|
@ -46,6 +48,7 @@ import org.geysermc.geyser.inventory.click.Click;
|
|||
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserShapedRecipe;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserShapelessRecipe;
|
||||
import org.geysermc.geyser.level.BedrockDimension;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
@ -134,6 +137,28 @@ public class InventoryUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a usable block space in the world to place a fake inventory block, and returns the position.
|
||||
*/
|
||||
@Nullable
|
||||
public static Vector3i findAvailableWorldSpace(GeyserSession session) {
|
||||
// Check if a fake block can be placed, either above the player or beneath.
|
||||
BedrockDimension dimension = session.getChunkCache().getBedrockDimension();
|
||||
int minY = dimension.minY(), maxY = minY + dimension.height();
|
||||
Vector3i flatPlayerPosition = session.getPlayerEntity().getPosition().toInt();
|
||||
Vector3i position = flatPlayerPosition.add(Vector3i.UP);
|
||||
if (position.getY() < minY) {
|
||||
return null;
|
||||
}
|
||||
if (position.getY() >= maxY) {
|
||||
position = flatPlayerPosition.sub(0, 4, 0);
|
||||
if (position.getY() >= maxY) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
public static void updateCursor(GeyserSession session) {
|
||||
InventorySlotPacket cursorPacket = new InventorySlotPacket();
|
||||
cursorPacket.setContainerId(ContainerId.UI);
|
||||
|
@ -148,18 +173,6 @@ public class InventoryUtils {
|
|||
return item1.getJavaId() == item2.getJavaId() && Objects.equals(item1.getNbt(), item2.getNbt());
|
||||
}
|
||||
|
||||
public static boolean canStack(ItemStack item1, ItemStack item2) {
|
||||
if (item1 == null || item2 == null)
|
||||
return false;
|
||||
return item1.getId() == item2.getId() && Objects.equals(item1.getNbt(), item2.getNbt());
|
||||
}
|
||||
|
||||
public static boolean canStack(ItemData item1, ItemData item2) {
|
||||
if (item1 == null || item2 == null)
|
||||
return false;
|
||||
return item1.equals(item2, false, true, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if an item stack represents air or has no count.
|
||||
*/
|
||||
|
@ -184,11 +197,22 @@ public class InventoryUtils {
|
|||
|
||||
root.put("display", display.build());
|
||||
return protocolVersion -> ItemData.builder()
|
||||
.id(Registries.ITEMS.forVersion(protocolVersion).getStoredItems().barrier().getBedrockId())
|
||||
.id(getUnusableSpaceBlockID(protocolVersion))
|
||||
.count(1)
|
||||
.tag(root.build()).build();
|
||||
}
|
||||
|
||||
private static int getUnusableSpaceBlockID(int protocolVersion) {
|
||||
String unusableSpaceBlock = GeyserImpl.getInstance().getConfig().getUnusableSpaceBlock();
|
||||
ItemMapping unusableSpaceBlockID = Registries.ITEMS.forVersion(protocolVersion).getMapping(unusableSpaceBlock);
|
||||
if (unusableSpaceBlockID != null) {
|
||||
return unusableSpaceBlockID.getBedrockId();
|
||||
} else {
|
||||
GeyserImpl.getInstance().getLogger().error("Invalid value" + unusableSpaceBlock + ". Resorting to barrier block.");
|
||||
return Registries.ITEMS.forVersion(protocolVersion).getStoredItems().barrier().getBedrockId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See {@link #findOrCreateItem(GeyserSession, String)}. This is for finding a specified {@link ItemStack}.
|
||||
*
|
||||
|
|
Binary file not shown.
BIN
core/src/main/resources/bedrock/block_palette.1_19_50.nbt
Normal file
BIN
core/src/main/resources/bedrock/block_palette.1_19_50.nbt
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:acacia_chest_boat",
|
||||
"id" : 642
|
||||
"id" : 645
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:acacia_door",
|
||||
|
@ -19,6 +19,10 @@
|
|||
"name" : "minecraft:acacia_fence_gate",
|
||||
"id" : 187
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:acacia_hanging_sign",
|
||||
"id" : -504
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:acacia_pressure_plate",
|
||||
"id" : -150
|
||||
|
@ -131,17 +135,97 @@
|
|||
"name" : "minecraft:bamboo",
|
||||
"id" : -163
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_button",
|
||||
"id" : -511
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_chest_raft",
|
||||
"id" : 648
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_door",
|
||||
"id" : -517
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_double_slab",
|
||||
"id" : -521
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_fence",
|
||||
"id" : -515
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_fence_gate",
|
||||
"id" : -516
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_hanging_sign",
|
||||
"id" : -522
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_mosaic",
|
||||
"id" : -509
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_mosaic_double_slab",
|
||||
"id" : -525
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_mosaic_slab",
|
||||
"id" : -524
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_mosaic_stairs",
|
||||
"id" : -523
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_planks",
|
||||
"id" : -510
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_pressure_plate",
|
||||
"id" : -514
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_raft",
|
||||
"id" : 638
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_sapling",
|
||||
"id" : -164
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_sign",
|
||||
"id" : 637
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_slab",
|
||||
"id" : -513
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_stairs",
|
||||
"id" : -512
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_standing_sign",
|
||||
"id" : -518
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_trapdoor",
|
||||
"id" : -520
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bamboo_wall_sign",
|
||||
"id" : -519
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:banner",
|
||||
"id" : 567
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:banner_pattern",
|
||||
"id" : 651
|
||||
"id" : 655
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:barrel",
|
||||
|
@ -217,7 +301,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:birch_chest_boat",
|
||||
"id" : 639
|
||||
"id" : 642
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:birch_door",
|
||||
|
@ -227,6 +311,10 @@
|
|||
"name" : "minecraft:birch_fence_gate",
|
||||
"id" : 184
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:birch_hanging_sign",
|
||||
"id" : -502
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:birch_pressure_plate",
|
||||
"id" : -151
|
||||
|
@ -329,7 +417,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:boat",
|
||||
"id" : 649
|
||||
"id" : 653
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:bone",
|
||||
|
@ -435,6 +523,10 @@
|
|||
"name" : "minecraft:calcite",
|
||||
"id" : -326
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:camel_spawn_egg",
|
||||
"id" : 633
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:camera",
|
||||
"id" : 593
|
||||
|
@ -541,7 +633,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:chest_boat",
|
||||
"id" : 645
|
||||
"id" : 649
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:chest_minecart",
|
||||
|
@ -555,6 +647,10 @@
|
|||
"name" : "minecraft:chicken_spawn_egg",
|
||||
"id" : 435
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:chiseled_bookshelf",
|
||||
"id" : -526
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:chiseled_deepslate",
|
||||
"id" : -395
|
||||
|
@ -827,6 +923,10 @@
|
|||
"name" : "minecraft:crimson_fungus",
|
||||
"id" : -228
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:crimson_hanging_sign",
|
||||
"id" : -506
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:crimson_hyphae",
|
||||
"id" : -299
|
||||
|
@ -921,7 +1021,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:dark_oak_chest_boat",
|
||||
"id" : 643
|
||||
"id" : 646
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:dark_oak_door",
|
||||
|
@ -931,6 +1031,10 @@
|
|||
"name" : "minecraft:dark_oak_fence_gate",
|
||||
"id" : 186
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:dark_oak_hanging_sign",
|
||||
"id" : -505
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:dark_oak_pressure_plate",
|
||||
"id" : -152
|
||||
|
@ -1121,7 +1225,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:disc_fragment_5",
|
||||
"id" : 637
|
||||
"id" : 640
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:dispenser",
|
||||
|
@ -1193,11 +1297,11 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:dye",
|
||||
"id" : 650
|
||||
"id" : 654
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:echo_shard",
|
||||
"id" : 647
|
||||
"id" : 651
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:egg",
|
||||
|
@ -1725,7 +1829,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:end_crystal",
|
||||
"id" : 653
|
||||
"id" : 657
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:end_gateway",
|
||||
|
@ -1933,7 +2037,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:glow_berries",
|
||||
"id" : 654
|
||||
"id" : 658
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:glow_frame",
|
||||
|
@ -2405,7 +2509,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:jungle_chest_boat",
|
||||
"id" : 640
|
||||
"id" : 643
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:jungle_door",
|
||||
|
@ -2415,6 +2519,10 @@
|
|||
"name" : "minecraft:jungle_fence_gate",
|
||||
"id" : 185
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:jungle_hanging_sign",
|
||||
"id" : -503
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:jungle_pressure_plate",
|
||||
"id" : -153
|
||||
|
@ -2665,7 +2773,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:mangrove_boat",
|
||||
"id" : 635
|
||||
"id" : 636
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:mangrove_button",
|
||||
|
@ -2673,11 +2781,11 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:mangrove_chest_boat",
|
||||
"id" : 644
|
||||
"id" : 647
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:mangrove_door",
|
||||
"id" : 633
|
||||
"id" : 634
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:mangrove_double_slab",
|
||||
|
@ -2691,6 +2799,10 @@
|
|||
"name" : "minecraft:mangrove_fence_gate",
|
||||
"id" : -492
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:mangrove_hanging_sign",
|
||||
"id" : -508
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:mangrove_leaves",
|
||||
"id" : -472
|
||||
|
@ -2717,7 +2829,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:mangrove_sign",
|
||||
"id" : 634
|
||||
"id" : 635
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:mangrove_slab",
|
||||
|
@ -2861,7 +2973,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:music_disc_5",
|
||||
"id" : 636
|
||||
"id" : 639
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:music_disc_blocks",
|
||||
|
@ -3037,7 +3149,11 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:oak_chest_boat",
|
||||
"id" : 638
|
||||
"id" : 641
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:oak_hanging_sign",
|
||||
"id" : -500
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:oak_sign",
|
||||
|
@ -3473,7 +3589,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:recovery_compass",
|
||||
"id" : 646
|
||||
"id" : 650
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:red_candle",
|
||||
|
@ -3781,7 +3897,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:spawn_egg",
|
||||
"id" : 652
|
||||
"id" : 656
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:spider_eye",
|
||||
|
@ -3813,7 +3929,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:spruce_chest_boat",
|
||||
"id" : 641
|
||||
"id" : 644
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:spruce_door",
|
||||
|
@ -3823,6 +3939,10 @@
|
|||
"name" : "minecraft:spruce_fence_gate",
|
||||
"id" : 183
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:spruce_hanging_sign",
|
||||
"id" : -501
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:spruce_pressure_plate",
|
||||
"id" : -154
|
||||
|
@ -4081,7 +4201,7 @@
|
|||
},
|
||||
{
|
||||
"name" : "minecraft:trader_llama_spawn_egg",
|
||||
"id" : 648
|
||||
"id" : 652
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:trapdoor",
|
||||
|
@ -4223,6 +4343,10 @@
|
|||
"name" : "minecraft:warped_fungus_on_a_stick",
|
||||
"id" : 618
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:warped_hanging_sign",
|
||||
"id" : -507
|
||||
},
|
||||
{
|
||||
"name" : "minecraft:warped_hyphae",
|
||||
"id" : -298
|
|
@ -183,6 +183,10 @@ log-player-ip-addresses: true
|
|||
# auto-update.
|
||||
notify-on-new-bedrock-update: true
|
||||
|
||||
# Which item to use to mark unavailable slots in a Bedrock player inventory. Examples of this are the 2x2 crafting grid while in creative,
|
||||
# or custom inventory menus with sizes different from the usual 3x9. A barrier block is the default item.
|
||||
unusable-space-block: minecraft:barrier
|
||||
|
||||
# bStats is a stat tracker that is entirely anonymous and tracks only basic information
|
||||
# about Geyser, such as how many people are online, how many servers are using Geyser,
|
||||
# what OS is being used, etc. You can learn more about bStats here: https://bstats.org/.
|
||||
|
|
|
@ -85,6 +85,7 @@ public class MessageTranslatorTest {
|
|||
@Test
|
||||
public void convertToPlainText() {
|
||||
Assert.assertEquals("JSON message is not handled properly", "Many colors here", MessageTranslator.convertToPlainText("{\"extra\":[{\"color\":\"red\",\"text\":\"M\"},{\"color\":\"gold\",\"text\":\"a\"},{\"color\":\"yellow\",\"text\":\"n\"},{\"color\":\"green\",\"text\":\"y \"},{\"color\":\"aqua\",\"text\":\"c\"},{\"color\":\"dark_purple\",\"text\":\"o\"},{\"color\":\"red\",\"text\":\"l\"},{\"color\":\"gold\",\"text\":\"o\"},{\"color\":\"yellow\",\"text\":\"r\"},{\"color\":\"green\",\"text\":\"s \"},{\"color\":\"aqua\",\"text\":\"h\"},{\"color\":\"dark_purple\",\"text\":\"e\"},{\"color\":\"red\",\"text\":\"r\"},{\"color\":\"gold\",\"text\":\"e\"}],\"text\":\"\"}", "en_US"));
|
||||
Assert.assertEquals("Legacy formatted message is not handled properly (Colors)", "Many colors here", MessageTranslator.convertToPlainText("§cM§6a§en§ay §bc§5o§cl§6o§er§as §bh§5e§cr§6e"));
|
||||
Assert.assertEquals("Legacy formatted message is not handled properly (Colors)", "Many colors here", MessageTranslator.convertToPlainText("§cM§6a§en§ay §bc§5o§cl§6o§er§as §bh§5e§cr§6e", "en_US"));
|
||||
Assert.assertEquals("Legacy formatted message is not handled properly (Style)", "Obf Bold Strikethrough Underline Italic Reset", MessageTranslator.convertToPlainText("§kObf §lBold §mStrikethrough §nUnderline §oItalic §rReset", "en_US"));
|
||||
Assert.assertEquals("Valid lenient JSON is not handled properly", "Strange", MessageTranslator.convertToPlainText("§rStrange", "en_US"));
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
[versions]
|
||||
jackson = "2.13.4"
|
||||
jackson = "2.14.0"
|
||||
fastutil = "8.5.2"
|
||||
netty = "4.1.80.Final"
|
||||
guava = "29.0-jre"
|
||||
gson = "2.3.1" # Provided by Spigot 1.8.8
|
||||
websocket = "1.5.1"
|
||||
protocol = "2.9.14-20221025.193624-1"
|
||||
protocol = "2.9.15-20221129.204554-2"
|
||||
raknet = "1.6.28-20220125.214016-6"
|
||||
mcauthlib = "d9d773e"
|
||||
mcprotocollib = "1.19.3-SNAPSHOT"
|
||||
|
@ -82,7 +82,7 @@ junit = { group = "junit", name = "junit", version.ref = "junit" }
|
|||
mcauthlib = { group = "com.github.GeyserMC", name = "MCAuthLib", version.ref = "mcauthlib" }
|
||||
mcprotocollib = { group = "com.github.steveice10", name = "mcprotocollib", version.ref = "mcprotocollib" }
|
||||
packetlib = { group = "com.github.steveice10", name = "packetlib", version.ref = "packetlib" }
|
||||
protocol = { group = "com.nukkitx.protocol", name = "bedrock-v557", version.ref = "protocol" }
|
||||
protocol = { group = "com.nukkitx.protocol", name = "bedrock-v560", version.ref = "protocol" }
|
||||
raknet = { group = "com.nukkitx.network", name = "raknet", version.ref = "raknet" }
|
||||
sponge-api = { group = "org.spongepowered", name = "spongeapi", version.ref = "sponge" }
|
||||
terminalconsoleappender = { group = "net.minecrell", name = "terminalconsoleappender", version.ref = "terminalconsoleappender" }
|
||||
|
|
Loading…
Reference in a new issue