mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Merge branch 'master' of https://github.com/GeyserMC/Geyser into scoreboard-changes
This commit is contained in:
commit
1611e26ec0
29 changed files with 399 additions and 106 deletions
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
|
@ -66,7 +66,7 @@ pipeline {
|
|||
}
|
||||
deleteDir()
|
||||
withCredentials([string(credentialsId: 'geyser-discord-webhook', variable: 'DISCORD_WEBHOOK')]) {
|
||||
discordSend description: "**Build:** [${currentBuild.id}](${env.BUILD_URL})\n**Status:** [${currentBuild.currentResult}](${env.BUILD_URL})\n${changes}\n\n[**Artifacts on Jenkins**](https://ci.nukkitx.com/job/Geyser)", footer: 'Cloudburst Jenkins', link: env.BUILD_URL, successful: currentBuild.resultIsBetterOrEqualTo('SUCCESS'), title: "${env.JOB_NAME} #${currentBuild.id}", webhookURL: DISCORD_WEBHOOK
|
||||
discordSend description: "**Build:** [${currentBuild.id}](${env.BUILD_URL})\n**Status:** [${currentBuild.currentResult}](${env.BUILD_URL})\n${changes}\n\n[**Artifacts on Jenkins**](https://ci.opencollab.dev/job/GeyserMC/job/Geyser)", footer: 'Open Collaboration Jenkins', link: env.BUILD_URL, successful: currentBuild.resultIsBetterOrEqualTo('SUCCESS'), title: "${env.JOB_NAME} #${currentBuild.id}", webhookURL: DISCORD_WEBHOOK
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
[](https://java.com/)
|
||||
|
||||
[](LICENSE)
|
||||
[](https://ci.nukkitx.com/job/GeyserMC/job/Geyser/job/master/)
|
||||
[](https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/master/)
|
||||
[](http://discord.geysermc.org/)
|
||||
[](http://hits.dwyl.io/Geyser/GeyserMC)
|
||||
[](https://translate.geysermc.org/)
|
||||
|
@ -52,6 +52,8 @@ Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set
|
|||
The following things can't be fixed because of Bedrock limitations. They might be fixable in the future, but not as of now.
|
||||
|
||||
- Custom heads in inventories
|
||||
- Clickable links in chat
|
||||
- Glowing effect
|
||||
|
||||
## Compiling
|
||||
1. Clone the repo to your computer
|
||||
|
|
|
@ -125,7 +125,7 @@ public class GeyserSpigot1_12WorldManager extends GeyserSpigotWorldManager {
|
|||
for (int blockY = 0; blockY < 16; blockY++) { // Cache-friendly iteration order
|
||||
for (int blockZ = 0; blockZ < 16; blockZ++) {
|
||||
for (int blockX = 0; blockX < 16; blockX++) {
|
||||
Block block = world.getBlockAt(x, y, z);
|
||||
Block block = world.getBlockAt((x << 4) + blockX, (y << 4) + blockY, (z << 4) + blockZ);
|
||||
// Black magic that gets the old block state ID
|
||||
int blockId = (block.getType().getId() << 4) | (block.getData() & 0xF);
|
||||
chunk.set(blockX, blockY, blockZ, getLegacyBlock(storage, blockId, (x << 4) + blockX, (y << 4) + blockY, (z << 4) + blockZ));
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<dependency>
|
||||
<groupId>com.github.CloudburstMC.Protocol</groupId>
|
||||
<artifactId>bedrock-v422</artifactId>
|
||||
<version>87d862d69d</version>
|
||||
<version>d41b84e86c</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -124,14 +124,26 @@
|
|||
<version>26201a4</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-serializer-gson</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.github.steveice10</groupId>
|
||||
<artifactId>packetlib</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.steveice10</groupId>
|
||||
<artifactId>PacketLib</artifactId>
|
||||
<version>54f761c</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion> <!-- Move this exclusion back to MCProtocolLib it gets the latest PacketLib -->
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -140,6 +152,12 @@
|
|||
<version>4.1.43.Final</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-codec-haproxy</artifactId>
|
||||
<version>4.1.56.Final</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.reflections</groupId>
|
||||
<artifactId>reflections</artifactId>
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.geysermc.connector.network.session.GeyserSession;
|
|||
import org.geysermc.connector.network.translators.BiomeTranslator;
|
||||
import org.geysermc.connector.network.translators.EntityIdentifierRegistry;
|
||||
import org.geysermc.connector.network.translators.PacketTranslatorRegistry;
|
||||
import org.geysermc.connector.network.translators.collision.CollisionTranslator;
|
||||
import org.geysermc.connector.network.translators.effect.EffectRegistry;
|
||||
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||
|
@ -54,7 +55,6 @@ import org.geysermc.connector.network.translators.sound.SoundRegistry;
|
|||
import org.geysermc.connector.network.translators.world.WorldManager;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||
import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator;
|
||||
import org.geysermc.connector.network.translators.collision.CollisionTranslator;
|
||||
import org.geysermc.connector.network.translators.world.block.entity.SkullBlockEntityTranslator;
|
||||
import org.geysermc.connector.scoreboard.ScoreboardUpdater;
|
||||
import org.geysermc.connector.utils.DimensionUtils;
|
||||
|
@ -68,10 +68,7 @@ import java.net.InetAddress;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
@ -328,6 +325,38 @@ public class GeyserConnector {
|
|||
players.remove(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a player by their current UUID
|
||||
*
|
||||
* @param uuid the uuid
|
||||
* @return the player or <code>null</code> if there is no player online with this UUID
|
||||
*/
|
||||
public GeyserSession getPlayerByUuid(UUID uuid) {
|
||||
for (GeyserSession session : players) {
|
||||
if (session.getPlayerEntity().getUuid().equals(uuid)) {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a player by their Xbox user identifier
|
||||
*
|
||||
* @param xuid the Xbox user identifier
|
||||
* @return the player or <code>null</code> if there is no player online with this xuid
|
||||
*/
|
||||
public GeyserSession getPlayerByXuid(String xuid) {
|
||||
for (GeyserSession session : players) {
|
||||
if (session.getAuthData() != null && session.getAuthData().getXboxUUID().equals(xuid)) {
|
||||
return session;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static GeyserConnector start(PlatformType platformType, GeyserBootstrap bootstrap) {
|
||||
return new GeyserConnector(platformType, bootstrap);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ public class VersionCommand extends GeyserCommand {
|
|||
Properties gitProp = new Properties();
|
||||
gitProp.load(FileUtils.getResource("git.properties"));
|
||||
|
||||
String buildXML = WebUtils.getBody("https://ci.nukkitx.com/job/GeyserMC/job/Geyser/job/" + URLEncoder.encode(gitProp.getProperty("git.branch"), StandardCharsets.UTF_8.toString()) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber");
|
||||
String buildXML = WebUtils.getBody("https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/" + URLEncoder.encode(gitProp.getProperty("git.branch"), StandardCharsets.UTF_8.toString()) + "/lastSuccessfulBuild/api/xml?xpath=//buildNumber");
|
||||
if (buildXML.startsWith("<buildNumber>")) {
|
||||
int latestBuildNum = Integer.parseInt(buildXML.replaceAll("<(\\\\)?(/)?buildNumber>", "").trim());
|
||||
int buildNum = Integer.parseInt(gitProp.getProperty("git.build.number"));
|
||||
|
|
|
@ -34,7 +34,7 @@ import java.util.Map;
|
|||
|
||||
public interface GeyserConfiguration {
|
||||
|
||||
// Modify this when you update the config
|
||||
// Modify this when you introduce breaking changes into the config
|
||||
int CURRENT_CONFIG_VERSION = 4;
|
||||
|
||||
IBedrockConfiguration getBedrock();
|
||||
|
@ -117,6 +117,8 @@ public interface GeyserConfiguration {
|
|||
void setPort(int port);
|
||||
|
||||
String getAuthType();
|
||||
|
||||
boolean isUseProxyProtocol();
|
||||
}
|
||||
|
||||
interface IUserAuthenticationInfo {
|
||||
|
|
|
@ -148,6 +148,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
|
|||
@Setter
|
||||
@JsonProperty("auth-type")
|
||||
private String authType = "online";
|
||||
|
||||
@JsonProperty("use-proxy-protocol")
|
||||
private boolean useProxyProtocol = false;
|
||||
}
|
||||
|
||||
@Getter
|
||||
|
|
|
@ -29,6 +29,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadat
|
|||
import com.github.steveice10.mc.protocol.data.game.world.particle.Particle;
|
||||
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.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.effect.EffectRegistry;
|
||||
|
@ -45,6 +46,8 @@ public class AreaEffectCloudEntity extends Entity {
|
|||
metadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, 0.0f);
|
||||
metadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_RATE, -0.005f);
|
||||
metadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, -0.5f);
|
||||
|
||||
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||
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.connector.GeyserConnector;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.item.ItemEntry;
|
||||
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
||||
import org.geysermc.connector.network.translators.item.Potion;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public class ThrownPotionEntity extends ThrowableEntity {
|
||||
private static final EnumSet<Potion> NON_ENCHANTED_POTIONS = EnumSet.of(Potion.WATER, Potion.MUNDANE, Potion.THICK, Potion.AWKWARD);
|
||||
|
||||
public ThrownPotionEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 7 && entityMetadata.getType() == MetadataType.ITEM) {
|
||||
ItemStack itemStack = (ItemStack) entityMetadata.getValue();
|
||||
ItemEntry itemEntry = ItemRegistry.getItem(itemStack);
|
||||
if (itemEntry.getJavaIdentifier().endsWith("potion") && itemStack.getNbt() != null) {
|
||||
Tag potionTag = itemStack.getNbt().get("Potion");
|
||||
if (potionTag instanceof StringTag) {
|
||||
Potion potion = Potion.getByJavaIdentifier(((StringTag) potionTag).getValue());
|
||||
if (potion != null) {
|
||||
metadata.put(EntityData.POTION_AUX_VALUE, potion.getBedrockId());
|
||||
metadata.getFlags().setFlag(EntityFlag.ENCHANTED, !NON_ENCHANTED_POTIONS.contains(potion));
|
||||
} else {
|
||||
metadata.put(EntityData.POTION_AUX_VALUE, 0);
|
||||
GeyserConnector.getInstance().getLogger().debug("Unknown java potion: " + potionTag.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
boolean isLingering = itemEntry.getJavaIdentifier().equals("minecraft:lingering_potion");
|
||||
metadata.getFlags().setFlag(EntityFlag.LINGERING, isLingering);
|
||||
}
|
||||
}
|
||||
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
}
|
|
@ -123,7 +123,7 @@ public enum EntityType {
|
|||
PAINTING(PaintingEntity.class, 83, 0f),
|
||||
MINECART(MinecartEntity.class, 84, 0.7f, 0.98f, 0.98f, 0.35f),
|
||||
FIREBALL(ItemedFireballEntity.class, 85, 1.0f),
|
||||
THROWN_POTION(ThrowableEntity.class, 86, 0.25f, 0.25f, 0.25f, 0f, "minecraft:splash_potion"),
|
||||
THROWN_POTION(ThrownPotionEntity.class, 86, 0.25f, 0.25f, 0.25f, 0f, "minecraft:splash_potion"),
|
||||
THROWN_ENDERPEARL(ThrowableEntity.class, 87, 0.25f, 0.25f, 0.25f, 0f, "minecraft:ender_pearl"),
|
||||
LEASH_KNOT(LeashKnotEntity.class, 88, 0.5f, 0.375f),
|
||||
WITHER_SKULL(WitherSkullEntity.class, 89, 0.3125f),
|
||||
|
|
|
@ -132,11 +132,6 @@ public class LoggingPacketHandler implements BedrockPacketHandler {
|
|||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(EntityFallPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(EntityPickRequestPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
|
@ -826,4 +821,43 @@ public class LoggingPacketHandler implements BedrockPacketHandler {
|
|||
public boolean handle(PositionTrackingDBServerBroadcastPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
// 1.16.100 new packets
|
||||
|
||||
@Override
|
||||
public boolean handle(MotionPredictionHintsPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(AnimateEntityPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(CameraShakePacket packet) {
|
||||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(PlayerFogPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(CorrectPlayerMovePredictionPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handle(ItemComponentPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
}
|
||||
|
||||
// 1.16.200 new packet
|
||||
|
||||
@Override
|
||||
public boolean handle(FilterTextPacket packet) {
|
||||
return defaultHandler(packet);
|
||||
}
|
||||
}
|
|
@ -39,6 +39,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye
|
|||
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.login.server.LoginSuccessPacket;
|
||||
import com.github.steveice10.packetlib.BuiltinFlags;
|
||||
import com.github.steveice10.packetlib.Client;
|
||||
import com.github.steveice10.packetlib.event.session.*;
|
||||
import com.github.steveice10.packetlib.packet.Packet;
|
||||
|
@ -250,6 +251,12 @@ public class GeyserSession implements CommandSender {
|
|||
@Setter
|
||||
private ScheduledFuture<?> movementSendIfIdle;
|
||||
|
||||
/**
|
||||
* Controls whether the daylight cycle gamerule has been sent to the client, so the sun/moon remain motionless.
|
||||
*/
|
||||
@Setter
|
||||
private boolean daylightCycle = true;
|
||||
|
||||
private boolean reducedDebugInfo = false;
|
||||
|
||||
@Setter
|
||||
|
@ -453,6 +460,10 @@ public class GeyserSession implements CommandSender {
|
|||
}
|
||||
|
||||
downstream = new Client(remoteServer.getAddress(), remoteServer.getPort(), protocol, new TcpSessionFactory());
|
||||
if (connector.getConfig().getRemote().isUseProxyProtocol()) {
|
||||
downstream.getSession().setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
|
||||
downstream.getSession().setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
|
||||
}
|
||||
// Let Geyser handle sending the keep alive
|
||||
downstream.getSession().setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false);
|
||||
downstream.getSession().addListener(new SessionAdapter() {
|
||||
|
@ -642,7 +653,6 @@ public class GeyserSession implements CommandSender {
|
|||
|
||||
public void setRenderDistance(int renderDistance) {
|
||||
renderDistance = GenericMath.ceil(++renderDistance * MathUtils.SQRT_OF_TWO); //square to circle
|
||||
if (renderDistance > 32) renderDistance = 32; // <3 u ViaVersion but I don't like crashing clients x)
|
||||
this.renderDistance = renderDistance;
|
||||
|
||||
ChunkRadiusUpdatedPacket chunkRadiusUpdatedPacket = new ChunkRadiusUpdatedPacket();
|
||||
|
|
|
@ -46,7 +46,6 @@ public class BedrockBlockPickRequestTranslator extends PacketTranslator<BlockPic
|
|||
return;
|
||||
}
|
||||
|
||||
String targetIdentifier = BlockTranslator.getJavaIdBlockMap().inverse().get(blockToPick).split("\\[")[0];
|
||||
InventoryUtils.findOrCreatePickedBlock(session, targetIdentifier);
|
||||
InventoryUtils.findOrCreateItem(session, BlockTranslator.getPickItem(blockToPick));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,6 @@ public class BedrockEntityPickRequestTranslator extends PacketTranslator<EntityP
|
|||
// Verify it is, indeed, an item
|
||||
if (entry == null) return;
|
||||
|
||||
InventoryUtils.findOrCreatePickedBlock(session, fullItemName);
|
||||
InventoryUtils.findOrCreateItem(session, fullItemName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.connector.network.translators.bedrock;
|
||||
|
||||
import com.nukkitx.protocol.bedrock.packet.FilterTextPacket;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
|
||||
/**
|
||||
* Used to send strings to the server and filter out unwanted words.
|
||||
* Java doesn't care, so we don't care, and we approve all strings.
|
||||
*/
|
||||
@Translator(packet = FilterTextPacket.class)
|
||||
public class BedrockFilterTextTranslator extends PacketTranslator<FilterTextPacket> {
|
||||
|
||||
@Override
|
||||
public void translate(FilterTextPacket packet, GeyserSession session) {
|
||||
packet.setFromServer(true);
|
||||
session.sendUpstreamPacket(packet);
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ public class BedrockTextTranslator extends PacketTranslator<TextPacket> {
|
|||
|
||||
@Override
|
||||
public void translate(TextPacket packet, GeyserSession session) {
|
||||
String message = packet.getMessage().replaceAll("^\\.", "/").trim();
|
||||
String message = packet.getMessage();
|
||||
|
||||
if (MessageTranslator.isTooLong(message, session)) {
|
||||
return;
|
||||
|
|
|
@ -45,8 +45,39 @@ import java.util.stream.Collectors;
|
|||
|
||||
@ItemRemapper
|
||||
public class BannerTranslator extends ItemTranslator {
|
||||
/**
|
||||
* Holds what a Java ominous banner pattern looks like.
|
||||
*
|
||||
* Translating the patterns over to Bedrock does not work effectively, but Bedrock has a dedicated type for
|
||||
* ominous banners that we set instead. This variable is used to detect Java ominous banner patterns, and apply
|
||||
* the correct ominous banner pattern if Bedrock pulls the item from creative.
|
||||
*/
|
||||
public static final ListTag OMINOUS_BANNER_PATTERN;
|
||||
|
||||
private final List<ItemEntry> appliedItems;
|
||||
|
||||
static {
|
||||
OMINOUS_BANNER_PATTERN = new ListTag("Patterns");
|
||||
// Construct what an ominous banner is supposed to look like
|
||||
OMINOUS_BANNER_PATTERN.add(getPatternTag("mr", 9));
|
||||
OMINOUS_BANNER_PATTERN.add(getPatternTag("bs", 8));
|
||||
OMINOUS_BANNER_PATTERN.add(getPatternTag("cs", 7));
|
||||
OMINOUS_BANNER_PATTERN.add(getPatternTag("bo", 8));
|
||||
OMINOUS_BANNER_PATTERN.add(getPatternTag("ms", 15));
|
||||
OMINOUS_BANNER_PATTERN.add(getPatternTag("hh", 8));
|
||||
OMINOUS_BANNER_PATTERN.add(getPatternTag("mc", 8));
|
||||
OMINOUS_BANNER_PATTERN.add(getPatternTag("bo", 15));
|
||||
}
|
||||
|
||||
private static CompoundTag getPatternTag(String pattern, int color) {
|
||||
StringTag patternType = new StringTag("Pattern", pattern);
|
||||
IntTag colorTag = new IntTag("Color", color);
|
||||
CompoundTag tag = new CompoundTag("");
|
||||
tag.put(patternType);
|
||||
tag.put(colorTag);
|
||||
return tag;
|
||||
}
|
||||
|
||||
public BannerTranslator() {
|
||||
appliedItems = ItemRegistry.ITEM_ENTRIES.values()
|
||||
.stream()
|
||||
|
@ -62,7 +93,7 @@ public class BannerTranslator extends ItemTranslator {
|
|||
*/
|
||||
public static NbtList<NbtMap> convertBannerPattern(ListTag patterns) {
|
||||
List<NbtMap> tagsList = new ArrayList<>();
|
||||
for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) {
|
||||
for (Tag patternTag : patterns.getValue()) {
|
||||
NbtMap newPatternTag = getBedrockBannerPattern((CompoundTag) patternTag);
|
||||
if (newPatternTag != null) {
|
||||
tagsList.add(newPatternTag);
|
||||
|
@ -134,7 +165,13 @@ public class BannerTranslator extends ItemTranslator {
|
|||
ListTag patterns = blockEntityTag.get("Patterns");
|
||||
|
||||
NbtMapBuilder builder = itemData.getTag().toBuilder();
|
||||
if (patterns.equals(OMINOUS_BANNER_PATTERN)) {
|
||||
// Remove the current patterns and set the ominous banner type
|
||||
builder.remove("Patterns");
|
||||
builder.putInt("Type", 1);
|
||||
} else {
|
||||
builder.put("Patterns", convertBannerPattern(patterns));
|
||||
}
|
||||
|
||||
itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.build());
|
||||
}
|
||||
|
@ -151,7 +188,14 @@ public class BannerTranslator extends ItemTranslator {
|
|||
ItemStack itemStack = super.translateToJava(itemData, itemEntry);
|
||||
|
||||
NbtMap nbtTag = itemData.getTag();
|
||||
if (nbtTag.containsKey("Patterns", NbtType.COMPOUND)) {
|
||||
if (nbtTag.containsKey("Type", NbtType.INT) && nbtTag.getInt("Type") == 1) {
|
||||
// Ominous banner pattern
|
||||
itemStack.getNbt().remove("Type");
|
||||
CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag");
|
||||
blockEntityTag.put(OMINOUS_BANNER_PATTERN);
|
||||
|
||||
itemStack.getNbt().put(blockEntityTag);
|
||||
} else if (nbtTag.containsKey("Patterns", NbtType.COMPOUND)) {
|
||||
List<NbtMap> patterns = nbtTag.getList("Patterns", NbtType.COMPOUND);
|
||||
|
||||
CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag");
|
||||
|
|
|
@ -52,9 +52,14 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator<ServerDeclar
|
|||
public void translate(ServerDeclareCommandsPacket packet, GeyserSession session) {
|
||||
// Don't send command suggestions if they are disabled
|
||||
if (!session.getConnector().getConfig().isCommandSuggestions()) {
|
||||
session.getConnector().getLogger().debug("Not sending command suggestions as they are disabled.");
|
||||
session.getConnector().getLogger().debug("Not sending translated command suggestions as they are disabled.");
|
||||
|
||||
// Send an empty packet so Bedrock doesn't override /help with its own, built-in help command.
|
||||
AvailableCommandsPacket emptyPacket = new AvailableCommandsPacket();
|
||||
session.sendUpstreamPacket(emptyPacket);
|
||||
return;
|
||||
}
|
||||
|
||||
List<CommandData> commandData = new ArrayList<>();
|
||||
Int2ObjectMap<String> commands = new Int2ObjectOpenHashMap<>();
|
||||
Int2ObjectMap<List<CommandNode>> commandArgs = new Int2ObjectOpenHashMap<>();
|
||||
|
@ -83,7 +88,7 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator<ServerDeclar
|
|||
}
|
||||
|
||||
// The command flags, not sure what these do apart from break things
|
||||
List<CommandData.Flag> flags = new ArrayList<>();
|
||||
List<CommandData.Flag> flags = Collections.emptyList();
|
||||
|
||||
// Loop through all the found commands
|
||||
for (int commandID : commands.keySet()) {
|
||||
|
@ -102,9 +107,7 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator<ServerDeclar
|
|||
|
||||
// Add our commands to the AvailableCommandsPacket for the bedrock client
|
||||
AvailableCommandsPacket availableCommandsPacket = new AvailableCommandsPacket();
|
||||
for (CommandData data : commandData) {
|
||||
availableCommandsPacket.getCommands().add(data);
|
||||
}
|
||||
availableCommandsPacket.getCommands().addAll(commandData);
|
||||
|
||||
GeyserConnector.getInstance().getLogger().debug("Sending command packet of " + commandData.size() + " commands");
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ public class JavaEntityStatusTranslator extends PacketTranslator<ServerEntitySta
|
|||
case LIVING_DROWN:
|
||||
case LIVING_HURT:
|
||||
case LIVING_HURT_SWEET_BERRY_BUSH:
|
||||
case LIVING_HURT_THORNS:
|
||||
entityEventPacket.setType(EntityEventType.HURT);
|
||||
break;
|
||||
case LIVING_DEATH:
|
||||
|
|
|
@ -34,8 +34,8 @@ import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
|
|||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||
import org.geysermc.connector.network.translators.sound.SoundRegistry;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||
|
||||
@Translator(packet = ServerPlayBuiltinSoundPacket.class)
|
||||
public class JavaPlayBuiltinSoundTranslator extends PacketTranslator<ServerPlayBuiltinSoundPacket> {
|
||||
|
@ -82,7 +82,11 @@ public class JavaPlayBuiltinSoundTranslator extends PacketTranslator<ServerPlayB
|
|||
// Bedrock has a number for each type of note, then proceeds up the scale by adding to that number
|
||||
soundPacket.setExtraData(soundMapping.getExtraData() + (int)(Math.round((Math.log10(packet.getPitch()) / Math.log10(2)) * 12)) + 12);
|
||||
} else if (sound == SoundEvent.PLACE && soundMapping.getExtraData() == -1) {
|
||||
if (!soundMapping.getIdentifier().equals(":")) {
|
||||
soundPacket.setExtraData(BlockTranslator.getBedrockBlockId(BlockTranslator.getJavaBlockState(soundMapping.getIdentifier())));
|
||||
} else {
|
||||
session.getConnector().getLogger().debug("PLACE sound mapping identifier was invalid! Please report: " + packet.toString());
|
||||
}
|
||||
soundPacket.setIdentifier(":");
|
||||
} else {
|
||||
soundPacket.setExtraData(soundMapping.getExtraData());
|
||||
|
|
|
@ -25,49 +25,38 @@
|
|||
|
||||
package org.geysermc.connector.network.translators.java.world;
|
||||
|
||||
import com.nukkitx.protocol.bedrock.data.GameRuleData;
|
||||
import com.nukkitx.protocol.bedrock.packet.GameRulesChangedPacket;
|
||||
import it.unimi.dsi.fastutil.longs.Long2LongMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTimePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetTimePacket;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTimePacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.SetTimePacket;
|
||||
|
||||
@Translator(packet = ServerUpdateTimePacket.class)
|
||||
public class JavaUpdateTimeTranslator extends PacketTranslator<ServerUpdateTimePacket> {
|
||||
|
||||
// If negative, the last time is stored so we know it's not some plugin behavior doing weird things.
|
||||
// Per-player for multi-world support
|
||||
private static final Long2LongMap LAST_RECORDED_TIMES = new Long2LongOpenHashMap();
|
||||
|
||||
@Override
|
||||
public void translate(ServerUpdateTimePacket packet, GeyserSession session) {
|
||||
|
||||
// Bedrock sends a GameRulesChangedPacket if there is no daylight cycle
|
||||
// Java just sends a negative long if there is no daylight cycle
|
||||
long lastTime = LAST_RECORDED_TIMES.getOrDefault(session.getPlayerEntity().getEntityId(), 0);
|
||||
long time = packet.getTime();
|
||||
|
||||
if (lastTime != time) {
|
||||
// https://minecraft.gamepedia.com/Day-night_cycle#24-hour_Minecraft_day
|
||||
SetTimePacket setTimePacket = new SetTimePacket();
|
||||
setTimePacket.setTime((int) Math.abs(time) % 24000);
|
||||
session.sendUpstreamPacket(setTimePacket);
|
||||
// TODO: Performance efficient to always do this?
|
||||
LAST_RECORDED_TIMES.put(session.getPlayerEntity().getEntityId(), time);
|
||||
}
|
||||
if (lastTime < 0 && time >= 0) {
|
||||
if (!session.isDaylightCycle() && time >= 0) {
|
||||
// Client thinks there is no daylight cycle but there is
|
||||
setDoDaylightCycleGamerule(session, true);
|
||||
} else if (lastTime != time && time < 0) {
|
||||
} else if (session.isDaylightCycle() && time < 0) {
|
||||
// Client thinks there is daylight cycle but there isn't
|
||||
setDoDaylightCycleGamerule(session, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void setDoDaylightCycleGamerule(GeyserSession session, boolean doCycle) {
|
||||
session.sendGameRule("dodaylightcycle", doCycle);
|
||||
// Save the value so we don't have to constantly send a daylight cycle gamerule update
|
||||
session.setDaylightCycle(doCycle);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,15 +30,18 @@ import com.google.common.collect.BiMap;
|
|||
import com.google.common.collect.HashBiMap;
|
||||
import com.nukkitx.nbt.*;
|
||||
import it.unimi.dsi.fastutil.ints.*;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.network.translators.world.block.entity.BlockEntity;
|
||||
import org.geysermc.connector.utils.FileUtils;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public class BlockTranslator {
|
||||
/**
|
||||
|
@ -65,8 +68,6 @@ public class BlockTranslator {
|
|||
// Bedrock carpet ID, used in LlamaEntity.java for decoration
|
||||
public static final int CARPET = 171;
|
||||
|
||||
private static final Int2ObjectMap<String> JAVA_ID_TO_BLOCK_ENTITY_MAP = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
public static final Int2DoubleMap JAVA_RUNTIME_ID_TO_HARDNESS = new Int2DoubleOpenHashMap();
|
||||
public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND = new Int2BooleanOpenHashMap();
|
||||
public static final Int2ObjectMap<String> JAVA_RUNTIME_ID_TO_TOOL_TYPE = new Int2ObjectOpenHashMap<>();
|
||||
|
@ -74,6 +75,8 @@ public class BlockTranslator {
|
|||
// The index of the collision data in collision.json
|
||||
public static final Int2IntMap JAVA_RUNTIME_ID_TO_COLLISION_INDEX = new Int2IntOpenHashMap();
|
||||
|
||||
private static final Int2ObjectMap<String> JAVA_RUNTIME_ID_TO_PICK_ITEM = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* Java numeric ID to java unique identifier, used for block names in the statistics screen
|
||||
*/
|
||||
|
@ -173,19 +176,12 @@ public class BlockTranslator {
|
|||
JAVA_RUNTIME_ID_TO_COLLISION_INDEX.put(javaRuntimeId, collisionIndexNode.intValue());
|
||||
}
|
||||
|
||||
JAVA_ID_BLOCK_MAP.put(javaId, javaRuntimeId);
|
||||
JsonNode pickItemNode = entry.getValue().get("pick_item");
|
||||
if (pickItemNode != null) {
|
||||
JAVA_RUNTIME_ID_TO_PICK_ITEM.put(javaRuntimeId, pickItemNode.textValue());
|
||||
}
|
||||
|
||||
// Used for adding all "special" Java block states to block state map
|
||||
String identifier;
|
||||
String bedrockIdentifier = entry.getValue().get("bedrock_identifier").asText();
|
||||
for (Class<?> clazz : ref.getTypesAnnotatedWith(BlockEntity.class)) {
|
||||
identifier = clazz.getAnnotation(BlockEntity.class).regex();
|
||||
// Endswith, or else the block bedrock gets picked up for bed
|
||||
if (bedrockIdentifier.endsWith(identifier) && !identifier.equals("")) {
|
||||
JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaRuntimeId, clazz.getAnnotation(BlockEntity.class).name());
|
||||
break;
|
||||
}
|
||||
}
|
||||
JAVA_ID_BLOCK_MAP.put(javaId, javaRuntimeId);
|
||||
|
||||
BlockStateValues.storeBlockStateValues(entry, javaRuntimeId);
|
||||
|
||||
|
@ -196,6 +192,8 @@ public class BlockTranslator {
|
|||
JAVA_ID_TO_JAVA_IDENTIFIER_MAP.put(uniqueJavaId, cleanJavaIdentifier);
|
||||
}
|
||||
|
||||
String bedrockIdentifier = entry.getValue().get("bedrock_identifier").asText();
|
||||
|
||||
if (!cleanJavaIdentifier.equals(bedrockIdentifier)) {
|
||||
JAVA_TO_BEDROCK_IDENTIFIERS.put(cleanJavaIdentifier, bedrockIdentifier);
|
||||
}
|
||||
|
@ -352,12 +350,12 @@ public class BlockTranslator {
|
|||
return BLOCK_STATE_VERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param javaId the Java string identifier to search for
|
||||
* @return the Java block state integer, or {@link #JAVA_AIR_ID} if there is no valid entry.
|
||||
*/
|
||||
public static int getJavaBlockState(String javaId) {
|
||||
return JAVA_ID_BLOCK_MAP.get(javaId);
|
||||
}
|
||||
|
||||
public static String getBlockEntityString(int javaId) {
|
||||
return JAVA_ID_TO_BLOCK_ENTITY_MAP.get(javaId);
|
||||
return JAVA_ID_BLOCK_MAP.getOrDefault(javaId, JAVA_AIR_ID);
|
||||
}
|
||||
|
||||
public static boolean isWaterlogged(int state) {
|
||||
|
@ -371,4 +369,19 @@ public class BlockTranslator {
|
|||
public static int getJavaWaterloggedState(int bedrockId) {
|
||||
return BEDROCK_TO_JAVA_BLOCK_MAP.get(1 << 31 | bedrockId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the item a Java client would receive when pressing
|
||||
* the Pick Block key on a specific Java block state.
|
||||
*
|
||||
* @param javaId The Java runtime id of the block
|
||||
* @return The Java identifier of the item
|
||||
*/
|
||||
public static String getPickItem(int javaId) {
|
||||
String itemIdentifier = JAVA_RUNTIME_ID_TO_PICK_ITEM.get(javaId);
|
||||
if (itemIdentifier == null) {
|
||||
return JAVA_ID_BLOCK_MAP.inverse().get(javaId).split("\\[")[0];
|
||||
}
|
||||
return itemIdentifier;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,8 +47,14 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator implement
|
|||
|
||||
if (tag.contains("Patterns")) {
|
||||
ListTag patterns = tag.get("Patterns");
|
||||
if (patterns.equals(BannerTranslator.OMINOUS_BANNER_PATTERN)) {
|
||||
// This is an ominous banner; don't try to translate the raw patterns (it doesn't translate correctly)
|
||||
// and tell the Bedrock client that this is an ominous banner
|
||||
builder.putInt("Type", 1);
|
||||
} else {
|
||||
builder.put("Patterns", BannerTranslator.convertBannerPattern(patterns));
|
||||
}
|
||||
}
|
||||
|
||||
if (tag.contains("CustomName")) {
|
||||
builder.put("CustomName", tag.get("CustomName").getValue());
|
||||
|
|
|
@ -81,11 +81,10 @@ public class SkinManager {
|
|||
|
||||
// This attempts to find the xuid of the player so profile images show up for xbox accounts
|
||||
String xuid = "";
|
||||
for (GeyserSession player : GeyserConnector.getInstance().getPlayers()) {
|
||||
if (player.getPlayerEntity().getUuid().equals(uuid)) {
|
||||
GeyserSession player = GeyserConnector.getInstance().getPlayerByUuid(uuid);
|
||||
|
||||
if (player != null) {
|
||||
xuid = player.getAuthData().getXboxUUID();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerListPacket.Entry entry;
|
||||
|
@ -268,11 +267,10 @@ public class SkinManager {
|
|||
// return default skin with default cape when texture data is invalid
|
||||
String skinUrl = isAlex ? SkinProvider.EMPTY_SKIN_ALEX.getTextureUrl() : SkinProvider.EMPTY_SKIN.getTextureUrl();
|
||||
if ("steve".equals(skinUrl) || "alex".equals(skinUrl)) {
|
||||
for (GeyserSession session : GeyserConnector.getInstance().getPlayers()) {
|
||||
if (session.getPlayerEntity().getUuid().equals(profile.getId())) {
|
||||
GeyserSession session = GeyserConnector.getInstance().getPlayerByUuid(profile.getId());
|
||||
|
||||
if (session != null) {
|
||||
skinUrl = session.getClientData().getSkinId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new GameProfileData(skinUrl, SkinProvider.EMPTY_CAPE.getTextureUrl(), isAlex);
|
||||
|
|
|
@ -144,12 +144,10 @@ public class SkinProvider {
|
|||
String newSkinUrl = skinUrl;
|
||||
|
||||
if ("steve".equals(skinUrl) || "alex".equals(skinUrl)) {
|
||||
// TODO: Don't have a for loop for this? Have a proper map?
|
||||
for (GeyserSession session : GeyserConnector.getInstance().getPlayers()) {
|
||||
if (session.getPlayerEntity().getUuid().equals(playerId)) {
|
||||
GeyserSession session = GeyserConnector.getInstance().getPlayerByUuid(playerId);
|
||||
|
||||
if (session != null) {
|
||||
newSkinUrl = session.getClientData().getSkinId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
|
|||
import org.geysermc.connector.network.translators.item.ItemEntry;
|
||||
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
|
@ -168,13 +169,17 @@ public class InventoryUtils {
|
|||
* @param session the Bedrock client's session
|
||||
* @param itemName the Java identifier of the item to search/select
|
||||
*/
|
||||
public static void findOrCreatePickedBlock(GeyserSession session, String itemName) {
|
||||
public static void findOrCreateItem(GeyserSession session, String itemName) {
|
||||
// Get the inventory to choose a slot to pick
|
||||
Inventory inventory = session.getInventoryCache().getOpenInventory();
|
||||
if (inventory == null) {
|
||||
inventory = session.getInventory();
|
||||
}
|
||||
|
||||
if (itemName.equals("minecraft:air")) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check hotbar for item
|
||||
for (int i = 36; i < 45; i++) {
|
||||
if (inventory.getItem(i) == null) {
|
||||
|
@ -219,12 +224,17 @@ public class InventoryUtils {
|
|||
}
|
||||
}
|
||||
|
||||
ItemEntry entry = ItemRegistry.getItemEntry(itemName);
|
||||
if (entry != null) {
|
||||
ClientCreativeInventoryActionPacket actionPacket = new ClientCreativeInventoryActionPacket(slot,
|
||||
new ItemStack(ItemRegistry.getItemEntry(itemName).getJavaId()));
|
||||
new ItemStack(entry.getJavaId()));
|
||||
if ((slot - 36) != session.getInventory().getHeldItemSlot()) {
|
||||
setHotbarItem(session, slot);
|
||||
}
|
||||
session.sendDownstreamPacket(actionPacket);
|
||||
} else {
|
||||
session.getConnector().getLogger().debug("Cannot find item for block " + itemName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,11 @@ remote:
|
|||
port: 25565
|
||||
# Authentication type. Can be offline, online, or floodgate (see https://github.com/GeyserMC/Geyser/wiki/Floodgate).
|
||||
auth-type: online
|
||||
# Whether to enable PROXY protocol or not while connecting to the server.
|
||||
# This is useful only when:
|
||||
# 1) Your server supports PROXY protocol (it probably doesn't)
|
||||
# 2) You run Velocity or BungeeCord with respective option enabled.
|
||||
use-proxy-protocol: false
|
||||
|
||||
# Floodgate uses encryption to ensure use from authorised sources.
|
||||
# This should point to the public key generated by Floodgate (Bungee or CraftBukkit)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 2d14c9dc3d75df7463fc7605a6cff63b5926a03e
|
||||
Subproject commit 143285afb4bdf4d5ef40ef7a7959477dabf4d34c
|
Loading…
Add table
Add a link
Reference in a new issue