Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-26 08:10:11 +01:00
Merge remote-tracking branch 'origin/feature/1.19-bedrock' into feature/cumulus-1.1
# Conflicts: # core/src/main/java/org/geysermc/geyser/session/cache/AdvancementsCache.java
Dieser Commit ist enthalten in:
Commit
5fe24ac867
@ -17,7 +17,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
|
||||
|
||||
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!
|
||||
|
||||
### Currently supporting Minecraft Bedrock 1.18.0 - 1.18.31 and Minecraft Java 1.18.2.
|
||||
### Currently supporting Minecraft Bedrock 1.19 and Minecraft Java 1.19.0.
|
||||
|
||||
## Setting Up
|
||||
Take a look [here](https://wiki.geysermc.org/geyser/setup/) for how to set up Geyser.
|
||||
|
@ -13,7 +13,7 @@
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>papermc</id>
|
||||
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>viaversion-repo</id>
|
||||
|
@ -169,9 +169,10 @@ public class GeyserSpigotInjector extends GeyserInjector {
|
||||
* For the future, if someone wants to properly fix this - as of December 28, 2021, it happens on 1.16.5/1.17.1/1.18.1 EXCEPT Spigot 1.16.5
|
||||
*/
|
||||
private void workAroundWeirdBug(GeyserBootstrap bootstrap) {
|
||||
MinecraftProtocol protocol = new MinecraftProtocol();
|
||||
LocalSession session = new LocalSession(bootstrap.getGeyserConfig().getRemote().getAddress(),
|
||||
bootstrap.getGeyserConfig().getRemote().getPort(), this.serverSocketAddress,
|
||||
InetAddress.getLoopbackAddress().getHostAddress(), new MinecraftProtocol());
|
||||
InetAddress.getLoopbackAddress().getHostAddress(), protocol, protocol.createHelper());
|
||||
session.connect();
|
||||
}
|
||||
|
||||
|
@ -209,6 +209,7 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
|
||||
return;
|
||||
}
|
||||
}
|
||||
geyserLogger.setDebug(geyserConfig.isDebugMode());
|
||||
GeyserConfiguration.checkGeyserConfiguration(geyserConfig, geyserLogger);
|
||||
|
||||
// Allow libraries like Protocol to have their debug information passthrough
|
||||
|
14
core/pom.xml
14
core/pom.xml
@ -72,7 +72,7 @@
|
||||
<groupId>com.nukkitx</groupId>
|
||||
<artifactId>nbt</artifactId>
|
||||
<!-- Used for key/value interning -->
|
||||
<version>2.1.0</version>
|
||||
<version>2.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -120,8 +120,8 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.CloudburstMC.Protocol</groupId>
|
||||
<artifactId>bedrock-v503</artifactId>
|
||||
<version>297567d</version>
|
||||
<artifactId>bedrock-beta</artifactId>
|
||||
<version>be0cc73</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@ -153,9 +153,9 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.GeyserMC</groupId>
|
||||
<artifactId>MCProtocolLib</artifactId>
|
||||
<version>0771504</version>
|
||||
<groupId>com.github.steveice10</groupId>
|
||||
<artifactId>mcprotocollib</artifactId>
|
||||
<version>1.19-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@ -171,7 +171,7 @@
|
||||
<dependency>
|
||||
<groupId>com.github.steveice10</groupId>
|
||||
<artifactId>packetlib</artifactId>
|
||||
<version>2.1-SNAPSHOT</version>
|
||||
<version>3.0</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -43,7 +43,7 @@ public class FloodgateKeyLoader {
|
||||
if (floodgateDataFolder != null) {
|
||||
Path autoKey = floodgateDataFolder.resolve("key.pem");
|
||||
if (Files.exists(autoKey)) {
|
||||
logger.info(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.auto_loaded"));
|
||||
logger.debug(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.auto_loaded"));
|
||||
return autoKey;
|
||||
} else {
|
||||
logger.error(GeyserLocale.getLocaleStringLog("geyser.bootstrap.floodgate.missing_key"));
|
||||
@ -52,7 +52,7 @@ public class FloodgateKeyLoader {
|
||||
|
||||
Path floodgateKey;
|
||||
if (config.getFloodgateKeyFile().equals("public-key.pem")) {
|
||||
logger.info("Floodgate 2.0 doesn't use a public/private key system anymore. We'll search for key.pem instead");
|
||||
logger.debug("Floodgate 2.0 doesn't use a public/private key system anymore. We'll search for key.pem instead");
|
||||
floodgateKey = geyserDataFolder.resolve("key.pem");
|
||||
} else {
|
||||
floodgateKey = geyserDataFolder.resolve(config.getFloodgateKeyFile());
|
||||
|
@ -66,6 +66,7 @@ import org.geysermc.geyser.session.SessionManager;
|
||||
import org.geysermc.geyser.session.auth.AuthType;
|
||||
import org.geysermc.geyser.skin.FloodgateSkinUploader;
|
||||
import org.geysermc.geyser.skin.SkinProvider;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.text.MinecraftLocale;
|
||||
import org.geysermc.geyser.translator.inventory.item.ItemTranslator;
|
||||
@ -203,7 +204,6 @@ public class GeyserImpl implements GeyserApi {
|
||||
|
||||
GeyserLogger logger = bootstrap.getGeyserLogger();
|
||||
GeyserConfiguration config = bootstrap.getGeyserConfig();
|
||||
logger.setDebug(config.isDebugMode());
|
||||
|
||||
ScoreboardUpdater.init();
|
||||
|
||||
@ -249,18 +249,6 @@ public class GeyserImpl implements GeyserApi {
|
||||
// Ensure that PacketLib does not create an event loop for handling packets; we'll do that ourselves
|
||||
TcpSession.USE_EVENT_LOOP_FOR_PACKETS = false;
|
||||
|
||||
if (config.getRemote().getAuthType() == AuthType.FLOODGATE) {
|
||||
try {
|
||||
Key key = new AesKeyProducer().produceFrom(config.getFloodgateKeyPath());
|
||||
cipher = new AesCipher(new Base64Topping());
|
||||
cipher.init(key);
|
||||
logger.info(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.loaded_key"));
|
||||
skinUploader = new FloodgateSkinUploader(this).start();
|
||||
} catch (Exception exception) {
|
||||
logger.severe(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.bad_key"), exception);
|
||||
}
|
||||
}
|
||||
|
||||
String branch = "unknown";
|
||||
int buildNumber = -1;
|
||||
if (this.productionEnvironment()) {
|
||||
@ -321,14 +309,34 @@ public class GeyserImpl implements GeyserApi {
|
||||
if (shouldStartListener) {
|
||||
bedrockServer.bind().whenComplete((avoid, throwable) -> {
|
||||
if (throwable == null) {
|
||||
logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().getAddress(), String.valueOf(config.getBedrock().getPort())));
|
||||
logger.info(GeyserLocale.getLocaleStringLog("geyser.core.start", config.getBedrock().getAddress(),
|
||||
String.valueOf(config.getBedrock().getPort())));
|
||||
} else {
|
||||
logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", config.getBedrock().getAddress(), String.valueOf(config.getBedrock().getPort())));
|
||||
throwable.printStackTrace();
|
||||
String address = config.getBedrock().getAddress();
|
||||
int port = config.getBedrock().getPort();
|
||||
logger.severe(GeyserLocale.getLocaleStringLog("geyser.core.fail", address, String.valueOf(port)));
|
||||
if (!"0.0.0.0".equals(address)) {
|
||||
logger.info(ChatColor.GREEN + "Suggestion: try setting `address` under `bedrock` in the Geyser config back to 0.0.0.0");
|
||||
logger.info(ChatColor.GREEN + "Then, restart this server.");
|
||||
}
|
||||
}
|
||||
}).join();
|
||||
}
|
||||
|
||||
if (config.getRemote().getAuthType() == AuthType.FLOODGATE) {
|
||||
try {
|
||||
Key key = new AesKeyProducer().produceFrom(config.getFloodgateKeyPath());
|
||||
cipher = new AesCipher(new Base64Topping());
|
||||
cipher.init(key);
|
||||
logger.debug(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.loaded_key"));
|
||||
// Note: this is positioned after the bind so the skin uploader doesn't try to run if Geyser fails
|
||||
// to load successfully. Spigot complains about class loader if the plugin is disabled.
|
||||
skinUploader = new FloodgateSkinUploader(this).start();
|
||||
} catch (Exception exception) {
|
||||
logger.severe(GeyserLocale.getLocaleStringLog("geyser.auth.floodgate.bad_key"), exception);
|
||||
}
|
||||
}
|
||||
|
||||
if (config.getMetrics().isEnabled()) {
|
||||
metrics = new Metrics(this, "GeyserMC", config.getMetrics().getUniqueId(), false, java.util.logging.Logger.getLogger(""));
|
||||
metrics.addCustomChart(new Metrics.SingleLineChart("players", sessionManager::size));
|
||||
|
@ -28,11 +28,11 @@ package org.geysermc.geyser.command.defaults;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandSender;
|
||||
import org.geysermc.geyser.command.GeyserCommand;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
|
||||
public class OffhandCommand extends GeyserCommand {
|
||||
|
||||
@ -46,8 +46,8 @@ public class OffhandCommand extends GeyserCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, BlockUtils.POSITION_ZERO,
|
||||
Direction.DOWN);
|
||||
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, Vector3i.ZERO,
|
||||
Direction.DOWN, session.getNextSequence());
|
||||
session.sendDownstreamPacket(releaseItemPacket);
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ import org.geysermc.geyser.text.AsteriskSerializer;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.network.MinecraftProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.CpuUtils;
|
||||
import org.geysermc.geyser.util.FileUtils;
|
||||
import org.geysermc.geyser.util.WebUtils;
|
||||
import org.geysermc.floodgate.util.DeviceOs;
|
||||
@ -64,6 +65,7 @@ public class DumpInfo {
|
||||
|
||||
private final DumpInfo.VersionInfo versionInfo;
|
||||
private final int cpuCount;
|
||||
private final String cpuName;
|
||||
private final Locale systemLocale;
|
||||
private final String systemEncoding;
|
||||
private Properties gitInfo;
|
||||
@ -80,6 +82,7 @@ public class DumpInfo {
|
||||
this.versionInfo = new VersionInfo();
|
||||
|
||||
this.cpuCount = Runtime.getRuntime().availableProcessors();
|
||||
this.cpuName = CpuUtils.tryGetProcessorName();
|
||||
this.systemLocale = Locale.getDefault();
|
||||
this.systemEncoding = System.getProperty("file.encoding");
|
||||
|
||||
|
@ -51,6 +51,7 @@ import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
|
||||
public final class EntityDefinitions {
|
||||
public static final EntityDefinition<AllayEntity> ALLAY;
|
||||
public static final EntityDefinition<AreaEffectCloudEntity> AREA_EFFECT_CLOUD;
|
||||
public static final EntityDefinition<ArmorStandEntity> ARMOR_STAND;
|
||||
public static final EntityDefinition<TippedArrowEntity> ARROW;
|
||||
@ -63,6 +64,7 @@ public final class EntityDefinitions {
|
||||
public static final EntityDefinition<SpiderEntity> CAVE_SPIDER;
|
||||
public static final EntityDefinition<MinecartEntity> CHEST_MINECART;
|
||||
public static final EntityDefinition<ChickenEntity> CHICKEN;
|
||||
public static final EntityDefinition<ChestBoatEntity> CHEST_BOAT;
|
||||
public static final EntityDefinition<AbstractFishEntity> COD;
|
||||
public static final EntityDefinition<CommandBlockMinecartEntity> COMMAND_BLOCK_MINECART;
|
||||
public static final EntityDefinition<CowEntity> COW;
|
||||
@ -88,6 +90,7 @@ public final class EntityDefinitions {
|
||||
public static final EntityDefinition<FireworkEntity> FIREWORK_ROCKET;
|
||||
public static final EntityDefinition<FishingHookEntity> FISHING_BOBBER;
|
||||
public static final EntityDefinition<FoxEntity> FOX;
|
||||
public static final EntityDefinition<FrogEntity> FROG;
|
||||
public static final EntityDefinition<FurnaceMinecartEntity> FURNACE_MINECART; // Not present on Bedrock
|
||||
public static final EntityDefinition<GhastEntity> GHAST;
|
||||
public static final EntityDefinition<GiantEntity> GIANT;
|
||||
@ -143,6 +146,7 @@ public final class EntityDefinitions {
|
||||
public static final EntityDefinition<SquidEntity> SQUID;
|
||||
public static final EntityDefinition<AbstractSkeletonEntity> STRAY;
|
||||
public static final EntityDefinition<StriderEntity> STRIDER;
|
||||
public static final EntityDefinition<TadpoleEntity> TADPOLE;
|
||||
public static final EntityDefinition<TNTEntity> TNT;
|
||||
public static final EntityDefinition<MinecartEntity> TNT_MINECART;
|
||||
public static final EntityDefinition<TraderLlamaEntity> TRADER_LLAMA;
|
||||
@ -153,6 +157,7 @@ public final class EntityDefinitions {
|
||||
public static final EntityDefinition<VillagerEntity> VILLAGER;
|
||||
public static final EntityDefinition<VindicatorEntity> VINDICATOR;
|
||||
public static final EntityDefinition<AbstractMerchantEntity> WANDERING_TRADER;
|
||||
public static final EntityDefinition<WardenEntity> WARDEN;
|
||||
public static final EntityDefinition<RaidParticipantEntity> WITCH;
|
||||
public static final EntityDefinition<WitherEntity> WITHER;
|
||||
public static final EntityDefinition<AbstractSkeletonEntity> WITHER_SKELETON;
|
||||
@ -179,7 +184,7 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataType.INT, Entity::setAir) // Air/bubbles
|
||||
.addTranslator(MetadataType.OPTIONAL_CHAT, Entity::setDisplayName)
|
||||
.addTranslator(MetadataType.BOOLEAN, Entity::setDisplayNameVisible)
|
||||
.addTranslator(MetadataType.BOOLEAN, (entity, entityMetadata) -> entity.setFlag(EntityFlag.SILENT, ((BooleanEntityMetadata) entityMetadata).getPrimitiveValue()))
|
||||
.addTranslator(MetadataType.BOOLEAN, Entity::setSilent)
|
||||
.addTranslator(MetadataType.BOOLEAN, Entity::setGravity)
|
||||
.addTranslator(MetadataType.POSE, (entity, entityMetadata) -> entity.setPose(entityMetadata.getValue()))
|
||||
.addTranslator(MetadataType.INT, Entity::setFreezing)
|
||||
@ -209,6 +214,9 @@ public final class EntityDefinitions {
|
||||
.addTranslator(MetadataType.BOOLEAN, BoatEntity::setPaddlingRight)
|
||||
.addTranslator(MetadataType.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityData.BOAT_BUBBLE_TIME, entityMetadata.getValue())) // May not actually do anything
|
||||
.build();
|
||||
CHEST_BOAT = EntityDefinition.inherited(ChestBoatEntity::new, BOAT)
|
||||
.type(EntityType.CHEST_BOAT)
|
||||
.build();
|
||||
DRAGON_FIREBALL = EntityDefinition.inherited(FireballEntity::new, entityBase)
|
||||
.type(EntityType.DRAGON_FIREBALL)
|
||||
.heightAndWidth(1.0f)
|
||||
@ -274,6 +282,7 @@ public final class EntityDefinitions {
|
||||
.build();
|
||||
PAINTING = EntityDefinition.<PaintingEntity>inherited(null, entityBase)
|
||||
.type(EntityType.PAINTING)
|
||||
.addTranslator(MetadataType.PAINTING_VARIANT, PaintingEntity::setPaintingType)
|
||||
.build();
|
||||
SHULKER_BULLET = EntityDefinition.inherited(ThrowableEntity::new, entityBase)
|
||||
.type(EntityType.SHULKER_BULLET)
|
||||
@ -441,6 +450,10 @@ public final class EntityDefinitions {
|
||||
|
||||
// Extends mob
|
||||
{
|
||||
ALLAY = EntityDefinition.inherited(AllayEntity::new, mobEntityBase)
|
||||
.type(EntityType.ALLAY)
|
||||
.height(0.6f).width(0.35f)
|
||||
.build();
|
||||
BAT = EntityDefinition.inherited(BatEntity::new, mobEntityBase)
|
||||
.type(EntityType.BAT)
|
||||
.height(0.9f).width(0.5f)
|
||||
@ -550,6 +563,11 @@ public final class EntityDefinitions {
|
||||
.height(0.8f).width(0.4f)
|
||||
.addTranslator(MetadataType.BYTE, VexEntity::setVexFlags)
|
||||
.build();
|
||||
WARDEN = EntityDefinition.inherited(WardenEntity::new, mobEntityBase)
|
||||
.type(EntityType.WARDEN)
|
||||
.height(2.9f).width(0.9f)
|
||||
.addTranslator(MetadataType.INT, WardenEntity::setAngerLevel)
|
||||
.build();
|
||||
WITHER = EntityDefinition.inherited(WitherEntity::new, mobEntityBase)
|
||||
.type(EntityType.WITHER)
|
||||
.height(3.5f).width(0.9f)
|
||||
@ -634,6 +652,10 @@ public final class EntityDefinitions {
|
||||
.type(EntityType.SALMON)
|
||||
.height(0.5f).width(0.7f)
|
||||
.build();
|
||||
TADPOLE = EntityDefinition.inherited(TadpoleEntity::new, abstractFishEntityBase)
|
||||
.type(EntityType.TADPOLE)
|
||||
.height(0.3f).width(0.4f)
|
||||
.build();
|
||||
TROPICAL_FISH = EntityDefinition.inherited(TropicalFishEntity::new, abstractFishEntityBase)
|
||||
.type(EntityType.TROPICAL_FISH)
|
||||
.heightAndWidth(0.6f)
|
||||
@ -735,6 +757,12 @@ public final class EntityDefinitions {
|
||||
.addTranslator(null) // Trusted player 1
|
||||
.addTranslator(null) // Trusted player 2
|
||||
.build();
|
||||
FROG = EntityDefinition.inherited(FrogEntity::new, ageableEntityBase)
|
||||
.type(EntityType.FROG)
|
||||
.heightAndWidth(0.5f)
|
||||
.addTranslator(MetadataType.FROG_VARIANT, FrogEntity::setFrogVariant)
|
||||
.addTranslator(MetadataType.OPTIONAL_VARINT, FrogEntity::setTongueTarget)
|
||||
.build();
|
||||
HOGLIN = EntityDefinition.inherited(HoglinEntity::new, ageableEntityBase)
|
||||
.type(EntityType.HOGLIN)
|
||||
.height(1.4f).width(1.3965f)
|
||||
@ -871,7 +899,7 @@ public final class EntityDefinitions {
|
||||
CAT = EntityDefinition.inherited(CatEntity::new, tameableEntityBase)
|
||||
.type(EntityType.CAT)
|
||||
.height(0.35f).width(0.3f)
|
||||
.addTranslator(MetadataType.INT, CatEntity::setCatVariant)
|
||||
.addTranslator(MetadataType.CAT_VARIANT, CatEntity::setCatVariant)
|
||||
.addTranslator(MetadataType.BOOLEAN, CatEntity::setResting)
|
||||
.addTranslator(null) // "resting state one" //TODO
|
||||
.addTranslator(MetadataType.INT, CatEntity::setCollarColor)
|
||||
|
@ -52,4 +52,9 @@ public final class GeyserDirtyMetadata {
|
||||
public boolean hasEntries() {
|
||||
return !metadata.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return metadata.toString();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ChestBoatEntity extends BoatEntity {
|
||||
public ChestBoatEntity(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 InteractiveTag testInteraction(Hand hand) {
|
||||
return passengers.isEmpty() && !session.isSneaking() ? super.testInteraction(hand) : InteractiveTag.OPEN_CONTAINER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InteractionResult interact(Hand hand) {
|
||||
return passengers.isEmpty() && !session.isSneaking() ? super.interact(hand) : InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
@ -26,7 +26,6 @@
|
||||
package org.geysermc.geyser.entity.type;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
@ -50,13 +49,12 @@ public class EnderCrystalEntity extends Entity {
|
||||
setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
}
|
||||
|
||||
public void setBlockTarget(EntityMetadata<Optional<Position>, ?> entityMetadata) {
|
||||
public void setBlockTarget(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
|
||||
// Show beam
|
||||
// Usually performed client-side on Bedrock except for Ender Dragon respawn event
|
||||
Optional<Position> optionalPos = entityMetadata.getValue();
|
||||
Optional<Vector3i> optionalPos = entityMetadata.getValue();
|
||||
if (optionalPos.isPresent()) {
|
||||
Position pos = optionalPos.get();
|
||||
dirtyMetadata.put(EntityData.BLOCK_TARGET, Vector3i.from(pos.getX(), pos.getY(), pos.getZ()));
|
||||
dirtyMetadata.put(EntityData.BLOCK_TARGET, optionalPos.get());
|
||||
} else {
|
||||
dirtyMetadata.put(EntityData.BLOCK_TARGET, Vector3i.ZERO);
|
||||
}
|
||||
|
@ -94,6 +94,8 @@ public class Entity {
|
||||
private float boundingBoxWidth;
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected String nametag = "";
|
||||
@Setter(AccessLevel.NONE)
|
||||
protected boolean silent = false;
|
||||
/* Metadata end */
|
||||
|
||||
protected List<Entity> passengers = Collections.emptyList();
|
||||
@ -141,13 +143,19 @@ public class Entity {
|
||||
*/
|
||||
protected void initializeMetadata() {
|
||||
dirtyMetadata.put(EntityData.SCALE, 1f);
|
||||
dirtyMetadata.put(EntityData.COLOR, 0);
|
||||
dirtyMetadata.put(EntityData.COLOR, (byte) 0);
|
||||
dirtyMetadata.put(EntityData.MAX_AIR_SUPPLY, getMaxAir());
|
||||
setDimensions(Pose.STANDING);
|
||||
setFlag(EntityFlag.HAS_GRAVITY, true);
|
||||
setFlag(EntityFlag.HAS_COLLISION, true);
|
||||
setFlag(EntityFlag.CAN_SHOW_NAME, true);
|
||||
setFlag(EntityFlag.CAN_CLIMB, true);
|
||||
// Let the Java server (or us) supply all sounds for an entity
|
||||
setClientSideSilent();
|
||||
}
|
||||
|
||||
protected void setClientSideSilent() {
|
||||
setFlag(EntityFlag.SILENT, true);
|
||||
}
|
||||
|
||||
public void spawnEntity() {
|
||||
@ -351,7 +359,7 @@ public class Entity {
|
||||
dirtyMetadata.put(EntityData.AIR_SUPPLY, (short) MathUtils.constrain(amount, 0, getMaxAir()));
|
||||
}
|
||||
|
||||
protected int getMaxAir() {
|
||||
protected short getMaxAir() {
|
||||
return 300;
|
||||
}
|
||||
|
||||
@ -370,6 +378,10 @@ public class Entity {
|
||||
dirtyMetadata.put(EntityData.NAMETAG_ALWAYS_SHOW, (byte) (entityMetadata.getPrimitiveValue() ? 1 : 0));
|
||||
}
|
||||
|
||||
public final void setSilent(BooleanEntityMetadata entityMetadata) {
|
||||
silent = entityMetadata.getPrimitiveValue();
|
||||
}
|
||||
|
||||
public void setGravity(BooleanEntityMetadata entityMetadata) {
|
||||
setFlag(EntityFlag.HAS_GRAVITY, !entityMetadata.getPrimitiveValue());
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ package org.geysermc.geyser.entity.type;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
@ -58,7 +57,7 @@ public class EvokerFangsEntity extends Entity implements Tickable {
|
||||
|
||||
public void setAttackStarted() {
|
||||
this.attackStarted = true;
|
||||
if (!getFlag(EntityFlag.SILENT)) {
|
||||
if (!silent) {
|
||||
// Play the chomp sound
|
||||
PlaySoundPacket packet = new PlaySoundPacket();
|
||||
packet.setPosition(this.position);
|
||||
|
@ -36,8 +36,8 @@ import java.util.UUID;
|
||||
|
||||
public class FallingBlockEntity extends Entity {
|
||||
|
||||
public FallingBlockEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, int javaId) {
|
||||
super(session, entityId, geyserId, uuid, EntityDefinitions.FALLING_BLOCK, position, motion, yaw, pitch, 0f);
|
||||
public FallingBlockEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, int javaId) {
|
||||
super(session, entityId, geyserId, uuid, EntityDefinitions.FALLING_BLOCK, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
this.dirtyMetadata.put(EntityData.VARIANT, session.getBlockMappings().getBedrockBlockId(javaId));
|
||||
}
|
||||
|
@ -28,17 +28,16 @@ package org.geysermc.geyser.entity.type;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.level.block.BlockPositionIterator;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.level.physics.BoundingBox;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.collision.BlockCollision;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
@ -56,7 +55,7 @@ public class FishingHookEntity extends ThrowableEntity {
|
||||
|
||||
private final BoundingBox boundingBox;
|
||||
|
||||
public FishingHookEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, PlayerEntity owner) {
|
||||
public FishingHookEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, PlayerEntity owner) {
|
||||
super(session, entityId, geyserId, uuid, EntityDefinitions.FISHING_BOBBER, position, motion, yaw, pitch, 0f);
|
||||
|
||||
this.boundingBox = new BoundingBox(0.125, 0.125, 0.125, 0.25, 0.25, 0.25);
|
||||
@ -129,7 +128,7 @@ public class FishingHookEntity extends ThrowableEntity {
|
||||
}
|
||||
|
||||
private void sendSplashSound(GeyserSession session) {
|
||||
if (!getFlag(EntityFlag.SILENT)) {
|
||||
if (!silent) {
|
||||
float volume = (float) (0.2f * Math.sqrt(0.2 * (motion.getX() * motion.getX() + motion.getZ() * motion.getZ()) + motion.getY() * motion.getY()));
|
||||
if (volume > 1) {
|
||||
volume = 1;
|
||||
|
@ -79,8 +79,8 @@ public class ItemFrameEntity extends Entity {
|
||||
*/
|
||||
private boolean changed = true;
|
||||
|
||||
public ItemFrameEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, Direction direction) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, 0f);
|
||||
public ItemFrameEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, Direction direction) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
NbtMapBuilder blockBuilder = NbtMap.builder()
|
||||
.putString("name", this.definition.entityType() == EntityType.GLOW_ITEM_FRAME ? "minecraft:glow_frame" : "minecraft:frame")
|
||||
|
@ -29,7 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
@ -52,17 +51,13 @@ import lombok.Setter;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.AttributeUtils;
|
||||
import org.geysermc.geyser.util.ChunkUtils;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@ -123,12 +118,11 @@ public class LivingEntity extends Entity {
|
||||
session.sendUpstreamPacket(attributesPacket);
|
||||
}
|
||||
|
||||
public Vector3i setBedPosition(EntityMetadata<Optional<Position>, ?> entityMetadata) {
|
||||
Optional<Position> optionalPos = entityMetadata.getValue();
|
||||
public Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
|
||||
Optional<Vector3i> optionalPos = entityMetadata.getValue();
|
||||
if (optionalPos.isPresent()) {
|
||||
Position bedPosition = optionalPos.get();
|
||||
Vector3i vector = Vector3i.from(bedPosition.getX(), bedPosition.getY(), bedPosition.getZ());
|
||||
dirtyMetadata.put(EntityData.BED_POSITION, vector);
|
||||
Vector3i bedPosition = optionalPos.get();
|
||||
dirtyMetadata.put(EntityData.BED_POSITION, bedPosition);
|
||||
int bed = session.getGeyser().getWorldManager().getBlockAt(session, bedPosition);
|
||||
// Bed has to be updated, or else player is floating in the air
|
||||
ChunkUtils.updateBlock(session, bed, bedPosition);
|
||||
@ -136,7 +130,7 @@ public class LivingEntity extends Entity {
|
||||
// Has to be a byte or it does not work
|
||||
// (Bed position is what actually triggers sleep - "pose" is only optional)
|
||||
dirtyMetadata.put(EntityData.PLAYER_FLAGS, (byte) 2);
|
||||
return vector;
|
||||
return bedPosition;
|
||||
} else {
|
||||
// Player is no longer sleeping
|
||||
dirtyMetadata.put(EntityData.PLAYER_FLAGS, (byte) 0);
|
||||
|
@ -25,33 +25,45 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.packet.AddPaintingPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.level.PaintingType;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class PaintingEntity extends Entity {
|
||||
private static final double OFFSET = -0.46875;
|
||||
private final PaintingType paintingName;
|
||||
private final int direction;
|
||||
private final Direction direction;
|
||||
|
||||
public PaintingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, PaintingType paintingName, int direction) {
|
||||
super(session, entityId, geyserId, uuid, EntityDefinitions.PAINTING, position, Vector3f.ZERO, 0f, 0f, 0f);
|
||||
this.paintingName = paintingName;
|
||||
public PaintingEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, Direction direction) {
|
||||
super(session, entityId, geyserId, uuid, definition, position, motion, yaw, pitch, headYaw);
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity() {
|
||||
// Wait until we get the metadata needed
|
||||
}
|
||||
|
||||
public void setPaintingType(ObjectEntityMetadata<com.github.steveice10.mc.protocol.data.game.entity.type.PaintingType> entityMetadata) {
|
||||
PaintingType type = PaintingType.getByPaintingType(entityMetadata.getValue());
|
||||
AddPaintingPacket addPaintingPacket = new AddPaintingPacket();
|
||||
addPaintingPacket.setUniqueEntityId(geyserId);
|
||||
addPaintingPacket.setRuntimeEntityId(geyserId);
|
||||
addPaintingPacket.setMotive(paintingName.getBedrockName());
|
||||
addPaintingPacket.setPosition(fixOffset());
|
||||
addPaintingPacket.setDirection(direction);
|
||||
addPaintingPacket.setMotive(type.getBedrockName());
|
||||
addPaintingPacket.setPosition(fixOffset(type));
|
||||
addPaintingPacket.setDirection(switch (direction) {
|
||||
//TODO this doesn't seem right. Why did it work fine before?
|
||||
case SOUTH -> 0;
|
||||
case WEST -> 1;
|
||||
case NORTH -> 2;
|
||||
case EAST -> 3;
|
||||
default -> 0;
|
||||
});
|
||||
session.sendUpstreamPacket(addPaintingPacket);
|
||||
|
||||
valid = true;
|
||||
@ -64,17 +76,17 @@ public class PaintingEntity extends Entity {
|
||||
// Do nothing, as head look messes up paintings
|
||||
}
|
||||
|
||||
private Vector3f fixOffset() {
|
||||
private Vector3f fixOffset(PaintingType paintingName) {
|
||||
Vector3f position = super.position;
|
||||
position = position.add(0.5, 0.5, 0.5);
|
||||
double widthOffset = paintingName.getWidth() > 1 ? 0.5 : 0;
|
||||
double heightOffset = paintingName.getHeight() > 1 && paintingName.getHeight() != 3 ? 0.5 : 0;
|
||||
|
||||
return switch (direction) {
|
||||
case 0 -> position.add(widthOffset, heightOffset, OFFSET);
|
||||
case 1 -> position.add(-OFFSET, heightOffset, widthOffset);
|
||||
case 2 -> position.add(-widthOffset, heightOffset, -OFFSET);
|
||||
case 3 -> position.add(OFFSET, heightOffset, -widthOffset);
|
||||
case SOUTH -> position.add(widthOffset, heightOffset, OFFSET);
|
||||
case WEST -> position.add(-OFFSET, heightOffset, widthOffset);
|
||||
case NORTH -> position.add(-widthOffset, heightOffset, -OFFSET);
|
||||
case EAST -> position.add(OFFSET, heightOffset, -widthOffset);
|
||||
default -> position;
|
||||
};
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
@ -49,11 +50,11 @@ public class AbstractFishEntity extends WaterEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (EntityUtils.attemptToBucket(session, itemInHand)) {
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class AllayEntity extends MobEntity {
|
||||
public AllayEntity(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);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!this.hand.isValid() && !itemInHand.isEmpty()) {
|
||||
return InteractiveTag.GIVE_ITEM_TO_ALLAY;
|
||||
} else if (this.hand.isValid() && hand == Hand.MAIN_HAND && itemInHand.isEmpty()) {
|
||||
// Seems like there isn't a good tag for this yet
|
||||
return InteractiveTag.GIVE_ITEM_TO_ALLAY;
|
||||
} else {
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!this.hand.isValid() && !itemInHand.isEmpty()) {
|
||||
//TODO play sound?
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (this.hand.isValid() && hand == Hand.MAIN_HAND && itemInHand.isEmpty()) {
|
||||
//TOCHECK also play sound here?
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
@ -26,9 +26,7 @@
|
||||
package org.geysermc.geyser.entity.type.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Rotation;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
@ -165,27 +163,27 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
setFlag(EntityFlag.ADMIRING, (xd & 0x08) == 0x08); // Has no baseplate
|
||||
}
|
||||
|
||||
public void setHeadRotation(EntityMetadata<Rotation, ?> entityMetadata) {
|
||||
public void setHeadRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
|
||||
onRotationUpdate(EntityData.MARK_VARIANT, EntityFlag.INTERESTED, EntityFlag.CHARGED, EntityFlag.POWERED, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setBodyRotation(EntityMetadata<Rotation, ?> entityMetadata) {
|
||||
public void setBodyRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
|
||||
onRotationUpdate(EntityData.VARIANT, EntityFlag.IN_LOVE, EntityFlag.CELEBRATING, EntityFlag.CELEBRATING_SPECIAL, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setLeftArmRotation(EntityMetadata<Rotation, ?> entityMetadata) {
|
||||
public void setLeftArmRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
|
||||
onRotationUpdate(EntityData.TRADE_TIER, EntityFlag.CHARGING, EntityFlag.CRITICAL, EntityFlag.DANCING, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setRightArmRotation(EntityMetadata<Rotation, ?> entityMetadata) {
|
||||
public void setRightArmRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
|
||||
onRotationUpdate(EntityData.MAX_TRADE_TIER, EntityFlag.ELDER, EntityFlag.EMOTING, EntityFlag.IDLING, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setLeftLegRotation(EntityMetadata<Rotation, ?> entityMetadata) {
|
||||
public void setLeftLegRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
|
||||
onRotationUpdate(EntityData.SKIN_ID, EntityFlag.IS_ILLAGER_CAPTAIN, EntityFlag.IS_IN_UI, EntityFlag.LINGERING, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
public void setRightLegRotation(EntityMetadata<Rotation, ?> entityMetadata) {
|
||||
public void setRightLegRotation(EntityMetadata<Vector3f, ?> entityMetadata) {
|
||||
onRotationUpdate(EntityData.HURT_DIRECTION, EntityFlag.IS_PREGNANT, EntityFlag.SHEARED, EntityFlag.STALKING, entityMetadata.getValue());
|
||||
}
|
||||
|
||||
@ -200,13 +198,13 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
* @param negativeZToggle the flag to set true if the Z value of rotation is negative
|
||||
* @param rotation the Java rotation value
|
||||
*/
|
||||
private void onRotationUpdate(EntityData dataLeech, EntityFlag negativeXToggle, EntityFlag negativeYToggle, EntityFlag negativeZToggle, Rotation rotation) {
|
||||
private void onRotationUpdate(EntityData dataLeech, EntityFlag negativeXToggle, EntityFlag negativeYToggle, EntityFlag negativeZToggle, Vector3f rotation) {
|
||||
// Indicate that rotation should be checked
|
||||
setFlag(EntityFlag.BRIBED, true);
|
||||
|
||||
int rotationX = MathUtils.wrapDegreesToInt(rotation.getPitch());
|
||||
int rotationY = MathUtils.wrapDegreesToInt(rotation.getYaw());
|
||||
int rotationZ = MathUtils.wrapDegreesToInt(rotation.getRoll());
|
||||
int rotationX = MathUtils.wrapDegreesToInt(rotation.getX());
|
||||
int rotationY = MathUtils.wrapDegreesToInt(rotation.getY());
|
||||
int rotationZ = MathUtils.wrapDegreesToInt(rotation.getZ());
|
||||
// The top bit acts like binary and determines if each rotation goes above 100
|
||||
// We don't do this for the negative values out of concerns of the number being too big
|
||||
int topBit = (Math.abs(rotationX) >= 100 ? 4 : 0) + (Math.abs(rotationY) >= 100 ? 2 : 0) + (Math.abs(rotationZ) >= 100 ? 1 : 0);
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
@ -47,20 +48,20 @@ public class DolphinEntity extends WaterEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) {
|
||||
return InteractiveTag.FEED;
|
||||
}
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!itemInHand.isEmpty() && session.getTagCache().isFish(itemInHand)) {
|
||||
// Feed
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
@ -48,7 +49,7 @@ public class IronGolemEntity extends GolemEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().ironIngot()) {
|
||||
if (health < maxHealth) {
|
||||
// Healing the iron golem
|
||||
@ -57,6 +58,6 @@ public class IronGolemEntity extends GolemEntity {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
}
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ public class MobEntity extends LivingEntity {
|
||||
}
|
||||
}
|
||||
|
||||
InteractiveTag tag = testMobInteraction(itemStack);
|
||||
InteractiveTag tag = testMobInteraction(hand, itemStack);
|
||||
return tag != InteractiveTag.NONE ? tag : super.testInteraction(hand);
|
||||
}
|
||||
}
|
||||
@ -109,7 +109,7 @@ public class MobEntity extends LivingEntity {
|
||||
if (result.consumesAction()) {
|
||||
return result;
|
||||
} else {
|
||||
InteractionResult mobResult = mobInteract(itemInHand);
|
||||
InteractionResult mobResult = mobInteract(hand, itemInHand);
|
||||
return mobResult.consumesAction() ? mobResult : super.interact(hand);
|
||||
}
|
||||
}
|
||||
@ -137,12 +137,12 @@ public class MobEntity extends LivingEntity {
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
return InteractiveTag.NONE;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.geyser.entity.type.living;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
@ -51,7 +52,7 @@ public class SnowGolemEntity extends GolemEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (session.getItemMappings().getStoredItems().shears() == itemInHand.getJavaId() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
|
||||
// Shearing the snow golem
|
||||
return InteractiveTag.SHEAR;
|
||||
@ -61,7 +62,7 @@ public class SnowGolemEntity extends GolemEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (session.getItemMappings().getStoredItems().shears() == itemInHand.getJavaId() && isAlive() && !getFlag(EntityFlag.SHEARED)) {
|
||||
// Shearing the snow golem
|
||||
return InteractionResult.SUCCESS;
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.InteractiveTag;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TadpoleEntity extends AbstractFishEntity {
|
||||
public TadpoleEntity(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);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (isFood(itemInHand)) {
|
||||
return InteractiveTag.FEED;
|
||||
}
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (isFood(itemInHand)) {
|
||||
//TODO particles
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
|
||||
private boolean isFood(GeyserItemStack itemStack) {
|
||||
return itemStack.getJavaId() == session.getItemMappings().getStoredItems().slimeBall();
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
@ -63,16 +64,16 @@ public class AnimalEntity extends AgeableEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (canEat(itemInHand)) {
|
||||
return InteractiveTag.FEED;
|
||||
}
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (canEat(itemInHand)) {
|
||||
// FEED
|
||||
if (getFlag(EntityFlag.BABY)) {
|
||||
@ -82,6 +83,6 @@ public class AnimalEntity extends AgeableEntity {
|
||||
return InteractionResult.CONSUME;
|
||||
}
|
||||
}
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
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 com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
@ -64,7 +65,7 @@ public class AxolotlEntity extends AnimalEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getMaxAir() {
|
||||
protected short getMaxAir() {
|
||||
return 6000;
|
||||
}
|
||||
|
||||
@ -75,11 +76,11 @@ public class AxolotlEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (EntityUtils.attemptToBucket(session, itemInHand)) {
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
@ -44,9 +45,9 @@ public class CowEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (getFlag(EntityFlag.BABY) || !itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
return InteractiveTag.MILK;
|
||||
@ -54,9 +55,9 @@ public class CowEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (getFlag(EntityFlag.BABY) || !itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
|
||||
session.playSoundEvent(SoundEvent.MILK, position);
|
||||
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FrogEntity extends AnimalEntity {
|
||||
public FrogEntity(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
|
||||
public void setPose(Pose pose) {
|
||||
setFlag(EntityFlag.JUMP_GOAL_JUMP, pose == Pose.LONG_JUMPING);
|
||||
setFlag(EntityFlag.CROAKING, pose == Pose.CROAKING);
|
||||
setFlag(EntityFlag.EAT_MOB, pose == Pose.USING_TONGUE);
|
||||
|
||||
super.setPose(pose);
|
||||
}
|
||||
|
||||
public void setFrogVariant(IntEntityMetadata entityMetadata) {
|
||||
int variant = entityMetadata.getPrimitiveValue();
|
||||
dirtyMetadata.put(EntityData.VARIANT, switch (variant) {
|
||||
case 1 -> 2; // White
|
||||
case 2 -> 1; // Green
|
||||
default -> variant;
|
||||
});
|
||||
}
|
||||
|
||||
public void setTongueTarget(ObjectEntityMetadata<OptionalInt> entityMetadata) {
|
||||
OptionalInt entityId = entityMetadata.getValue();
|
||||
if (entityId.isPresent()) {
|
||||
Entity entity = session.getEntityCache().getEntityByJavaId(entityId.getAsInt());
|
||||
if (entity != null) {
|
||||
dirtyMetadata.put(EntityData.TARGET_EID, entity.getGeyserId());
|
||||
}
|
||||
} else {
|
||||
dirtyMetadata.put(EntityData.TARGET_EID, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canEat(String javaIdentifierStripped, ItemMapping mapping) {
|
||||
return mapping.getJavaId() == session.getItemMappings().getStoredItems().slimeBall();
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
@ -65,12 +66,12 @@ public class GoatEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!getFlag(EntityFlag.BABY) && itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bucket")) {
|
||||
session.playSoundEvent(isScreamer ? SoundEvent.MILK_SCREAMER : SoundEvent.MILK, position);
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public class HoglinEntity extends AnimalEntity {
|
||||
|
||||
@Override
|
||||
protected boolean isShaking() {
|
||||
return (!isImmuneToZombification && !session.isDimensionPiglinSafe()) || super.isShaking();
|
||||
return (!isImmuneToZombification && !session.getDimensionType().piglinSafe()) || super.isShaking();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
@ -52,7 +53,7 @@ public class MooshroomEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
|
||||
if (!isBaby()) {
|
||||
if (itemInHand.getJavaId() == storedItems.bowl()) {
|
||||
@ -63,12 +64,12 @@ public class MooshroomEntity extends AnimalEntity {
|
||||
return InteractiveTag.MOOSHROOM_SHEAR;
|
||||
}
|
||||
}
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
StoredItemMappings storedItems = session.getItemMappings().getStoredItems();
|
||||
boolean isBaby = isBaby();
|
||||
if (!isBaby && itemInHand.getJavaId() == storedItems.bowl()) {
|
||||
@ -81,6 +82,6 @@ public class MooshroomEntity extends AnimalEntity {
|
||||
// ?
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
@ -50,23 +51,23 @@ public class OcelotEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!getFlag(EntityFlag.TRUSTING) && canEat(itemInHand) && session.getPlayerEntity().getPosition().distanceSquared(position) < 9f) {
|
||||
// Attempt to feed
|
||||
return InteractiveTag.FEED;
|
||||
} else {
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!getFlag(EntityFlag.TRUSTING) && canEat(itemInHand) && session.getPlayerEntity().getPosition().distanceSquared(position) < 9f) {
|
||||
// Attempt to feed
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
||||
@ -93,16 +94,16 @@ public class PandaEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (mainGene == Gene.WORRIED && session.isThunder()) {
|
||||
return InteractiveTag.NONE;
|
||||
}
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (mainGene == Gene.WORRIED && session.isThunder()) {
|
||||
// Huh!
|
||||
return InteractionResult.PASS;
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
@ -51,12 +52,12 @@ public class PigEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
|
||||
// Mount
|
||||
return InteractiveTag.MOUNT;
|
||||
} else {
|
||||
InteractiveTag superTag = super.testMobInteraction(itemInHand);
|
||||
InteractiveTag superTag = super.testMobInteraction(hand, itemInHand);
|
||||
if (superTag != InteractiveTag.NONE) {
|
||||
return superTag;
|
||||
} else {
|
||||
@ -68,12 +69,12 @@ public class PigEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
|
||||
// Mount
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
InteractionResult superResult = super.mobInteract(itemInHand);
|
||||
InteractionResult superResult = super.mobInteract(hand, itemInHand);
|
||||
if (superResult.consumesAction()) {
|
||||
return superResult;
|
||||
} else {
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
@ -55,11 +56,11 @@ public class SheepEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().shears()) {
|
||||
return InteractiveTag.SHEAR;
|
||||
} else {
|
||||
InteractiveTag tag = super.testMobInteraction(itemInHand);
|
||||
InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
|
||||
if (tag != InteractiveTag.NONE) {
|
||||
return tag;
|
||||
} else {
|
||||
@ -74,11 +75,11 @@ public class SheepEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().shears()) {
|
||||
return InteractionResult.CONSUME;
|
||||
} else {
|
||||
InteractionResult superResult = super.mobInteract(itemInHand);
|
||||
InteractionResult superResult = super.mobInteract(hand, itemInHand);
|
||||
if (superResult.consumesAction()) {
|
||||
return superResult;
|
||||
} else {
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.geyser.entity.type.living.animal;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
@ -98,12 +99,12 @@ public class StriderEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
|
||||
// Mount Strider
|
||||
return InteractiveTag.RIDE_STRIDER;
|
||||
} else {
|
||||
InteractiveTag tag = super.testMobInteraction(itemInHand);
|
||||
InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
|
||||
if (tag != InteractiveTag.NONE) {
|
||||
return tag;
|
||||
} else {
|
||||
@ -115,12 +116,12 @@ public class StriderEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!canEat(itemInHand) && getFlag(EntityFlag.SADDLED) && passengers.isEmpty() && !session.isSneaking()) {
|
||||
// Mount Strider
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
InteractionResult superResult = super.mobInteract(itemInHand);
|
||||
InteractionResult superResult = super.mobInteract(hand, itemInHand);
|
||||
if (superResult.consumesAction()) {
|
||||
return superResult;
|
||||
} else {
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.geyser.entity.type.living.animal.horse;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
@ -129,12 +130,12 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
return testHorseInteraction(itemInHand);
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
return testHorseInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected final InteractiveTag testHorseInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected final InteractiveTag testHorseInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
boolean isBaby = isBaby();
|
||||
if (!isBaby) {
|
||||
if (getFlag(EntityFlag.TAMED) && session.isSneaking()) {
|
||||
@ -142,7 +143,7 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
}
|
||||
|
||||
if (!passengers.isEmpty()) {
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,7 +172,7 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
}
|
||||
|
||||
if (isBaby) {
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
} else {
|
||||
return InteractiveTag.MOUNT;
|
||||
}
|
||||
@ -179,12 +180,12 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
return mobHorseInteract(itemInHand);
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
return mobHorseInteract(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
protected final InteractionResult mobHorseInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected final InteractionResult mobHorseInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
boolean isBaby = isBaby();
|
||||
if (!isBaby) {
|
||||
if (getFlag(EntityFlag.TAMED) && session.isSneaking()) {
|
||||
@ -193,7 +194,7 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
}
|
||||
|
||||
if (!passengers.isEmpty()) {
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,7 +228,7 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
}
|
||||
|
||||
if (isBaby) {
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
} else {
|
||||
// Attempt to mount
|
||||
// TODO client-set flags sitting standing?
|
||||
@ -249,15 +250,15 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
|
||||
/* Just a place to stuff common code for the undead variants without having duplicate code */
|
||||
|
||||
protected final InteractiveTag testUndeadHorseInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected final InteractiveTag testUndeadHorseInteraction(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!getFlag(EntityFlag.TAMED)) {
|
||||
return InteractiveTag.NONE;
|
||||
} else if (isBaby()) {
|
||||
return testHorseInteraction(itemInHand);
|
||||
return testHorseInteraction(hand, itemInHand);
|
||||
} else if (session.isSneaking()) {
|
||||
return InteractiveTag.OPEN_CONTAINER;
|
||||
} else if (!passengers.isEmpty()) {
|
||||
return testHorseInteraction(itemInHand);
|
||||
return testHorseInteraction(hand, itemInHand);
|
||||
} else {
|
||||
if (session.getItemMappings().getStoredItems().saddle() == itemInHand.getJavaId()) {
|
||||
return InteractiveTag.OPEN_CONTAINER;
|
||||
@ -271,16 +272,16 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||
}
|
||||
}
|
||||
|
||||
protected final InteractionResult undeadHorseInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected final InteractionResult undeadHorseInteract(@Nonnull Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (!getFlag(EntityFlag.TAMED)) {
|
||||
return InteractionResult.PASS;
|
||||
} else if (isBaby()) {
|
||||
return mobHorseInteract(itemInHand);
|
||||
return mobHorseInteract(hand, itemInHand);
|
||||
} else if (session.isSneaking()) {
|
||||
// Opens inventory
|
||||
return InteractionResult.SUCCESS;
|
||||
} else if (!passengers.isEmpty()) {
|
||||
return mobHorseInteract(itemInHand);
|
||||
return mobHorseInteract(hand, itemInHand);
|
||||
} else {
|
||||
// The client tests for saddle but it doesn't matter for us at this point.
|
||||
return InteractionResult.SUCCESS;
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living.animal.horse;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
@ -42,13 +43,13 @@ public class SkeletonHorseEntity extends AbstractHorseEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
return testUndeadHorseInteraction(itemInHand);
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
return testUndeadHorseInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
return undeadHorseInteract(itemInHand);
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
return undeadHorseInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living.animal.horse;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
@ -42,13 +43,13 @@ public class ZombieHorseEntity extends AbstractHorseEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
return testUndeadHorseInteraction(itemInHand);
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
return testUndeadHorseInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
return undeadHorseInteract(itemInHand);
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
return undeadHorseInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.entity.type.living.animal.tameable;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
@ -105,7 +106,7 @@ public class CatEntity extends TameableEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
boolean tamed = getFlag(EntityFlag.TAMED);
|
||||
if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
|
||||
// Toggle sitting
|
||||
@ -117,7 +118,7 @@ public class CatEntity extends TameableEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
boolean tamed = getFlag(EntityFlag.TAMED);
|
||||
if (tamed && ownerBedrockId == session.getPlayerEntity().getGeyserId()) {
|
||||
return InteractionResult.SUCCESS;
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living.animal.tameable;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
@ -58,7 +59,7 @@ public class ParrotEntity extends TameableEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
String javaIdentifierStripped = itemInHand.getMapping(session).getJavaIdentifier().replace("minecraft:", "");
|
||||
boolean tame = getFlag(EntityFlag.TAMED);
|
||||
if (!tame && isTameFood(javaIdentifierStripped)) {
|
||||
@ -69,12 +70,12 @@ public class ParrotEntity extends TameableEntity {
|
||||
// Sitting/standing
|
||||
return getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
|
||||
}
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
String javaIdentifierStripped = itemInHand.getMapping(session).getJavaIdentifier().replace("minecraft:", "");
|
||||
boolean tame = getFlag(EntityFlag.TAMED);
|
||||
if (!tame && isTameFood(javaIdentifierStripped)) {
|
||||
@ -85,6 +86,6 @@ public class ParrotEntity extends TameableEntity {
|
||||
// Sitting/standing
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.animal.tameable;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
@ -103,7 +104,7 @@ public class WolfEntity extends TameableEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (getFlag(EntityFlag.ANGRY)) {
|
||||
return InteractiveTag.NONE;
|
||||
}
|
||||
@ -122,12 +123,12 @@ public class WolfEntity extends TameableEntity {
|
||||
return getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
|
||||
}
|
||||
}
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (ownerBedrockId == session.getPlayerEntity().getGeyserId() || getFlag(EntityFlag.TAMED)
|
||||
|| itemInHand.getMapping(session).getJavaIdentifier().equals("minecraft:bone") && !getFlag(EntityFlag.ANGRY)) {
|
||||
// Sitting toggle or feeding; not angry
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.entity.type.living.merchant;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
@ -51,7 +52,7 @@ public class AbstractMerchantEntity extends AgeableEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
String javaIdentifier = itemInHand.getMapping(session).getJavaIdentifier();
|
||||
if (!javaIdentifier.equals("minecraft:villager_spawn_egg")
|
||||
&& (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING) && ((VillagerEntity) this).isCanTradeWith())) {
|
||||
@ -60,12 +61,12 @@ public class AbstractMerchantEntity extends AgeableEntity {
|
||||
return InteractiveTag.TRADE;
|
||||
}
|
||||
}
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
String javaIdentifier = itemInHand.getMapping(session).getJavaIdentifier();
|
||||
if (!javaIdentifier.equals("minecraft:villager_spawn_egg")
|
||||
&& (definition != EntityDefinitions.VILLAGER || !getFlag(EntityFlag.SLEEPING))
|
||||
@ -73,7 +74,7 @@ public class AbstractMerchantEntity extends AgeableEntity {
|
||||
// Trading time
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
package org.geysermc.geyser.entity.type.living.merchant;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.VillagerData;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
@ -103,7 +102,7 @@ public class VillagerEntity extends AbstractMerchantEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3i setBedPosition(EntityMetadata<Optional<Position>, ?> entityMetadata) {
|
||||
public Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
|
||||
return bedPosition = super.setBedPosition(entityMetadata);
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,6 @@ public class BasePiglinEntity extends MonsterEntity {
|
||||
|
||||
@Override
|
||||
protected boolean isShaking() {
|
||||
return (!isImmuneToZombification && !session.isDimensionPiglinSafe()) || super.isShaking();
|
||||
return (!isImmuneToZombification && !session.getDimensionType().piglinSafe()) || super.isShaking();
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living.monster;
|
||||
|
||||
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 com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
@ -63,23 +64,23 @@ public class CreeperEntity extends MonsterEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().flintAndSteel()) {
|
||||
return InteractiveTag.IGNITE_CREEPER;
|
||||
} else {
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().flintAndSteel()) {
|
||||
// Ignite creeper
|
||||
session.playSoundEvent(SoundEvent.IGNITE, position);
|
||||
return InteractionResult.SUCCESS;
|
||||
} else {
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ public class EnderDragonEntity extends MobEntity implements Tickable {
|
||||
*/
|
||||
private void effectTick() {
|
||||
Random random = ThreadLocalRandom.current();
|
||||
if (!getFlag(EntityFlag.SILENT)) {
|
||||
if (!silent) {
|
||||
if (Math.cos(wingPosition * 2f * Math.PI) <= -0.3f && Math.cos(lastWingPosition * 2f * Math.PI) >= -0.3f) {
|
||||
PlaySoundPacket playSoundPacket = new PlaySoundPacket();
|
||||
playSoundPacket.setSound("mob.enderdragon.flap");
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.geyser.entity.type.living.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
@ -71,8 +72,8 @@ public class PiglinEntity extends BasePiglinEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
InteractiveTag tag = super.testMobInteraction(itemInHand);
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
InteractiveTag tag = super.testMobInteraction(hand, itemInHand);
|
||||
if (tag != InteractiveTag.NONE) {
|
||||
return tag;
|
||||
} else {
|
||||
@ -82,8 +83,8 @@ public class PiglinEntity extends BasePiglinEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
InteractionResult superResult = super.mobInteract(itemInHand);
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
InteractionResult superResult = super.mobInteract(hand, itemInHand);
|
||||
if (superResult.consumesAction()) {
|
||||
return superResult;
|
||||
} else {
|
||||
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.monster;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.IntEntityMetadata;
|
||||
import com.nukkitx.math.GenericMath;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.PlaySoundPacket;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.Tickable;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
public class WardenEntity extends MonsterEntity implements Tickable {
|
||||
private int heartBeatDelay;
|
||||
private int tickCount;
|
||||
|
||||
private int sonicBoomTickDuration;
|
||||
|
||||
public WardenEntity(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
|
||||
public void setPose(Pose pose) {
|
||||
setFlag(EntityFlag.DIGGING, pose == Pose.DIGGING);
|
||||
setFlag(EntityFlag.EMERGING, pose == Pose.EMERGING);
|
||||
setFlag(EntityFlag.ROARING, pose == Pose.ROARING);
|
||||
setFlag(EntityFlag.SNIFFING, pose == Pose.SNIFFING);
|
||||
super.setPose(pose);
|
||||
}
|
||||
|
||||
public void setAngerLevel(IntEntityMetadata entityMetadata) {
|
||||
float anger = (float) entityMetadata.getPrimitiveValue() / 80f;
|
||||
heartBeatDelay = 40 - GenericMath.floor(MathUtils.clamp(anger, 0.0F, 1.0F) * 30F);
|
||||
dirtyMetadata.put(EntityData.HEARTBEAT_INTERVAL_TICKS, heartBeatDelay);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
if (++tickCount % heartBeatDelay == 0 && !silent) {
|
||||
// We have to do these calculations because they're clientside on Java Edition but we mute entities
|
||||
// to prevent hearing their step sounds
|
||||
ThreadLocalRandom random = ThreadLocalRandom.current();
|
||||
|
||||
PlaySoundPacket packet = new PlaySoundPacket();
|
||||
packet.setSound("mob.warden.heartbeat");
|
||||
packet.setPosition(position);
|
||||
packet.setPitch((random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f);
|
||||
packet.setVolume(1.0f);
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
|
||||
if (sonicBoomTickDuration > 0) {
|
||||
sonicBoomTickDuration--;
|
||||
if (sonicBoomTickDuration == 0) {
|
||||
setFlag(EntityFlag.SONIC_BOOM, false);
|
||||
updateBedrockMetadata();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onSonicBoom() {
|
||||
setFlag(EntityFlag.SONIC_BOOM, true);
|
||||
updateBedrockMetadata();
|
||||
|
||||
sonicBoomTickDuration = 3 * 20;
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ 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.VillagerData;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
@ -67,22 +68,22 @@ public class ZombieVillagerEntity extends ZombieEntity {
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractiveTag testMobInteraction(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractiveTag testMobInteraction(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().goldenApple()) {
|
||||
return InteractiveTag.CURE;
|
||||
} else {
|
||||
return super.testMobInteraction(itemInHand);
|
||||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
protected InteractionResult mobInteract(@Nonnull GeyserItemStack itemInHand) {
|
||||
protected InteractionResult mobInteract(Hand hand, @Nonnull GeyserItemStack itemInHand) {
|
||||
if (itemInHand.getJavaId() == session.getItemMappings().getStoredItems().goldenApple()) {
|
||||
// The client doesn't know if the entity has weakness as that's not usually sent over the network
|
||||
return InteractionResult.CONSUME;
|
||||
} else {
|
||||
return super.mobInteract(itemInHand);
|
||||
return super.mobInteract(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,6 @@ package org.geysermc.geyser.entity.type.player;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
|
||||
@ -169,6 +168,12 @@ public class PlayerEntity extends LivingEntity {
|
||||
}
|
||||
|
||||
session.sendUpstreamPacket(movePlayerPacket);
|
||||
|
||||
if (teleported) {
|
||||
// As of 1.19.0, head yaw seems to be ignored during teleports.
|
||||
updateHeadLookRotation(headYaw);
|
||||
}
|
||||
|
||||
if (leftParrot != null) {
|
||||
leftParrot.moveAbsolute(position, yaw, pitch, headYaw, true, teleported);
|
||||
}
|
||||
@ -211,52 +216,8 @@ public class PlayerEntity extends LivingEntity {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateHeadLookRotation(float headYaw) {
|
||||
moveRelative(0, 0, 0, getYaw(), getPitch(), headYaw, isOnGround());
|
||||
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
|
||||
movePlayerPacket.setRuntimeEntityId(geyserId);
|
||||
movePlayerPacket.setPosition(position);
|
||||
movePlayerPacket.setRotation(getBedrockRotation());
|
||||
movePlayerPacket.setMode(MovePlayerPacket.Mode.HEAD_ROTATION);
|
||||
session.sendUpstreamPacket(movePlayerPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePositionAndRotation(double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) {
|
||||
moveRelative(moveX, moveY, moveZ, yaw, pitch, isOnGround);
|
||||
if (leftParrot != null) {
|
||||
leftParrot.moveRelative(moveX, moveY, moveZ, yaw, pitch, isOnGround);
|
||||
}
|
||||
if (rightParrot != null) {
|
||||
rightParrot.moveRelative(moveX, moveY, moveZ, yaw, pitch, isOnGround);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateRotation(float yaw, float pitch, float headYaw, boolean isOnGround) {
|
||||
// the method below is called by super.updateRotation(yaw, pitch, isOnGround).
|
||||
// but we have to be able to set the headYaw, so we call the method below directly.
|
||||
super.moveRelative(0, 0, 0, yaw, pitch, headYaw, isOnGround);
|
||||
|
||||
// Both packets need to be sent or else player head rotation isn't correctly updated
|
||||
MovePlayerPacket movePlayerPacket = new MovePlayerPacket();
|
||||
movePlayerPacket.setRuntimeEntityId(geyserId);
|
||||
movePlayerPacket.setPosition(position);
|
||||
movePlayerPacket.setRotation(getBedrockRotation());
|
||||
movePlayerPacket.setOnGround(isOnGround);
|
||||
movePlayerPacket.setMode(MovePlayerPacket.Mode.HEAD_ROTATION);
|
||||
session.sendUpstreamPacket(movePlayerPacket);
|
||||
if (leftParrot != null) {
|
||||
leftParrot.updateRotation(yaw, pitch, isOnGround);
|
||||
}
|
||||
if (rightParrot != null) {
|
||||
rightParrot.updateRotation(yaw, pitch, isOnGround);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateRotation(float yaw, float pitch, boolean isOnGround) {
|
||||
updateRotation(yaw, pitch, getHeadYaw(), isOnGround);
|
||||
moveRelative(0, 0, 0, yaw, pitch, headYaw, isOnGround);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -265,7 +226,7 @@ public class PlayerEntity extends LivingEntity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector3i setBedPosition(EntityMetadata<Optional<Position>, ?> entityMetadata) {
|
||||
public Vector3i setBedPosition(EntityMetadata<Optional<Vector3i>, ?> entityMetadata) {
|
||||
return bedPosition = super.setBedPosition(entityMetadata);
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.player;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType;
|
||||
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.type.ByteEntityMetadata;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
@ -40,11 +41,10 @@ import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.AttributeUtils;
|
||||
import org.geysermc.geyser.util.DimensionUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* The entity class specifically for a {@link GeyserSession}'s player.
|
||||
@ -75,6 +75,11 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
valid = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setClientSideSilent() {
|
||||
// Do nothing, since we want the session player to hear their own footstep sounds for example.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnEntity() {
|
||||
// Already logged in
|
||||
@ -222,4 +227,14 @@ public class SessionPlayerEntity extends PlayerEntity {
|
||||
this.attributes.put(type, attributeData);
|
||||
return attributeData;
|
||||
}
|
||||
|
||||
public void setLastDeathPosition(@Nullable GlobalPos pos) {
|
||||
if (pos != null) {
|
||||
dirtyMetadata.put(EntityData.PLAYER_LAST_DEATH_POS, pos.getPosition());
|
||||
dirtyMetadata.put(EntityData.PLAYER_LAST_DEATH_DIMENSION, DimensionUtils.javaToBedrock(pos.getDimension()));
|
||||
dirtyMetadata.put(EntityData.PLAYER_HAS_DIED, (byte) 1);
|
||||
} else {
|
||||
dirtyMetadata.put(EntityData.PLAYER_HAS_DIED, (byte) 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public class GeyserEnchantOption {
|
||||
*/
|
||||
private static final List<String> ENCHANT_NAMES = Arrays.asList("tougher armor", "lukeeey", "fall better",
|
||||
"explode less", "camo toy", "breathe better", "rtm five one six", "armor stab", "water walk", "you are elsa",
|
||||
"tim two zero three", "fast walk nether", "oof ouch owie", "enemy on fire", "spider sad", "aj ferguson", "redned",
|
||||
"tim two zero three", "fast walk nether", "davchoo", "oof ouch owie", "enemy on fire", "spider sad", "aj ferguson", "redned",
|
||||
"more items thx", "long sword reach", "fast tool", "give me block", "less breaky break", "cube craft",
|
||||
"strong arrow", "fist arrow", "spicy arrow", "many many arrows", "geyser", "come here fish", "i like this",
|
||||
"stabby stab", "supreme mortal", "avatar i guess", "more arrows", "fly finder seventeen", "in and out",
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
package org.geysermc.geyser.inventory.holder;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
@ -36,9 +35,9 @@ import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
@ -154,8 +153,7 @@ public class BlockInventoryHolder extends InventoryHolder {
|
||||
}
|
||||
|
||||
Vector3i holderPos = inventory.getHolderPosition();
|
||||
Position pos = new Position(holderPos.getX(), holderPos.getY(), holderPos.getZ());
|
||||
int realBlock = session.getGeyser().getWorldManager().getBlockAt(session, pos.getX(), pos.getY(), pos.getZ());
|
||||
int realBlock = session.getGeyser().getWorldManager().getBlockAt(session, holderPos.getX(), holderPos.getY(), holderPos.getZ());
|
||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||
blockPacket.setDataLayer(0);
|
||||
blockPacket.setBlockPosition(holderPos);
|
||||
|
@ -67,7 +67,8 @@ public enum Enchantment {
|
||||
MULTISHOT,
|
||||
PIERCING,
|
||||
QUICK_CHARGE,
|
||||
SOUL_SPEED;
|
||||
SOUL_SPEED,
|
||||
SWIFT_SNEAK;
|
||||
|
||||
private static final Enchantment[] VALUES = values();
|
||||
|
||||
@ -109,6 +110,7 @@ public enum Enchantment {
|
||||
FROST_WALKER,
|
||||
BINDING_CURSE,
|
||||
SOUL_SPEED,
|
||||
SWIFT_SNEAK,
|
||||
SHARPNESS,
|
||||
SMITE,
|
||||
BANE_OF_ARTHROPODS,
|
||||
|
@ -60,6 +60,7 @@ public class StoredItemMappings {
|
||||
private final int saddle;
|
||||
private final int shears;
|
||||
private final ItemMapping shield;
|
||||
private final int slimeBall;
|
||||
private final int waterBucket;
|
||||
private final ItemMapping wheat;
|
||||
private final ItemMapping writableBook;
|
||||
@ -87,6 +88,7 @@ public class StoredItemMappings {
|
||||
this.saddle = load(itemMappings, "saddle").getJavaId();
|
||||
this.shears = load(itemMappings, "shears").getJavaId();
|
||||
this.shield = load(itemMappings, "shield");
|
||||
this.slimeBall = load(itemMappings, "slime_ball").getJavaId();
|
||||
this.waterBucket = load(itemMappings, "water_bucket").getJavaId();
|
||||
this.wheat = load(itemMappings, "wheat");
|
||||
this.writableBook = load(itemMappings, "writable_book");
|
||||
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.level;
|
||||
import com.github.steveice10.mc.protocol.data.game.advancement.Advancement;
|
||||
import lombok.NonNull;
|
||||
import org.geysermc.geyser.session.cache.AdvancementsCache;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -69,6 +70,14 @@ public class GeyserAdvancement {
|
||||
return this.advancement.getDisplayData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Purple for challenges and green for normal advancements
|
||||
*/
|
||||
public String getDisplayColor() {
|
||||
Advancement.DisplayData displayData = getDisplayData();
|
||||
return displayData != null && displayData.getFrameType() == Advancement.DisplayData.FrameType.CHALLENGE ? ChatColor.LIGHT_PURPLE : ChatColor.GREEN;
|
||||
}
|
||||
|
||||
public String getRootId(AdvancementsCache advancementsCache) {
|
||||
if (rootId == null) {
|
||||
if (this.advancement.getParentId() == null) {
|
||||
|
@ -27,15 +27,14 @@ package org.geysermc.geyser.level;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.ChunkCache;
|
||||
import org.geysermc.geyser.translator.inventory.LecternInventoryTranslator;
|
||||
import org.geysermc.geyser.level.block.BlockStateValues;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@ -83,7 +82,7 @@ public class GeyserWorldManager extends WorldManager {
|
||||
|
||||
@Override
|
||||
public void setGameRule(GeyserSession session, String name, Object value) {
|
||||
session.sendDownstreamPacket(new ServerboundChatPacket("/gamerule " + name + " " + value));
|
||||
session.sendCommand("gamerule " + name + " " + value);
|
||||
gameruleCache.put(name, String.valueOf(value));
|
||||
}
|
||||
|
||||
@ -109,12 +108,12 @@ public class GeyserWorldManager extends WorldManager {
|
||||
|
||||
@Override
|
||||
public void setPlayerGameMode(GeyserSession session, GameMode gameMode) {
|
||||
session.sendDownstreamPacket(new ServerboundChatPacket("/gamemode " + gameMode.name().toLowerCase(Locale.ROOT)));
|
||||
session.sendCommand("gamemode " + gameMode.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDifficulty(GeyserSession session, Difficulty difficulty) {
|
||||
session.sendDownstreamPacket(new ServerboundChatPacket("/difficulty " + difficulty.name().toLowerCase(Locale.ROOT)));
|
||||
session.sendCommand("difficulty " + difficulty.name().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
56
core/src/main/java/org/geysermc/geyser/level/JavaDimension.java
Normale Datei
56
core/src/main/java/org/geysermc/geyser/level/JavaDimension.java
Normale Datei
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.level;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
||||
import org.geysermc.geyser.util.JavaCodecEntry;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Represents the information we store from the current Java dimension
|
||||
* @param piglinSafe Whether piglins and hoglins are safe from conversion in this dimension.
|
||||
* This controls if they have the shaking effect applied in the dimension.
|
||||
*/
|
||||
public record JavaDimension(int minY, int maxY, boolean piglinSafe, double worldCoordinateScale) {
|
||||
|
||||
public static void load(CompoundTag tag, Map<String, JavaDimension> map) {
|
||||
for (CompoundTag dimension : JavaCodecEntry.iterateAsTag(tag.get("minecraft:dimension_type"))) {
|
||||
CompoundTag elements = dimension.get("element");
|
||||
int minY = ((IntTag) elements.get("min_y")).getValue();
|
||||
int maxY = ((IntTag) elements.get("height")).getValue();
|
||||
// Logical height can be ignored probably - seems to be for artificial limits like the Nether.
|
||||
|
||||
// Set if piglins/hoglins should shake
|
||||
boolean piglinSafe = ((Number) elements.get("piglin_safe").getValue()).byteValue() != (byte) 0;
|
||||
// Load world coordinate scale for the world border
|
||||
double coordinateScale = ((Number) elements.get("coordinate_scale").getValue()).doubleValue();
|
||||
|
||||
map.put((String) dimension.get("name").getValue(), new JavaDimension(minY, maxY, piglinSafe, coordinateScale));
|
||||
}
|
||||
}
|
||||
}
|
@ -56,17 +56,17 @@ public enum PaintingType {
|
||||
SKELETON("Skeleton", 4, 3),
|
||||
DONKEY_KONG("DonkeyKong", 4, 3),
|
||||
POINTER("Pointer", 4, 4),
|
||||
PIG_SCENE("Pigscene", 4, 4),
|
||||
BURNING_SKULL("BurningSkull", 4, 4);
|
||||
PIGSCENE("Pigscene", 4, 4),
|
||||
BURNING_SKULL("BurningSkull", 4, 4),
|
||||
EARTH("Earth", 2, 2),
|
||||
WIND("Wind", 2, 2),
|
||||
WATER("Water", 2, 2),
|
||||
FIRE("Fire", 2, 2);
|
||||
|
||||
private static final PaintingType[] VALUES = values();
|
||||
private String bedrockName;
|
||||
private int width;
|
||||
private int height;
|
||||
|
||||
public com.github.steveice10.mc.protocol.data.game.entity.type.PaintingType toJavaType() {
|
||||
return com.github.steveice10.mc.protocol.data.game.entity.type.PaintingType.valueOf(name());
|
||||
}
|
||||
private final String bedrockName;
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
public static PaintingType getByName(String javaName) {
|
||||
for (PaintingType paintingName : VALUES) {
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
package org.geysermc.geyser.level;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
@ -41,17 +40,6 @@ import org.geysermc.geyser.session.GeyserSession;
|
||||
*/
|
||||
public abstract class WorldManager {
|
||||
|
||||
/**
|
||||
* Gets the Java block state at the specified location
|
||||
*
|
||||
* @param session the session
|
||||
* @param position the position
|
||||
* @return the block state at the specified location
|
||||
*/
|
||||
public int getBlockAt(GeyserSession session, Position position) {
|
||||
return this.getBlockAt(session, position.getX(), position.getY(), position.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Java block state at the specified location
|
||||
*
|
||||
@ -59,7 +47,7 @@ public abstract class WorldManager {
|
||||
* @param vector the position
|
||||
* @return the block state at the specified location
|
||||
*/
|
||||
public int getBlockAt(GeyserSession session, Vector3i vector) {
|
||||
public final int getBlockAt(GeyserSession session, Vector3i vector) {
|
||||
return this.getBlockAt(session, vector.getX(), vector.getY(), vector.getZ());
|
||||
}
|
||||
|
||||
|
@ -28,9 +28,7 @@ package org.geysermc.geyser.network;
|
||||
import com.github.steveice10.mc.protocol.codec.MinecraftCodec;
|
||||
import com.github.steveice10.mc.protocol.codec.PacketCodec;
|
||||
import com.nukkitx.protocol.bedrock.BedrockPacketCodec;
|
||||
import com.nukkitx.protocol.bedrock.v475.Bedrock_v475;
|
||||
import com.nukkitx.protocol.bedrock.v486.Bedrock_v486;
|
||||
import com.nukkitx.protocol.bedrock.v503.Bedrock_v503;
|
||||
import com.nukkitx.protocol.bedrock.beta.BedrockBeta;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@ -45,7 +43,7 @@ public final class MinecraftProtocol {
|
||||
* Default Bedrock codec that should act as a fallback. Should represent the latest available
|
||||
* release of the game that Geyser supports.
|
||||
*/
|
||||
public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v503.V503_CODEC;
|
||||
public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = BedrockBeta.BETA_CODEC;
|
||||
/**
|
||||
* A list of all supported Bedrock versions that can join Geyser
|
||||
*/
|
||||
@ -58,12 +56,8 @@ public final class MinecraftProtocol {
|
||||
private static final PacketCodec DEFAULT_JAVA_CODEC = MinecraftCodec.CODEC;
|
||||
|
||||
static {
|
||||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v475.V475_CODEC.toBuilder().minecraftVersion("1.18.0/1.18.1/1.18.2").build());
|
||||
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v486.V486_CODEC.toBuilder()
|
||||
.minecraftVersion("1.18.10/1.18.12") // 1.18.11 is also supported, but was only on Switch and since that auto-updates it's not needed
|
||||
.build());
|
||||
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder()
|
||||
.minecraftVersion("1.18.30/1.18.31")
|
||||
.minecraftVersion("1.19.0")
|
||||
.build());
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.geyser.network.netty;
|
||||
|
||||
import com.github.steveice10.packetlib.BuiltinFlags;
|
||||
import com.github.steveice10.packetlib.codec.PacketCodecHelper;
|
||||
import com.github.steveice10.packetlib.packet.PacketProtocol;
|
||||
import com.github.steveice10.packetlib.tcp.*;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
@ -47,15 +48,17 @@ public final class LocalSession extends TcpSession {
|
||||
|
||||
private final SocketAddress targetAddress;
|
||||
private final String clientIp;
|
||||
private final PacketCodecHelper codecHelper;
|
||||
|
||||
public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol) {
|
||||
public LocalSession(String host, int port, SocketAddress targetAddress, String clientIp, PacketProtocol protocol, PacketCodecHelper codecHelper) {
|
||||
super(host, port, protocol);
|
||||
this.targetAddress = targetAddress;
|
||||
this.clientIp = clientIp;
|
||||
this.codecHelper = codecHelper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() {
|
||||
public void connect(boolean wait) {
|
||||
if (this.disconnected) {
|
||||
throw new IllegalStateException("Connection has already been disconnected.");
|
||||
}
|
||||
@ -102,6 +105,11 @@ public final class LocalSession extends TcpSession {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PacketCodecHelper getCodecHelper() {
|
||||
return this.codecHelper;
|
||||
}
|
||||
|
||||
// TODO duplicate code
|
||||
private void addHAProxySupport(ChannelPipeline pipeline) {
|
||||
InetSocketAddress clientAddress = getFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS);
|
||||
|
@ -27,7 +27,7 @@ package org.geysermc.geyser.registry;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.event.SoundEvent;
|
||||
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.recipe.RecipeType;
|
||||
import com.github.steveice10.packetlib.packet.Packet;
|
||||
@ -155,9 +155,9 @@ public final class Registries {
|
||||
public static final SimpleMappedRegistry<String, SoundMapping> SOUNDS = SimpleMappedRegistry.create("mappings/sounds.json", SoundRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A mapped registry holding {@link SoundEvent}s to their corresponding {@link LevelEventTranslator}.
|
||||
* A mapped registry holding {@link LevelEvent}s to their corresponding {@link LevelEventTranslator}.
|
||||
*/
|
||||
public static final SimpleMappedRegistry<SoundEvent, LevelEventTranslator> SOUND_EVENTS = SimpleMappedRegistry.create("mappings/effects.json", SoundEventsRegistryLoader::new);
|
||||
public static final SimpleMappedRegistry<LevelEvent, LevelEventTranslator> SOUND_LEVEL_EVENTS = SimpleMappedRegistry.create("mappings/effects.json", SoundEventsRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A mapped registry holding {@link SoundTranslator}s to their corresponding {@link SoundInteractionTranslator}.
|
||||
|
@ -26,7 +26,7 @@
|
||||
package org.geysermc.geyser.registry.loader;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.event.SoundEvent;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.event.LevelEvent;
|
||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
@ -41,37 +41,37 @@ import java.util.Map;
|
||||
/**
|
||||
* Loads sound effects from the given resource path.
|
||||
*/
|
||||
public class SoundEventsRegistryLoader extends EffectRegistryLoader<Map<SoundEvent, LevelEventTranslator>> {
|
||||
public class SoundEventsRegistryLoader extends EffectRegistryLoader<Map<LevelEvent, LevelEventTranslator>> {
|
||||
|
||||
@Override
|
||||
public Map<SoundEvent, LevelEventTranslator> load(String input) {
|
||||
public Map<LevelEvent, LevelEventTranslator> load(String input) {
|
||||
this.loadFile(input);
|
||||
|
||||
Iterator<Map.Entry<String, JsonNode>> effectsIterator = this.get(input).fields();
|
||||
Map<SoundEvent, LevelEventTranslator> soundEffects = new Object2ObjectOpenHashMap<>();
|
||||
Map<LevelEvent, LevelEventTranslator> soundEffects = new Object2ObjectOpenHashMap<>();
|
||||
while (effectsIterator.hasNext()) {
|
||||
Map.Entry<String, JsonNode> entry = effectsIterator.next();
|
||||
JsonNode node = entry.getValue();
|
||||
try {
|
||||
String type = node.get("type").asText();
|
||||
SoundEvent javaEffect = null;
|
||||
LevelEvent javaEffect = null;
|
||||
LevelEventTranslator transformer = null;
|
||||
switch (type) {
|
||||
case "soundLevel" -> {
|
||||
javaEffect = SoundEvent.valueOf(entry.getKey());
|
||||
javaEffect = LevelEvent.valueOf(entry.getKey());
|
||||
LevelEventType levelEventType = LevelEventType.valueOf(node.get("name").asText());
|
||||
int data = node.has("data") ? node.get("data").intValue() : 0;
|
||||
transformer = new SoundLevelEventTranslator(levelEventType, data);
|
||||
}
|
||||
case "soundEvent" -> {
|
||||
javaEffect = SoundEvent.valueOf(entry.getKey());
|
||||
javaEffect = LevelEvent.valueOf(entry.getKey());
|
||||
com.nukkitx.protocol.bedrock.data.SoundEvent soundEvent = com.nukkitx.protocol.bedrock.data.SoundEvent.valueOf(node.get("name").asText());
|
||||
String identifier = node.has("identifier") ? node.get("identifier").asText() : "";
|
||||
int extraData = node.has("extraData") ? node.get("extraData").intValue() : -1;
|
||||
transformer = new SoundEventEventTranslator(soundEvent, identifier, extraData);
|
||||
}
|
||||
case "playSound" -> {
|
||||
javaEffect = SoundEvent.valueOf(entry.getKey());
|
||||
javaEffect = LevelEvent.valueOf(entry.getKey());
|
||||
String name = node.get("name").asText();
|
||||
float volume = node.has("volume") ? node.get("volume").floatValue() : 1.0f;
|
||||
boolean pitchSub = node.has("pitch_sub") && node.get("pitch_sub").booleanValue();
|
||||
@ -85,7 +85,7 @@ public class SoundEventsRegistryLoader extends EffectRegistryLoader<Map<SoundEve
|
||||
soundEffects.put(javaEffect, transformer);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
GeyserImpl.getInstance().getLogger().warning("Failed to map sound effect " + entry.getKey() + " : " + e.toString());
|
||||
GeyserImpl.getInstance().getLogger().warning("Failed to map sound effect " + entry.getKey() + " : " + e);
|
||||
}
|
||||
}
|
||||
return soundEffects;
|
||||
|
@ -54,8 +54,9 @@ public class SoundRegistryLoader implements RegistryLoader<String, Map<String, S
|
||||
while(soundsIterator.hasNext()) {
|
||||
Map.Entry<String, JsonNode> next = soundsIterator.next();
|
||||
JsonNode brMap = next.getValue();
|
||||
soundMappings.put(next.getKey(), new SoundMapping(
|
||||
next.getKey(),
|
||||
String javaSound = next.getKey();
|
||||
soundMappings.put(javaSound, new SoundMapping(
|
||||
javaSound,
|
||||
brMap.has("bedrock_mapping") && brMap.get("bedrock_mapping").isTextual() ? brMap.get("bedrock_mapping").asText() : null,
|
||||
brMap.has("playsound_mapping") && brMap.get("playsound_mapping").isTextual() ? brMap.get("playsound_mapping").asText() : null,
|
||||
brMap.has("extra_data") && brMap.get("extra_data").isInt() ? brMap.get("extra_data").asInt() : -1,
|
||||
|
@ -28,9 +28,7 @@ package org.geysermc.geyser.registry.populator;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.nukkitx.nbt.*;
|
||||
import com.nukkitx.protocol.bedrock.v475.Bedrock_v475;
|
||||
import com.nukkitx.protocol.bedrock.v486.Bedrock_v486;
|
||||
import com.nukkitx.protocol.bedrock.v503.Bedrock_v503;
|
||||
import com.nukkitx.protocol.bedrock.beta.BedrockBeta;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
@ -61,51 +59,9 @@ public class BlockRegistryPopulator {
|
||||
private static final ImmutableMap<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> BLOCK_MAPPERS;
|
||||
private static final BiFunction<String, NbtMapBuilder, String> EMPTY_MAPPER = (bedrockIdentifier, statesBuilder) -> null;
|
||||
|
||||
private static final BiFunction<String, NbtMapBuilder, String> V486_MAPPER = (bedrockIdentifier, statesBuilder) -> {
|
||||
statesBuilder.remove("no_drop_bit"); // Used in skulls
|
||||
if (bedrockIdentifier.equals("minecraft:glow_lichen")) {
|
||||
// Moved around north, south, west
|
||||
int bits = (int) statesBuilder.get("multi_face_direction_bits");
|
||||
boolean north = (bits & (1 << 2)) != 0;
|
||||
boolean south = (bits & (1 << 3)) != 0;
|
||||
boolean west = (bits & (1 << 4)) != 0;
|
||||
if (north) {
|
||||
bits |= 1 << 4;
|
||||
} else {
|
||||
bits &= ~(1 << 4);
|
||||
}
|
||||
if (south) {
|
||||
bits |= 1 << 2;
|
||||
} else {
|
||||
bits &= ~(1 << 2);
|
||||
}
|
||||
if (west) {
|
||||
bits |= 1 << 3;
|
||||
} else {
|
||||
bits &= ~(1 << 3);
|
||||
}
|
||||
statesBuilder.put("multi_face_direction_bits", bits);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
static {
|
||||
ImmutableMap.Builder<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>> stateMapperBuilder = ImmutableMap.<ObjectIntPair<String>, BiFunction<String, NbtMapBuilder, String>>builder()
|
||||
.put(ObjectIntPair.of("1_18_0", Bedrock_v475.V475_CODEC.getProtocolVersion()), EMPTY_MAPPER)
|
||||
.put(ObjectIntPair.of("1_18_10", Bedrock_v486.V486_CODEC.getProtocolVersion()), V486_MAPPER)
|
||||
.put(ObjectIntPair.of("1_18_30", Bedrock_v503.V503_CODEC.getProtocolVersion()), (bedrockIdentifier, statesBuilder) -> {
|
||||
// Apply these fixes too
|
||||
V486_MAPPER.apply(bedrockIdentifier, statesBuilder);
|
||||
return switch (bedrockIdentifier) {
|
||||
case "minecraft:pistonArmCollision" -> "minecraft:piston_arm_collision";
|
||||
case "minecraft:stickyPistonArmCollision" -> "minecraft:sticky_piston_arm_collision";
|
||||
case "minecraft:movingBlock" -> "minecraft:moving_block";
|
||||
case "minecraft:tripWire" -> "minecraft:trip_wire";
|
||||
case "minecraft:seaLantern" -> "minecraft:sea_lantern";
|
||||
case "minecraft:concretePowder" -> "minecraft:concrete_powder";
|
||||
default -> null;
|
||||
};
|
||||
});
|
||||
.put(ObjectIntPair.of("1_19_0", BedrockBeta.BETA_CODEC.getProtocolVersion()), EMPTY_MAPPER);
|
||||
|
||||
BLOCK_MAPPERS = stateMapperBuilder.build();
|
||||
}
|
||||
@ -294,7 +250,7 @@ public class BlockRegistryPopulator {
|
||||
builder.pickItem(pickItemNode.textValue().intern());
|
||||
}
|
||||
|
||||
if (javaId.equals("minecraft:obsidian") || javaId.equals("minecraft:crying_obsidian") || javaId.startsWith("minecraft:respawn_anchor")) {
|
||||
if (javaId.equals("minecraft:obsidian") || javaId.equals("minecraft:crying_obsidian") || javaId.startsWith("minecraft:respawn_anchor") || javaId.startsWith("minecraft:reinforced_deepslate")) {
|
||||
builder.pistonBehavior(PistonBehavior.BLOCK);
|
||||
} else {
|
||||
JsonNode pistonBehaviorNode = entry.getValue().get("piston_behavior");
|
||||
|
@ -31,13 +31,11 @@ import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import com.nukkitx.nbt.NbtType;
|
||||
import com.nukkitx.nbt.NbtUtils;
|
||||
import com.nukkitx.protocol.bedrock.beta.BedrockBeta;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ComponentItemData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
||||
import com.nukkitx.protocol.bedrock.v475.Bedrock_v475;
|
||||
import com.nukkitx.protocol.bedrock.v486.Bedrock_v486;
|
||||
import com.nukkitx.protocol.bedrock.v503.Bedrock_v503;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
@ -66,9 +64,7 @@ public class ItemRegistryPopulator {
|
||||
|
||||
public static void populate() {
|
||||
Map<String, PaletteVersion> paletteVersions = new Object2ObjectOpenHashMap<>();
|
||||
paletteVersions.put("1_18_0", new PaletteVersion(Bedrock_v475.V475_CODEC.getProtocolVersion(), Collections.emptyMap()));
|
||||
paletteVersions.put("1_18_10", new PaletteVersion(Bedrock_v486.V486_CODEC.getProtocolVersion(), Collections.emptyMap()));
|
||||
paletteVersions.put("1_18_30", new PaletteVersion(Bedrock_v503.V503_CODEC.getProtocolVersion(), Collections.emptyMap()));
|
||||
paletteVersions.put("1_19_0", new PaletteVersion(BedrockBeta.BETA_CODEC.getProtocolVersion(), Collections.emptyMap()));
|
||||
|
||||
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
|
||||
|
||||
@ -230,18 +226,6 @@ public class ItemRegistryPopulator {
|
||||
mappingItem = entry.getValue();
|
||||
}
|
||||
|
||||
String bedrockIdentifier;
|
||||
if (javaIdentifier.equals("minecraft:globe_banner_pattern") && palette.getValue().protocolVersion() < Bedrock_v486.V486_CODEC.getProtocolVersion()) {
|
||||
bedrockIdentifier = "minecraft:banner_pattern";
|
||||
} else {
|
||||
bedrockIdentifier = mappingItem.getBedrockIdentifier();
|
||||
if (palette.getValue().protocolVersion() >= Bedrock_v503.V503_CODEC.getProtocolVersion()) {
|
||||
if (bedrockIdentifier.equals("minecraft:sealantern")) {
|
||||
bedrockIdentifier = "minecraft:sea_lantern";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (usingFurnaceMinecart && javaIdentifier.equals("minecraft:furnace_minecart")) {
|
||||
javaFurnaceMinecartId = itemIndex;
|
||||
itemIndex++;
|
||||
@ -250,6 +234,7 @@ public class ItemRegistryPopulator {
|
||||
continue;
|
||||
}
|
||||
|
||||
String bedrockIdentifier = mappingItem.getBedrockIdentifier();
|
||||
int bedrockId = bedrockIdentifierToId.getInt(bedrockIdentifier);
|
||||
if (bedrockId == Short.MIN_VALUE) {
|
||||
throw new RuntimeException("Missing Bedrock ID in mappings: " + bedrockIdentifier);
|
||||
|
@ -38,10 +38,10 @@ public class SoundMapping {
|
||||
|
||||
public SoundMapping(String java, String bedrock, String playsound, int extraData, String identifier, boolean levelEvent) {
|
||||
this.java = java;
|
||||
this.bedrock = bedrock == null || bedrock.equalsIgnoreCase("") ? null : bedrock;
|
||||
this.playsound = playsound == null || playsound.equalsIgnoreCase("") ? null : playsound;
|
||||
this.bedrock = bedrock == null || bedrock.isEmpty() ? null : bedrock;
|
||||
this.playsound = playsound == null || playsound.isEmpty() ? null : playsound;
|
||||
this.extraData = extraData;
|
||||
this.identifier = identifier == null || identifier.equalsIgnoreCase("") ? ":" : identifier;
|
||||
this.identifier = identifier == null || identifier.isEmpty() ? ":" : identifier;
|
||||
this.levelEvent = levelEvent;
|
||||
}
|
||||
}
|
@ -34,8 +34,10 @@ import com.github.steveice10.mc.auth.service.MojangAuthenticationService;
|
||||
import com.github.steveice10.mc.auth.service.MsaAuthenticationService;
|
||||
import com.github.steveice10.mc.protocol.MinecraftConstants;
|
||||
import com.github.steveice10.mc.protocol.MinecraftProtocol;
|
||||
import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper;
|
||||
import com.github.steveice10.mc.protocol.data.ProtocolState;
|
||||
import com.github.steveice10.mc.protocol.data.UnexpectedEncryptionException;
|
||||
import com.github.steveice10.mc.protocol.data.game.MessageType;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
@ -47,6 +49,8 @@ import com.github.steveice10.mc.protocol.data.game.setting.SkinPart;
|
||||
import com.github.steveice10.mc.protocol.data.game.statistic.CustomStatistic;
|
||||
import com.github.steveice10.mc.protocol.data.game.statistic.Statistic;
|
||||
import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundClientInformationPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket;
|
||||
@ -61,6 +65,7 @@ import com.github.steveice10.packetlib.tcp.TcpClientSession;
|
||||
import com.github.steveice10.packetlib.tcp.TcpSession;
|
||||
import com.nukkitx.math.GenericMath;
|
||||
import com.nukkitx.math.vector.*;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.protocol.bedrock.BedrockPacket;
|
||||
import com.nukkitx.protocol.bedrock.BedrockServerSession;
|
||||
import com.nukkitx.protocol.bedrock.data.*;
|
||||
@ -69,6 +74,7 @@ import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.packet.*;
|
||||
import io.netty.channel.Channel;
|
||||
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.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
@ -81,6 +87,7 @@ import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
import org.checkerframework.common.value.qual.IntRange;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.cumulus.form.Form;
|
||||
@ -101,6 +108,7 @@ import org.geysermc.geyser.inventory.Inventory;
|
||||
import org.geysermc.geyser.inventory.PlayerInventory;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserRecipe;
|
||||
import org.geysermc.geyser.inventory.recipe.GeyserStonecutterData;
|
||||
import org.geysermc.geyser.level.JavaDimension;
|
||||
import org.geysermc.geyser.level.WorldManager;
|
||||
import org.geysermc.geyser.level.physics.CollisionManager;
|
||||
import org.geysermc.geyser.network.netty.LocalSession;
|
||||
@ -115,6 +123,7 @@ import org.geysermc.geyser.session.cache.*;
|
||||
import org.geysermc.geyser.skin.FloodgateSkinUploader;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.text.MinecraftLocale;
|
||||
import org.geysermc.geyser.text.TextDecoration;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.*;
|
||||
@ -124,6 +133,7 @@ import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
@ -318,12 +328,15 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
||||
*/
|
||||
@Setter
|
||||
private String dimension = DimensionUtils.OVERWORLD;
|
||||
/**
|
||||
* Whether piglins and hoglins are safe from conversion in this dimension.
|
||||
* This controls if they have the shaking effect applied in the dimension.
|
||||
*/
|
||||
@MonotonicNonNull
|
||||
@Setter
|
||||
private boolean dimensionPiglinSafe;
|
||||
private JavaDimension dimensionType = null;
|
||||
/**
|
||||
* All dimensions that the client could possibly connect to.
|
||||
*/
|
||||
private final Map<String, JavaDimension> dimensions = new Object2ObjectOpenHashMap<>(3);
|
||||
|
||||
private final Map<MessageType, TextDecoration> chatTypes = new EnumMap<>(MessageType.class);
|
||||
|
||||
@Setter
|
||||
private int breakingBlock;
|
||||
@ -480,15 +493,6 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
||||
@Setter
|
||||
private boolean thunder = false;
|
||||
|
||||
/**
|
||||
* Stores the last text inputted into a sign.
|
||||
* <p>
|
||||
* Bedrock sends packets every time you update the sign, Java only wants the final packet.
|
||||
* Until we determine that the user has finished editing, we save the sign's current status.
|
||||
*/
|
||||
@Setter
|
||||
private String lastSignMessage;
|
||||
|
||||
/**
|
||||
* Stores a map of all statistics sent from the server.
|
||||
* The server only sends new statistics back to us, so in order to show all statistics we need to cache existing ones.
|
||||
@ -840,7 +844,8 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
||||
if (geyser.getBootstrap().getSocketAddress() != null) {
|
||||
// We're going to connect through the JVM and not through TCP
|
||||
downstream = new LocalSession(this.remoteAddress, this.remotePort,
|
||||
geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(), this.protocol);
|
||||
geyser.getBootstrap().getSocketAddress(), upstream.getAddress().getAddress().getHostAddress(),
|
||||
this.protocol, this.protocol.createHelper());
|
||||
} else {
|
||||
downstream = new TcpClientSession(this.remoteAddress, this.remotePort, this.protocol);
|
||||
disableSrvResolving();
|
||||
@ -1012,7 +1017,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
||||
setDaylightCycle(true);
|
||||
}
|
||||
|
||||
downstream.connect();
|
||||
downstream.connect(false);
|
||||
}
|
||||
|
||||
public void disconnect(String reason) {
|
||||
@ -1261,9 +1266,9 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
||||
|
||||
ServerboundUseItemPacket useItemPacket;
|
||||
if (playerInventory.getItemInHand().getJavaId() == shield.getJavaId()) {
|
||||
useItemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND);
|
||||
useItemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, getNextSequence());
|
||||
} else if (playerInventory.getOffhand().getJavaId() == shield.getJavaId()) {
|
||||
useItemPacket = new ServerboundUseItemPacket(Hand.OFF_HAND);
|
||||
useItemPacket = new ServerboundUseItemPacket(Hand.OFF_HAND, getNextSequence());
|
||||
} else {
|
||||
// No blocking
|
||||
return false;
|
||||
@ -1292,7 +1297,7 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
||||
private boolean disableBlocking() {
|
||||
if (playerEntity.getFlag(EntityFlag.BLOCKING)) {
|
||||
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM,
|
||||
BlockUtils.POSITION_ZERO, Direction.DOWN);
|
||||
Vector3i.ZERO, Direction.DOWN, getNextSequence());
|
||||
sendDownstreamPacket(releaseItemPacket);
|
||||
playerEntity.setFlag(EntityFlag.BLOCKING, false);
|
||||
return true;
|
||||
@ -1360,6 +1365,20 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
||||
return clientData.getLanguageCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a chat message to the Java server.
|
||||
*/
|
||||
public void sendChat(String message) {
|
||||
sendDownstreamPacket(new ServerboundChatPacket(message, Instant.now().toEpochMilli(), 0L, ByteArrays.EMPTY_ARRAY, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a command to the Java server.
|
||||
*/
|
||||
public void sendCommand(String command) {
|
||||
sendDownstreamPacket(new ServerboundChatCommandPacket(command, Instant.now().toEpochMilli(), 0L, Collections.emptyMap(), false));
|
||||
}
|
||||
|
||||
public void setServerRenderDistance(int renderDistance) {
|
||||
renderDistance = GenericMath.ceil(++renderDistance * MathUtils.SQRT_OF_TWO); //square to circle
|
||||
this.serverRenderDistance = renderDistance;
|
||||
@ -1452,6 +1471,9 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
||||
startGamePacket.setInventoriesServerAuthoritative(true);
|
||||
startGamePacket.setServerEngine(""); // Do we want to fill this in?
|
||||
|
||||
startGamePacket.setPlayerPropertyData(NbtMap.EMPTY);
|
||||
startGamePacket.setWorldTemplateId(UUID.randomUUID());
|
||||
|
||||
SyncedPlayerMovementSettings settings = new SyncedPlayerMovementSettings();
|
||||
settings.setMovementMode(AuthoritativeMovementMode.CLIENT);
|
||||
settings.setRewindHistorySize(0);
|
||||
@ -1653,6 +1675,10 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
||||
sendDownstreamPacket(clientSettingsPacket);
|
||||
}
|
||||
|
||||
public int getNextSequence() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for updating statistic values since we only get changes from the server
|
||||
*
|
||||
@ -1729,4 +1755,8 @@ public class GeyserSession implements GeyserConnection, CommandSender {
|
||||
packet.setExtraData(-1);
|
||||
sendUpstreamPacket(packet);
|
||||
}
|
||||
|
||||
public MinecraftCodecHelper getCodecHelper() {
|
||||
return (MinecraftCodecHelper) this.downstream.getCodecHelper();
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +37,7 @@ import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.text.MinecraftLocale;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -75,33 +76,20 @@ public class AdvancementsCache {
|
||||
.translator(MinecraftLocale::getLocaleString, session.getLocale())
|
||||
.title("gui.advancements");
|
||||
|
||||
boolean hasAdvancements = false;
|
||||
List<String> rootAdvancementIds = new ArrayList<>();
|
||||
for (Map.Entry<String, GeyserAdvancement> advancement : storedAdvancements.entrySet()) {
|
||||
if (advancement.getValue().getParentId() == null) { // No parent means this is a root advancement
|
||||
hasAdvancements = true;
|
||||
builder.button(MessageTranslator.convertMessage(advancement.getValue().getDisplayData().getTitle(), session.getLocale()));
|
||||
rootAdvancementIds.add(advancement.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasAdvancements) {
|
||||
if (rootAdvancementIds.isEmpty()) {
|
||||
builder.content("advancements.empty");
|
||||
}
|
||||
|
||||
builder.validResultHandler((response) -> {
|
||||
String id = "";
|
||||
|
||||
int advancementIndex = 0;
|
||||
for (Map.Entry<String, GeyserAdvancement> advancement : storedAdvancements.entrySet()) {
|
||||
if (advancement.getValue().getParentId() == null) { // Root advancement
|
||||
if (advancementIndex == response.clickedButtonId()) {
|
||||
id = advancement.getKey();
|
||||
break;
|
||||
} else {
|
||||
advancementIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String id = rootAdvancementIds.get(response.clickedButtonId());
|
||||
if (!id.equals("")) {
|
||||
if (id.equals(currentAdvancementCategoryId)) {
|
||||
// The server thinks we are already on this tab
|
||||
@ -130,12 +118,16 @@ public class AdvancementsCache {
|
||||
.title(MessageTranslator.convertMessage(categoryAdvancement.getDisplayData().getTitle(), language))
|
||||
.content(MessageTranslator.convertMessage(categoryAdvancement.getDisplayData().getDescription(), language));
|
||||
|
||||
List<GeyserAdvancement> visibleAdvancements = new ArrayList<>();
|
||||
if (currentAdvancementCategoryId != null) {
|
||||
for (GeyserAdvancement advancement : storedAdvancements.values()) {
|
||||
if (advancement != null) {
|
||||
boolean earned = isEarned(advancement);
|
||||
if (earned || !advancement.getDisplayData().isHidden()) {
|
||||
if (advancement.getParentId() != null && currentAdvancementCategoryId.equals(advancement.getRootId(this))) {
|
||||
boolean color = isEarned(advancement) || !advancement.getDisplayData().isShowToast();
|
||||
builder.button((color ? ChatColor.DARK_GREEN : "") + MessageTranslator.convertMessage(advancement.getDisplayData().getTitle()) + '\n');
|
||||
String color = earned ? advancement.getDisplayColor() : "";
|
||||
builder.button(color + MessageTranslator.convertMessage(advancement.getDisplayData().getTitle()) + '\n');
|
||||
|
||||
visibleAdvancements.add(advancement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -148,22 +140,8 @@ public class AdvancementsCache {
|
||||
session.sendDownstreamPacket(new ServerboundSeenAdvancementsPacket());
|
||||
|
||||
}).validResultHandler((response) -> {
|
||||
GeyserAdvancement advancement = null;
|
||||
int advancementIndex = 0;
|
||||
// Loop around to find the advancement that the client pressed
|
||||
for (GeyserAdvancement advancementEntry : storedAdvancements.values()) {
|
||||
if (advancementEntry.getParentId() != null &&
|
||||
currentAdvancementCategoryId.equals(advancementEntry.getRootId(this))) {
|
||||
if (advancementIndex == response.clickedButtonId()) {
|
||||
advancement = advancementEntry;
|
||||
break;
|
||||
} else {
|
||||
advancementIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (advancement != null) {
|
||||
if (response.getClickedButtonId() < visibleAdvancements.size()) {
|
||||
GeyserAdvancement advancement = visibleAdvancements.get(response.clickedButtonId());
|
||||
buildAndShowInfoForm(advancement);
|
||||
} else {
|
||||
buildAndShowMenuForm();
|
||||
|
93
core/src/main/java/org/geysermc/geyser/text/TextDecoration.java
Normale Datei
93
core/src/main/java/org/geysermc/geyser/text/TextDecoration.java
Normale Datei
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.text;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.ListTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
public final class TextDecoration {
|
||||
private final String translationKey;
|
||||
private final Style style;
|
||||
private final Set<Parameter> parameters;
|
||||
|
||||
public TextDecoration(CompoundTag tag) {
|
||||
translationKey = (String) tag.get("translation_key").getValue();
|
||||
|
||||
CompoundTag styleTag = tag.get("style");
|
||||
Style.Builder builder = Style.style();
|
||||
StringTag color = styleTag.get("color");
|
||||
if (color != null) {
|
||||
builder.color(NamedTextColor.NAMES.value(color.getValue()));
|
||||
}
|
||||
//TODO implement the rest
|
||||
Tag italic = styleTag.get("italic");
|
||||
if (italic != null && ((Number) italic.getValue()).byteValue() == (byte) 1) {
|
||||
builder.decorate(net.kyori.adventure.text.format.TextDecoration.ITALIC);
|
||||
}
|
||||
style = builder.build();
|
||||
|
||||
this.parameters = EnumSet.noneOf(Parameter.class);
|
||||
ListTag parameters = tag.get("parameters");
|
||||
for (Tag parameter : parameters) {
|
||||
this.parameters.add(Parameter.valueOf(((String) parameter.getValue()).toUpperCase(Locale.ROOT)));
|
||||
}
|
||||
}
|
||||
|
||||
public String translationKey() {
|
||||
return translationKey;
|
||||
}
|
||||
|
||||
public Style style() {
|
||||
return style;
|
||||
}
|
||||
|
||||
public Set<Parameter> parameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TextDecoration{" +
|
||||
"translationKey='" + translationKey + '\'' +
|
||||
", style=" + style +
|
||||
", parameters=" + parameters +
|
||||
'}';
|
||||
}
|
||||
|
||||
public enum Parameter {
|
||||
CONTENT,
|
||||
SENDER,
|
||||
TEAM_NAME
|
||||
}
|
||||
}
|
@ -48,6 +48,8 @@ import org.geysermc.geyser.inventory.updater.UIInventoryUpdater;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InventoryUtils;
|
||||
|
||||
import java.util.OptionalInt;
|
||||
|
||||
public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
public BeaconInventoryTranslator() {
|
||||
super(1, new BlockInventoryHolder("minecraft:beacon", com.nukkitx.protocol.bedrock.data.inventory.ContainerType.BEACON) {
|
||||
@ -111,11 +113,15 @@ public class BeaconInventoryTranslator extends AbstractBlockInventoryTranslator
|
||||
public ItemStackResponsePacket.Response translateSpecialRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
|
||||
// Input a beacon payment
|
||||
BeaconPaymentStackRequestActionData beaconPayment = (BeaconPaymentStackRequestActionData) request.getActions()[0];
|
||||
ServerboundSetBeaconPacket packet = new ServerboundSetBeaconPacket(beaconPayment.getPrimaryEffect(), beaconPayment.getSecondaryEffect());
|
||||
ServerboundSetBeaconPacket packet = new ServerboundSetBeaconPacket(toJava(beaconPayment.getPrimaryEffect()), toJava(beaconPayment.getSecondaryEffect()));
|
||||
session.sendDownstreamPacket(packet);
|
||||
return acceptRequest(request, makeContainerEntries(session, inventory, IntSets.emptySet()));
|
||||
}
|
||||
|
||||
private OptionalInt toJava(int effectChoice) {
|
||||
return effectChoice == -1 ? OptionalInt.empty() : OptionalInt.of(effectChoice);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bedrockSlotToJava(StackRequestSlotInfoData slotInfoData) {
|
||||
if (slotInfoData.getContainer() == ContainerSlotType.BEACON_PAYMENT) {
|
||||
|
@ -37,7 +37,6 @@ import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.AutoCraft
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.stackrequestactions.CraftRecipeStackRequestActionData;
|
||||
import com.nukkitx.protocol.bedrock.packet.ItemStackResponsePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket;
|
||||
import com.nukkitx.protocol.bedrock.v486.Bedrock_v486;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
@ -140,10 +139,6 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
|
||||
|
||||
@Override
|
||||
public ItemStackResponsePacket.Response translateCraftingRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
|
||||
if (session.getUpstream().getProtocolVersion() < Bedrock_v486.V486_CODEC.getProtocolVersion()) {
|
||||
return super.translateCraftingRequest(session, inventory, request);
|
||||
}
|
||||
|
||||
// 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
|
||||
// store a map of net ID to trade index on our end.
|
||||
@ -153,12 +148,6 @@ public class MerchantInventoryTranslator extends BaseInventoryTranslator {
|
||||
|
||||
@Override
|
||||
public ItemStackResponsePacket.Response translateAutoCraftingRequest(GeyserSession session, Inventory inventory, ItemStackRequest request) {
|
||||
if (session.getUpstream().getProtocolVersion() < Bedrock_v486.V486_CODEC.getProtocolVersion()) {
|
||||
// We're not crafting here
|
||||
// Called at least by consoles when pressing a trade option button
|
||||
return translateRequest(session, inventory, request);
|
||||
}
|
||||
|
||||
// 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
|
||||
// store a map of net ID to trade index on our end.
|
||||
|
@ -42,6 +42,7 @@ import org.geysermc.geyser.level.chunk.bitarray.BitArray;
|
||||
import org.geysermc.geyser.level.chunk.bitarray.BitArrayVersion;
|
||||
import org.geysermc.geyser.level.chunk.bitarray.SingletonBitArray;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.util.JavaCodecEntry;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
|
||||
// Array index formula by https://wiki.vg/Chunk_Format
|
||||
@ -55,27 +56,26 @@ public class BiomeTranslator {
|
||||
ListTag serverBiomes = worldGen.get("value");
|
||||
session.setBiomeGlobalPalette(MathUtils.getGlobalPaletteForSize(serverBiomes.size()));
|
||||
|
||||
for (Tag tag : serverBiomes) {
|
||||
CompoundTag biomeTag = (CompoundTag) tag;
|
||||
|
||||
for (CompoundTag biomeTag : JavaCodecEntry.iterateAsTag(worldGen)) {
|
||||
String javaIdentifier = ((StringTag) biomeTag.get("name")).getValue();
|
||||
int bedrockId = Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, -1);
|
||||
int bedrockId = Registries.BIOME_IDENTIFIERS.get().getOrDefault(javaIdentifier, 0);
|
||||
int javaId = ((IntTag) biomeTag.get("id")).getValue();
|
||||
|
||||
if (bedrockId == -1) {
|
||||
// There is no matching Bedrock variation for this biome; let's set the closest match based on biome category
|
||||
String category = ((StringTag) ((CompoundTag) biomeTag.get("element")).get("category")).getValue();
|
||||
String replacementBiome = switch (category) {
|
||||
case "extreme_hills" -> "minecraft:mountains";
|
||||
case "icy" -> "minecraft:ice_spikes";
|
||||
case "mesa" -> "minecraft:badlands";
|
||||
case "mushroom" -> "minecraft:mushroom_fields";
|
||||
case "nether" -> "minecraft:nether_wastes";
|
||||
default -> "minecraft:ocean"; // Typically ID 0 so a good default
|
||||
case "taiga", "jungle", "plains", "savanna", "the_end", "beach", "ocean", "desert", "river", "swamp" -> "minecraft:" + category;
|
||||
};
|
||||
bedrockId = Registries.BIOME_IDENTIFIERS.get().getInt(replacementBiome);
|
||||
}
|
||||
// TODO - the category tag no longer exists - find a better replacement option
|
||||
// if (bedrockId == -1) {
|
||||
// // There is no matching Bedrock variation for this biome; let's set the closest match based on biome category
|
||||
// String category = ((StringTag) ((CompoundTag) biomeTag.get("element")).get("category")).getValue();
|
||||
// String replacementBiome = switch (category) {
|
||||
// case "extreme_hills" -> "minecraft:mountains";
|
||||
// case "icy" -> "minecraft:ice_spikes";
|
||||
// case "mesa" -> "minecraft:badlands";
|
||||
// case "mushroom" -> "minecraft:mushroom_fields";
|
||||
// case "nether" -> "minecraft:nether_wastes";
|
||||
// default -> "minecraft:ocean"; // Typically ID 0 so a good default
|
||||
// case "taiga", "jungle", "plains", "savanna", "the_end", "beach", "ocean", "desert", "river", "swamp" -> "minecraft:" + category;
|
||||
// };
|
||||
// bedrockId = Registries.BIOME_IDENTIFIERS.get().getInt(replacementBiome);
|
||||
// }
|
||||
|
||||
// When we see the Java ID, we should instead apply the Bedrock ID
|
||||
biomeTranslations.put(javaId, bedrockId);
|
||||
|
@ -40,7 +40,7 @@ public record SoundEventEventTranslator(SoundEvent soundEvent,
|
||||
levelSoundEvent.setIdentifier(identifier);
|
||||
levelSoundEvent.setExtraData(extraData);
|
||||
levelSoundEvent.setRelativeVolumeDisabled(packet.isBroadcast());
|
||||
levelSoundEvent.setPosition(Vector3f.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()).add(0.5f, 0.5f, 0.5f));
|
||||
levelSoundEvent.setPosition(Vector3f.from(packet.getPosition().getX() + 0.5f, packet.getPosition().getY() + 0.5f, packet.getPosition().getZ() + 0.5f));
|
||||
levelSoundEvent.setBabySound(false);
|
||||
session.sendUpstreamPacket(levelSoundEvent);
|
||||
}
|
||||
|
@ -25,12 +25,11 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetJigsawBlockPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundSignUpdatePacket;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||
import com.nukkitx.protocol.bedrock.v503.Bedrock_v503;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
@ -45,16 +44,8 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator<BlockEnti
|
||||
String id = tag.getString("id");
|
||||
if (id.equals("Sign")) {
|
||||
String text = tag.getString("Text");
|
||||
// This is the reason why this all works - Bedrock sends packets every time you update the sign, Java only wants the final packet
|
||||
// But Bedrock sends one final packet when you're done editing the sign, which should be equal to the last message since there's no edits
|
||||
// So if the latest update does not match the last cached update then it's still being edited
|
||||
// TODO check 1.19:
|
||||
// Bedrock only sends one packet as of 1.18.30. I (Camotoy) am suspicious this is a bug, but if it's permanent then we don't need the lastSignMessage variable.
|
||||
if (session.getUpstream().getProtocolVersion() < Bedrock_v503.V503_CODEC.getProtocolVersion() && !text.equals(session.getLastSignMessage())) {
|
||||
session.setLastSignMessage(text);
|
||||
return;
|
||||
}
|
||||
// Otherwise the two messages are identical and we can get to work deconstructing
|
||||
// Note: as of 1.18.30, only one packet is sent from Bedrock when the sign is finished.
|
||||
// Previous versions did not have this behavior.
|
||||
StringBuilder newMessage = new StringBuilder();
|
||||
// While Bedrock's sign lines are one string, Java's is an array of each line
|
||||
// (Initialized all with empty strings because it complains about null)
|
||||
@ -109,16 +100,13 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator<BlockEnti
|
||||
}
|
||||
// Put the final line on since it isn't done in the for loop
|
||||
if (iterator < lines.length) lines[iterator] = newMessage.toString();
|
||||
Position pos = new Position(tag.getInt("x"), tag.getInt("y"), tag.getInt("z"));
|
||||
Vector3i pos = Vector3i.from(tag.getInt("x"), tag.getInt("y"), tag.getInt("z"));
|
||||
ServerboundSignUpdatePacket signUpdatePacket = new ServerboundSignUpdatePacket(pos, lines);
|
||||
session.sendDownstreamPacket(signUpdatePacket);
|
||||
|
||||
// We set the sign text cached in the session to null to indicate there is no work-in-progress sign
|
||||
session.setLastSignMessage(null);
|
||||
|
||||
} else if (id.equals("JigsawBlock")) {
|
||||
// Client has just sent a jigsaw block update
|
||||
Position pos = new Position(tag.getInt("x"), tag.getInt("y"), tag.getInt("z"));
|
||||
Vector3i pos = Vector3i.from(tag.getInt("x"), tag.getInt("y"), tag.getInt("z"));
|
||||
String name = tag.getString("name");
|
||||
String target = tag.getString("target");
|
||||
String pool = tag.getString("target_pool");
|
||||
|
@ -25,10 +25,9 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.level.block.CommandBlockMode;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCommandMinecartPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCommandBlockPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundSetCommandMinecartPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.CommandBlockUpdatePacket;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
@ -53,8 +52,7 @@ public class BedrockCommandBlockUpdateTranslator extends PacketTranslator<Comman
|
||||
boolean isConditional = packet.isConditional();
|
||||
boolean automatic = !packet.isRedstoneMode(); // Automatic = Always Active option in Java
|
||||
ServerboundSetCommandBlockPacket commandBlockPacket = new ServerboundSetCommandBlockPacket(
|
||||
new Position(packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ()),
|
||||
command, mode, outputTracked, isConditional, automatic);
|
||||
packet.getBlockPosition(), command, mode, outputTracked, isConditional, automatic);
|
||||
session.sendDownstreamPacket(commandBlockPacket);
|
||||
} else {
|
||||
ServerboundSetCommandMinecartPacket commandMinecartPacket = new ServerboundSetCommandMinecartPacket(
|
||||
|
@ -25,15 +25,13 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import com.nukkitx.protocol.bedrock.packet.CommandRequestPacket;
|
||||
import org.geysermc.common.PlatformType;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.command.CommandManager;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.CommandRequestPacket;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
|
||||
@Translator(packet = CommandRequestPacket.class)
|
||||
@ -52,8 +50,7 @@ public class BedrockCommandRequestTranslator extends PacketTranslator<CommandReq
|
||||
return;
|
||||
}
|
||||
|
||||
ServerboundChatPacket chatPacket = new ServerboundChatPacket(message);
|
||||
session.sendDownstreamPacket(chatPacket);
|
||||
session.sendCommand(message.substring(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public class BedrockEntityPickRequestTranslator extends PacketTranslator<EntityP
|
||||
// Get the corresponding item
|
||||
String itemName;
|
||||
switch (entity.getDefinition().entityType()) {
|
||||
case BOAT -> {
|
||||
case BOAT, CHEST_BOAT -> {
|
||||
// Include type of boat in the name
|
||||
int variant = ((BoatEntity) entity).getVariant();
|
||||
String typeOfBoat = switch (variant) {
|
||||
@ -61,9 +61,10 @@ public class BedrockEntityPickRequestTranslator extends PacketTranslator<EntityP
|
||||
case 3 -> "jungle";
|
||||
case 4 -> "acacia";
|
||||
case 5 -> "dark_oak";
|
||||
case 6 -> "mangrove";
|
||||
default -> "oak";
|
||||
};
|
||||
itemName = typeOfBoat + "_boat";
|
||||
itemName = typeOfBoat + "_" + entity.getDefinition().entityType().name().toLowerCase(Locale.ROOT);
|
||||
}
|
||||
case LEASH_KNOT -> itemName = "lead";
|
||||
case CHEST_MINECART, COMMAND_BLOCK_MINECART, FURNACE_MINECART, HOPPER_MINECART, TNT_MINECART ->
|
||||
|
@ -26,7 +26,6 @@
|
||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
@ -121,8 +120,9 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||
|
||||
ServerboundPlayerActionPacket dropPacket = new ServerboundPlayerActionPacket(
|
||||
dropAll ? PlayerAction.DROP_ITEM_STACK : PlayerAction.DROP_ITEM,
|
||||
BlockUtils.POSITION_ZERO,
|
||||
Direction.DOWN
|
||||
Vector3i.ZERO,
|
||||
Direction.DOWN,
|
||||
session.getNextSequence()
|
||||
);
|
||||
session.sendDownstreamPacket(dropPacket);
|
||||
|
||||
@ -256,24 +256,25 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||
if (blockState == BlockStateValues.JAVA_WATER_ID) {
|
||||
// Otherwise causes multiple mobs to spawn - just send a use item packet
|
||||
// TODO when we fix mobile bucket rotation, use it for this, too
|
||||
ServerboundUseItemPacket itemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND);
|
||||
ServerboundUseItemPacket itemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getNextSequence());
|
||||
session.sendDownstreamPacket(itemPacket);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ServerboundUseItemOnPacket blockPacket = new ServerboundUseItemOnPacket(
|
||||
new Position(packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ()),
|
||||
packet.getBlockPosition(),
|
||||
Direction.VALUES[packet.getBlockFace()],
|
||||
Hand.MAIN_HAND,
|
||||
packet.getClickPosition().getX(), packet.getClickPosition().getY(), packet.getClickPosition().getZ(),
|
||||
false);
|
||||
false,
|
||||
session.getNextSequence());
|
||||
session.sendDownstreamPacket(blockPacket);
|
||||
|
||||
if (packet.getItemInHand() != null) {
|
||||
// Otherwise boats will not be able to be placed in survival and buckets won't work on mobile
|
||||
if (session.getItemMappings().getBoatIds().contains(packet.getItemInHand().getId())) {
|
||||
ServerboundUseItemPacket itemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND);
|
||||
ServerboundUseItemPacket itemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getNextSequence());
|
||||
session.sendDownstreamPacket(itemPacket);
|
||||
} else if (session.getItemMappings().getBucketIds().contains(packet.getItemInHand().getId())) {
|
||||
// Let the server decide if the bucket item should change, not the client, and revert the changes the client made
|
||||
@ -290,7 +291,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||
// Delay the interaction in case the client doesn't intend to actually use the bucket
|
||||
// See BedrockActionTranslator.java
|
||||
session.setBucketScheduledFuture(session.scheduleInEventLoop(() -> {
|
||||
ServerboundUseItemPacket itemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND);
|
||||
ServerboundUseItemPacket itemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getNextSequence());
|
||||
session.sendDownstreamPacket(itemPacket);
|
||||
}, 5, TimeUnit.MILLISECONDS));
|
||||
}
|
||||
@ -336,7 +337,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||
}
|
||||
}
|
||||
|
||||
ServerboundUseItemPacket useItemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND);
|
||||
ServerboundUseItemPacket useItemPacket = new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getNextSequence());
|
||||
session.sendDownstreamPacket(useItemPacket);
|
||||
|
||||
List<LegacySetItemSlotData> legacySlots = packet.getLegacySlots();
|
||||
@ -417,8 +418,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||
}
|
||||
|
||||
PlayerAction action = session.getGameMode() == GameMode.CREATIVE ? PlayerAction.START_DIGGING : PlayerAction.FINISH_DIGGING;
|
||||
Position pos = new Position(packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ());
|
||||
ServerboundPlayerActionPacket breakPacket = new ServerboundPlayerActionPacket(action, pos, Direction.VALUES[packet.getBlockFace()]);
|
||||
ServerboundPlayerActionPacket breakPacket = new ServerboundPlayerActionPacket(action, packet.getBlockPosition(), Direction.VALUES[packet.getBlockFace()], session.getNextSequence());
|
||||
session.sendDownstreamPacket(breakPacket);
|
||||
}
|
||||
}
|
||||
@ -426,8 +426,8 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||
case ITEM_RELEASE:
|
||||
if (packet.getActionType() == 0) {
|
||||
// Followed to the Minecraft Protocol specification outlined at wiki.vg
|
||||
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, BlockUtils.POSITION_ZERO,
|
||||
Direction.DOWN);
|
||||
ServerboundPlayerActionPacket releaseItemPacket = new ServerboundPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, Vector3i.ZERO,
|
||||
Direction.DOWN, session.getNextSequence());
|
||||
session.sendDownstreamPacket(releaseItemPacket);
|
||||
}
|
||||
break;
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
|
||||
@ -53,11 +52,12 @@ public class BedrockLecternUpdateTranslator extends PacketTranslator<LecternUpda
|
||||
|
||||
// Emulate an interact packet
|
||||
ServerboundUseItemOnPacket blockPacket = new ServerboundUseItemOnPacket(
|
||||
new Position(packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ()),
|
||||
packet.getBlockPosition(),
|
||||
Direction.DOWN,
|
||||
Hand.MAIN_HAND,
|
||||
0, 0, 0, // Java doesn't care about these when dealing with a lectern
|
||||
false);
|
||||
false,
|
||||
session.getNextSequence());
|
||||
session.sendDownstreamPacket(blockPacket);
|
||||
} else {
|
||||
// Bedrock wants to either move a page or exit
|
||||
|
@ -65,7 +65,7 @@ public class BedrockMobEquipmentTranslator extends PacketTranslator<MobEquipment
|
||||
// Activate shield since we are already sneaking
|
||||
// (No need to send a release item packet - Java doesn't do this when swapping items)
|
||||
// Required to do it a tick later or else it doesn't register
|
||||
session.scheduleInEventLoop(() -> session.sendDownstreamPacket(new ServerboundUseItemPacket(Hand.MAIN_HAND)),
|
||||
session.scheduleInEventLoop(() -> session.sendDownstreamPacket(new ServerboundUseItemPacket(Hand.MAIN_HAND, session.getNextSequence())),
|
||||
50, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.TextPacket;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.ChatColor;
|
||||
@ -63,7 +62,6 @@ public class BedrockTextTranslator extends PacketTranslator<TextPacket> {
|
||||
return;
|
||||
}
|
||||
|
||||
ServerboundChatPacket chatPacket = new ServerboundChatPacket(message);
|
||||
session.sendDownstreamPacket(chatPacket);
|
||||
session.sendChat(message);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.bedrock.entity.player;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.*;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket;
|
||||
@ -129,8 +128,8 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
||||
session.setSprinting(false);
|
||||
break;
|
||||
case DROP_ITEM:
|
||||
Position position = new Position(vector.getX(), vector.getY(), vector.getZ());
|
||||
ServerboundPlayerActionPacket dropItemPacket = new ServerboundPlayerActionPacket(PlayerAction.DROP_ITEM, position, Direction.VALUES[packet.getFace()]);
|
||||
ServerboundPlayerActionPacket dropItemPacket = new ServerboundPlayerActionPacket(PlayerAction.DROP_ITEM,
|
||||
vector, Direction.VALUES[packet.getFace()], session.getNextSequence());
|
||||
session.sendDownstreamPacket(dropItemPacket);
|
||||
break;
|
||||
case STOP_SLEEP:
|
||||
@ -163,16 +162,16 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
||||
int blockUp = session.getGeyser().getWorldManager().getBlockAt(session, fireBlockPos);
|
||||
String identifier = BlockRegistries.JAVA_IDENTIFIERS.get().get(blockUp);
|
||||
if (identifier.startsWith("minecraft:fire") || identifier.startsWith("minecraft:soul_fire")) {
|
||||
ServerboundPlayerActionPacket startBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.START_DIGGING, new Position(fireBlockPos.getX(),
|
||||
fireBlockPos.getY(), fireBlockPos.getZ()), Direction.VALUES[packet.getFace()]);
|
||||
ServerboundPlayerActionPacket startBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.START_DIGGING, fireBlockPos,
|
||||
Direction.VALUES[packet.getFace()], session.getNextSequence());
|
||||
session.sendDownstreamPacket(startBreakingPacket);
|
||||
if (session.getGameMode() == GameMode.CREATIVE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
position = new Position(vector.getX(), vector.getY(), vector.getZ());
|
||||
ServerboundPlayerActionPacket startBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.START_DIGGING, position, Direction.VALUES[packet.getFace()]);
|
||||
ServerboundPlayerActionPacket startBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.START_DIGGING,
|
||||
vector, Direction.VALUES[packet.getFace()], session.getNextSequence());
|
||||
session.sendDownstreamPacket(startBreakingPacket);
|
||||
break;
|
||||
case CONTINUE_BREAK:
|
||||
@ -207,8 +206,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
|
||||
}
|
||||
}
|
||||
|
||||
position = new Position(vector.getX(), vector.getY(), vector.getZ());
|
||||
ServerboundPlayerActionPacket abortBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.CANCEL_DIGGING, position, Direction.DOWN);
|
||||
ServerboundPlayerActionPacket abortBreakingPacket = new ServerboundPlayerActionPacket(PlayerAction.CANCEL_DIGGING, vector, Direction.DOWN, session.getNextSequence());
|
||||
session.sendDownstreamPacket(abortBreakingPacket);
|
||||
LevelEventPacket stopBreak = new LevelEventPacket();
|
||||
stopBreak.setType(LevelEventType.BLOCK_STOP_BREAK);
|
||||
|
@ -28,13 +28,13 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerActionPacket;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.packet.EmotePacket;
|
||||
import org.geysermc.geyser.configuration.EmoteOffhandWorkaroundOption;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.util.BlockUtils;
|
||||
|
||||
@Translator(packet = EmotePacket.class)
|
||||
public class BedrockEmoteTranslator extends PacketTranslator<EmotePacket> {
|
||||
@ -43,8 +43,8 @@ public class BedrockEmoteTranslator extends PacketTranslator<EmotePacket> {
|
||||
public void translate(GeyserSession session, EmotePacket packet) {
|
||||
if (session.getGeyser().getConfig().getEmoteOffhandWorkaround() != EmoteOffhandWorkaroundOption.DISABLED) {
|
||||
// Activate the workaround - we should trigger the offhand now
|
||||
ServerboundPlayerActionPacket swapHandsPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, BlockUtils.POSITION_ZERO,
|
||||
Direction.DOWN);
|
||||
ServerboundPlayerActionPacket swapHandsPacket = new ServerboundPlayerActionPacket(PlayerAction.SWAP_HANDS, Vector3i.ZERO,
|
||||
Direction.DOWN, session.getNextSequence());
|
||||
session.sendDownstreamPacket(swapHandsPacket);
|
||||
|
||||
if (session.getGeyser().getConfig().getEmoteOffhandWorkaround() == EmoteOffhandWorkaroundOption.NO_EMOTES) {
|
||||
|
@ -28,10 +28,10 @@ package org.geysermc.geyser.translator.protocol.bedrock.entity.player;
|
||||
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.PlayerState;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundInteractPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerCommandPacket;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.InteractPacket;
|
||||
@ -96,12 +96,10 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
|
||||
case OPEN_INVENTORY:
|
||||
if (session.getOpenInventory() == null) {
|
||||
Entity ridingEntity = session.getPlayerEntity().getVehicle();
|
||||
if (ridingEntity instanceof AbstractHorseEntity) {
|
||||
if (ridingEntity.getFlag(EntityFlag.TAMED)) {
|
||||
// We should request to open the horse inventory instead
|
||||
ServerboundPlayerCommandPacket openHorseWindowPacket = new ServerboundPlayerCommandPacket(session.getPlayerEntity().getEntityId(), PlayerState.OPEN_HORSE_INVENTORY);
|
||||
session.sendDownstreamPacket(openHorseWindowPacket);
|
||||
}
|
||||
if (ridingEntity instanceof AbstractHorseEntity || (ridingEntity != null && ridingEntity.getDefinition().entityType() == EntityType.CHEST_BOAT)) {
|
||||
// This mob has an inventory of its own that we should open instead.
|
||||
ServerboundPlayerCommandPacket openVehicleWindowPacket = new ServerboundPlayerCommandPacket(session.getPlayerEntity().getEntityId(), PlayerState.OPEN_VEHICLE_INVENTORY);
|
||||
session.sendDownstreamPacket(openVehicleWindowPacket);
|
||||
} else {
|
||||
session.setOpenInventory(session.getPlayerInventory());
|
||||
|
||||
|
@ -222,7 +222,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
||||
case BLOCK_POS -> CommandParam.BLOCK_POSITION;
|
||||
case COLUMN_POS, VEC3 -> CommandParam.POSITION;
|
||||
case MESSAGE -> CommandParam.MESSAGE;
|
||||
case NBT, NBT_COMPOUND_TAG, NBT_TAG, NBT_PATH -> CommandParam.JSON;
|
||||
case NBT_COMPOUND_TAG, NBT_TAG, NBT_PATH -> CommandParam.JSON; //TODO NBT was removed
|
||||
case RESOURCE_LOCATION, FUNCTION -> CommandParam.FILE_PATH;
|
||||
case BOOL -> ENUM_BOOLEAN;
|
||||
case OPERATION -> CommandParam.OPERATOR; // ">=", "==", etc
|
||||
@ -248,7 +248,7 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
||||
/**
|
||||
* Stores the command description and parameter data for best optimizing the Bedrock commands packet.
|
||||
*/
|
||||
private static record BedrockCommandInfo(String description, CommandParamData[][] paramData) {
|
||||
private record BedrockCommandInfo(String description, CommandParamData[][] paramData) {
|
||||
}
|
||||
|
||||
@Getter
|
||||
@ -317,15 +317,21 @@ public class JavaCommandsTranslator extends PacketTranslator<ClientboundCommands
|
||||
Object mappedType = mapCommandType(session, paramNode);
|
||||
CommandEnumData enumData = null;
|
||||
CommandParam type = null;
|
||||
boolean optional = this.paramNode.isExecutable();
|
||||
if (mappedType instanceof String[]) {
|
||||
enumData = new CommandEnumData(paramNode.getParser().name().toLowerCase(), (String[]) mappedType, false);
|
||||
} else {
|
||||
type = (CommandParam) mappedType;
|
||||
// Bedrock throws a fit if an optional message comes after a string or target
|
||||
// Example vanilla commands: ban-ip, ban, and kick
|
||||
if (optional && type == CommandParam.MESSAGE && (paramData.getType() == CommandParam.STRING || paramData.getType() == CommandParam.TARGET)) {
|
||||
optional = false;
|
||||
}
|
||||
}
|
||||
// IF enumData != null:
|
||||
// In game, this will show up like <paramNode.getName(): enumData.getName()>
|
||||
// So if paramNode.getName() == "value" and enumData.getName() == "bool": <value: bool>
|
||||
children.add(new ParamInfo(paramNode, new CommandParamData(paramNode.getName(), this.paramNode.isExecutable(), enumData, type, null, Collections.emptyList())));
|
||||
children.add(new ParamInfo(paramNode, new CommandParamData(paramNode.getName(), optional, enumData, type, null, Collections.emptyList())));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,48 +25,79 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.MessageType;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundLoginPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
||||
import com.nukkitx.protocol.bedrock.data.GameRuleData;
|
||||
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
|
||||
import com.nukkitx.protocol.bedrock.packet.AdventureSettingsPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.GameRulesChangedPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket;
|
||||
import org.geysermc.floodgate.pluginmessage.PluginMessageChannels;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||
import org.geysermc.geyser.level.JavaDimension;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.auth.AuthType;
|
||||
import org.geysermc.geyser.text.TextDecoration;
|
||||
import org.geysermc.geyser.translator.level.BiomeTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.util.ChunkUtils;
|
||||
import org.geysermc.geyser.util.DimensionUtils;
|
||||
import org.geysermc.geyser.util.JavaCodecEntry;
|
||||
import org.geysermc.geyser.util.PluginMessageUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Translator(packet = ClientboundLoginPacket.class)
|
||||
public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket> {
|
||||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundLoginPacket packet) {
|
||||
PlayerEntity entity = session.getPlayerEntity();
|
||||
SessionPlayerEntity entity = session.getPlayerEntity();
|
||||
entity.setEntityId(packet.getEntityId());
|
||||
|
||||
Map<String, JavaDimension> dimensions = session.getDimensions();
|
||||
dimensions.clear();
|
||||
|
||||
JavaDimension.load(packet.getRegistry(), dimensions);
|
||||
|
||||
Map<MessageType, TextDecoration> chatTypes = session.getChatTypes();
|
||||
chatTypes.clear();
|
||||
for (CompoundTag tag : JavaCodecEntry.iterateAsTag(packet.getRegistry().get("minecraft:chat_type"))) {
|
||||
int id = ((IntTag) tag.get("id")).getValue();
|
||||
CompoundTag element = tag.get("element");
|
||||
CompoundTag chat = element.get("chat");
|
||||
if (chat == null) {
|
||||
continue;
|
||||
}
|
||||
CompoundTag decoration = chat.get("decoration");
|
||||
if (decoration == null) {
|
||||
continue;
|
||||
}
|
||||
MessageType type = MessageType.from(id);
|
||||
chatTypes.put(type, new TextDecoration(decoration));
|
||||
}
|
||||
|
||||
// If the player is already initialized and a join game packet is sent, they
|
||||
// are swapping servers
|
||||
String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
|
||||
if (session.isSpawned()) {
|
||||
String fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), newDimension);
|
||||
String fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), packet.getDimension());
|
||||
DimensionUtils.switchDimension(session, fakeDim);
|
||||
|
||||
session.getWorldCache().removeScoreboard();
|
||||
}
|
||||
session.setWorldName(packet.getWorldName());
|
||||
|
||||
BiomeTranslator.loadServerBiomes(session, packet.getDimensionCodec());
|
||||
BiomeTranslator.loadServerBiomes(session, packet.getRegistry());
|
||||
session.getTagCache().clear();
|
||||
|
||||
session.setGameMode(packet.getGameMode());
|
||||
|
||||
String newDimension = packet.getDimension();
|
||||
|
||||
boolean needsSpawnPacket = !session.isSentSpawnPacket();
|
||||
if (needsSpawnPacket) {
|
||||
// The player has yet to spawn so let's do that using some of the information in this Java packet
|
||||
@ -85,6 +116,8 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
||||
session.sendUpstreamPacket(playerGameTypePacket);
|
||||
}
|
||||
|
||||
entity.setLastDeathPosition(packet.getLastDeathPos());
|
||||
|
||||
entity.updateBedrockMetadata();
|
||||
|
||||
// Send if client should show respawn screen
|
||||
@ -113,6 +146,7 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
||||
session.sendFog("minecraft:fog_hell");
|
||||
}
|
||||
|
||||
ChunkUtils.loadDimensionTag(session, packet.getDimension());
|
||||
session.setDimensionType(dimensions.get(newDimension));
|
||||
ChunkUtils.loadDimension(session);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.translator.protocol.java;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerChatPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.TextPacket;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.text.TextDecoration;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Translator(packet = ClientboundPlayerChatPacket.class)
|
||||
public class JavaPlayerChatTranslator extends PacketTranslator<ClientboundPlayerChatPacket> {
|
||||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundPlayerChatPacket packet) {
|
||||
TextPacket textPacket = new TextPacket();
|
||||
textPacket.setPlatformChatId("");
|
||||
textPacket.setSourceName("");
|
||||
textPacket.setXuid(session.getAuthData().xuid());
|
||||
// TODO new types
|
||||
textPacket.setType(switch (packet.getType()) {
|
||||
case CHAT -> TextPacket.Type.CHAT;
|
||||
case SYSTEM -> TextPacket.Type.SYSTEM;
|
||||
case GAME_INFO -> TextPacket.Type.TIP;
|
||||
default -> TextPacket.Type.RAW;
|
||||
});
|
||||
|
||||
textPacket.setNeedsTranslation(false);
|
||||
Component message = packet.getUnsignedContent() == null ? packet.getSignedContent() : packet.getUnsignedContent();
|
||||
|
||||
TextDecoration decoration = session.getChatTypes().get(packet.getType());
|
||||
if (decoration != null) {
|
||||
// As of 1.19 - do this to apply all the styling for signed messages
|
||||
// Though, Bedrock cannot care about the signed stuff.
|
||||
TranslatableComponent.Builder withDecoration = Component.translatable()
|
||||
.key(decoration.translationKey())
|
||||
.style(decoration.style());
|
||||
Set<TextDecoration.Parameter> parameters = decoration.parameters();
|
||||
List<Component> args = new ArrayList<>(3);
|
||||
if (parameters.contains(TextDecoration.Parameter.TEAM_NAME)) {
|
||||
args.add(packet.getSenderTeamName());
|
||||
}
|
||||
if (parameters.contains(TextDecoration.Parameter.SENDER)) {
|
||||
args.add(packet.getSenderName());
|
||||
}
|
||||
if (parameters.contains(TextDecoration.Parameter.CONTENT)) {
|
||||
args.add(message);
|
||||
}
|
||||
withDecoration.args(args);
|
||||
textPacket.setMessage(MessageTranslator.convertMessage(withDecoration.build(), session.getLocale()));
|
||||
} else {
|
||||
textPacket.setMessage(MessageTranslator.convertMessage(message, session.getLocale()));
|
||||
}
|
||||
|
||||
session.sendUpstreamPacket(textPacket);
|
||||
}
|
||||
}
|
@ -33,9 +33,9 @@ import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket;
|
||||
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.util.ChunkUtils;
|
||||
import org.geysermc.geyser.util.DimensionUtils;
|
||||
|
||||
@ -55,6 +55,9 @@ public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPa
|
||||
session.setOpenInventory(null);
|
||||
session.setClosingInventory(false);
|
||||
|
||||
entity.setLastDeathPosition(packet.getLastDeathPos());
|
||||
entity.updateBedrockMetadata();
|
||||
|
||||
SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket();
|
||||
playerGameTypePacket.setGamemode(packet.getGamemode().ordinal());
|
||||
session.sendUpstreamPacket(playerGameTypePacket);
|
||||
@ -78,7 +81,7 @@ public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPa
|
||||
session.setThunder(false);
|
||||
}
|
||||
|
||||
String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
|
||||
String newDimension = packet.getDimension();
|
||||
if (!session.getDimension().equals(newDimension) || !packet.getWorldName().equals(session.getWorldName())) {
|
||||
// Switching to a new world (based off the world name change); send a fake dimension change
|
||||
if (!packet.getWorldName().equals(session.getWorldName()) && (session.getDimension().equals(newDimension)
|
||||
@ -90,8 +93,9 @@ public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPa
|
||||
}
|
||||
session.setWorldName(packet.getWorldName());
|
||||
DimensionUtils.switchDimension(session, newDimension);
|
||||
}
|
||||
|
||||
ChunkUtils.loadDimensionTag(session, packet.getDimension());
|
||||
session.setDimensionType(session.getDimensions().get(newDimension));
|
||||
ChunkUtils.loadDimension(session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,31 +25,32 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundChatPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSystemChatPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.TextPacket;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
|
||||
@Translator(packet = ClientboundChatPacket.class)
|
||||
public class JavaChatTranslator extends PacketTranslator<ClientboundChatPacket> {
|
||||
@Translator(packet = ClientboundSystemChatPacket.class)
|
||||
public class JavaSystemChatTranslator extends PacketTranslator<ClientboundSystemChatPacket> {
|
||||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundChatPacket packet) {
|
||||
public void translate(GeyserSession session, ClientboundSystemChatPacket packet) {
|
||||
TextPacket textPacket = new TextPacket();
|
||||
textPacket.setPlatformChatId("");
|
||||
textPacket.setSourceName("");
|
||||
textPacket.setXuid(session.getAuthData().xuid());
|
||||
// TODO new types
|
||||
textPacket.setType(switch (packet.getType()) {
|
||||
case CHAT -> TextPacket.Type.CHAT;
|
||||
case SYSTEM -> TextPacket.Type.SYSTEM;
|
||||
case NOTIFICATION -> TextPacket.Type.TIP;
|
||||
case GAME_INFO -> TextPacket.Type.TIP;
|
||||
default -> TextPacket.Type.RAW;
|
||||
});
|
||||
|
||||
textPacket.setNeedsTranslation(false);
|
||||
textPacket.setMessage(MessageTranslator.convertMessage(packet.getMessage(), session.getLocale()));
|
||||
textPacket.setMessage(MessageTranslator.convertMessage(packet.getContent(), session.getLocale()));
|
||||
|
||||
session.sendUpstreamPacket(textPacket);
|
||||
}
|
@ -27,7 +27,7 @@ package org.geysermc.geyser.translator.protocol.java;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.advancement.Advancement;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundUpdateAdvancementsPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetTitlePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.ToastRequestPacket;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
@ -36,7 +36,7 @@ import org.geysermc.geyser.session.cache.AdvancementsCache;
|
||||
import org.geysermc.geyser.level.GeyserAdvancement;
|
||||
import org.geysermc.geyser.text.MinecraftLocale;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Locale;
|
||||
|
||||
@Translator(packet = ClientboundUpdateAdvancementsPacket.class)
|
||||
public class JavaUpdateAdvancementsTranslator extends PacketTranslator<ClientboundUpdateAdvancementsPacket> {
|
||||
@ -56,48 +56,39 @@ public class JavaUpdateAdvancementsTranslator extends PacketTranslator<Clientbou
|
||||
|
||||
advancementsCache.getStoredAdvancementProgress().putAll(packet.getProgress());
|
||||
|
||||
sendToolbarAdvancementUpdates(session, packet);
|
||||
|
||||
// Adds advancements to the player's stored advancements when advancements are sent
|
||||
for (Advancement advancement : packet.getAdvancements()) {
|
||||
if (advancement.getDisplayData() != null && !advancement.getDisplayData().isHidden()) {
|
||||
if (advancement.getDisplayData() != null && (!advancement.getDisplayData().isHidden() || advancement.getDisplayData().isShowToast())) {
|
||||
GeyserAdvancement geyserAdvancement = GeyserAdvancement.from(advancement);
|
||||
advancementsCache.getStoredAdvancements().put(advancement.getId(), geyserAdvancement);
|
||||
} else {
|
||||
advancementsCache.getStoredAdvancements().remove(advancement.getId());
|
||||
}
|
||||
}
|
||||
|
||||
sendAdvancementToasts(session, packet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle all advancements progress updates
|
||||
*/
|
||||
public void sendToolbarAdvancementUpdates(GeyserSession session, ClientboundUpdateAdvancementsPacket packet) {
|
||||
public void sendAdvancementToasts(GeyserSession session, ClientboundUpdateAdvancementsPacket packet) {
|
||||
if (packet.isReset()) {
|
||||
// Advancements are being cleared, so they can't be granted
|
||||
return;
|
||||
}
|
||||
for (Map.Entry<String, Map<String, Long>> progress : packet.getProgress().entrySet()) {
|
||||
GeyserAdvancement advancement = session.getAdvancementsCache().getStoredAdvancements().get(progress.getKey());
|
||||
for (String advancementId : packet.getProgress().keySet()) {
|
||||
GeyserAdvancement advancement = session.getAdvancementsCache().getStoredAdvancements().get(advancementId);
|
||||
if (advancement != null && advancement.getDisplayData() != null) {
|
||||
if (session.getAdvancementsCache().isEarned(advancement)) {
|
||||
// Java uses some pink color for toast challenge completes
|
||||
String color = advancement.getDisplayData().getFrameType() == Advancement.DisplayData.FrameType.CHALLENGE ?
|
||||
"§d" : "§a";
|
||||
if (advancement.getDisplayData().isShowToast() && session.getAdvancementsCache().isEarned(advancement)) {
|
||||
String frameType = advancement.getDisplayData().getFrameType().toString().toLowerCase(Locale.ROOT);
|
||||
String frameTitle = advancement.getDisplayColor() + MinecraftLocale.getLocaleString("advancements.toast." + frameType, session.getLocale());
|
||||
String advancementName = MessageTranslator.convertMessage(advancement.getDisplayData().getTitle(), session.getLocale());
|
||||
|
||||
// Send an action bar message stating they earned an achievement
|
||||
// Sent for instances where broadcasting advancements through chat are disabled
|
||||
SetTitlePacket titlePacket = new SetTitlePacket();
|
||||
titlePacket.setText(color + "[" + MinecraftLocale.getLocaleString("advancements.toast." +
|
||||
advancement.getDisplayData().getFrameType().toString().toLowerCase(), session.getLocale()) + "]§f " + advancementName);
|
||||
titlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
|
||||
titlePacket.setFadeOutTime(3);
|
||||
titlePacket.setFadeInTime(3);
|
||||
titlePacket.setStayTime(3);
|
||||
titlePacket.setXuid("");
|
||||
titlePacket.setPlatformOnlineId("");
|
||||
session.sendUpstreamPacket(titlePacket);
|
||||
ToastRequestPacket toastRequestPacket = new ToastRequestPacket();
|
||||
toastRequestPacket.setTitle(frameTitle);
|
||||
toastRequestPacket.setContent(advancementName);
|
||||
session.sendUpstreamPacket(toastRequestPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,7 +38,6 @@ import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.CraftingData;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||
import com.nukkitx.protocol.bedrock.packet.CraftingDataPacket;
|
||||
import com.nukkitx.protocol.bedrock.v486.Bedrock_v486;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@ -82,8 +81,6 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
|
||||
// Get the last known network ID (first used for the pregenerated recipes) and increment from there.
|
||||
int netId = InventoryUtils.LAST_RECIPE_NET_ID + 1;
|
||||
|
||||
boolean applySmithingRecipes = session.getUpstream().getProtocolVersion() >= Bedrock_v486.V486_CODEC.getProtocolVersion();
|
||||
|
||||
Int2ObjectMap<GeyserRecipe> recipeMap = new Int2ObjectOpenHashMap<>(Registries.RECIPES.forVersion(session.getUpstream().getProtocolVersion()));
|
||||
Int2ObjectMap<List<StoneCuttingRecipeData>> unsortedStonecutterData = new Int2ObjectOpenHashMap<>();
|
||||
CraftingDataPacket craftingDataPacket = new CraftingDataPacket();
|
||||
@ -138,10 +135,6 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
|
||||
}
|
||||
case SMITHING -> {
|
||||
// Required to translate these as of 1.18.10, or else they cannot be crafted
|
||||
if (!applySmithingRecipes) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SmithingRecipeData recipeData = (SmithingRecipeData) recipe.getData();
|
||||
ItemData output = ItemTranslator.translateToBedrock(session, recipeData.getResult());
|
||||
for (ItemStack base : recipeData.getBase().getOptions()) {
|
||||
|
@ -26,7 +26,6 @@
|
||||
package org.geysermc.geyser.translator.protocol.java.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.ClientboundEntityEventPacket;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
@ -38,11 +37,11 @@ import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.entity.type.EvokerFangsEntity;
|
||||
import org.geysermc.geyser.entity.type.FishingHookEntity;
|
||||
import org.geysermc.geyser.entity.type.LivingEntity;
|
||||
import org.geysermc.geyser.entity.type.living.monster.WardenEntity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@Translator(packet = ClientboundEntityEventPacket.class)
|
||||
@ -56,7 +55,7 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
|
||||
|
||||
EntityEventPacket entityEventPacket = new EntityEventPacket();
|
||||
entityEventPacket.setRuntimeEntityId(entity.getGeyserId());
|
||||
switch (packet.getStatus()) {
|
||||
switch (packet.getEvent()) {
|
||||
case PLAYER_ENABLE_REDUCED_DEBUG:
|
||||
session.setReducedDebugInfo(true);
|
||||
return;
|
||||
@ -180,8 +179,9 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
|
||||
case IRON_GOLEM_EMPTY_HAND:
|
||||
entityEventPacket.setType(EntityEventType.GOLEM_FLOWER_WITHDRAW);
|
||||
break;
|
||||
case IRON_GOLEM_ATTACK:
|
||||
if (entity.getDefinition() == EntityDefinitions.IRON_GOLEM || entity.getDefinition() == EntityDefinitions.EVOKER_FANGS) {
|
||||
case ATTACK:
|
||||
if (entity.getDefinition() == EntityDefinitions.IRON_GOLEM || entity.getDefinition() == EntityDefinitions.EVOKER_FANGS
|
||||
|| entity.getDefinition() == EntityDefinitions.WARDEN) {
|
||||
entityEventPacket.setType(EntityEventType.ATTACK_START);
|
||||
if (entity.getDefinition() == EntityDefinitions.EVOKER_FANGS) {
|
||||
((EvokerFangsEntity) entity).setAttackStarted();
|
||||
@ -236,28 +236,19 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
|
||||
break;
|
||||
case MAKE_POOF_PARTICLES:
|
||||
if (entity instanceof LivingEntity) {
|
||||
// Not ideal, but...
|
||||
// LevelEventType.PARTICLE_DEATH_SMOKE doesn't work (as of 1.18.2 Bedrock)
|
||||
// EntityEventType.DEATH_SMOKE_CLOUD also plays the entity death noise
|
||||
// Bedrock sends the particles through EntityEventType.DEATH, but Java despawns the entity
|
||||
// prematurely so they don't show up.
|
||||
Vector3f position = entity.getPosition();
|
||||
float baseX = position.getX();
|
||||
float baseY = position.getY();
|
||||
float baseZ = position.getZ();
|
||||
float height = entity.getBoundingBoxHeight();
|
||||
float width = entity.getBoundingBoxWidth();
|
||||
Random random = ThreadLocalRandom.current();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
// Reconstruct the Java Edition (1.18.1) logic, but in floats
|
||||
float x = baseX + width * (2.0f * random.nextFloat() - 1f);
|
||||
float y = baseY + height * random.nextFloat();
|
||||
float z = baseZ + width * (2.0f * random.nextFloat() - 1f);
|
||||
LevelEventPacket levelEventPacket = new LevelEventPacket();
|
||||
levelEventPacket.setPosition(Vector3f.from(x, y, z));
|
||||
levelEventPacket.setType(LevelEventType.PARTICLE_EXPLODE);
|
||||
session.sendUpstreamPacket(levelEventPacket);
|
||||
// Note that this event usually makes noise, but because we set all entities as silent on the
|
||||
// client end this isn't an issue.
|
||||
entityEventPacket.setType(EntityEventType.DEATH_SMOKE_CLOUD);
|
||||
}
|
||||
break;
|
||||
case WARDEN_RECEIVE_SIGNAL:
|
||||
if (entity.getDefinition() == EntityDefinitions.WARDEN) {
|
||||
entityEventPacket.setType(EntityEventType.VIBRATION_DETECTED);
|
||||
}
|
||||
break;
|
||||
case WARDEN_SONIC_BOOM:
|
||||
if (entity instanceof WardenEntity wardenEntity) {
|
||||
wardenEntity.onSonicBoom();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -23,27 +23,23 @@
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java.entity.spawn;
|
||||
package org.geysermc.geyser.translator.protocol.java.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddPaintingPacket;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.type.PaintingEntity;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundSoundEntityPacket;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.level.PaintingType;
|
||||
|
||||
@Translator(packet = ClientboundAddPaintingPacket.class)
|
||||
public class JavaAddPaintingTranslator extends PacketTranslator<ClientboundAddPaintingPacket> {
|
||||
import org.geysermc.geyser.util.SoundUtils;
|
||||
|
||||
@Translator(packet = ClientboundSoundEntityPacket.class)
|
||||
public class JavaSoundEntityTranslator extends PacketTranslator<ClientboundSoundEntityPacket> {
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundAddPaintingPacket packet) {
|
||||
Vector3f position = Vector3f.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ());
|
||||
|
||||
PaintingEntity entity = new PaintingEntity(session, packet.getEntityId(),
|
||||
session.getEntityCache().getNextEntityId().incrementAndGet(), packet.getUuid(),
|
||||
position, PaintingType.getByPaintingType(packet.getPaintingType()), packet.getDirection().getHorizontalIndex());
|
||||
|
||||
session.getEntityCache().spawnEntity(entity);
|
||||
public void translate(GeyserSession session, ClientboundSoundEntityPacket packet) {
|
||||
Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
SoundUtils.playBuiltinSound(session, packet.getSound(), entity.getPosition(), packet.getVolume(), packet.getPitch());
|
||||
}
|
||||
}
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren