Merge branch 'master' of https://github.com/GeyserMC/Geyser into feature/protocol-3.0

This commit is contained in:
Camotoy 2022-12-20 19:47:45 -05:00
commit 4fe9aeca40
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
142 changed files with 2276 additions and 11909 deletions

View file

@ -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! 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.51 and Minecraft Java 1.19.3.
## Setting Up ## Setting Up
Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser. Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser.

View file

@ -29,7 +29,6 @@ import lombok.Getter;
import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.Plugin;
import org.geysermc.geyser.dump.BootstrapDumpInfo; import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.text.AsteriskSerializer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -52,15 +51,17 @@ public class GeyserBungeeDumpInfo extends BootstrapDumpInfo {
this.plugins = new ArrayList<>(); this.plugins = new ArrayList<>();
for (net.md_5.bungee.api.config.ListenerInfo listener : proxy.getConfig().getListeners()) { for (net.md_5.bungee.api.config.ListenerInfo listener : proxy.getConfig().getListeners()) {
String hostname = listener.getHost().getHostString(); this.listeners.add(new ListenerInfo(listener.getHost().getHostString(), listener.getHost().getPort()));
if (!AsteriskSerializer.showSensitive && !(hostname.equals("") || hostname.equals("0.0.0.0"))) {
hostname = "***";
}
this.listeners.add(new ListenerInfo(hostname, listener.getHost().getPort()));
} }
for (Plugin plugin : proxy.getPluginManager().getPlugins()) { for (Plugin plugin : proxy.getPluginManager().getPlugins()) {
this.plugins.add(new PluginInfo(true, plugin.getDescription().getName(), plugin.getDescription().getVersion(), plugin.getDescription().getMain(), Collections.singletonList(plugin.getDescription().getAuthor()))); this.plugins.add(new PluginInfo(
true,
plugin.getDescription().getName(),
plugin.getDescription().getVersion(),
plugin.getDescription().getMain(),
Collections.singletonList(plugin.getDescription().getAuthor()))
);
} }
} }
} }

View file

@ -76,7 +76,7 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
// Copied from ViaVersion. // Copied from ViaVersion.
// https://github.com/ViaVersion/ViaVersion/blob/b8072aad86695cc8ec6f5e4103e43baf3abf6cc5/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java#L43 // https://github.com/ViaVersion/ViaVersion/blob/b8072aad86695cc8ec6f5e4103e43baf3abf6cc5/bungee/src/main/java/us/myles/ViaVersion/BungeePlugin.java#L43
try { try {
ProtocolConstants.class.getField("MINECRAFT_1_19_1"); ProtocolConstants.class.getField("MINECRAFT_1_19_3");
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
getLogger().warning(" / \\"); getLogger().warning(" / \\");
getLogger().warning(" / \\"); getLogger().warning(" / \\");

View file

@ -1,8 +1,5 @@
plugins { plugins {
id("fabric-loom") version "1.0-SNAPSHOT" id("fabric-loom") version "1.0-SNAPSHOT"
id("maven-publish")
id("com.github.johnrengelman.shadow")
id("java")
} }
java { java {

View file

@ -25,65 +25,58 @@
package org.geysermc.geyser.platform.fabric; package org.geysermc.geyser.platform.fabric;
import lombok.AllArgsConstructor;
import lombok.Getter;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.ModContainer; import net.fabricmc.loader.api.ModContainer;
import net.fabricmc.loader.api.metadata.ModMetadata;
import net.fabricmc.loader.api.metadata.Person;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import org.geysermc.geyser.dump.BootstrapDumpInfo; import org.geysermc.geyser.dump.BootstrapDumpInfo;
import org.geysermc.geyser.text.AsteriskSerializer; import org.geysermc.geyser.text.AsteriskSerializer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
@SuppressWarnings("unused") // The way that the dump renders makes them used @Getter
public class GeyserFabricDumpInfo extends BootstrapDumpInfo { public class GeyserFabricDumpInfo extends BootstrapDumpInfo {
private String platformVersion = null; private String platformVersion = null;
private final EnvType environmentType; private final EnvType environmentType;
@AsteriskSerializer.Asterisk(isIp = true)
private final String serverIP; private final String serverIP;
private final int serverPort; private final int serverPort;
private final List<ModInfo> mods; private final List<ModInfo> mods;
public GeyserFabricDumpInfo(MinecraftServer server) { public GeyserFabricDumpInfo(MinecraftServer server) {
super(); FabricLoader.getInstance().getModContainer("fabricloader").ifPresent(mod ->
for (ModContainer modContainer : FabricLoader.getInstance().getAllMods()) { this.platformVersion = mod.getMetadata().getVersion().getFriendlyString());
if (modContainer.getMetadata().getId().equals("fabricloader")) {
this.platformVersion = modContainer.getMetadata().getVersion().getFriendlyString();
break;
}
}
this.environmentType = FabricLoader.getInstance().getEnvironmentType(); this.environmentType = FabricLoader.getInstance().getEnvironmentType();
if (AsteriskSerializer.showSensitive || (server.getLocalIp() == null || server.getLocalIp().equals("") || server.getLocalIp().equals("0.0.0.0"))) { this.serverIP = server.getLocalIp() == null ? "unknown" : server.getLocalIp();
this.serverIP = server.getLocalIp();
} else {
this.serverIP = "***";
}
this.serverPort = server.getPort(); this.serverPort = server.getPort();
this.mods = new ArrayList<>(); this.mods = new ArrayList<>();
for (ModContainer mod : FabricLoader.getInstance().getAllMods()) { for (ModContainer mod : FabricLoader.getInstance().getAllMods()) {
this.mods.add(new ModInfo(mod)); ModMetadata meta = mod.getMetadata();
this.mods.add(new ModInfo(
FabricLoader.getInstance().isModLoaded(meta.getId()),
meta.getId(),
meta.getVersion().getFriendlyString(),
meta.getAuthors().stream().map(Person::getName).collect(Collectors.toList()))
);
} }
} }
public String getPlatformVersion() { @Getter
return platformVersion; @AllArgsConstructor
} public static class ModInfo {
public boolean enabled;
public EnvType getEnvironmentType() { public String name;
return environmentType; public String version;
} public List<String> authors;
public String getServerIP() {
return this.serverIP;
}
public int getServerPort() {
return this.serverPort;
}
public List<ModInfo> getMods() {
return this.mods;
} }
} }

View file

@ -246,7 +246,10 @@ public class GeyserFabricMod implements ModInitializer, GeyserBootstrap {
@Override @Override
public InputStream getResourceOrNull(String resource) { public InputStream getResourceOrNull(String resource) {
// We need to handle this differently, because Fabric shares the classloader across multiple mods // We need to handle this differently, because Fabric shares the classloader across multiple mods
Path path = this.mod.getPath(resource); Path path = this.mod.findPath(resource).orElse(null);
if (path == null) {
return null;
}
try { try {
return path.getFileSystem() return path.getFileSystem()

View file

@ -1,66 +0,0 @@
/*
* Copyright (c) 2019-2022 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.geyser.platform.fabric;
import net.fabricmc.loader.api.ModContainer;
import java.util.ArrayList;
import java.util.List;
/**
* A wrapper for Fabric mod information to be presented in a Geyser dump
*/
public class ModInfo {
private final String name;
private final String id;
private final String version;
private final List<String> authors;
public ModInfo(ModContainer mod) {
this.name = mod.getMetadata().getName();
this.id = mod.getMetadata().getId();
this.authors = new ArrayList<>();
mod.getMetadata().getAuthors().forEach((person) -> this.authors.add(person.getName()));
this.version = mod.getMetadata().getVersion().getFriendlyString();
}
public String getName() {
return this.name;
}
public String getId() {
return this.id;
}
public String getVersion() {
return this.version;
}
public List<String> getAuthors() {
return this.authors;
}
}

View file

@ -26,9 +26,9 @@
package org.geysermc.geyser.platform.fabric.world; package org.geysermc.geyser.platform.fabric.world;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import me.lucko.fabric.api.permissions.v0.Permissions; import me.lucko.fabric.api.permissions.v0.Permissions;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;

View file

@ -41,6 +41,8 @@ public class GeyserSpigotDumpInfo extends BootstrapDumpInfo {
private final String platformVersion; private final String platformVersion;
private final String platformAPIVersion; private final String platformAPIVersion;
private final boolean onlineMode; private final boolean onlineMode;
@AsteriskSerializer.Asterisk(isIp = true)
private final String serverIP; private final String serverIP;
private final int serverPort; private final int serverPort;
private final List<PluginInfo> plugins; private final List<PluginInfo> plugins;
@ -51,12 +53,7 @@ public class GeyserSpigotDumpInfo extends BootstrapDumpInfo {
this.platformVersion = Bukkit.getVersion(); this.platformVersion = Bukkit.getVersion();
this.platformAPIVersion = Bukkit.getBukkitVersion(); this.platformAPIVersion = Bukkit.getBukkitVersion();
this.onlineMode = Bukkit.getOnlineMode(); this.onlineMode = Bukkit.getOnlineMode();
String ip = Bukkit.getIp(); this.serverIP = Bukkit.getIp();
if (AsteriskSerializer.showSensitive || (ip.equals("") || ip.equals("0.0.0.0"))) {
this.serverIP = ip;
} else {
this.serverIP = "***";
}
this.serverPort = Bukkit.getPort(); this.serverPort = Bukkit.getPort();
this.plugins = new ArrayList<>(); this.plugins = new ArrayList<>();

View file

@ -32,6 +32,7 @@ import org.geysermc.geyser.adapters.spigot.SpigotAdapters;
import org.geysermc.geyser.adapters.spigot.SpigotWorldAdapter; import org.geysermc.geyser.adapters.spigot.SpigotWorldAdapter;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.jetbrains.annotations.Nullable;
public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager { public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
protected final SpigotWorldAdapter adapter; protected final SpigotWorldAdapter adapter;
@ -49,4 +50,12 @@ public class GeyserSpigotNativeWorldManager extends GeyserSpigotWorldManager {
} }
return adapter.getBlockAt(player.getWorld(), x, y, z); return adapter.getBlockAt(player.getWorld(), x, y, z);
} }
@Nullable
@Override
public String[] getBiomeIdentifiers(boolean withTags) {
// Biome identifiers will basically always be the same for one server, since you have to re-send the
// ClientboundLoginPacket to change the registry. Therefore, don't bother caching for each player.
return adapter.getBiomeSuggestions(withTags);
}
} }

View file

@ -26,9 +26,9 @@
package org.geysermc.geyser.platform.spigot.world.manager; package org.geysermc.geyser.platform.spigot.world.manager;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -38,7 +38,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.geysermc.geyser.level.GameRule; import org.geysermc.geyser.level.GameRule;
import org.geysermc.geyser.level.GeyserWorldManager; import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -51,7 +51,7 @@ import java.util.List;
/** /**
* The base world manager to use when there is no supported NMS revision * The base world manager to use when there is no supported NMS revision
*/ */
public class GeyserSpigotWorldManager extends GeyserWorldManager { public class GeyserSpigotWorldManager extends WorldManager {
private final Plugin plugin; private final Plugin plugin;
public GeyserSpigotWorldManager(Plugin plugin) { public GeyserSpigotWorldManager(Plugin plugin) {
@ -151,12 +151,12 @@ public class GeyserSpigotWorldManager extends GeyserWorldManager {
return true; return true;
} }
public Boolean getGameRuleBool(GeyserSession session, GameRule gameRule) { public boolean getGameRuleBool(GeyserSession session, GameRule gameRule) {
String value = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getGameRuleValue(gameRule.getJavaID()); String value = Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getGameRuleValue(gameRule.getJavaID());
if (!value.isEmpty()) { if (!value.isEmpty()) {
return Boolean.parseBoolean(value); return Boolean.parseBoolean(value);
} }
return (Boolean) gameRule.getDefaultValue(); return gameRule.getDefaultBooleanValue();
} }
@Override @Override
@ -165,7 +165,7 @@ public class GeyserSpigotWorldManager extends GeyserWorldManager {
if (!value.isEmpty()) { if (!value.isEmpty()) {
return Integer.parseInt(value); return Integer.parseInt(value);
} }
return (int) gameRule.getDefaultValue(); return gameRule.getDefaultIntValue();
} }
@Override @Override

View file

@ -45,6 +45,8 @@ public class GeyserSpongeDumpInfo extends BootstrapDumpInfo {
private final String platformName; private final String platformName;
private final String platformVersion; private final String platformVersion;
private final boolean onlineMode; private final boolean onlineMode;
@AsteriskSerializer.Asterisk(isIp = true)
private final String serverIP; private final String serverIP;
private final int serverPort; private final int serverPort;
private final List<PluginInfo> plugins; private final List<PluginInfo> plugins;
@ -56,12 +58,7 @@ public class GeyserSpongeDumpInfo extends BootstrapDumpInfo {
this.platformVersion = platformMeta.version().getQualifier(); this.platformVersion = platformMeta.version().getQualifier();
this.onlineMode = Sponge.server().isOnlineModeEnabled(); this.onlineMode = Sponge.server().isOnlineModeEnabled();
Optional<InetSocketAddress> socketAddress = Sponge.server().boundAddress(); Optional<InetSocketAddress> socketAddress = Sponge.server().boundAddress();
String hostString = socketAddress.map(InetSocketAddress::getHostString).orElse("unknown"); this.serverIP = socketAddress.map(InetSocketAddress::getHostString).orElse("unknown");
if (AsteriskSerializer.showSensitive || (hostString.equals("") || hostString.equals("0.0.0.0") || hostString.equals("unknown"))) {
this.serverIP = hostString;
} else {
this.serverIP = "***";
}
this.serverPort = socketAddress.map(InetSocketAddress::getPort).orElse(-1); this.serverPort = socketAddress.map(InetSocketAddress::getPort).orElse(-1);
this.plugins = new ArrayList<>(); this.plugins = new ArrayList<>();

View file

@ -41,6 +41,8 @@ public class GeyserVelocityDumpInfo extends BootstrapDumpInfo {
private final String platformVersion; private final String platformVersion;
private final String platformVendor; private final String platformVendor;
private final boolean onlineMode; private final boolean onlineMode;
@AsteriskSerializer.Asterisk(isIp = true)
private final String serverIP; private final String serverIP;
private final int serverPort; private final int serverPort;
private final List<PluginInfo> plugins; private final List<PluginInfo> plugins;
@ -51,12 +53,7 @@ public class GeyserVelocityDumpInfo extends BootstrapDumpInfo {
this.platformVersion = proxy.getVersion().getVersion(); this.platformVersion = proxy.getVersion().getVersion();
this.platformVendor = proxy.getVersion().getVendor(); this.platformVendor = proxy.getVersion().getVendor();
this.onlineMode = proxy.getConfiguration().isOnlineMode(); this.onlineMode = proxy.getConfiguration().isOnlineMode();
String hostString = proxy.getBoundAddress().getHostString(); this.serverIP = proxy.getBoundAddress().getHostString();
if (AsteriskSerializer.showSensitive || (hostString.equals("") || hostString.equals("0.0.0.0"))) {
this.serverIP = hostString;
} else {
this.serverIP = "***";
}
this.serverPort = proxy.getBoundAddress().getPort(); this.serverPort = proxy.getBoundAddress().getPort();
this.plugins = new ArrayList<>(); this.plugins = new ArrayList<>();

View file

@ -16,11 +16,11 @@ dependencies {
// Within the gradle plugin classpath, there is a version conflict between loom and some other // 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. // 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> { tasks.withType<KotlinCompile> {
kotlinOptions { kotlinOptions {
jvmTarget = "16" jvmTarget = "16"
} }
} }

View file

@ -111,6 +111,8 @@ public interface GeyserConfiguration {
boolean isNotifyOnNewBedrockUpdate(); boolean isNotifyOnNewBedrockUpdate();
String getUnusableSpaceBlock();
IMetricsInfo getMetrics(); IMetricsInfo getMetrics();
int getPendingAuthenticationTimeout(); int getPendingAuthenticationTimeout();

View file

@ -154,6 +154,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
@JsonProperty("notify-on-new-bedrock-update") @JsonProperty("notify-on-new-bedrock-update")
private boolean notifyOnNewBedrockUpdate = true; private boolean notifyOnNewBedrockUpdate = true;
@JsonProperty("unusable-space-block")
private String unusableSpaceBlock = "minecraft:barrier";
private MetricsInfo metrics = new MetricsInfo(); private MetricsInfo metrics = new MetricsInfo();
@JsonProperty("pending-authentication-timeout") @JsonProperty("pending-authentication-timeout")

View file

@ -29,6 +29,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import org.geysermc.common.PlatformType; import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.text.AsteriskSerializer;
import java.util.List; import java.util.List;
@ -53,6 +54,8 @@ public class BootstrapDumpInfo {
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public static class ListenerInfo { public static class ListenerInfo {
@AsteriskSerializer.Asterisk(isIp = true)
public String ip; public String ip;
public int port; public int port;
} }

View file

@ -60,6 +60,7 @@ public final class EntityDefinitions {
public static final EntityDefinition<BeeEntity> BEE; public static final EntityDefinition<BeeEntity> BEE;
public static final EntityDefinition<BlazeEntity> BLAZE; public static final EntityDefinition<BlazeEntity> BLAZE;
public static final EntityDefinition<BoatEntity> BOAT; public static final EntityDefinition<BoatEntity> BOAT;
public static final EntityDefinition<CamelEntity> CAMEL;
public static final EntityDefinition<CatEntity> CAT; public static final EntityDefinition<CatEntity> CAT;
public static final EntityDefinition<SpiderEntity> CAVE_SPIDER; public static final EntityDefinition<SpiderEntity> CAVE_SPIDER;
public static final EntityDefinition<MinecartEntity> CHEST_MINECART; public static final EntityDefinition<MinecartEntity> CHEST_MINECART;
@ -859,6 +860,13 @@ public final class EntityDefinitions {
.addTranslator(MetadataType.BYTE, AbstractHorseEntity::setHorseFlags) .addTranslator(MetadataType.BYTE, AbstractHorseEntity::setHorseFlags)
.addTranslator(null) // UUID of owner .addTranslator(null) // UUID of owner
.build(); .build();
CAMEL = EntityDefinition.inherited(CamelEntity::new, abstractHorseEntityBase)
.type(EntityType.CAMEL)
.identifier("minecraft:llama") // todo 1.20
.height(2.375f).width(1.7f)
.addTranslator(MetadataType.BOOLEAN, CamelEntity::setDashing)
.addTranslator(null) // Last pose change tick
.build();
HORSE = EntityDefinition.inherited(HorseEntity::new, abstractHorseEntityBase) HORSE = EntityDefinition.inherited(HorseEntity::new, abstractHorseEntityBase)
.type(EntityType.HORSE) .type(EntityType.HORSE)
.height(1.6f).width(1.3965f) .height(1.6f).width(1.3965f)

View file

@ -48,6 +48,8 @@ import org.cloudburstmc.protocol.bedrock.packet.RemoveEntityPacket;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.GeyserDirtyMetadata; 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.session.GeyserSession;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.EntityUtils;
@ -360,6 +362,7 @@ public class Entity {
setFlag(EntityFlag.ON_FIRE, ((xd & 0x01) == 0x01) && !getFlag(EntityFlag.FIRE_IMMUNE)); // Otherwise immune entities sometimes flicker onfire 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.SNEAKING, (xd & 0x02) == 0x02);
setFlag(EntityFlag.SPRINTING, (xd & 0x08) == 0x08); setFlag(EntityFlag.SPRINTING, (xd & 0x08) == 0x08);
// Swimming is ignored here and instead we rely on the pose // Swimming is ignored here and instead we rely on the pose
setFlag(EntityFlag.GLIDING, (xd & 0x80) == 0x80); setFlag(EntityFlag.GLIDING, (xd & 0x80) == 0x80);

View file

@ -31,9 +31,9 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityMotionPacket;
import org.geysermc.floodgate.util.DeviceOs; import org.geysermc.floodgate.util.DeviceOs;

View file

@ -33,8 +33,8 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2019-2022 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.geyser.entity.type.living.animal.horse;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
public class CamelEntity extends AbstractHorseEntity {
private static final float SITTING_HEIGHT_DIFFERENCE = 1.43F;
public CamelEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
}
@Override
protected void initializeMetadata() {
super.initializeMetadata();
this.dirtyMetadata.put(EntityDataTypes.VARIANT, 2); // Closest llama colour to camel
}
@Override
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
return "cactus".equals(javaIdentifierStripped);
}
@Override
protected void setDimensions(Pose pose) {
if (pose == Pose.SITTING) {
setBoundingBoxWidth(definition.height() - SITTING_HEIGHT_DIFFERENCE);
setBoundingBoxWidth(definition.width());
} else {
super.setDimensions(pose);
}
}
public void setDashing(BooleanEntityMetadata entityMetadata) {
}
}

View file

@ -25,16 +25,19 @@
package org.geysermc.geyser.entity.type.living.monster; package org.geysermc.geyser.entity.type.living.monster;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.OptionalIntMetadataType;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet; import org.cloudburstmc.protocol.bedrock.packet.LevelSoundEvent2Packet;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import java.util.OptionalInt;
import java.util.UUID; import java.util.UUID;
public class EndermanEntity extends MonsterEntity { public class EndermanEntity extends MonsterEntity {
@ -43,8 +46,15 @@ public class EndermanEntity extends MonsterEntity {
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw); super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
} }
public void setCarriedBlock(IntEntityMetadata entityMetadata) { public void setCarriedBlock(EntityMetadata<OptionalInt, OptionalIntMetadataType> entityMetadata) {
dirtyMetadata.put(EntityDataTypes.BLOCK, session.getBlockMappings().getBedrockBlock(entityMetadata.getPrimitiveValue())); BlockDefinition bedrockBlockId;
if (entityMetadata.getValue().isPresent()) {
bedrockBlockId = session.getBlockMappings().getBedrockBlock(entityMetadata.getValue().getAsInt());
} else {
bedrockBlockId = session.getBlockMappings().getBedrockAir();
}
dirtyMetadata.put(EntityDataTypes.CARRY_BLOCK_STATE, bedrockBlockId);
} }
/** /**

View file

@ -30,13 +30,13 @@ import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeTyp
import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos; import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.AttributeData; import org.cloudburstmc.protocol.bedrock.data.AttributeData;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -47,7 +47,6 @@ import javax.annotation.Nullable;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID;
/** /**
* The entity class specifically for a {@link GeyserSession}'s player. * The entity class specifically for a {@link GeyserSession}'s player.
@ -120,6 +119,16 @@ public class SessionPlayerEntity extends PlayerEntity {
refreshSpeed = true; refreshSpeed = true;
} }
/**
* Since 1.19.40, the client must be re-informed of its bounding box on respawn
* See https://github.com/GeyserMC/Geyser/issues/3370
*/
public void updateBoundingBox() {
dirtyMetadata.put(EntityDataTypes.HEIGHT, getBoundingBoxHeight());
dirtyMetadata.put(EntityDataTypes.WIDTH, getBoundingBoxWidth());
updateBedrockMetadata();
}
@Override @Override
public boolean setBoundingBoxHeight(float height) { public boolean setBoundingBoxHeight(float height) {
if (super.setBoundingBoxHeight(height)) { if (super.setBoundingBoxHeight(height)) {

View file

@ -76,7 +76,7 @@ public class AnvilContainer extends Container {
String originalName = ItemUtils.getCustomName(getInput().getNbt()); String originalName = ItemUtils.getCustomName(getInput().getNbt());
String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.locale()); String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.locale());
String plainNewName = MessageTranslator.convertToPlainText(rename, session.locale()); String plainNewName = MessageTranslator.convertToPlainText(rename);
if (!plainOriginalName.equals(plainNewName)) { if (!plainOriginalName.equals(plainNewName)) {
// Strip out formatting since Java Edition does not allow it // Strip out formatting since Java Edition does not allow it
correctRename = plainNewName; correctRename = plainNewName;

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;

View file

@ -30,10 +30,7 @@ import com.github.steveice10.mc.protocol.data.game.inventory.ContainerActionType
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import com.github.steveice10.mc.protocol.data.game.inventory.MoveToHotbarAction; import com.github.steveice10.mc.protocol.data.game.inventory.MoveToHotbarAction;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.SlotType; import org.geysermc.geyser.inventory.SlotType;
@ -124,12 +121,14 @@ public final class ClickPlan {
} }
ItemStack clickedItemStack; ItemStack clickedItemStack;
if (!planIter.hasNext() && refresh) { if (emulatePost1_16Logic) {
clickedItemStack = InventoryUtils.REFRESH_ITEM; // The action must be simulated first as Java expects the new contents of the cursor (as of 1.18.1)
clickedItemStack = simulatedCursor.getItemStack();
} else { } else {
if (emulatePost1_16Logic) { if (!planIter.hasNext() && refresh) {
// The action must be simulated first as Java expects the new contents of the cursor (as of 1.18.1) // Doesn't have the intended effect with state IDs since this won't cause a complete window refresh
clickedItemStack = simulatedCursor.getItemStack(); // (It will eventually once state IDs desync, but this causes more problems than not)
clickedItemStack = InventoryUtils.REFRESH_ITEM;
} else { } else {
if (action.click.actionType == ContainerActionType.DROP_ITEM || action.slot == Click.OUTSIDE_SLOT) { if (action.click.actionType == ContainerActionType.DROP_ITEM || action.slot == Click.OUTSIDE_SLOT) {
clickedItemStack = null; clickedItemStack = null;

View file

@ -25,9 +25,8 @@
package org.geysermc.geyser.inventory.holder; package org.geysermc.geyser.inventory.holder;
import com.google.common.collect.ImmutableSet;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket; import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket;
@ -39,6 +38,7 @@ import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.util.BlockUtils; import org.geysermc.geyser.util.BlockUtils;
import org.geysermc.geyser.util.InventoryUtils;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -63,14 +63,14 @@ public class BlockInventoryHolder extends InventoryHolder {
Set<String> validBlocksTemp = new HashSet<>(validBlocks.length + 1); Set<String> validBlocksTemp = new HashSet<>(validBlocks.length + 1);
Collections.addAll(validBlocksTemp, validBlocks); Collections.addAll(validBlocksTemp, validBlocks);
validBlocksTemp.add(BlockUtils.getCleanIdentifier(javaBlockIdentifier)); validBlocksTemp.add(BlockUtils.getCleanIdentifier(javaBlockIdentifier));
this.validBlocks = ImmutableSet.copyOf(validBlocksTemp); this.validBlocks = Set.copyOf(validBlocksTemp);
} else { } else {
this.validBlocks = Collections.singleton(BlockUtils.getCleanIdentifier(javaBlockIdentifier)); this.validBlocks = Collections.singleton(BlockUtils.getCleanIdentifier(javaBlockIdentifier));
} }
} }
@Override @Override
public void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) { public boolean prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory) {
// Check to see if there is an existing block we can use that the player just selected. // Check to see if there is an existing block we can use that the player just selected.
// First, verify that the player's position has not changed, so we don't try to select a block wildly out of range. // First, verify that the player's position has not changed, so we don't try to select a block wildly out of range.
// (This could be a virtual inventory that the player is opening) // (This could be a virtual inventory that the player is opening)
@ -83,13 +83,16 @@ public class BlockInventoryHolder extends InventoryHolder {
inventory.setHolderPosition(session.getLastInteractionBlockPosition()); inventory.setHolderPosition(session.getLastInteractionBlockPosition());
((Container) inventory).setUsingRealBlock(true, javaBlockString[0]); ((Container) inventory).setUsingRealBlock(true, javaBlockString[0]);
setCustomName(session, session.getLastInteractionBlockPosition(), inventory, javaBlockId); setCustomName(session, session.getLastInteractionBlockPosition(), inventory, javaBlockId);
return;
return true;
} }
} }
// Otherwise, time to conjure up a fake block! Vector3i position = InventoryUtils.findAvailableWorldSpace(session);
Vector3i position = session.getPlayerEntity().getPosition().toInt(); if (position == null) {
position = position.add(Vector3i.UP); return false;
}
UpdateBlockPacket blockPacket = new UpdateBlockPacket(); UpdateBlockPacket blockPacket = new UpdateBlockPacket();
blockPacket.setDataLayer(0); blockPacket.setDataLayer(0);
blockPacket.setBlockPosition(position); blockPacket.setBlockPosition(position);
@ -99,6 +102,8 @@ public class BlockInventoryHolder extends InventoryHolder {
inventory.setHolderPosition(position); inventory.setHolderPosition(position);
setCustomName(session, position, inventory, defaultJavaBlockState); setCustomName(session, position, inventory, defaultJavaBlockState);
return true;
} }
/** /**

View file

@ -30,7 +30,7 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.inventory.InventoryTranslator; import org.geysermc.geyser.translator.inventory.InventoryTranslator;
public abstract class InventoryHolder { public abstract class InventoryHolder {
public abstract void prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory); public abstract boolean prepareInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory);
public abstract void openInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory); public abstract void openInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory);
public abstract void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory); public abstract void closeInventory(InventoryTranslator translator, GeyserSession session, Inventory inventory);
} }

View file

@ -31,8 +31,8 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;

View file

@ -25,8 +25,8 @@
package org.geysermc.geyser.item.components; package org.geysermc.geyser.item.components;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View file

@ -25,7 +25,7 @@
package org.geysermc.geyser.item.components; package org.geysermc.geyser.item.components;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import java.util.Locale; import java.util.Locale;

View file

@ -32,43 +32,41 @@ import lombok.Getter;
* It is used to construct the list for the settings menu * It is used to construct the list for the settings menu
*/ */
public enum GameRule { public enum GameRule {
ANNOUNCEADVANCEMENTS("announceAdvancements", Boolean.class, true), // JE only ANNOUNCEADVANCEMENTS("announceAdvancements", true), // JE only
COMMANDBLOCKOUTPUT("commandBlockOutput", Boolean.class, true), COMMANDBLOCKOUTPUT("commandBlockOutput", true),
DISABLEELYTRAMOVEMENTCHECK("disableElytraMovementCheck", Boolean.class, false), // JE only DISABLEELYTRAMOVEMENTCHECK("disableElytraMovementCheck", false), // JE only
DISABLERAIDS("disableRaids", Boolean.class, false), // JE only DISABLERAIDS("disableRaids", false), // JE only
DODAYLIGHTCYCLE("doDaylightCycle", Boolean.class, true), DODAYLIGHTCYCLE("doDaylightCycle", true),
DOENTITYDROPS("doEntityDrops", Boolean.class, true), DOENTITYDROPS("doEntityDrops", true),
DOFIRETICK("doFireTick", Boolean.class, true), DOFIRETICK("doFireTick", true),
DOIMMEDIATERESPAWN("doImmediateRespawn", Boolean.class, false), DOIMMEDIATERESPAWN("doImmediateRespawn", false),
DOINSOMNIA("doInsomnia", Boolean.class, true), DOINSOMNIA("doInsomnia", true),
DOLIMITEDCRAFTING("doLimitedCrafting", Boolean.class, false), // JE only DOLIMITEDCRAFTING("doLimitedCrafting", false), // JE only
DOMOBLOOT("doMobLoot", Boolean.class, true), DOMOBLOOT("doMobLoot", true),
DOMOBSPAWNING("doMobSpawning", Boolean.class, true), DOMOBSPAWNING("doMobSpawning", true),
DOPATROLSPAWNING("doPatrolSpawning", Boolean.class, true), // JE only DOPATROLSPAWNING("doPatrolSpawning", true), // JE only
DOTILEDROPS("doTileDrops", Boolean.class, true), DOTILEDROPS("doTileDrops", true),
DOTRADERSPAWNING("doTraderSpawning", Boolean.class, true), // JE only DOTRADERSPAWNING("doTraderSpawning", true), // JE only
DOWEATHERCYCLE("doWeatherCycle", Boolean.class, true), DOWEATHERCYCLE("doWeatherCycle", true),
DROWNINGDAMAGE("drowningDamage", Boolean.class, true), DROWNINGDAMAGE("drowningDamage", true),
FALLDAMAGE("fallDamage", Boolean.class, true), FALLDAMAGE("fallDamage", true),
FIREDAMAGE("fireDamage", Boolean.class, true), FIREDAMAGE("fireDamage", true),
FREEZEDAMAGE("freezeDamage", Boolean.class, true), FREEZEDAMAGE("freezeDamage", true),
FORGIVEDEADPLAYERS("forgiveDeadPlayers", Boolean.class, true), // JE only FORGIVEDEADPLAYERS("forgiveDeadPlayers", true), // JE only
KEEPINVENTORY("keepInventory", Boolean.class, false), KEEPINVENTORY("keepInventory", false),
LOGADMINCOMMANDS("logAdminCommands", Boolean.class, true), // JE only LOGADMINCOMMANDS("logAdminCommands", true), // JE only
MAXCOMMANDCHAINLENGTH("maxCommandChainLength", Integer.class, 65536), MAXCOMMANDCHAINLENGTH("maxCommandChainLength", 65536),
MAXENTITYCRAMMING("maxEntityCramming", Integer.class, 24), // JE only MAXENTITYCRAMMING("maxEntityCramming", 24), // JE only
MOBGRIEFING("mobGriefing", Boolean.class, true), MOBGRIEFING("mobGriefing", true),
NATURALREGENERATION("naturalRegeneration", Boolean.class, true), NATURALREGENERATION("naturalRegeneration", true),
PLAYERSSLEEPINGPERCENTAGE("playersSleepingPercentage", Integer.class, 100), // JE only PLAYERSSLEEPINGPERCENTAGE("playersSleepingPercentage", 100), // JE only
RANDOMTICKSPEED("randomTickSpeed", Integer.class, 3), RANDOMTICKSPEED("randomTickSpeed", 3),
REDUCEDDEBUGINFO("reducedDebugInfo", Boolean.class, false), // JE only REDUCEDDEBUGINFO("reducedDebugInfo", false), // JE only
SENDCOMMANDFEEDBACK("sendCommandFeedback", Boolean.class, true), SENDCOMMANDFEEDBACK("sendCommandFeedback", true),
SHOWDEATHMESSAGES("showDeathMessages", Boolean.class, true), SHOWDEATHMESSAGES("showDeathMessages", true),
SPAWNRADIUS("spawnRadius", Integer.class, 10), SPAWNRADIUS("spawnRadius", 10),
SPECTATORSGENERATECHUNKS("spectatorsGenerateChunks", Boolean.class, true), // JE only SPECTATORSGENERATECHUNKS("spectatorsGenerateChunks", true), // JE only
UNIVERSALANGER("universalAnger", Boolean.class, false), // JE only UNIVERSALANGER("universalAnger", false); // JE only
UNKNOWN("unknown", Object.class);
public static final GameRule[] VALUES = values(); public static final GameRule[] VALUES = values();
@ -78,48 +76,25 @@ public enum GameRule {
@Getter @Getter
private final Class<?> type; private final Class<?> type;
@Getter private final int defaultValue;
private final Object defaultValue;
GameRule(String javaID, Class<?> type) { GameRule(String javaID, boolean defaultValue) {
this(javaID, type, null); this.javaID = javaID;
this.type = Boolean.class;
this.defaultValue = defaultValue ? 1 : 0;
} }
GameRule(String javaID, Class<?> type, Object defaultValue) { GameRule(String javaID, int defaultValue) {
this.javaID = javaID; this.javaID = javaID;
this.type = type; this.type = Integer.class;
this.defaultValue = defaultValue; this.defaultValue = defaultValue;
} }
/** public boolean getDefaultBooleanValue() {
* Convert a string to an object of the correct type for the current gamerule return defaultValue != 0;
*
* @param value The string value to convert
* @return The converted and formatted value
*/
public Object convertValue(String value) {
if (type.equals(Boolean.class)) {
return Boolean.parseBoolean(value);
} else if (type.equals(Integer.class)) {
return Integer.parseInt(value);
}
return null;
} }
/** public int getDefaultIntValue() {
* Fetch a game rule by the given Java ID return defaultValue;
*
* @param id The ID of the gamerule
* @return A {@link GameRule} object representing the requested ID or {@link GameRule#UNKNOWN}
*/
public static GameRule fromJavaID(String id) {
for (GameRule gamerule : VALUES) {
if (gamerule.javaID.equals(id)) {
return gamerule;
}
}
return UNKNOWN;
} }
} }

View file

@ -25,10 +25,8 @@
package org.geysermc.geyser.level; package org.geysermc.geyser.level;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; import org.cloudburstmc.nbt.NbtMap;
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty; import org.cloudburstmc.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
@ -36,11 +34,8 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.ChunkCache; import org.geysermc.geyser.session.cache.ChunkCache;
import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator; import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator;
import java.util.Locale;
public class GeyserWorldManager extends WorldManager { public class GeyserWorldManager extends WorldManager {
private final Object2ObjectMap<String, String> gameruleCache = new Object2ObjectOpenHashMap<>();
private static final Object2ObjectMap<String, String> gameruleCache = new Object2ObjectOpenHashMap<>();
@Override @Override
public int getBlockAt(GeyserSession session, int x, int y, int z) { public int getBlockAt(GeyserSession session, int x, int y, int z) {
@ -82,18 +77,18 @@ public class GeyserWorldManager extends WorldManager {
@Override @Override
public void setGameRule(GeyserSession session, String name, Object value) { public void setGameRule(GeyserSession session, String name, Object value) {
session.sendCommand("gamerule " + name + " " + value); super.setGameRule(session, name, value);
gameruleCache.put(name, String.valueOf(value)); gameruleCache.put(name, String.valueOf(value));
} }
@Override @Override
public Boolean getGameRuleBool(GeyserSession session, GameRule gameRule) { public boolean getGameRuleBool(GeyserSession session, GameRule gameRule) {
String value = gameruleCache.get(gameRule.getJavaID()); String value = gameruleCache.get(gameRule.getJavaID());
if (value != null) { if (value != null) {
return Boolean.parseBoolean(value); return Boolean.parseBoolean(value);
} }
return gameRule.getDefaultValue() != null ? (Boolean) gameRule.getDefaultValue() : false; return gameRule.getDefaultBooleanValue();
} }
@Override @Override
@ -103,17 +98,7 @@ public class GeyserWorldManager extends WorldManager {
return Integer.parseInt(value); return Integer.parseInt(value);
} }
return gameRule.getDefaultValue() != null ? (int) gameRule.getDefaultValue() : 0; return gameRule.getDefaultIntValue();
}
@Override
public void setPlayerGameMode(GeyserSession session, GameMode gameMode) {
session.sendCommand("gamemode " + gameMode.name().toLowerCase(Locale.ROOT));
}
@Override
public void setDifficulty(GeyserSession session, Difficulty difficulty) {
session.sendCommand("difficulty " + difficulty.name().toLowerCase(Locale.ROOT));
} }
@Override @Override

View file

@ -28,9 +28,12 @@ package org.geysermc.geyser.level;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; 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.data.game.setting.Difficulty;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import javax.annotation.Nullable;
import java.util.Locale;
/** /**
* Class that manages or retrieves various information * Class that manages or retrieves various information
* from the world. Everything in this class should be * from the world. Everything in this class should be
@ -105,7 +108,9 @@ public abstract class WorldManager {
* @param name The gamerule to change * @param name The gamerule to change
* @param value The new value for the gamerule * @param value The new value for the gamerule
*/ */
public abstract void setGameRule(GeyserSession session, String name, Object value); public void setGameRule(GeyserSession session, String name, Object value) {
session.sendCommand("gamerule " + name + " " + value);
}
/** /**
* Gets a gamerule value as a boolean * Gets a gamerule value as a boolean
@ -114,7 +119,7 @@ public abstract class WorldManager {
* @param gameRule The gamerule to fetch the value of * @param gameRule The gamerule to fetch the value of
* @return The boolean representation of the value * @return The boolean representation of the value
*/ */
public abstract Boolean getGameRuleBool(GeyserSession session, GameRule gameRule); public abstract boolean getGameRuleBool(GeyserSession session, GameRule gameRule);
/** /**
* Get a gamerule value as an integer * Get a gamerule value as an integer
@ -131,7 +136,9 @@ public abstract class WorldManager {
* @param session The session of the player to change the game mode of * @param session The session of the player to change the game mode of
* @param gameMode The game mode to change the player to * @param gameMode The game mode to change the player to
*/ */
public abstract void setPlayerGameMode(GeyserSession session, GameMode gameMode); public void setPlayerGameMode(GeyserSession session, GameMode gameMode) {
session.sendCommand("gamemode " + gameMode.name().toLowerCase(Locale.ROOT));
}
/** /**
* Change the difficulty of the Java server * Change the difficulty of the Java server
@ -139,7 +146,9 @@ public abstract class WorldManager {
* @param session The session of the user that requested the change * @param session The session of the user that requested the change
* @param difficulty The difficulty to change to * @param difficulty The difficulty to change to
*/ */
public abstract void setDifficulty(GeyserSession session, Difficulty difficulty); public void setDifficulty(GeyserSession session, Difficulty difficulty) {
session.sendCommand("difficulty " + difficulty.name().toLowerCase(Locale.ROOT));
}
/** /**
* Checks if the given session's player has a permission * Checks if the given session's player has a permission
@ -149,4 +158,12 @@ public abstract class WorldManager {
* @return True if the player has the requested permission, false if not * @return True if the player has the requested permission, false if not
*/ */
public abstract boolean hasPermission(GeyserSession session, String permission); public abstract boolean hasPermission(GeyserSession session, String permission);
/**
* Returns a list of biome identifiers available on the server.
*/
@Nullable
public String[] getBiomeIdentifiers(boolean withTags) {
return null;
}
} }

View file

@ -28,12 +28,11 @@ package org.geysermc.geyser.network;
import com.github.steveice10.mc.protocol.codec.MinecraftCodec; import com.github.steveice10.mc.protocol.codec.MinecraftCodec;
import com.github.steveice10.mc.protocol.codec.PacketCodec; import com.github.steveice10.mc.protocol.codec.PacketCodec;
import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec; import org.cloudburstmc.protocol.bedrock.codec.BedrockCodec;
import org.cloudburstmc.protocol.bedrock.codec.v527.Bedrock_v527;
import org.cloudburstmc.protocol.bedrock.codec.v534.Bedrock_v534;
import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544; import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544;
import org.cloudburstmc.protocol.bedrock.codec.v545.Bedrock_v545; import org.cloudburstmc.protocol.bedrock.codec.v545.Bedrock_v545;
import org.cloudburstmc.protocol.bedrock.codec.v554.Bedrock_v554; import org.cloudburstmc.protocol.bedrock.codec.v554.Bedrock_v554;
import org.cloudburstmc.protocol.bedrock.codec.v557.Bedrock_v557; import org.cloudburstmc.protocol.bedrock.codec.v557.Bedrock_v557;
import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560;
import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec; import org.cloudburstmc.protocol.bedrock.netty.codec.packet.BedrockPacketCodec;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -49,7 +48,7 @@ public final class GameProtocol {
* Default Bedrock codec that should act as a fallback. Should represent the latest available * Default Bedrock codec that should act as a fallback. Should represent the latest available
* release of the game that Geyser supports. * release of the game that Geyser supports.
*/ */
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v557.CODEC; public static final BedrockCodec DEFAULT_BEDROCK_CODEC = Bedrock_v560.CODEC;
/** /**
* A list of all supported Bedrock versions that can join Geyser * A list of all supported Bedrock versions that can join Geyser
*/ */
@ -62,12 +61,6 @@ public final class GameProtocol {
private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC; private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC;
static { static {
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v527.CODEC.toBuilder()
.minecraftVersion("1.19.0/1.19.2")
.build());
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v534.CODEC.toBuilder()
.minecraftVersion("1.19.10/1.19.11")
.build());
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v544.CODEC); SUPPORTED_BEDROCK_CODECS.add(Bedrock_v544.CODEC);
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v545.CODEC.toBuilder() SUPPORTED_BEDROCK_CODECS.add(Bedrock_v545.CODEC.toBuilder()
.minecraftVersion("1.19.21/1.19.22") .minecraftVersion("1.19.21/1.19.22")
@ -75,7 +68,12 @@ public final class GameProtocol {
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v554.CODEC.toBuilder() SUPPORTED_BEDROCK_CODECS.add(Bedrock_v554.CODEC.toBuilder()
.minecraftVersion("1.19.30/1.19.31") .minecraftVersion("1.19.30/1.19.31")
.build()); .build());
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC); SUPPORTED_BEDROCK_CODECS.add(Bedrock_v557.CODEC.toBuilder()
.minecraftVersion("1.19.40/1.19.41")
.build());
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder()
.minecraftVersion("1.19.50/1.19.51")
.build());
} }
/** /**
@ -94,11 +92,11 @@ public final class GameProtocol {
/* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */ /* Bedrock convenience methods to gatekeep features and easily remove the check on version removal */
public static boolean supports1_19_10(GeyserSession session) { public static boolean supports1_19_30(GeyserSession session) {
return session.getUpstream().getProtocolVersion() >= Bedrock_v534.CODEC.getProtocolVersion(); return session.getUpstream().getProtocolVersion() >= Bedrock_v554.CODEC.getProtocolVersion();
} }
public static boolean supports1_19_30(GeyserSession session) { public static boolean supports1_19_50(GeyserSession session) {
return session.getUpstream().getProtocolVersion() >= Bedrock_v554.CODEC.getProtocolVersion(); return session.getUpstream().getProtocolVersion() >= Bedrock_v554.CODEC.getProtocolVersion();
} }
@ -117,7 +115,7 @@ public final class GameProtocol {
* @return the supported Minecraft: Java Edition version names * @return the supported Minecraft: Java Edition version names
*/ */
public static List<String> getJavaVersions() { public static List<String> getJavaVersions() {
return List.of(DEFAULT_JAVA_CODEC.getMinecraftVersion(), "1.19.2"); return List.of(DEFAULT_JAVA_CODEC.getMinecraftVersion());
} }
/** /**

View file

@ -61,9 +61,13 @@ import org.geysermc.geyser.util.MathUtils;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayDeque;
import java.util.Deque;
public class UpstreamPacketHandler extends LoggingPacketHandler { public class UpstreamPacketHandler extends LoggingPacketHandler {
private Deque<String> packsToSent = new ArrayDeque<>();
public UpstreamPacketHandler(GeyserImpl geyser, GeyserSession session) { public UpstreamPacketHandler(GeyserImpl geyser, GeyserSession session) {
super(geyser, session); super(geyser, session);
} }
@ -186,24 +190,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
break; break;
case SEND_PACKS: case SEND_PACKS:
for(String id : packet.getPackIds()) { packsToSent.addAll(packet.getPackIds());
ResourcePackDataInfoPacket data = new ResourcePackDataInfoPacket(); sendPackDataInfo(packsToSent.pop());
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.RESOURCES);
session.sendUpstreamPacket(data);
}
break; break;
case HAVE_ALL_PACKS: case HAVE_ALL_PACKS:
@ -296,7 +284,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
data.setPackId(packet.getPackId()); data.setPackId(packet.getPackId());
int offset = packet.getChunkIndex() * ResourcePack.CHUNK_SIZE; 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())) { try (InputStream inputStream = new FileInputStream(pack.getFile())) {
inputStream.skip(offset); inputStream.skip(offset);
@ -308,6 +297,31 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
data.setData(Unpooled.wrappedBuffer(packData)); data.setData(Unpooled.wrappedBuffer(packData));
session.sendUpstreamPacket(data); 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 PacketSignal.HANDLED; return PacketSignal.HANDLED;
} }
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.RESOURCES);
session.sendUpstreamPacket(data);
}
} }

View file

@ -41,9 +41,6 @@ import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioDatagramChannel;
import org.cloudburstmc.netty.channel.raknet.RakChannelFactory; import org.cloudburstmc.netty.channel.raknet.RakChannelFactory;
import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption; import org.cloudburstmc.netty.channel.raknet.config.RakChannelOption;
import org.cloudburstmc.netty.handler.codec.raknet.common.UnconnectedPingEncoder;
import org.cloudburstmc.netty.handler.codec.raknet.common.UnconnectedPongDecoder;
import org.cloudburstmc.netty.handler.codec.raknet.common.UnconnectedPongEncoder;
import org.cloudburstmc.netty.handler.codec.raknet.server.RakServerOfflineHandler; import org.cloudburstmc.netty.handler.codec.raknet.server.RakServerOfflineHandler;
import org.cloudburstmc.protocol.bedrock.BedrockPong; import org.cloudburstmc.protocol.bedrock.BedrockPong;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
@ -57,7 +54,6 @@ import org.geysermc.geyser.translator.text.MessageTranslator;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Random;
import java.util.function.Function; import java.util.function.Function;
public final class GeyserServer { public final class GeyserServer {
@ -158,13 +154,9 @@ public final class GeyserServer {
pong.subMotd(config.getBedrock().secondaryMotd()); pong.subMotd(config.getBedrock().secondaryMotd());
} }
if (config.isPassthroughPlayerCounts() && pingInfo != null) { // https://github.com/GeyserMC/Geyser/issues/3388
pong.playerCount(pingInfo.getPlayers().getOnline()); pong.motd(pong.motd().replace(';', ':'));
pong.maximumPlayerCount(pingInfo.getPlayers().getMax()); pong.subMotd(pong.subMotd().replace(';', ':'));
} else {
pong.playerCount(geyser.getSessionManager().getSessions().size());
pong.maximumPlayerCount(config.getMaxPlayers());
}
// Fallbacks to prevent errors and allow Bedrock to see the server // Fallbacks to prevent errors and allow Bedrock to see the server
if (pong.motd() == null || pong.motd().isBlank()) { if (pong.motd() == null || pong.motd().isBlank()) {
@ -193,6 +185,14 @@ public final class GeyserServer {
} }
} }
if (config.isPassthroughPlayerCounts() && pingInfo != null) {
pong.playerCount(pingInfo.getPlayers().getOnline());
pong.maximumPlayerCount(pingInfo.getPlayers().getMax());
} else {
pong.playerCount(geyser.getSessionManager().getSessions().size());
pong.maximumPlayerCount(config.getMaxPlayers());
}
//Bedrock will not even attempt a connection if the client thinks the server is full //Bedrock will not even attempt a connection if the client thinks the server is full
//so we have to fake it not being full //so we have to fake it not being full
if (pong.playerCount() >= pong.maximumPlayerCount()) { if (pong.playerCount() >= pong.maximumPlayerCount()) {

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.ping;
import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonMappingException;
import com.nukkitx.nbt.util.VarInts; import org.cloudburstmc.nbt.util.VarInts;
import io.netty.handler.codec.haproxy.HAProxyCommand; import io.netty.handler.codec.haproxy.HAProxyCommand;
import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol; import io.netty.handler.codec.haproxy.HAProxyProxiedProtocol;
import io.netty.util.NetUtil; import io.netty.util.NetUtil;

View file

@ -31,15 +31,15 @@ import com.github.steveice10.mc.protocol.data.game.level.event.LevelEvent;
import com.github.steveice10.mc.protocol.data.game.level.particle.ParticleType; import com.github.steveice10.mc.protocol.data.game.level.particle.ParticleType;
import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
import com.github.steveice10.packetlib.packet.Packet; import com.github.steveice10.packetlib.packet.Packet;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.inventory.CraftingData;
import org.cloudburstmc.protocol.bedrock.data.inventory.PotionMixData;
import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.CraftingData;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData;
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket; import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment; import org.geysermc.geyser.inventory.item.Enchantment.JavaEnchantment;
@ -181,12 +181,15 @@ public final class Registries {
POTION_MIXES = SimpleRegistry.create(PotionMixRegistryLoader::new); POTION_MIXES = SimpleRegistry.create(PotionMixRegistryLoader::new);
ENCHANTMENTS = SimpleMappedRegistry.create("mappings/enchantments.json", EnchantmentRegistryLoader::new); ENCHANTMENTS = SimpleMappedRegistry.create("mappings/enchantments.json", EnchantmentRegistryLoader::new);
// TEMPORARY FIX TO MAKE OLD BIOMES NBT WORK WITH 1.19.30 // Remove unneeded client generation data from NbtMapBuilder
NbtMapBuilder biomesNbt = NbtMap.builder(); NbtMapBuilder biomesNbt = NbtMap.builder();
for (Map.Entry<String, Object> entry : BIOMES_NBT.get().entrySet()) { for (Map.Entry<String, Object> entry : BIOMES_NBT.get().entrySet()) {
String key = entry.getKey(); String key = entry.getKey();
NbtMapBuilder value = ((NbtMap) entry.getValue()).toBuilder(); NbtMapBuilder value = ((NbtMap) entry.getValue()).toBuilder();
value.put("name_hash", key); value.remove("minecraft:consolidated_features");
value.remove("minecraft:multinoise_generation_rules");
value.remove("minecraft:surface_material_adjustments");
value.remove( "minecraft:surface_parameters");
biomesNbt.put(key, value.build()); biomesNbt.put(key, value.build());
} }
BIOMES_NBT.set(biomesNbt.build()); BIOMES_NBT.set(biomesNbt.build());

View file

@ -25,9 +25,9 @@
package org.geysermc.geyser.registry.loader; package org.geysermc.geyser.registry.loader;
import com.nukkitx.nbt.NBTInputStream; import org.cloudburstmc.nbt.NBTInputStream;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtUtils; import org.cloudburstmc.nbt.NbtUtils;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
/** /**

View file

@ -25,7 +25,7 @@
package org.geysermc.geyser.registry.loader; package org.geysermc.geyser.registry.loader;
import org.cloudburstmc.protocol.bedrock.data.inventory.PotionMixData; import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.PotionMixData;
import org.geysermc.geyser.inventory.item.Potion; import org.geysermc.geyser.inventory.item.Potion;
import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;

View file

@ -28,24 +28,16 @@ package org.geysermc.geyser.registry.populator;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.nukkitx.nbt.NBTInputStream;
import com.nukkitx.nbt.NbtList;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.*;
import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; import org.cloudburstmc.nbt.*;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.cloudburstmc.protocol.bedrock.codec.v527.Bedrock_v527;
import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544; import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544;
import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleBlockDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleBlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleDefinitionRegistry;
import org.cloudburstmc.protocol.common.DefinitionRegistry; import org.cloudburstmc.protocol.common.DefinitionRegistry;
import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.physics.PistonBehavior; import org.geysermc.geyser.level.physics.PistonBehavior;
@ -56,12 +48,7 @@ import org.geysermc.geyser.util.BlockUtils;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayDeque; import java.util.*;
import java.util.Arrays;
import java.util.Deque;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@ -84,13 +71,9 @@ public final class BlockRegistryPopulator {
private static void registerBedrockBlocks() { private static void registerBedrockBlocks() {
BiFunction<String, NbtMapBuilder, String> emptyMapper = (bedrockIdentifier, statesBuilder) -> null; BiFunction<String, NbtMapBuilder, String> emptyMapper = (bedrockIdentifier, statesBuilder) -> null;
ImmutableMap<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> blockMappers = ImmutableMap.<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>>builder() ImmutableMap<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> blockMappers = ImmutableMap.<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>>builder()
.put(ObjectIntPair.of("1_19_0", Bedrock_v527.CODEC.getProtocolVersion()), (bedrockIdentifier, statesBuilder) -> { .put(ObjectIntPair.of("1_19_20", Bedrock_v544.CODEC.getProtocolVersion()), emptyMapper)
if (bedrockIdentifier.equals("minecraft:muddy_mangrove_roots")) { .put(ObjectIntPair.of("1_19_50", Bedrock_v560.CODEC.getProtocolVersion()), emptyMapper)
statesBuilder.remove("pillar_axis"); .build();
}
return null;
})
.put(ObjectIntPair.of("1_19_20", Bedrock_v544.CODEC.getProtocolVersion()), emptyMapper).build();
for (Map.Entry<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> palette : blockMappers.entrySet()) { for (Map.Entry<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> palette : blockMappers.entrySet()) {
NbtList<NbtMap> blocksTag; NbtList<NbtMap> blocksTag;
@ -129,7 +112,7 @@ public final class BlockRegistryPopulator {
BiFunction<String, NbtMapBuilder, String> stateMapper = blockMappers.getOrDefault(palette.getKey(), emptyMapper); BiFunction<String, NbtMapBuilder, String> stateMapper = blockMappers.getOrDefault(palette.getKey(), emptyMapper);
BlockDefinition[] javaToBedrockBlocks = new BlockDefinition[BLOCKS_JSON.size()]; BlockDefinition[] javaToBedrockBlocks = new BlockDefinition[BLOCKS_JSON.size()];
DefinitionRegistry.Builder<BlockDefinition> registry = SimpleDefinitionRegistry.builder(); SimpleDefinitionRegistry.Builder<BlockDefinition> registry = SimpleDefinitionRegistry.builder();
Map<String, NbtMap> flowerPotBlocks = new Object2ObjectOpenHashMap<>(); Map<String, NbtMap> flowerPotBlocks = new Object2ObjectOpenHashMap<>();
Map<NbtMap, BlockDefinition> itemFrames = new Object2ObjectOpenHashMap<>(); Map<NbtMap, BlockDefinition> itemFrames = new Object2ObjectOpenHashMap<>();

View file

@ -26,8 +26,8 @@
package org.geysermc.geyser.registry.populator; package org.geysermc.geyser.registry.populator;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtUtils; import org.cloudburstmc.nbt.NbtUtils;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserBootstrap;

View file

@ -26,9 +26,9 @@
package org.geysermc.geyser.registry.populator; package org.geysermc.geyser.registry.populator;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
@ -174,6 +174,33 @@ public class CustomItemRegistryPopulator {
computeArmorProperties(mapping.getArmorType(), mapping.getProtectionValue(), componentBuilder); computeArmorProperties(mapping.getArmorType(), mapping.getProtectionValue(), componentBuilder);
} }
if (mapping.getFirstBlockRuntimeId() != null) {
computeBlockItemProperties(mapping.getBedrockIdentifier(), componentBuilder);
}
if (mapping.isEdible()) {
computeConsumableProperties(itemProperties, componentBuilder, 1, false);
}
if (mapping.isEntityPlacer()) {
computeEntityPlacerProperties(componentBuilder);
}
switch (mapping.getBedrockIdentifier()) {
case "minecraft:fire_charge", "minecraft:flint_and_steel" -> {
computeBlockItemProperties("minecraft:fire", componentBuilder);
}
case "minecraft:bow", "minecraft:crossbow", "minecraft:trident" -> {
computeChargeableProperties(itemProperties, componentBuilder);
}
case "minecraft:honey_bottle", "minecraft:milk_bucket", "minecraft:potion" -> {
computeConsumableProperties(itemProperties, componentBuilder, 2, true);
}
case "minecraft:experience_bottle", "minecraft:egg", "minecraft:ender_pearl", "minecraft:ender_eye", "minecraft:lingering_potion", "minecraft:snowball", "minecraft:splash_potion" -> {
computeThrowableProperties(componentBuilder);
}
}
computeRenderOffsets(false, customItemData, componentBuilder); computeRenderOffsets(false, customItemData, componentBuilder);
componentBuilder.putCompound("item_properties", itemProperties.build()); componentBuilder.putCompound("item_properties", itemProperties.build());
@ -310,6 +337,48 @@ public class CustomItemRegistryPopulator {
} }
} }
private static void computeBlockItemProperties(String blockItem, NbtMapBuilder componentBuilder) {
// carved pumpkin should be able to be worn and for that we would need to add wearable and armor with protection 0 here
// however this would have the side effect of preventing carved pumpkins from working as an attachable on the RP side outside the head slot
// it also causes the item to glitch when right clicked to "equip" so this should only be added here later if these issues can be overcome
// all block items registered should be given this component to prevent double placement
componentBuilder.putCompound("minecraft:block_placer", NbtMap.builder().putString("block", blockItem).build());
}
private static void computeChargeableProperties(NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder) {
// setting high use_duration prevents the consume animation from playing
itemProperties.putInt("use_duration", Integer.MAX_VALUE);
// display item as tool (mainly for crossbow and bow)
itemProperties.putBoolean("hand_equipped", true);
// ensure client moves at slow speed while charging (note: this was calculated by hand as the movement modifer value does not seem to scale linearly)
componentBuilder.putCompound("minecraft:chargeable", NbtMap.builder().putFloat("movement_modifier", 0.35F).build());
}
private static void computeConsumableProperties(NbtMapBuilder itemProperties, NbtMapBuilder componentBuilder, int useAnimation, boolean canAlwaysEat) {
// this is the duration of the use animation in ticks; note that in behavior packs this is set as a float in seconds, but over the network it is an int in ticks
itemProperties.putInt("use_duration", 32);
// this dictates that the item will use the eat or drink animation (in the first person) and play eat or drink sounds
// note that in behavior packs this is set as the string "eat" or "drink", but over the network it as an int, with these values being 1 and 2 respectively
itemProperties.putInt("use_animation", useAnimation);
// this component is required to allow the eat animation to play
componentBuilder.putCompound("minecraft:food", NbtMap.builder().putBoolean("can_always_eat", canAlwaysEat).build());
}
private static void computeEntityPlacerProperties(NbtMapBuilder componentBuilder) {
// all items registered that place entities should be given this component to prevent double placement
// it is okay that the entity here does not match the actual one since we control what entity actually spawns
componentBuilder.putCompound("minecraft:entity_placer", NbtMap.builder().putString("entity", "minecraft:minecart").build());
}
private static void computeThrowableProperties(NbtMapBuilder componentBuilder) {
// allows item to be thrown when holding down right click (individual presses are required w/o this component)
componentBuilder.putCompound("minecraft:throwable", NbtMap.builder().putBoolean("do_swing_animation", true).build());
// this must be set to something for the swing animation to play
// it is okay that the projectile here does not match the actual one since we control what entity actually spawns
componentBuilder.putCompound("minecraft:projectile", NbtMap.builder().putString("projectile_entity", "minecraft:snowball").build());
}
private static void computeRenderOffsets(boolean isHat, CustomItemData customItemData, NbtMapBuilder componentBuilder) { private static void computeRenderOffsets(boolean isHat, CustomItemData customItemData, NbtMapBuilder componentBuilder) {
if (isHat) { if (isHat) {
componentBuilder.remove("minecraft:render_offsets"); componentBuilder.remove("minecraft:render_offsets");

View file

@ -28,30 +28,19 @@ package org.geysermc.geyser.registry.populator;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder; import com.google.common.collect.MultimapBuilder;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType;
import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.Pair;
import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.objects.*;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.cloudburstmc.nbt.NbtMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import org.cloudburstmc.nbt.NbtMapBuilder;
import it.unimi.dsi.fastutil.ints.IntSet; import org.cloudburstmc.nbt.NbtType;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.cloudburstmc.protocol.bedrock.codec.v527.Bedrock_v527;
import org.cloudburstmc.protocol.bedrock.codec.v534.Bedrock_v534;
import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544; import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544;
import org.cloudburstmc.protocol.bedrock.codec.v560.Bedrock_v560;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent; import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.SimpleDefinitionRegistry;
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.common.DefinitionRegistry; import org.cloudburstmc.protocol.common.SimpleDefinitionRegistry;
import org.geysermc.geyser.GeyserBootstrap; import org.geysermc.geyser.GeyserBootstrap;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.item.custom.CustomItemData; import org.geysermc.geyser.api.item.custom.CustomItemData;
@ -61,23 +50,12 @@ import org.geysermc.geyser.inventory.item.StoredItemMappings;
import org.geysermc.geyser.item.GeyserCustomMappingData; import org.geysermc.geyser.item.GeyserCustomMappingData;
import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.*;
import org.geysermc.geyser.registry.type.GeyserMappingItem;
import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.registry.type.NonVanillaItemRegistration;
import org.geysermc.geyser.registry.type.PaletteItem;
import org.geysermc.geyser.util.ItemUtils; import org.geysermc.geyser.util.ItemUtils;
import org.geysermc.geyser.util.collection.FixedInt2IntMap; import org.geysermc.geyser.util.collection.FixedInt2IntMap;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
/** /**
@ -90,10 +68,8 @@ public class ItemRegistryPopulator {
public static void populate() { public static void populate() {
Map<String, PaletteVersion> paletteVersions = new Object2ObjectOpenHashMap<>(); Map<String, PaletteVersion> paletteVersions = new Object2ObjectOpenHashMap<>();
paletteVersions.put("1_19_0", new PaletteVersion(Bedrock_v527.CODEC.getProtocolVersion(),
Collections.singletonMap("minecraft:trader_llama_spawn_egg", "minecraft:llama_spawn_egg")));
paletteVersions.put("1_19_10", new PaletteVersion(Bedrock_v534.CODEC.getProtocolVersion(), Collections.emptyMap()));
paletteVersions.put("1_19_20", new PaletteVersion(Bedrock_v544.CODEC.getProtocolVersion(), Collections.emptyMap())); paletteVersions.put("1_19_20", new PaletteVersion(Bedrock_v544.CODEC.getProtocolVersion(), Collections.emptyMap()));
paletteVersions.put("1_19_50", new PaletteVersion(Bedrock_v560.CODEC.getProtocolVersion(), Collections.emptyMap()));
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap(); GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
@ -147,7 +123,7 @@ public class ItemRegistryPopulator {
int nextFreeBedrockId = 0; int nextFreeBedrockId = 0;
List<ComponentItemData> componentItemData = new ObjectArrayList<>(); List<ComponentItemData> componentItemData = new ObjectArrayList<>();
DefinitionRegistry.Builder<ItemDefinition> registry = SimpleDefinitionRegistry.builder(); SimpleDefinitionRegistry.Builder<ItemDefinition> registry = SimpleDefinitionRegistry.builder();
Map<String, ItemDefinition> definitions = new Object2ObjectLinkedOpenHashMap<>(); Map<String, ItemDefinition> definitions = new Object2ObjectLinkedOpenHashMap<>();
for (PaletteItem entry : itemEntries) { for (PaletteItem entry : itemEntries) {

View file

@ -29,13 +29,13 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType; import com.github.steveice10.mc.protocol.data.game.recipe.RecipeType;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtUtils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import org.cloudburstmc.protocol.bedrock.data.inventory.CraftingData; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtUtils;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.crafting.CraftingData;
import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount; import org.cloudburstmc.protocol.bedrock.data.inventory.descriptor.ItemDescriptorWithCount;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.recipe.GeyserRecipe; import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
@ -50,15 +50,7 @@ import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.*;
import java.util.Base64;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import static org.geysermc.geyser.util.InventoryUtils.LAST_RECIPE_NET_ID; import static org.geysermc.geyser.util.InventoryUtils.LAST_RECIPE_NET_ID;
@ -90,8 +82,6 @@ public class RecipeRegistryPopulator {
Collections.singletonList(CraftingData.fromMulti(UUID.fromString("d392b075-4ba1-40ae-8789-af868d56f6ce"), ++LAST_RECIPE_NET_ID))); Collections.singletonList(CraftingData.fromMulti(UUID.fromString("d392b075-4ba1-40ae-8789-af868d56f6ce"), ++LAST_RECIPE_NET_ID)));
craftingData.put(RecipeType.CRAFTING_SPECIAL_MAPCLONING, craftingData.put(RecipeType.CRAFTING_SPECIAL_MAPCLONING,
Collections.singletonList(CraftingData.fromMulti(UUID.fromString("85939755-ba10-4d9d-a4cc-efb7a8e943c4"), ++LAST_RECIPE_NET_ID))); Collections.singletonList(CraftingData.fromMulti(UUID.fromString("85939755-ba10-4d9d-a4cc-efb7a8e943c4"), ++LAST_RECIPE_NET_ID)));
craftingData.put(RecipeType.CRAFTING_SPECIAL_BANNERADDPATTERN,
Collections.singletonList(CraftingData.fromMulti(UUID.fromString("b5c5d105-75a2-4076-af2b-923ea2bf4bf0"), ++LAST_RECIPE_NET_ID)));
// https://github.com/pmmp/PocketMine-MP/blob/stable/src/pocketmine/inventory/MultiRecipe.php // https://github.com/pmmp/PocketMine-MP/blob/stable/src/pocketmine/inventory/MultiRecipe.php

View file

@ -25,14 +25,11 @@
package org.geysermc.geyser.registry.type; package org.geysermc.geyser.registry.type;
import com.nukkitx.nbt.NbtList;
import com.nukkitx.nbt.NbtMap;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import lombok.Builder; import lombok.Builder;
import lombok.Value; import lombok.Value;
import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.common.DefinitionRegistry; import org.cloudburstmc.protocol.common.DefinitionRegistry;
import java.util.Map; import java.util.Map;
@ -78,6 +75,6 @@ public class BlockMappings {
} }
public boolean isItemFrame(BlockDefinition definition) { public boolean isItemFrame(BlockDefinition definition) {
return this.itemFrames.containsKey(definition.getState()); return this.itemFrames.containsKey(definition.getRuntimeId());
} }
} }

View file

@ -48,4 +48,6 @@ public class GeyserMappingItem {
@JsonProperty("repair_materials") List<String> repairMaterials; @JsonProperty("repair_materials") List<String> repairMaterials;
@JsonProperty("has_suspicious_stew_effect") boolean hasSuspiciousStewEffect = false; @JsonProperty("has_suspicious_stew_effect") boolean hasSuspiciousStewEffect = false;
@JsonProperty("dye_color") int dyeColor = -1; @JsonProperty("dye_color") int dyeColor = -1;
@JsonProperty("is_edible") boolean edible = false;
@JsonProperty("is_entity_placer") boolean entityPlacer = false;
} }

View file

@ -25,7 +25,6 @@
package org.geysermc.geyser.session; package org.geysermc.geyser.session;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.auth.exception.request.InvalidCredentialsException; import com.github.steveice10.mc.auth.exception.request.InvalidCredentialsException;
import com.github.steveice10.mc.auth.exception.request.RequestException; import com.github.steveice10.mc.auth.exception.request.RequestException;
@ -58,19 +57,13 @@ 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.mc.protocol.packet.login.serverbound.ServerboundCustomQueryPacket;
import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.BuiltinFlags;
import com.github.steveice10.packetlib.Session; import com.github.steveice10.packetlib.Session;
import com.github.steveice10.packetlib.event.session.ConnectedEvent; import com.github.steveice10.packetlib.event.session.*;
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.packet.Packet;
import com.github.steveice10.packetlib.tcp.TcpClientSession; import com.github.steveice10.packetlib.tcp.TcpClientSession;
import com.github.steveice10.packetlib.tcp.TcpSession; import com.github.steveice10.packetlib.tcp.TcpSession;
import com.nimbusds.jwt.SignedJWT; import com.nimbusds.jwt.SignedJWT;
import com.nukkitx.nbt.NbtMap;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import io.netty.channel.EventLoop; import io.netty.channel.EventLoop;
import it.unimi.dsi.fastutil.bytes.ByteArrays;
import it.unimi.dsi.fastutil.ints.Int2IntMap; import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
@ -89,23 +82,10 @@ import lombok.experimental.Accessors;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.common.value.qual.IntRange; import org.checkerframework.common.value.qual.IntRange;
import org.cloudburstmc.math.GenericMath; import org.cloudburstmc.math.GenericMath;
import org.cloudburstmc.math.vector.Vector2f; import org.cloudburstmc.math.vector.*;
import org.cloudburstmc.math.vector.Vector2i; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.math.vector.Vector3d;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.BedrockServerSession; import org.cloudburstmc.protocol.bedrock.BedrockServerSession;
import org.cloudburstmc.protocol.bedrock.data.Ability; import org.cloudburstmc.protocol.bedrock.data.*;
import org.cloudburstmc.protocol.bedrock.data.AbilityLayer;
import org.cloudburstmc.protocol.bedrock.data.AdventureSetting;
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
import org.cloudburstmc.protocol.bedrock.data.AuthoritativeMovementMode;
import org.cloudburstmc.protocol.bedrock.data.ChatRestrictionLevel;
import org.cloudburstmc.protocol.bedrock.data.GamePublishSetting;
import org.cloudburstmc.protocol.bedrock.data.GameRuleData;
import org.cloudburstmc.protocol.bedrock.data.GameType;
import org.cloudburstmc.protocol.bedrock.data.PlayerPermission;
import org.cloudburstmc.protocol.bedrock.data.SoundEvent;
import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission; import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.cloudburstmc.protocol.bedrock.packet.*; import org.cloudburstmc.protocol.bedrock.packet.*;
@ -137,7 +117,6 @@ import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
import org.geysermc.geyser.level.JavaDimension; import org.geysermc.geyser.level.JavaDimension;
import org.geysermc.geyser.level.WorldManager; import org.geysermc.geyser.level.WorldManager;
import org.geysermc.geyser.level.physics.CollisionManager; import org.geysermc.geyser.level.physics.CollisionManager;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.network.netty.LocalSession; import org.geysermc.geyser.network.netty.LocalSession;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.BlockMappings; import org.geysermc.geyser.registry.type.BlockMappings;
@ -145,20 +124,7 @@ import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
import org.geysermc.geyser.session.auth.AuthData; import org.geysermc.geyser.session.auth.AuthData;
import org.geysermc.geyser.session.auth.BedrockClientData; import org.geysermc.geyser.session.auth.BedrockClientData;
import org.geysermc.geyser.session.cache.AdvancementsCache; import org.geysermc.geyser.session.cache.*;
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.skin.FloodgateSkinUploader;
import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.text.MinecraftLocale; import org.geysermc.geyser.text.MinecraftLocale;
@ -174,14 +140,7 @@ import java.net.ConnectException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList; import java.util.*;
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.CompletableFuture;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -336,6 +295,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
*/ */
@Setter @Setter
private String worldName = null; private String worldName = null;
/**
* As of Java 1.19.3, the client only uses these for commands.
*/
@Setter
private String[] levels;
private boolean sneaking; private boolean sneaking;
@ -656,6 +620,12 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
creativePacket.setContents(this.itemMappings.getCreativeItems()); creativePacket.setContents(this.itemMappings.getCreativeItems());
upstream.sendPacket(creativePacket); upstream.sendPacket(creativePacket);
// Potion mixes are registered by default, as they are needed to be able to put ingredients into the brewing stand.
CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
craftingDataPacket.setCleanRecipes(true);
craftingDataPacket.getPotionMixData().addAll(Registries.POTION_MIXES.get());
upstream.sendPacket(craftingDataPacket);
PlayStatusPacket playStatusPacket = new PlayStatusPacket(); PlayStatusPacket playStatusPacket = new PlayStatusPacket();
playStatusPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN); playStatusPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN);
upstream.sendPacket(playStatusPacket); upstream.sendPacket(playStatusPacket);
@ -1389,14 +1359,14 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
* Sends a chat message to the Java server. * Sends a chat message to the Java server.
*/ */
public void sendChat(String message) { public void sendChat(String message) {
sendDownstreamPacket(new ServerboundChatPacket(message, Instant.now().toEpochMilli(), 0L, ByteArrays.EMPTY_ARRAY, false, Collections.emptyList(), null)); sendDownstreamPacket(new ServerboundChatPacket(message, Instant.now().toEpochMilli(), 0L, null, 0, new BitSet()));
} }
/** /**
* Sends a command to the Java server. * Sends a command to the Java server.
*/ */
public void sendCommand(String command) { public void sendCommand(String command) {
sendDownstreamPacket(new ServerboundChatCommandPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), false, Collections.emptyList(), null)); sendDownstreamPacket(new ServerboundChatCommandPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyList(), 0, new BitSet()));
} }
public void setServerRenderDistance(int renderDistance) { public void setServerRenderDistance(int renderDistance) {
@ -1454,7 +1424,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
startGamePacket.setRotation(Vector2f.from(1, 1)); startGamePacket.setRotation(Vector2f.from(1, 1));
startGamePacket.setSeed(-1L); startGamePacket.setSeed(-1L);
startGamePacket.setDimensionId(DimensionUtils.javaToBedrock(dimension)); startGamePacket.setDimensionId(DimensionUtils.javaToBedrock(chunkCache.getBedrockDimension()));
startGamePacket.setGeneratorId(1); startGamePacket.setGeneratorId(1);
startGamePacket.setLevelGameType(GameType.SURVIVAL); startGamePacket.setLevelGameType(GameType.SURVIVAL);
startGamePacket.setDifficulty(1); startGamePacket.setDifficulty(1);
@ -1655,76 +1625,40 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
boolean spectator = gameMode == GameMode.SPECTATOR; boolean spectator = gameMode == GameMode.SPECTATOR;
boolean worldImmutable = gameMode == GameMode.ADVENTURE || spectator; boolean worldImmutable = gameMode == GameMode.ADVENTURE || spectator;
if (GameProtocol.supports1_19_10(this)) { UpdateAdventureSettingsPacket adventureSettingsPacket = new UpdateAdventureSettingsPacket();
UpdateAdventureSettingsPacket adventureSettingsPacket = new UpdateAdventureSettingsPacket(); adventureSettingsPacket.setNoMvP(false);
adventureSettingsPacket.setNoMvP(false); adventureSettingsPacket.setNoPvM(false);
adventureSettingsPacket.setNoPvM(false); adventureSettingsPacket.setImmutableWorld(worldImmutable);
adventureSettingsPacket.setImmutableWorld(worldImmutable); adventureSettingsPacket.setShowNameTags(false);
adventureSettingsPacket.setShowNameTags(false); adventureSettingsPacket.setAutoJump(true);
adventureSettingsPacket.setAutoJump(true); sendUpstreamPacket(adventureSettingsPacket);
sendUpstreamPacket(adventureSettingsPacket);
UpdateAbilitiesPacket updateAbilitiesPacket = new UpdateAbilitiesPacket(); UpdateAbilitiesPacket updateAbilitiesPacket = new UpdateAbilitiesPacket();
updateAbilitiesPacket.setUniqueEntityId(bedrockId); updateAbilitiesPacket.setUniqueEntityId(bedrockId);
updateAbilitiesPacket.setCommandPermission(commandPermission); updateAbilitiesPacket.setCommandPermission(commandPermission);
updateAbilitiesPacket.setPlayerPermission(playerPermission); updateAbilitiesPacket.setPlayerPermission(playerPermission);
AbilityLayer abilityLayer = new AbilityLayer(); AbilityLayer abilityLayer = new AbilityLayer();
Set<Ability> abilities = abilityLayer.getAbilityValues(); Set<Ability> abilities = abilityLayer.getAbilityValues();
if (canFly || spectator) { if (canFly || spectator) {
abilities.add(Ability.MAY_FLY); abilities.add(Ability.MAY_FLY);
}
// Default stuff we have to fill in
abilities.add(Ability.BUILD);
abilities.add(Ability.MINE);
// Needed so you can drop items
abilities.add(Ability.DOORS_AND_SWITCHES);
if (gameMode == GameMode.CREATIVE) {
// Needed so the client doesn't attempt to take away items
abilities.add(Ability.INSTABUILD);
}
if (commandPermission == CommandPermission.GAME_DIRECTORS) {
// Fixes a bug? since 1.19.11 where the player can change their gamemode in Bedrock settings and
// a packet is not sent to the server.
// https://github.com/GeyserMC/Geyser/issues/3191
abilities.add(Ability.OPERATOR_COMMANDS);
}
if (flying || spectator) {
if (spectator && !flying) {
// We're "flying locked" in this gamemode
flying = true;
ServerboundPlayerAbilitiesPacket abilitiesPacket = new ServerboundPlayerAbilitiesPacket(true);
sendDownstreamPacket(abilitiesPacket);
}
abilities.add(Ability.FLYING);
}
if (spectator) {
abilities.add(Ability.NO_CLIP);
}
abilityLayer.setLayerType(AbilityLayer.Type.BASE);
abilityLayer.setFlySpeed(flySpeed);
// https://github.com/GeyserMC/Geyser/issues/3139 as of 1.19.10
abilityLayer.setWalkSpeed(walkSpeed == 0f ? 0.01f : walkSpeed);
Collections.addAll(abilityLayer.getAbilitiesSet(), USED_ABILITIES);
updateAbilitiesPacket.getAbilityLayers().add(abilityLayer);
sendUpstreamPacket(updateAbilitiesPacket);
return;
} }
AdventureSettingsPacket adventureSettingsPacket = new AdventureSettingsPacket(); // Default stuff we have to fill in
adventureSettingsPacket.setUniqueEntityId(bedrockId); abilities.add(Ability.BUILD);
adventureSettingsPacket.setCommandPermission(commandPermission); abilities.add(Ability.MINE);
adventureSettingsPacket.setPlayerPermission(playerPermission); // Needed so you can drop items
abilities.add(Ability.DOORS_AND_SWITCHES);
if (gameMode == GameMode.CREATIVE) {
// Needed so the client doesn't attempt to take away items
abilities.add(Ability.INSTABUILD);
}
Set<AdventureSetting> flags = adventureSettingsPacket.getSettings(); if (commandPermission == CommandPermission.GAME_DIRECTORS) {
if (canFly || spectator) { // Fixes a bug? since 1.19.11 where the player can change their gamemode in Bedrock settings and
flags.add(AdventureSetting.MAY_FLY); // a packet is not sent to the server.
// https://github.com/GeyserMC/Geyser/issues/3191
abilities.add(Ability.OPERATOR_COMMANDS);
} }
if (flying || spectator) { if (flying || spectator) {
@ -1734,20 +1668,21 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
ServerboundPlayerAbilitiesPacket abilitiesPacket = new ServerboundPlayerAbilitiesPacket(true); ServerboundPlayerAbilitiesPacket abilitiesPacket = new ServerboundPlayerAbilitiesPacket(true);
sendDownstreamPacket(abilitiesPacket); sendDownstreamPacket(abilitiesPacket);
} }
flags.add(AdventureSetting.FLYING); abilities.add(Ability.FLYING);
}
if (worldImmutable) {
flags.add(AdventureSetting.WORLD_IMMUTABLE);
} }
if (spectator) { if (spectator) {
flags.add(AdventureSetting.NO_CLIP); abilities.add(Ability.NO_CLIP);
} }
flags.add(AdventureSetting.AUTO_JUMP); abilityLayer.setLayerType(AbilityLayer.Type.BASE);
abilityLayer.setFlySpeed(flySpeed);
// https://github.com/GeyserMC/Geyser/issues/3139 as of 1.19.10
abilityLayer.setWalkSpeed(walkSpeed == 0f ? 0.01f : walkSpeed);
Collections.addAll(abilityLayer.getAbilitiesSet(), USED_ABILITIES);
sendUpstreamPacket(adventureSettingsPacket); updateAbilitiesPacket.getAbilityLayers().add(abilityLayer);
sendUpstreamPacket(updateAbilitiesPacket);
} }
private int getRenderDistance() { private int getRenderDistance() {

View file

@ -43,6 +43,8 @@ import java.util.Optional;
public class AsteriskSerializer extends StdSerializer<Object> implements ContextualSerializer { public class AsteriskSerializer extends StdSerializer<Object> implements ContextualSerializer {
public static final String[] NON_SENSITIVE_ADDRESSES = {"", "0.0.0.0", "localhost", "127.0.0.1", "auto", "unknown"};
public static boolean showSensitive = false; public static boolean showSensitive = false;
@Target({ElementType.FIELD}) @Target({ElementType.FIELD})
@ -91,11 +93,11 @@ public class AsteriskSerializer extends StdSerializer<Object> implements Context
} }
private boolean isSensitiveIp(String ip) { private boolean isSensitiveIp(String ip) {
if (ip.equalsIgnoreCase("localhost") || ip.equalsIgnoreCase("auto")) { for (String address : NON_SENSITIVE_ADDRESSES) {
// `auto` should not be shown unless there is an obscure issue with setting the localhost address if (address.equalsIgnoreCase(ip)) {
return false; return false;
}
} }
return true;
return !ip.isEmpty() && !ip.equals("0.0.0.0") && !ip.equals("127.0.0.1");
} }
} }

View file

@ -25,7 +25,7 @@
package org.geysermc.geyser.text; package org.geysermc.geyser.text;
import com.github.steveice10.mc.protocol.data.game.BuiltinChatType; import com.github.steveice10.mc.protocol.data.game.chat.BuiltinChatType;
import org.cloudburstmc.protocol.bedrock.packet.TextPacket; import org.cloudburstmc.protocol.bedrock.packet.TextPacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;

View file

@ -65,8 +65,8 @@ public abstract class AbstractBlockInventoryTranslator extends BaseInventoryTran
} }
@Override @Override
public void prepareInventory(GeyserSession session, Inventory inventory) { public boolean prepareInventory(GeyserSession session, Inventory inventory) {
holder.prepareInventory(this, session, inventory); return holder.prepareInventory(this, session, inventory);
} }
@Override @Override

View file

@ -27,12 +27,12 @@ package org.geysermc.geyser.translator.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackResponse; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.CraftRecipeOptionalAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.CraftRecipeOptionalStackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestActionType;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
import org.geysermc.geyser.inventory.AnvilContainer; import org.geysermc.geyser.inventory.AnvilContainer;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.Inventory;
@ -49,27 +49,29 @@ public class AnvilInventoryTranslator extends AbstractBlockInventoryTranslator {
} }
@Override @Override
protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { protected boolean shouldHandleRequestFirst(ItemStackRequestAction action, Inventory inventory) {
return action.getType() == StackRequestActionType.CRAFT_RECIPE_OPTIONAL; return action.getType() == ItemStackRequestActionType.CRAFT_RECIPE_OPTIONAL;
} }
@Override @Override
protected ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { protected ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
// Guarded by shouldHandleRequestFirst check // Guarded by shouldHandleRequestFirst check
CraftRecipeOptionalStackRequestActionData data = (CraftRecipeOptionalStackRequestActionData) request.getActions()[0]; CraftRecipeOptionalAction data = (CraftRecipeOptionalAction) request.getActions()[0];
AnvilContainer container = (AnvilContainer) inventory; AnvilContainer container = (AnvilContainer) inventory;
// Required as of 1.18.30 - FilterTextPackets no longer appear to be sent if (request.getFilterStrings().length != 0) {
String name = request.getFilterStrings()[data.getFilteredStringIndex()]; // Required as of 1.18.30 - FilterTextPackets no longer appear to be sent
if (!Objects.equals(name, container.getNewName())) { String name = request.getFilterStrings()[data.getFilteredStringIndex()];
container.checkForRename(session, name); 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); return super.translateRequest(session, inventory, request);
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainer()) {
case ANVIL_INPUT -> 0; case ANVIL_INPUT -> 0;
case ANVIL_MATERIAL -> 1; case ANVIL_MATERIAL -> 1;

View file

@ -27,12 +27,8 @@ package org.geysermc.geyser.translator.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.Container;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.SlotType;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
public abstract class BaseInventoryTranslator extends InventoryTranslator { public abstract class BaseInventoryTranslator extends InventoryTranslator {
@ -46,7 +42,7 @@ public abstract class BaseInventoryTranslator extends InventoryTranslator {
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
int slotnum = slotInfoData.getSlot(); int slotnum = slotInfoData.getSlot();
switch (slotInfoData.getContainer()) { switch (slotInfoData.getContainer()) {
case HOTBAR_AND_INVENTORY: case HOTBAR_AND_INVENTORY:

View file

@ -27,17 +27,17 @@ package org.geysermc.geyser.translator.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetBeaconPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetBeaconPacket;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder;
import it.unimi.dsi.fastutil.ints.IntSets; import it.unimi.dsi.fastutil.ints.IntSets;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackResponse; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.BeaconPaymentAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.BeaconPaymentStackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestActionType;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
import org.geysermc.geyser.inventory.BeaconContainer; import org.geysermc.geyser.inventory.BeaconContainer;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.BedrockContainerSlot;
@ -105,14 +105,14 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator
} }
@Override @Override
protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { protected boolean shouldHandleRequestFirst(ItemStackRequestAction action, Inventory inventory) {
return action.getType() == StackRequestActionType.BEACON_PAYMENT; return action.getType() == ItemStackRequestActionType.BEACON_PAYMENT;
} }
@Override @Override
public ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { public ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
// Input a beacon payment // Input a beacon payment
BeaconPaymentStackRequestActionData beaconPayment = (BeaconPaymentStackRequestActionData) request.getActions()[0]; BeaconPaymentAction beaconPayment = (BeaconPaymentAction) request.getActions()[0];
ServerboundSetBeaconPacket packet = new ServerboundSetBeaconPacket(toJava(beaconPayment.getPrimaryEffect()), toJava(beaconPayment.getSecondaryEffect())); ServerboundSetBeaconPacket packet = new ServerboundSetBeaconPacket(toJava(beaconPayment.getPrimaryEffect()), toJava(beaconPayment.getSecondaryEffect()));
session.sendDownstreamPacket(packet); session.sendDownstreamPacket(packet);
return acceptRequest(request, makeContainerEntries(session, inventory, IntSets.emptySet())); return acceptRequest(request, makeContainerEntries(session, inventory, IntSets.emptySet()));
@ -123,7 +123,7 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.BEACON_PAYMENT) { if (slotInfoData.getContainer() == ContainerSlotType.BEACON_PAYMENT) {
return 0; return 0;
} }

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.translator.inventory;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.cloudburstmc.protocol.bedrock.packet.ContainerSetDataPacket; import org.cloudburstmc.protocol.bedrock.packet.ContainerSetDataPacket;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.Inventory;
@ -68,7 +68,7 @@ public class BrewingInventoryTranslator extends AbstractBlockInventoryTranslator
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.BREWING_INPUT) { if (slotInfoData.getContainer() == ContainerSlotType.BREWING_INPUT) {
// Ingredient // Ingredient
return 3; return 3;

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.translator.inventory;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -53,7 +53,7 @@ public class CartographyInventoryTranslator extends AbstractBlockInventoryTransl
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainer()) {
case CARTOGRAPHY_INPUT -> 0; case CARTOGRAPHY_INPUT -> 0;
case CARTOGRAPHY_ADDITIONAL -> 1; case CARTOGRAPHY_ADDITIONAL -> 1;

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.translator.inventory;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.SlotType; import org.geysermc.geyser.inventory.SlotType;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
@ -62,7 +62,7 @@ public class CraftingInventoryTranslator extends AbstractBlockInventoryTranslato
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.CRAFTING_INPUT) { if (slotInfoData.getContainer() == ContainerSlotType.CRAFTING_INPUT) {
// Java goes from 1 - 9, left to right then up to down // Java goes from 1 - 9, left to right then up to down
// Bedrock is the same, but it starts from 32. // Bedrock is the same, but it starts from 32.

View file

@ -30,18 +30,14 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.Ser
import it.unimi.dsi.fastutil.ints.IntSets; import it.unimi.dsi.fastutil.ints.IntSets;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantOptionData; import org.cloudburstmc.protocol.bedrock.data.inventory.EnchantOptionData;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackResponse; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.CraftRecipeAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.CraftRecipeStackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestActionType;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
import org.cloudburstmc.protocol.bedrock.packet.PlayerEnchantOptionsPacket; import org.cloudburstmc.protocol.bedrock.packet.PlayerEnchantOptionsPacket;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.EnchantingContainer;
import org.geysermc.geyser.inventory.GeyserEnchantOption;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.item.Enchantment; import org.geysermc.geyser.inventory.item.Enchantment;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -107,14 +103,14 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla
} }
@Override @Override
protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { protected boolean shouldHandleRequestFirst(ItemStackRequestAction action, Inventory inventory) {
return action.getType() == StackRequestActionType.CRAFT_RECIPE; return action.getType() == ItemStackRequestActionType.CRAFT_RECIPE;
} }
@Override @Override
public ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { public ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
// Client has requested an item to be enchanted // Client has requested an item to be enchanted
CraftRecipeStackRequestActionData craftRecipeData = (CraftRecipeStackRequestActionData) request.getActions()[0]; CraftRecipeAction craftRecipeData = (CraftRecipeAction) request.getActions()[0];
EnchantingContainer enchantingInventory = (EnchantingContainer) inventory; EnchantingContainer enchantingInventory = (EnchantingContainer) inventory;
int javaSlot = -1; int javaSlot = -1;
for (int i = 0; i < enchantingInventory.getEnchantOptions().length; i++) { for (int i = 0; i < enchantingInventory.getEnchantOptions().length; i++) {
@ -137,7 +133,7 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.ENCHANTING_INPUT) { if (slotInfoData.getContainer() == ContainerSlotType.ENCHANTING_INPUT) {
return 0; return 0;
} }

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.translator.inventory;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
@ -37,7 +37,7 @@ public class GrindstoneInventoryTranslator extends AbstractBlockInventoryTransla
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainer()) {
case GRINDSTONE_INPUT -> 0; case GRINDSTONE_INPUT -> 0;
case GRINDSTONE_ADDITIONAL -> 1; case GRINDSTONE_ADDITIONAL -> 1;

View file

@ -30,18 +30,18 @@ import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient; import com.github.steveice10.mc.protocol.data.game.recipe.Ingredient;
import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerEntry;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemEntry;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackRequest;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackResponse;
import org.cloudburstmc.protocol.bedrock.data.inventory.ResponseStatus;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.*;
import org.cloudburstmc.protocol.bedrock.packet.ItemStackResponsePacket;
import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.ints.*;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.*;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponseContainer;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponseSlot;
import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponseStatus;
import org.cloudburstmc.protocol.bedrock.packet.ItemStackResponsePacket;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.inventory.*; import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.click.Click; import org.geysermc.geyser.inventory.click.Click;
@ -105,13 +105,13 @@ public abstract class InventoryTranslator {
public final int size; public final int size;
public abstract void prepareInventory(GeyserSession session, Inventory inventory); public abstract boolean prepareInventory(GeyserSession session, Inventory inventory);
public abstract void openInventory(GeyserSession session, Inventory inventory); public abstract void openInventory(GeyserSession session, Inventory inventory);
public abstract void closeInventory(GeyserSession session, Inventory inventory); public abstract void closeInventory(GeyserSession session, Inventory inventory);
public abstract void updateProperty(GeyserSession session, Inventory inventory, int key, int value); public abstract void updateProperty(GeyserSession session, Inventory inventory, int key, int value);
public abstract void updateInventory(GeyserSession session, Inventory inventory); public abstract void updateInventory(GeyserSession session, Inventory inventory);
public abstract void updateSlot(GeyserSession session, Inventory inventory, int slot); public abstract void updateSlot(GeyserSession session, Inventory inventory, int slot);
public abstract int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData); public abstract int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData);
public abstract int javaSlotToBedrock(int javaSlot); public abstract int javaSlotToBedrock(int javaSlot);
public abstract BedrockContainerSlot javaSlotToBedrockContainer(int javaSlot); public abstract BedrockContainerSlot javaSlotToBedrockContainer(int javaSlot);
public abstract SlotType getSlotType(int javaSlot); public abstract SlotType getSlotType(int javaSlot);
@ -141,12 +141,12 @@ public abstract class InventoryTranslator {
* Should be overrided if this request matches a certain criteria and shouldn't be treated normally. * Should be overrided if this request matches a certain criteria and shouldn't be treated normally.
* E.G. anvil renaming or enchanting * E.G. anvil renaming or enchanting
*/ */
protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { protected boolean shouldHandleRequestFirst(ItemStackRequestAction action, Inventory inventory) {
return false; return false;
} }
/** /**
* If {@link #shouldHandleRequestFirst(StackRequestActionData, Inventory)} returns true, this will be called * If {@link #shouldHandleRequestFirst(ItemStackRequestAction, Inventory)} returns true, this will be called
*/ */
protected ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { protected ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
return rejectRequest(request); return rejectRequest(request);
@ -158,7 +158,7 @@ public abstract class InventoryTranslator {
for (ItemStackRequest request : requests) { for (ItemStackRequest request : requests) {
ItemStackResponse response; ItemStackResponse response;
if (request.getActions().length > 0) { if (request.getActions().length > 0) {
StackRequestActionData firstAction = request.getActions()[0]; ItemStackRequestAction firstAction = request.getActions()[0];
if (shouldHandleRequestFirst(firstAction, inventory)) { if (shouldHandleRequestFirst(firstAction, inventory)) {
// Some special request that shouldn't be processed normally // Some special request that shouldn't be processed normally
response = translateSpecialRequest(session, inventory, request); response = translateSpecialRequest(session, inventory, request);
@ -176,7 +176,7 @@ public abstract class InventoryTranslator {
response = rejectRequest(request); response = rejectRequest(request);
} }
if (response.getResult() != ResponseStatus.OK) { if (response.getResult() != ItemStackResponseStatus.OK) {
// Sync our copy of the inventory with Bedrock's to prevent desyncs // Sync our copy of the inventory with Bedrock's to prevent desyncs
refresh = true; refresh = true;
} }
@ -197,12 +197,12 @@ public abstract class InventoryTranslator {
public ItemStackResponse translateRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { public ItemStackResponse translateRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
ClickPlan plan = new ClickPlan(session, this, inventory); ClickPlan plan = new ClickPlan(session, this, inventory);
IntSet affectedSlots = new IntOpenHashSet(); IntSet affectedSlots = new IntOpenHashSet();
for (StackRequestActionData action : request.getActions()) { for (ItemStackRequestAction action : request.getActions()) {
GeyserItemStack cursor = session.getPlayerInventory().getCursor(); GeyserItemStack cursor = session.getPlayerInventory().getCursor();
switch (action.getType()) { switch (action.getType()) {
case TAKE: case TAKE:
case PLACE: { case PLACE: {
TransferStackRequestActionData transferAction = (TransferStackRequestActionData) action; TransferItemStackRequestAction transferAction = (TransferItemStackRequestAction) action;
if (!(checkNetId(session, inventory, transferAction.getSource()) && checkNetId(session, inventory, transferAction.getDestination()))) { if (!(checkNetId(session, inventory, transferAction.getSource()) && checkNetId(session, inventory, transferAction.getDestination()))) {
if (session.getGeyser().getConfig().isDebugMode()) { if (session.getGeyser().getConfig().isDebugMode()) {
session.getGeyser().getLogger().error("DEBUG: About to reject TAKE/PLACE request made by " + session.bedrockUsername()); session.getGeyser().getLogger().error("DEBUG: About to reject TAKE/PLACE request made by " + session.bedrockUsername());
@ -290,9 +290,9 @@ public abstract class InventoryTranslator {
break; break;
} }
case SWAP: { case SWAP: {
SwapStackRequestActionData swapAction = (SwapStackRequestActionData) action; SwapAction swapAction = (SwapAction) action;
StackRequestSlotInfoData source = swapAction.getSource(); ItemStackRequestSlotData source = swapAction.getSource();
StackRequestSlotInfoData destination = swapAction.getDestination(); ItemStackRequestSlotData destination = swapAction.getDestination();
if (!(checkNetId(session, inventory, source) && checkNetId(session, inventory, destination))) { if (!(checkNetId(session, inventory, source) && checkNetId(session, inventory, destination))) {
if (session.getGeyser().getConfig().isDebugMode()) { if (session.getGeyser().getConfig().isDebugMode()) {
@ -352,7 +352,7 @@ public abstract class InventoryTranslator {
break; break;
} }
case DROP: { case DROP: {
DropStackRequestActionData dropAction = (DropStackRequestActionData) action; DropAction dropAction = (DropAction) action;
if (!checkNetId(session, inventory, dropAction.getSource())) if (!checkNetId(session, inventory, dropAction.getSource()))
return rejectRequest(request); return rejectRequest(request);
@ -381,7 +381,7 @@ public abstract class InventoryTranslator {
case CONSUME: { // Tends to be called for UI inventories case CONSUME: { // Tends to be called for UI inventories
if (inventory instanceof CartographyContainer) { if (inventory instanceof CartographyContainer) {
// TODO add this for more inventories? Only seems to glitch out the cartography table, though. // TODO add this for more inventories? Only seems to glitch out the cartography table, though.
ConsumeStackRequestActionData consumeData = (ConsumeStackRequestActionData) action; ConsumeAction consumeData = (ConsumeAction) action;
int sourceSlot = bedrockSlotToJava(consumeData.getSource()); int sourceSlot = bedrockSlotToJava(consumeData.getSource());
if ((sourceSlot == 0 && inventory.getItem(1).isEmpty()) || (sourceSlot == 1 && inventory.getItem(0).isEmpty())) { if ((sourceSlot == 0 && inventory.getItem(1).isEmpty()) || (sourceSlot == 1 && inventory.getItem(0).isEmpty())) {
@ -436,7 +436,7 @@ public abstract class InventoryTranslator {
ClickPlan plan = new ClickPlan(session, this, inventory); ClickPlan plan = new ClickPlan(session, this, inventory);
// Track all the crafting table slots to report back the contents of the slots after crafting // Track all the crafting table slots to report back the contents of the slots after crafting
IntSet affectedSlots = new IntOpenHashSet(); IntSet affectedSlots = new IntOpenHashSet();
for (StackRequestActionData action : request.getActions()) { for (ItemStackRequestAction action : request.getActions()) {
switch (action.getType()) { switch (action.getType()) {
case CRAFT_RECIPE: { case CRAFT_RECIPE: {
if (craftState != CraftState.START) { if (craftState != CraftState.START) {
@ -446,7 +446,7 @@ public abstract class InventoryTranslator {
break; break;
} }
case CRAFT_RESULTS_DEPRECATED: { case CRAFT_RESULTS_DEPRECATED: {
CraftResultsDeprecatedStackRequestActionData deprecatedCraftAction = (CraftResultsDeprecatedStackRequestActionData) action; CraftResultsDeprecatedAction deprecatedCraftAction = (CraftResultsDeprecatedAction) action;
if (craftState != CraftState.RECIPE_ID) { if (craftState != CraftState.RECIPE_ID) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -467,12 +467,12 @@ public abstract class InventoryTranslator {
return rejectRequest(request); return rejectRequest(request);
} }
craftState = CraftState.INGREDIENTS; craftState = CraftState.INGREDIENTS;
affectedSlots.add(bedrockSlotToJava(((ConsumeStackRequestActionData) action).getSource())); affectedSlots.add(bedrockSlotToJava(((ConsumeAction) action).getSource()));
break; break;
} }
case TAKE: case TAKE:
case PLACE: { case PLACE: {
TransferStackRequestActionData transferAction = (TransferStackRequestActionData) action; TransferItemStackRequestAction transferAction = (TransferItemStackRequestAction) action;
if (craftState != CraftState.INGREDIENTS && craftState != CraftState.TRANSFER) { if (craftState != CraftState.INGREDIENTS && craftState != CraftState.TRANSFER) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -556,10 +556,10 @@ public abstract class InventoryTranslator {
ClickPlan plan = new ClickPlan(session, this, inventory); ClickPlan plan = new ClickPlan(session, this, inventory);
requestLoop: requestLoop:
for (StackRequestActionData action : request.getActions()) { for (ItemStackRequestAction action : request.getActions()) {
switch (action.getType()) { switch (action.getType()) {
case CRAFT_RECIPE_AUTO: { case CRAFT_RECIPE_AUTO: {
AutoCraftRecipeStackRequestActionData autoCraftAction = (AutoCraftRecipeStackRequestActionData) action; AutoCraftRecipeAction autoCraftAction = (AutoCraftRecipeAction) action;
// TODO autoCraftAction#getTimesCrafted 1.17.10 ??? // TODO autoCraftAction#getTimesCrafted 1.17.10 ???
if (craftState != CraftState.START) { if (craftState != CraftState.START) {
return rejectRequest(request); return rejectRequest(request);
@ -601,7 +601,7 @@ public abstract class InventoryTranslator {
break; break;
} }
case CRAFT_RESULTS_DEPRECATED: { case CRAFT_RESULTS_DEPRECATED: {
CraftResultsDeprecatedStackRequestActionData deprecatedCraftAction = (CraftResultsDeprecatedStackRequestActionData) action; CraftResultsDeprecatedAction deprecatedCraftAction = (CraftResultsDeprecatedAction) action;
if (craftState != CraftState.RECIPE_ID) { if (craftState != CraftState.RECIPE_ID) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -618,7 +618,7 @@ public abstract class InventoryTranslator {
break; break;
} }
case CONSUME: { case CONSUME: {
ConsumeStackRequestActionData consumeAction = (ConsumeStackRequestActionData) action; ConsumeAction consumeAction = (ConsumeAction) action;
if (craftState != CraftState.DEPRECATED && craftState != CraftState.INGREDIENTS) { if (craftState != CraftState.DEPRECATED && craftState != CraftState.INGREDIENTS) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -647,7 +647,7 @@ public abstract class InventoryTranslator {
} }
case TAKE: case TAKE:
case PLACE: { case PLACE: {
TransferStackRequestActionData transferAction = (TransferStackRequestActionData) action; TransferItemStackRequestAction transferAction = (TransferItemStackRequestAction) action;
if (craftState != CraftState.INGREDIENTS && craftState != CraftState.TRANSFER) { if (craftState != CraftState.INGREDIENTS && craftState != CraftState.TRANSFER) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -754,8 +754,8 @@ public abstract class InventoryTranslator {
} }
} }
protected static ItemStackResponse acceptRequest(ItemStackRequest request, List<ContainerEntry> containerEntries) { protected static ItemStackResponse acceptRequest(ItemStackRequest request, List<ItemStackResponseContainer> containerEntries) {
return new ItemStackResponse(ResponseStatus.OK, request.getRequestId(), containerEntries); return new ItemStackResponse(ItemStackResponseStatus.OK, request.getRequestId(), containerEntries);
} }
/** /**
@ -775,20 +775,20 @@ public abstract class InventoryTranslator {
if (throwError && GeyserImpl.getInstance().getConfig().isDebugMode()) { if (throwError && GeyserImpl.getInstance().getConfig().isDebugMode()) {
new Throwable("DEBUGGING: ItemStackRequest rejected " + request.toString()).printStackTrace(); new Throwable("DEBUGGING: ItemStackRequest rejected " + request.toString()).printStackTrace();
} }
return new ItemStackResponse(ResponseStatus.ERROR, request.getRequestId(), Collections.emptyList()); return new ItemStackResponse(ItemStackResponseStatus.ERROR, request.getRequestId(), Collections.emptyList());
} }
/** /**
* Print out the contents of an ItemStackRequest, should the net ID check fail. * Print out the contents of an ItemStackRequest, should the net ID check fail.
*/ */
protected void dumpStackRequestDetails(GeyserSession session, Inventory inventory, StackRequestSlotInfoData source, StackRequestSlotInfoData destination) { protected void dumpStackRequestDetails(GeyserSession session, Inventory inventory, ItemStackRequestSlotData source, ItemStackRequestSlotData destination) {
session.getGeyser().getLogger().error("Source: " + source.toString() + " Result: " + checkNetId(session, inventory, source)); session.getGeyser().getLogger().error("Source: " + source.toString() + " Result: " + checkNetId(session, inventory, source));
session.getGeyser().getLogger().error("Destination: " + destination.toString() + " Result: " + checkNetId(session, inventory, destination)); session.getGeyser().getLogger().error("Destination: " + destination.toString() + " Result: " + checkNetId(session, inventory, destination));
session.getGeyser().getLogger().error("Geyser's record of source slot: " + inventory.getItem(bedrockSlotToJava(source))); session.getGeyser().getLogger().error("Geyser's record of source slot: " + inventory.getItem(bedrockSlotToJava(source)));
session.getGeyser().getLogger().error("Geyser's record of destination slot: " + inventory.getItem(bedrockSlotToJava(destination))); session.getGeyser().getLogger().error("Geyser's record of destination slot: " + inventory.getItem(bedrockSlotToJava(destination)));
} }
public boolean checkNetId(GeyserSession session, Inventory inventory, StackRequestSlotInfoData slotInfoData) { public boolean checkNetId(GeyserSession session, Inventory inventory, ItemStackRequestSlotData slotInfoData) {
int netId = slotInfoData.getStackNetworkId(); int netId = slotInfoData.getStackNetworkId();
// "In my testing, sometimes the client thinks the netId of an item in the crafting grid is 1, even though we never said it was. // "In my testing, sometimes the client thinks the netId of an item in the crafting grid is 1, even though we never said it was.
// I think it only happens when we manually set the grid but that was my quick fix" // I think it only happens when we manually set the grid but that was my quick fix"
@ -846,30 +846,30 @@ public abstract class InventoryTranslator {
return -1; return -1;
} }
protected final List<ContainerEntry> makeContainerEntries(GeyserSession session, Inventory inventory, IntSet affectedSlots) { protected final List<ItemStackResponseContainer> makeContainerEntries(GeyserSession session, Inventory inventory, IntSet affectedSlots) {
Map<ContainerSlotType, List<ItemEntry>> containerMap = new HashMap<>(); Map<ContainerSlotType, List<ItemStackResponseSlot>> containerMap = new HashMap<>();
// Manually call iterator to prevent Integer boxing // Manually call iterator to prevent Integer boxing
IntIterator it = affectedSlots.iterator(); IntIterator it = affectedSlots.iterator();
while (it.hasNext()) { while (it.hasNext()) {
int slot = it.nextInt(); int slot = it.nextInt();
BedrockContainerSlot bedrockSlot = javaSlotToBedrockContainer(slot); BedrockContainerSlot bedrockSlot = javaSlotToBedrockContainer(slot);
List<ItemEntry> list = containerMap.computeIfAbsent(bedrockSlot.container(), k -> new ArrayList<>()); List<ItemStackResponseSlot> list = containerMap.computeIfAbsent(bedrockSlot.container(), k -> new ArrayList<>());
list.add(makeItemEntry(session, bedrockSlot.slot(), inventory.getItem(slot))); list.add(makeItemEntry(session, bedrockSlot.slot(), inventory.getItem(slot)));
} }
List<ContainerEntry> containerEntries = new ArrayList<>(); List<ItemStackResponseContainer> containerEntries = new ArrayList<>();
for (Map.Entry<ContainerSlotType, List<ItemEntry>> entry : containerMap.entrySet()) { for (Map.Entry<ContainerSlotType, List<ItemStackResponseSlot>> entry : containerMap.entrySet()) {
containerEntries.add(new ContainerEntry(entry.getKey(), entry.getValue())); containerEntries.add(new ItemStackResponseContainer(entry.getKey(), entry.getValue()));
} }
ItemEntry cursorEntry = makeItemEntry(session, 0, session.getPlayerInventory().getCursor()); ItemStackResponseSlot cursorEntry = makeItemEntry(session, 0, session.getPlayerInventory().getCursor());
containerEntries.add(new ContainerEntry(ContainerSlotType.CURSOR, Collections.singletonList(cursorEntry))); containerEntries.add(new ItemStackResponseContainer(ContainerSlotType.CURSOR, Collections.singletonList(cursorEntry)));
return containerEntries; return containerEntries;
} }
private static ItemEntry makeItemEntry(GeyserSession session, int bedrockSlot, GeyserItemStack itemStack) { private static ItemStackResponseSlot makeItemEntry(GeyserSession session, int bedrockSlot, GeyserItemStack itemStack) {
ItemEntry itemEntry; ItemStackResponseSlot itemEntry;
if (!itemStack.isEmpty()) { if (!itemStack.isEmpty()) {
// As of 1.16.210: Bedrock needs confirmation on what the current item durability is. // As of 1.16.210: Bedrock needs confirmation on what the current item durability is.
// If 0 is sent, then Bedrock thinks the item is not damaged // If 0 is sent, then Bedrock thinks the item is not damaged
@ -881,14 +881,14 @@ public abstract class InventoryTranslator {
} }
} }
itemEntry = new ItemEntry((byte) bedrockSlot, (byte) bedrockSlot, (byte) itemStack.getAmount(), itemStack.getNetId(), "", durability); itemEntry = new ItemStackResponseSlot((byte) bedrockSlot, (byte) bedrockSlot, (byte) itemStack.getAmount(), itemStack.getNetId(), "", durability);
} else { } else {
itemEntry = new ItemEntry((byte) bedrockSlot, (byte) bedrockSlot, (byte) 0, 0, "", 0); itemEntry = new ItemStackResponseSlot((byte) bedrockSlot, (byte) bedrockSlot, (byte) 0, 0, "", 0);
} }
return itemEntry; return itemEntry;
} }
protected static boolean isCursor(StackRequestSlotInfoData slotInfoData) { protected static boolean isCursor(ItemStackRequestSlotData slotInfoData) {
return slotInfoData.getContainer() == ContainerSlotType.CURSOR; return slotInfoData.getContainer() == ContainerSlotType.CURSOR;
} }

View file

@ -31,9 +31,9 @@ import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.Ser
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.Inventory;
@ -55,7 +55,8 @@ public class LecternInventoryTranslator extends BaseInventoryTranslator {
} }
@Override @Override
public void prepareInventory(GeyserSession session, Inventory inventory) { public boolean prepareInventory(GeyserSession session, Inventory inventory) {
return true;
} }
@Override @Override

View file

@ -28,19 +28,19 @@ package org.geysermc.geyser.translator.inventory;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.nukkitx.nbt.NbtMap;
import com.nukkitx.nbt.NbtType;
import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackResponse; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.CraftLoomAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.CraftLoomStackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.CraftResultsDeprecatedAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.CraftResultsDeprecatedStackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestActionType;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.GeyserItemStack; import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.Inventory;
@ -117,19 +117,19 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
} }
@Override @Override
protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { protected boolean shouldHandleRequestFirst(ItemStackRequestAction action, Inventory inventory) {
// If the LOOM_MATERIAL slot is not empty, we are crafting a pattern that does not come from an item // If the LOOM_MATERIAL slot is not empty, we are crafting a pattern that does not come from an item
return action.getType() == StackRequestActionType.CRAFT_LOOM && inventory.getItem(2).isEmpty(); return action.getType() == ItemStackRequestActionType.CRAFT_LOOM && inventory.getItem(2).isEmpty();
} }
@Override @Override
public ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { public ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
StackRequestActionData headerData = request.getActions()[0]; ItemStackRequestAction headerData = request.getActions()[0];
StackRequestActionData data = request.getActions()[1]; ItemStackRequestAction data = request.getActions()[1];
if (!(headerData instanceof CraftLoomStackRequestActionData)) { if (!(headerData instanceof CraftLoomAction)) {
return rejectRequest(request); return rejectRequest(request);
} }
if (!(data instanceof CraftResultsDeprecatedStackRequestActionData craftData)) { if (!(data instanceof CraftResultsDeprecatedAction craftData)) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -137,7 +137,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
List<NbtMap> newBlockEntityTag = craftData.getResultItems()[0].getTag().getList("Patterns", NbtType.COMPOUND); List<NbtMap> newBlockEntityTag = craftData.getResultItems()[0].getTag().getList("Patterns", NbtType.COMPOUND);
// Get the pattern that the Bedrock client requests - the last pattern in the Patterns list // Get the pattern that the Bedrock client requests - the last pattern in the Patterns list
NbtMap pattern = newBlockEntityTag.get(newBlockEntityTag.size() - 1); NbtMap pattern = newBlockEntityTag.get(newBlockEntityTag.size() - 1);
String bedrockPattern = ((CraftLoomStackRequestActionData) headerData).getPatternId(); String bedrockPattern = ((CraftLoomAction) headerData).getPatternId();
// Get the Java index of this pattern // Get the Java index of this pattern
int index = PATTERN_TO_INDEX.getOrDefault(bedrockPattern, -1); int index = PATTERN_TO_INDEX.getOrDefault(bedrockPattern, -1);
@ -181,7 +181,7 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainer()) {
case LOOM_INPUT -> 0; case LOOM_INPUT -> 0;
case LOOM_DYE -> 1; case LOOM_DYE -> 1;

View file

@ -31,19 +31,15 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData; import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackResponse; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.AutoCraftRecipeAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.AutoCraftRecipeStackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.CraftRecipeAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.CraftRecipeStackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.MerchantContainer;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.SlotType;
import org.geysermc.geyser.inventory.updater.InventoryUpdater; import org.geysermc.geyser.inventory.updater.InventoryUpdater;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -80,7 +76,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainer()) {
case TRADE2_INGREDIENT1 -> 0; case TRADE2_INGREDIENT1 -> 0;
case TRADE2_INGREDIENT2 -> 1; case TRADE2_INGREDIENT2 -> 1;
@ -98,7 +94,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
} }
@Override @Override
public void prepareInventory(GeyserSession session, Inventory inventory) { public boolean prepareInventory(GeyserSession session, Inventory inventory) {
MerchantContainer merchantInventory = (MerchantContainer) inventory; MerchantContainer merchantInventory = (MerchantContainer) inventory;
if (merchantInventory.getVillager() == null) { if (merchantInventory.getVillager() == null) {
long geyserId = session.getEntityCache().getNextEntityId().incrementAndGet(); long geyserId = session.getEntityCache().getNextEntityId().incrementAndGet();
@ -121,6 +117,8 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
merchantInventory.setVillager(villager); merchantInventory.setVillager(villager);
} }
return true;
} }
@Override @Override
@ -142,7 +140,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
// Behavior as of 1.18.10. // Behavior as of 1.18.10.
// We set the net ID to the trade index + 1. This doesn't appear to cause issues and means we don't have to // We set the net ID to the trade index + 1. This doesn't appear to cause issues and means we don't have to
// store a map of net ID to trade index on our end. // store a map of net ID to trade index on our end.
int tradeChoice = ((CraftRecipeStackRequestActionData) request.getActions()[0]).getRecipeNetworkId() - 1; int tradeChoice = ((CraftRecipeAction) request.getActions()[0]).getRecipeNetworkId() - 1;
return handleTrade(session, inventory, request, tradeChoice); return handleTrade(session, inventory, request, tradeChoice);
} }
@ -151,7 +149,7 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
// 1.18.10 update - seems impossible to call without consoles/controller input // 1.18.10 update - seems impossible to call without consoles/controller input
// We set the net ID to the trade index + 1. This doesn't appear to cause issues and means we don't have to // We set the net ID to the trade index + 1. This doesn't appear to cause issues and means we don't have to
// store a map of net ID to trade index on our end. // store a map of net ID to trade index on our end.
int tradeChoice = ((AutoCraftRecipeStackRequestActionData) request.getActions()[0]).getRecipeNetworkId() - 1; int tradeChoice = ((AutoCraftRecipeAction) request.getActions()[0]).getRecipeNetworkId() - 1;
return handleTrade(session, inventory, request, tradeChoice); return handleTrade(session, inventory, request, tradeChoice);
} }

View file

@ -36,22 +36,13 @@ import it.unimi.dsi.fastutil.ints.IntSet;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackResponse; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.*;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.CraftCreativeStackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.DestroyStackRequestActionData;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.DropStackRequestActionData;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.SwapStackRequestActionData;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.TransferStackRequestActionData;
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket; import org.cloudburstmc.protocol.bedrock.packet.InventorySlotPacket;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.SlotType;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.skin.FakeHeadProvider; import org.geysermc.geyser.skin.FakeHeadProvider;
import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.GeyserLocale;
@ -174,7 +165,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
int slotnum = slotInfoData.getSlot(); int slotnum = slotInfoData.getSlot();
switch (slotInfoData.getContainer()) { switch (slotInfoData.getContainer()) {
case HOTBAR_AND_INVENTORY: case HOTBAR_AND_INVENTORY:
@ -246,10 +237,10 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
PlayerInventory playerInv = session.getPlayerInventory(); PlayerInventory playerInv = session.getPlayerInventory();
IntSet affectedSlots = new IntOpenHashSet(); IntSet affectedSlots = new IntOpenHashSet();
for (StackRequestActionData action : request.getActions()) { for (ItemStackRequestAction action : request.getActions()) {
switch (action.getType()) { switch (action.getType()) {
case TAKE, PLACE -> { case TAKE, PLACE -> {
TransferStackRequestActionData transferAction = (TransferStackRequestActionData) action; TransferItemStackRequestAction transferAction = (TransferItemStackRequestAction ) action;
if (!(checkNetId(session, inventory, transferAction.getSource()) && checkNetId(session, inventory, transferAction.getDestination()))) { if (!(checkNetId(session, inventory, transferAction.getSource()) && checkNetId(session, inventory, transferAction.getDestination()))) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -296,7 +287,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
} }
} }
case SWAP -> { case SWAP -> {
SwapStackRequestActionData swapAction = (SwapStackRequestActionData) action; SwapAction swapAction = (SwapAction) action;
if (!(checkNetId(session, inventory, swapAction.getSource()) && checkNetId(session, inventory, swapAction.getDestination()))) { if (!(checkNetId(session, inventory, swapAction.getSource()) && checkNetId(session, inventory, swapAction.getDestination()))) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -336,7 +327,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
} }
} }
case DROP -> { case DROP -> {
DropStackRequestActionData dropAction = (DropStackRequestActionData) action; DropAction dropAction = (DropAction) action;
if (!checkNetId(session, inventory, dropAction.getSource())) { if (!checkNetId(session, inventory, dropAction.getSource())) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -364,7 +355,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
} }
case DESTROY -> { case DESTROY -> {
// Only called when a creative client wants to destroy an item... I think - Camotoy // Only called when a creative client wants to destroy an item... I think - Camotoy
DestroyStackRequestActionData destroyAction = (DestroyStackRequestActionData) action; DestroyAction destroyAction = (DestroyAction) action;
if (!checkNetId(session, inventory, destroyAction.getSource())) { if (!checkNetId(session, inventory, destroyAction.getSource())) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -403,10 +394,10 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
ItemStack javaCreativeItem = null; ItemStack javaCreativeItem = null;
IntSet affectedSlots = new IntOpenHashSet(); IntSet affectedSlots = new IntOpenHashSet();
CraftState craftState = CraftState.START; CraftState craftState = CraftState.START;
for (StackRequestActionData action : request.getActions()) { for (ItemStackRequestAction action : request.getActions()) {
switch (action.getType()) { switch (action.getType()) {
case CRAFT_CREATIVE: { case CRAFT_CREATIVE: {
CraftCreativeStackRequestActionData creativeAction = (CraftCreativeStackRequestActionData) action; CraftCreativeAction creativeAction = (CraftCreativeAction) action;
if (craftState != CraftState.START) { if (craftState != CraftState.START) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -430,7 +421,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
break; break;
} }
case DESTROY: { case DESTROY: {
DestroyStackRequestActionData destroyAction = (DestroyStackRequestActionData) action; DestroyAction destroyAction = (DestroyAction) action;
if (craftState != CraftState.DEPRECATED) { if (craftState != CraftState.DEPRECATED) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -442,7 +433,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
} }
case TAKE: case TAKE:
case PLACE: { case PLACE: {
TransferStackRequestActionData transferAction = (TransferStackRequestActionData) action; TransferItemStackRequestAction transferAction = (TransferItemStackRequestAction) action;
if (!(craftState == CraftState.DEPRECATED || craftState == CraftState.TRANSFER)) { if (!(craftState == CraftState.DEPRECATED || craftState == CraftState.TRANSFER)) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -480,7 +471,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
return rejectRequest(request); return rejectRequest(request);
} }
DropStackRequestActionData dropAction = (DropStackRequestActionData) action; DropAction dropAction = (DropAction) action;
if (dropAction.getSource().getContainer() != ContainerSlotType.CREATIVE_OUTPUT || dropAction.getSource().getSlot() != 50) { if (dropAction.getSource().getContainer() != ContainerSlotType.CREATIVE_OUTPUT || dropAction.getSource().getSlot() != 50) {
return rejectRequest(request); return rejectRequest(request);
} }
@ -517,7 +508,7 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
session.sendDownstreamPacket(creativePacket); session.sendDownstreamPacket(creativePacket);
} }
private static boolean isCraftingGrid(StackRequestSlotInfoData slotInfoData) { private static boolean isCraftingGrid(ItemStackRequestSlotData slotInfoData) {
return slotInfoData.getContainer() == ContainerSlotType.CRAFTING_INPUT; return slotInfoData.getContainer() == ContainerSlotType.CRAFTING_INPUT;
} }
@ -527,7 +518,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
} }
@Override @Override
public void prepareInventory(GeyserSession session, Inventory inventory) { public boolean prepareInventory(GeyserSession session, Inventory inventory) {
return true;
} }
@Override @Override

View file

@ -27,8 +27,8 @@ package org.geysermc.geyser.translator.inventory;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.translator.inventory;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
@ -37,7 +37,7 @@ public class SmithingInventoryTranslator extends AbstractBlockInventoryTranslato
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainer()) {
case SMITHING_TABLE_INPUT -> 0; case SMITHING_TABLE_INPUT -> 0;
case SMITHING_TABLE_MATERIAL -> 1; case SMITHING_TABLE_MATERIAL -> 1;

View file

@ -29,18 +29,13 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType; import com.github.steveice10.mc.protocol.data.game.inventory.ContainerType;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackRequest; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequest;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemStackResponse; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.CraftRecipeAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.CraftRecipeStackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestAction;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.action.ItemStackRequestActionType;
import org.cloudburstmc.protocol.bedrock.data.inventory.stackrequestactions.StackRequestActionType; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.response.ItemStackResponse;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.*;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.SlotType;
import org.geysermc.geyser.inventory.StonecutterContainer;
import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData; import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
import org.geysermc.geyser.inventory.updater.UIInventoryUpdater; import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
@ -51,14 +46,14 @@ public class StonecutterInventoryTranslator extends AbstractBlockInventoryTransl
} }
@Override @Override
protected boolean shouldHandleRequestFirst(StackRequestActionData action, Inventory inventory) { protected boolean shouldHandleRequestFirst(ItemStackRequestAction action, Inventory inventory) {
return action.getType() == StackRequestActionType.CRAFT_RECIPE; return action.getType() == ItemStackRequestActionType.CRAFT_RECIPE;
} }
@Override @Override
protected ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) { protected ItemStackResponse translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
// Guarded by shouldHandleRequestFirst // Guarded by shouldHandleRequestFirst
CraftRecipeStackRequestActionData data = (CraftRecipeStackRequestActionData) request.getActions()[0]; CraftRecipeAction data = (CraftRecipeAction) request.getActions()[0];
// Look up all possible options of cutting from this ID // Look up all possible options of cutting from this ID
GeyserStonecutterData craftingData = session.getStonecutterRecipes().get(data.getRecipeNetworkId()); GeyserStonecutterData craftingData = session.getStonecutterRecipes().get(data.getRecipeNetworkId());
@ -86,7 +81,7 @@ public class StonecutterInventoryTranslator extends AbstractBlockInventoryTransl
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
return switch (slotInfoData.getContainer()) { return switch (slotInfoData.getContainer()) {
case STONECUTTER_INPUT -> 0; case STONECUTTER_INPUT -> 0;
case STONECUTTER_RESULT, CREATIVE_OUTPUT -> 1; case STONECUTTER_RESULT, CREATIVE_OUTPUT -> 1;

View file

@ -26,8 +26,8 @@
package org.geysermc.geyser.translator.inventory.chest; package org.geysermc.geyser.translator.inventory.chest;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
@ -41,6 +41,7 @@ import org.geysermc.geyser.level.block.DoubleChestValue;
import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.level.block.entity.DoubleChestBlockEntityTranslator; import org.geysermc.geyser.translator.level.block.entity.DoubleChestBlockEntityTranslator;
import org.geysermc.geyser.util.InventoryUtils;
public class DoubleChestInventoryTranslator extends ChestInventoryTranslator { public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
private final int defaultJavaBlockState; private final int defaultJavaBlockState;
@ -51,7 +52,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
} }
@Override @Override
public void prepareInventory(GeyserSession session, Inventory inventory) { public boolean prepareInventory(GeyserSession session, Inventory inventory) {
// See BlockInventoryHolder - same concept there except we're also dealing with a specific block state // See BlockInventoryHolder - same concept there except we're also dealing with a specific block state
if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) { if (session.getLastInteractionPlayerPosition().equals(session.getPlayerEntity().getPosition())) {
int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition()); int javaBlockId = session.getGeyser().getWorldManager().getBlockAt(session, session.getLastInteractionBlockPosition());
@ -77,11 +78,16 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
dataPacket.setData(tag.build()); dataPacket.setData(tag.build());
dataPacket.setBlockPosition(session.getLastInteractionBlockPosition()); dataPacket.setBlockPosition(session.getLastInteractionBlockPosition());
session.sendUpstreamPacket(dataPacket); session.sendUpstreamPacket(dataPacket);
return;
return true;
} }
} }
Vector3i position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP); Vector3i position = InventoryUtils.findAvailableWorldSpace(session);
if (position == null) {
return false;
}
Vector3i pairPosition = position.add(Vector3i.UNIT_X); Vector3i pairPosition = position.add(Vector3i.UNIT_X);
BlockDefinition definition = session.getBlockMappings().getBedrockBlock(defaultJavaBlockState); BlockDefinition definition = session.getBlockMappings().getBedrockBlock(defaultJavaBlockState);
@ -126,6 +132,8 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
session.sendUpstreamPacket(dataPacket); session.sendUpstreamPacket(dataPacket);
inventory.setHolderPosition(position); inventory.setHolderPosition(position);
return true;
} }
@Override @Override

View file

@ -52,8 +52,8 @@ public class SingleChestInventoryTranslator extends ChestInventoryTranslator {
} }
@Override @Override
public void prepareInventory(GeyserSession session, Inventory inventory) { public boolean prepareInventory(GeyserSession session, Inventory inventory) {
holder.prepareInventory(this, session, inventory); return holder.prepareInventory(this, session, inventory);
} }
@Override @Override

View file

@ -40,7 +40,8 @@ public abstract class AbstractHorseInventoryTranslator extends BaseInventoryTran
} }
@Override @Override
public void prepareInventory(GeyserSession session, Inventory inventory) { public boolean prepareInventory(GeyserSession session, Inventory inventory) {
return true;
} }
@Override @Override

View file

@ -28,7 +28,7 @@ package org.geysermc.geyser.translator.inventory.horse;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerId;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryContentPacket;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.BedrockContainerSlot;
import org.geysermc.geyser.inventory.Inventory; import org.geysermc.geyser.inventory.Inventory;
@ -52,7 +52,7 @@ public abstract class ChestedHorseInventoryTranslator extends AbstractHorseInven
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.HORSE_EQUIP) { if (slotInfoData.getContainer() == ContainerSlotType.HORSE_EQUIP) {
return this.equipSlot; return this.equipSlot;
} }

View file

@ -26,7 +26,7 @@
package org.geysermc.geyser.translator.inventory.horse; package org.geysermc.geyser.translator.inventory.horse;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerSlotType;
import org.cloudburstmc.protocol.bedrock.data.inventory.StackRequestSlotInfoData; import org.cloudburstmc.protocol.bedrock.data.inventory.itemstack.request.ItemStackRequestSlotData;
import org.geysermc.geyser.inventory.BedrockContainerSlot; import org.geysermc.geyser.inventory.BedrockContainerSlot;
public class HorseInventoryTranslator extends AbstractHorseInventoryTranslator { public class HorseInventoryTranslator extends AbstractHorseInventoryTranslator {
@ -35,7 +35,7 @@ public class HorseInventoryTranslator extends AbstractHorseInventoryTranslator {
} }
@Override @Override
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) { public int bedrockSlotToJava(ItemStackRequestSlotData slotInfoData) {
if (slotInfoData.getContainer() == ContainerSlotType.HORSE_EQUIP) { if (slotInfoData.getContainer() == ContainerSlotType.HORSE_EQUIP) {
return slotInfoData.getSlot(); return slotInfoData.getSlot();
} }

View file

@ -39,10 +39,10 @@ import com.github.steveice10.opennbt.tag.builtin.LongTag;
import com.github.steveice10.opennbt.tag.builtin.ShortTag; import com.github.steveice10.opennbt.tag.builtin.ShortTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.nbt.NbtList; import org.cloudburstmc.nbt.NbtList;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
@ -380,7 +380,7 @@ public abstract class ItemTranslator {
if (tag instanceof LongArrayTag) { if (tag instanceof LongArrayTag) {
//Long array tag does not exist in BE //Long array tag does not exist in BE
//LongArrayTag longArrayTag = (LongArrayTag) tag; //LongArrayTag longArrayTag = (LongArrayTag) tag;
//return new com.nukkitx.nbt.tag.LongArrayTag(longArrayTag.getName(), longArrayTag.getValue()); //return new org.cloudburstmc.nbt.tag.LongArrayTag(longArrayTag.getName(), longArrayTag.getValue());
return null; return null;
} }

View file

@ -26,9 +26,9 @@
package org.geysermc.geyser.translator.inventory.item.nbt; package org.geysermc.geyser.translator.inventory.item.nbt;
import com.github.steveice10.opennbt.tag.builtin.*; import com.github.steveice10.opennbt.tag.builtin.*;
import com.nukkitx.nbt.NbtList; import org.cloudburstmc.nbt.NbtList;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;

View file

@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.translator.inventory.item.nbt.BannerTranslator; import org.geysermc.geyser.translator.inventory.item.nbt.BannerTranslator;

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.translator.level.block.entity;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
@BlockEntity(type = BlockEntityType.BEACON) @BlockEntity(type = BlockEntityType.BEACON)
public class BeaconBlockEntityTranslator extends BlockEntityTranslator { public class BeaconBlockEntityTranslator extends BlockEntityTranslator {

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.translator.level.block.entity;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
@BlockEntity(type = BlockEntityType.BED) @BlockEntity(type = BlockEntityType.BED)

View file

@ -26,9 +26,9 @@
package org.geysermc.geyser.translator.level.block.entity; package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtList; import org.cloudburstmc.nbt.NbtList;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;

View file

@ -28,8 +28,8 @@ package org.geysermc.geyser.translator.level.block.entity;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.util.BlockEntityUtils; import org.geysermc.geyser.util.BlockEntityUtils;
/** /**

View file

@ -29,8 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.network.GameProtocol; import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.translator.level.block.entity;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.*; import com.github.steveice10.opennbt.tag.builtin.*;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;

View file

@ -28,7 +28,7 @@ package org.geysermc.geyser.translator.level.block.entity;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.level.block.DoubleChestValue; import org.geysermc.geyser.level.block.DoubleChestValue;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;

View file

@ -26,7 +26,7 @@
package org.geysermc.geyser.translator.level.block.entity; package org.geysermc.geyser.translator.level.block.entity;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
public class EmptyBlockEntityTranslator extends BlockEntityTranslator { public class EmptyBlockEntityTranslator extends BlockEntityTranslator {
@Override @Override

View file

@ -30,9 +30,9 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntTag; import com.github.steveice10.opennbt.tag.builtin.IntTag;
import com.github.steveice10.opennbt.tag.builtin.LongTag; import com.github.steveice10.opennbt.tag.builtin.LongTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.nbt.NbtList; import org.cloudburstmc.nbt.NbtList;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList; import it.unimi.dsi.fastutil.ints.IntList;

View file

@ -26,8 +26,8 @@
package org.geysermc.geyser.translator.level.block.entity; package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;

View file

@ -29,7 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
@BlockEntity(type = BlockEntityType.JIGSAW) @BlockEntity(type = BlockEntityType.JIGSAW)

View file

@ -29,8 +29,8 @@ import com.github.steveice10.mc.protocol.data.game.level.block.value.PistonValue
import org.cloudburstmc.math.vector.Vector3d; import org.cloudburstmc.math.vector.Vector3d;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket; import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;

View file

@ -26,7 +26,7 @@
package org.geysermc.geyser.translator.level.block.entity; package org.geysermc.geyser.translator.level.block.entity;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
/** /**

View file

@ -27,7 +27,7 @@ package org.geysermc.geyser.translator.level.block.entity;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.translator.inventory.ShulkerInventoryTranslator; import org.geysermc.geyser.translator.inventory.ShulkerInventoryTranslator;

View file

@ -28,11 +28,11 @@ package org.geysermc.geyser.translator.level.block.entity;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.SignUtils; import org.geysermc.geyser.util.SignUtils;
@BlockEntity(type = BlockEntityType.SIGN) @BlockEntity(type = {BlockEntityType.SIGN, BlockEntityType.HANGING_SIGN})
public class SignBlockEntityTranslator extends BlockEntityTranslator { public class SignBlockEntityTranslator extends BlockEntityTranslator {
/** /**
* Maps a color stored in a sign's Color tag to its ARGB value. * Maps a color stored in a sign's Color tag to its ARGB value.
@ -88,6 +88,7 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator {
signWidth += SignUtils.getCharacterWidth(c); signWidth += SignUtils.getCharacterWidth(c);
} }
// todo 1.20: update for hanging signs (smaller width). Currently OK because bedrock sees hanging signs as normal signs
if (signWidth <= SignUtils.BEDROCK_CHARACTER_WIDTH_MAX) { if (signWidth <= SignUtils.BEDROCK_CHARACTER_WIDTH_MAX) {
finalSignLine.append(c); finalSignLine.append(c);
} else { } else {

View file

@ -30,7 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.StringTag;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.skin.SkinProvider; import org.geysermc.geyser.skin.SkinProvider;

View file

@ -27,8 +27,9 @@ package org.geysermc.geyser.translator.level.block.entity;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import org.geysermc.geyser.entity.EntityDefinition; import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.registry.Registries; import org.geysermc.geyser.registry.Registries;
@ -68,16 +69,18 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
CompoundTag spawnData = tag.get("SpawnData"); CompoundTag spawnData = tag.get("SpawnData");
if (spawnData != null) { if (spawnData != null) {
String entityID = (String) ((CompoundTag) spawnData.get("entity")) StringTag idTag = ((CompoundTag) spawnData.get("entity")).get("id");
.get("id") if (idTag != null) {
.getValue(); // As of 1.19.3, spawners can be empty
builder.put("EntityIdentifier", entityID); String entityId = idTag.getValue();
builder.put("EntityIdentifier", entityId);
EntityDefinition<?> definition = Registries.JAVA_ENTITY_IDENTIFIERS.get(entityID); EntityDefinition<?> definition = Registries.JAVA_ENTITY_IDENTIFIERS.get(entityId);
if (definition != null) { if (definition != null) {
builder.put("DisplayEntityWidth", definition.width()); builder.put("DisplayEntityWidth", definition.width());
builder.put("DisplayEntityHeight", definition.height()); builder.put("DisplayEntityHeight", definition.height());
builder.put("DisplayEntityScale", 1.0f); builder.put("DisplayEntityScale", 1.0f);
}
} }
} }

View file

@ -28,7 +28,7 @@ package org.geysermc.geyser.translator.protocol.bedrock;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetJigsawBlockPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetJigsawBlockPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundSignUpdatePacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundSignUpdatePacket;
import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket; import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
@ -57,6 +57,10 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator<BlockEnti
// This converts the message into the array'd message Java wants // This converts the message into the array'd message Java wants
for (char character : text.toCharArray()) { for (char character : text.toCharArray()) {
widthCount += SignUtils.getCharacterWidth(character); widthCount += SignUtils.getCharacterWidth(character);
// todo 1.20: update for hanging signs (smaller width). Currently bedrock thinks hanging signs are normal,
// so it thinks hanging signs have more width than they actually do. Seems like JE just truncates it.
// If we get a return in Bedrock, or go over the character width max, that signals to use the next line. // If we get a return in Bedrock, or go over the character width max, that signals to use the next line.
if (character == '\n' || widthCount > SignUtils.JAVA_CHARACTER_WIDTH_MAX) { if (character == '\n' || widthCount > SignUtils.JAVA_CHARACTER_WIDTH_MAX) {
// We need to apply some more logic if we went over the character width max // We need to apply some more logic if we went over the character width max

View file

@ -29,6 +29,7 @@ import org.cloudburstmc.protocol.bedrock.packet.CommandRequestPacket;
import org.geysermc.common.PlatformType; import org.geysermc.common.PlatformType;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.GeyserSession; 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.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
@ -38,16 +39,14 @@ public class BedrockCommandRequestTranslator extends PacketTranslator<CommandReq
@Override @Override
public void translate(GeyserSession session, CommandRequestPacket packet) { public void translate(GeyserSession session, CommandRequestPacket packet) {
String command = packet.getCommand().replace("/", ""); String command = MessageTranslator.convertToPlainText(packet.getCommand());
if (!(session.getGeyser().getPlatformType() == PlatformType.STANDALONE if (!(session.getGeyser().getPlatformType() == PlatformType.STANDALONE
&& GeyserImpl.getInstance().commandManager().runCommand(session, command))) { && GeyserImpl.getInstance().commandManager().runCommand(session, command.substring(1)))) {
String message = packet.getCommand().trim(); if (MessageTranslator.isTooLong(command, session)) {
if (MessageTranslator.isTooLong(message, session)) {
return; return;
} }
session.sendCommand(message.substring(1)); session.sendCommand(command.substring(1));
} }
} }
} }

View file

@ -32,12 +32,7 @@ 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.InteractAction;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction; 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.inventory.ServerboundContainerClickPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.*;
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 it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@ -47,10 +42,10 @@ import org.cloudburstmc.math.vector.Vector3i;
import org.cloudburstmc.protocol.bedrock.data.LevelEvent; import org.cloudburstmc.protocol.bedrock.data.LevelEvent;
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition; import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType; import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
import org.cloudburstmc.protocol.bedrock.data.inventory.InventoryActionData;
import org.cloudburstmc.protocol.bedrock.data.inventory.InventorySource;
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData; import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
import org.cloudburstmc.protocol.bedrock.data.inventory.LegacySetItemSlotData; import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.InventoryActionData;
import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.InventorySource;
import org.cloudburstmc.protocol.bedrock.data.inventory.transaction.LegacySetItemSlotData;
import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket; import org.cloudburstmc.protocol.bedrock.packet.ContainerOpenPacket;
import org.cloudburstmc.protocol.bedrock.packet.InventoryTransactionPacket; import org.cloudburstmc.protocol.bedrock.packet.InventoryTransactionPacket;
import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket; import org.cloudburstmc.protocol.bedrock.packet.LevelEventPacket;
@ -64,7 +59,6 @@ import org.geysermc.geyser.inventory.Inventory;
import org.geysermc.geyser.inventory.PlayerInventory; import org.geysermc.geyser.inventory.PlayerInventory;
import org.geysermc.geyser.inventory.click.Click; import org.geysermc.geyser.inventory.click.Click;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.network.GameProtocol;
import org.geysermc.geyser.registry.BlockRegistries; import org.geysermc.geyser.registry.BlockRegistries;
import org.geysermc.geyser.registry.type.ItemMapping; import org.geysermc.geyser.registry.type.ItemMapping;
import org.geysermc.geyser.registry.type.ItemMappings; import org.geysermc.geyser.registry.type.ItemMappings;
@ -73,11 +67,7 @@ import org.geysermc.geyser.translator.inventory.InventoryTranslator;
import org.geysermc.geyser.translator.inventory.item.ItemTranslator; import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
import org.geysermc.geyser.util.BlockUtils; import org.geysermc.geyser.util.*;
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.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -478,10 +468,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
InteractAction.ATTACK, session.isSneaking()); InteractAction.ATTACK, session.isSneaking());
session.sendDownstreamPacket(attackPacket); session.sendDownstreamPacket(attackPacket);
if (GameProtocol.supports1_19_10(session)) { // Since 1.19.10, LevelSoundEventPackets are no longer sent by the client when attacking entities
// Since 1.19.10, LevelSoundEventPackets are no longer sent by the client when attacking entities CooldownUtils.sendCooldown(session);
CooldownUtils.sendCooldown(session);
}
} }
} }
break; break;

View file

@ -25,9 +25,9 @@
package org.geysermc.geyser.translator.protocol.bedrock; package org.geysermc.geyser.translator.protocol.bedrock;
import com.nukkitx.nbt.NbtMap; import org.cloudburstmc.nbt.NbtMap;
import com.nukkitx.nbt.NbtMapBuilder; import org.cloudburstmc.nbt.NbtMapBuilder;
import com.nukkitx.nbt.NbtType; import org.cloudburstmc.nbt.NbtType;
import org.cloudburstmc.protocol.bedrock.packet.PositionTrackingDBClientRequestPacket; import org.cloudburstmc.protocol.bedrock.packet.PositionTrackingDBClientRequestPacket;
import org.cloudburstmc.protocol.bedrock.packet.PositionTrackingDBServerBroadcastPacket; import org.cloudburstmc.protocol.bedrock.packet.PositionTrackingDBServerBroadcastPacket;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;

View file

@ -37,21 +37,7 @@ public class BedrockTextTranslator extends PacketTranslator<TextPacket> {
@Override @Override
public void translate(GeyserSession session, TextPacket packet) { public void translate(GeyserSession session, TextPacket packet) {
String message = packet.getMessage(); String message = MessageTranslator.convertToPlainText(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();
}
if (message.isBlank()) { if (message.isBlank()) {
// Java Edition (as of 1.17.1) just doesn't pass on these messages, so... we won't either! // Java Edition (as of 1.17.1) just doesn't pass on these messages, so... we won't either!

View file

@ -83,6 +83,9 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
attributesPacket.setRuntimeEntityId(entity.getGeyserId()); attributesPacket.setRuntimeEntityId(entity.getGeyserId());
attributesPacket.getAttributes().addAll(entity.getAttributes().values()); attributesPacket.getAttributes().addAll(entity.getAttributes().values());
session.sendUpstreamPacket(attributesPacket); session.sendUpstreamPacket(attributesPacket);
// Bounding box must be sent after a player dies and respawns since 1.19.40
entity.updateBoundingBox();
break; break;
case START_SWIMMING: case START_SWIMMING:
if (!entity.getFlag(EntityFlag.SWIMMING)) { if (!entity.getFlag(EntityFlag.SWIMMING)) {

Some files were not shown because too many files have changed in this diff Show more