mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Merge remote-tracking branch 'origin/master' into floodgate-2.0
# Conflicts: # connector/src/main/java/org/geysermc/connector/dump/BootstrapDumpInfo.java # connector/src/main/java/org/geysermc/connector/dump/DumpInfo.java # connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java # connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java # connector/src/main/java/org/geysermc/connector/utils/SettingsUtils.java
This commit is contained in:
commit
3b9674ac29
53 changed files with 744 additions and 269 deletions
|
@ -25,7 +25,6 @@
|
||||||
|
|
||||||
package org.geysermc.connector.command.defaults;
|
package org.geysermc.connector.command.defaults;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
|
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
|
||||||
import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
|
import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
|
||||||
|
@ -33,15 +32,12 @@ import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.command.CommandSender;
|
import org.geysermc.connector.command.CommandSender;
|
||||||
import org.geysermc.connector.command.GeyserCommand;
|
import org.geysermc.connector.command.GeyserCommand;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.utils.BlockUtils;
|
||||||
|
|
||||||
public class OffhandCommand extends GeyserCommand {
|
public class OffhandCommand extends GeyserCommand {
|
||||||
|
|
||||||
private final GeyserConnector connector;
|
|
||||||
|
|
||||||
public OffhandCommand(GeyserConnector connector, String name, String description, String permission) {
|
public OffhandCommand(GeyserConnector connector, String name, String description, String permission) {
|
||||||
super(name, description, permission);
|
super(name, description, permission);
|
||||||
|
|
||||||
this.connector = connector;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -50,7 +46,7 @@ public class OffhandCommand extends GeyserCommand {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.SWAP_HANDS, new Position(0,0,0),
|
ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.SWAP_HANDS, BlockUtils.POSITION_ZERO,
|
||||||
BlockFace.DOWN);
|
BlockFace.DOWN);
|
||||||
session.sendDownstreamPacket(releaseItemPacket);
|
session.sendDownstreamPacket(releaseItemPacket);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.configuration;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.databind.JsonDeserializer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public enum EmoteOffhandWorkaroundOption {
|
||||||
|
NO_EMOTES,
|
||||||
|
EMOTES_AND_OFFHAND,
|
||||||
|
DISABLED;
|
||||||
|
|
||||||
|
public static class Deserializer extends JsonDeserializer<EmoteOffhandWorkaroundOption> {
|
||||||
|
@Override
|
||||||
|
public EmoteOffhandWorkaroundOption deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
|
||||||
|
String value = p.getValueAsString();
|
||||||
|
switch (value) {
|
||||||
|
case "no-emotes":
|
||||||
|
return NO_EMOTES;
|
||||||
|
case "emotes-and-offhand":
|
||||||
|
return EMOTES_AND_OFFHAND;
|
||||||
|
default:
|
||||||
|
return DISABLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,6 +77,8 @@ public interface GeyserConfiguration {
|
||||||
|
|
||||||
boolean isShowCoordinates();
|
boolean isShowCoordinates();
|
||||||
|
|
||||||
|
EmoteOffhandWorkaroundOption getEmoteOffhandWorkaround();
|
||||||
|
|
||||||
String getDefaultLocale();
|
String getDefaultLocale();
|
||||||
|
|
||||||
Path getFloodgateKeyPath();
|
Path getFloodgateKeyPath();
|
||||||
|
@ -138,6 +140,8 @@ public interface GeyserConfiguration {
|
||||||
boolean isPasswordAuthentication();
|
boolean isPasswordAuthentication();
|
||||||
|
|
||||||
boolean isUseProxyProtocol();
|
boolean isUseProxyProtocol();
|
||||||
|
|
||||||
|
boolean isForwardHost();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IUserAuthenticationInfo {
|
interface IUserAuthenticationInfo {
|
||||||
|
|
|
@ -28,6 +28,7 @@ package org.geysermc.connector.configuration;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
|
@ -100,6 +101,10 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
|
||||||
@JsonProperty("show-coordinates")
|
@JsonProperty("show-coordinates")
|
||||||
private boolean showCoordinates = true;
|
private boolean showCoordinates = true;
|
||||||
|
|
||||||
|
@JsonDeserialize(using = EmoteOffhandWorkaroundOption.Deserializer.class)
|
||||||
|
@JsonProperty("emote-offhand-workaround")
|
||||||
|
private EmoteOffhandWorkaroundOption emoteOffhandWorkaround = EmoteOffhandWorkaroundOption.DISABLED;
|
||||||
|
|
||||||
@JsonProperty("allow-third-party-ears")
|
@JsonProperty("allow-third-party-ears")
|
||||||
private boolean allowThirdPartyEars = false;
|
private boolean allowThirdPartyEars = false;
|
||||||
|
|
||||||
|
@ -197,6 +202,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
|
||||||
|
|
||||||
@JsonProperty("use-proxy-protocol")
|
@JsonProperty("use-proxy-protocol")
|
||||||
private boolean useProxyProtocol = false;
|
private boolean useProxyProtocol = false;
|
||||||
|
|
||||||
|
@JsonProperty("forward-hostname")
|
||||||
|
private boolean forwardHost = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
|
|
|
@ -27,8 +27,12 @@ package org.geysermc.connector.dump;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import com.github.steveice10.mc.protocol.MinecraftConstants;
|
import com.github.steveice10.mc.protocol.MinecraftConstants;
|
||||||
|
import com.google.common.hash.Hashing;
|
||||||
|
import com.google.common.io.ByteSource;
|
||||||
|
import com.google.common.io.Files;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.common.serializer.AsteriskSerializer;
|
import org.geysermc.connector.common.serializer.AsteriskSerializer;
|
||||||
|
@ -40,6 +44,7 @@ import org.geysermc.connector.utils.FileUtils;
|
||||||
import org.geysermc.floodgate.util.DeviceOs;
|
import org.geysermc.floodgate.util.DeviceOs;
|
||||||
import org.geysermc.floodgate.util.FloodgateConfigHolder;
|
import org.geysermc.floodgate.util.FloodgateConfigHolder;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
@ -56,6 +61,7 @@ public class DumpInfo {
|
||||||
private Properties gitInfo;
|
private Properties gitInfo;
|
||||||
private final GeyserConfiguration config;
|
private final GeyserConfiguration config;
|
||||||
private final Object floodgateConfig;
|
private final Object floodgateConfig;
|
||||||
|
private final HashInfo hashInfo;
|
||||||
private final Object2IntMap<DeviceOs> userPlatforms;
|
private final Object2IntMap<DeviceOs> userPlatforms;
|
||||||
private final RamInfo ramInfo;
|
private final RamInfo ramInfo;
|
||||||
private final BootstrapDumpInfo bootstrapInfo;
|
private final BootstrapDumpInfo bootstrapInfo;
|
||||||
|
@ -71,6 +77,27 @@ public class DumpInfo {
|
||||||
|
|
||||||
this.config = GeyserConnector.getInstance().getConfig();
|
this.config = GeyserConnector.getInstance().getConfig();
|
||||||
this.floodgateConfig = FloodgateConfigHolder.getConfig();
|
this.floodgateConfig = FloodgateConfigHolder.getConfig();
|
||||||
|
|
||||||
|
String md5Hash = "unknown";
|
||||||
|
String sha256Hash = "unknown";
|
||||||
|
try {
|
||||||
|
// https://stackoverflow.com/questions/320542/how-to-get-the-path-of-a-running-jar-file
|
||||||
|
// https://stackoverflow.com/questions/304268/getting-a-files-md5-checksum-in-java
|
||||||
|
File file = new File(DumpInfo.class.getProtectionDomain().getCodeSource().getLocation().toURI());
|
||||||
|
ByteSource byteSource = Files.asByteSource(file);
|
||||||
|
// Jenkins uses MD5 for its hash
|
||||||
|
//noinspection UnstableApiUsage
|
||||||
|
md5Hash = byteSource.hash(Hashing.md5()).toString();
|
||||||
|
//noinspection UnstableApiUsage
|
||||||
|
sha256Hash = byteSource.hash(Hashing.sha256()).toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (GeyserConnector.getInstance().getConfig().isDebugMode()) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.hashInfo = new HashInfo(md5Hash, sha256Hash);
|
||||||
|
|
||||||
this.ramInfo = new DumpInfo.RamInfo();
|
this.ramInfo = new DumpInfo.RamInfo();
|
||||||
|
|
||||||
this.userPlatforms = new Object2IntOpenHashMap<>();
|
this.userPlatforms = new Object2IntOpenHashMap<>();
|
||||||
|
@ -108,6 +135,13 @@ public class DumpInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public static class HashInfo {
|
||||||
|
private final String md5Hash;
|
||||||
|
private final String sha256Hash;
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public static class NetworkInfo {
|
public static class NetworkInfo {
|
||||||
private final boolean dockerCheck;
|
private final boolean dockerCheck;
|
||||||
|
|
|
@ -34,4 +34,14 @@ public class AnimalEntity extends AgeableEntity {
|
||||||
public AnimalEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
public AnimalEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param javaIdentifierStripped the stripped Java identifier of the item that is potential breeding food. For example,
|
||||||
|
* <code>wheat</code>.
|
||||||
|
* @return true if this is a valid item to breed with for this animal.
|
||||||
|
*/
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
// This is what it defaults to. OK.
|
||||||
|
return javaIdentifierStripped.equals("wheat");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
package org.geysermc.connector.entity.living.animal;
|
package org.geysermc.connector.entity.living.animal;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
||||||
|
@ -34,7 +35,15 @@ import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
||||||
import org.geysermc.connector.entity.type.EntityType;
|
import org.geysermc.connector.entity.type.EntityType;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class BeeEntity extends AnimalEntity {
|
public class BeeEntity extends AnimalEntity {
|
||||||
|
/**
|
||||||
|
* A list of all flowers. Used for feeding bees.
|
||||||
|
*/
|
||||||
|
private static final Set<String> FLOWERS = ImmutableSet.of("dandelion", "poppy", "blue_orchid", "allium", "azure_bluet",
|
||||||
|
"red_tulip", "pink_tulip", "white_tulip", "orange_tulip", "cornflower", "lily_of_the_valley", "wither_rose",
|
||||||
|
"sunflower", "lilac", "rose_bush", "peony");
|
||||||
|
|
||||||
public BeeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
public BeeEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||||
|
@ -63,4 +72,9 @@ public class BeeEntity extends AnimalEntity {
|
||||||
}
|
}
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return FLOWERS.contains(javaIdentifierStripped);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.entity.living.animal;
|
||||||
|
|
||||||
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
|
import org.geysermc.connector.entity.type.EntityType;
|
||||||
|
|
||||||
|
public class ChickenEntity extends AnimalEntity {
|
||||||
|
|
||||||
|
public ChickenEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||||
|
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.contains("seeds");
|
||||||
|
}
|
||||||
|
}
|
|
@ -52,4 +52,9 @@ public class FoxEntity extends AnimalEntity {
|
||||||
}
|
}
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.equals("sweet_berries");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,4 +47,9 @@ public class HoglinEntity extends AnimalEntity {
|
||||||
}
|
}
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.equals("crimson_fungus");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,4 +44,9 @@ public class OcelotEntity extends AnimalEntity {
|
||||||
}
|
}
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,11 @@ public class PandaEntity extends AnimalEntity {
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.equals("bamboo");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the panda's appearance, and take into consideration the recessive brown and weak traits that only show up
|
* Update the panda's appearance, and take into consideration the recessive brown and weak traits that only show up
|
||||||
* when both main and hidden genes match
|
* when both main and hidden genes match
|
||||||
|
|
|
@ -46,6 +46,11 @@ public class PigEntity extends AnimalEntity {
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("potato") || javaIdentifierStripped.equals("beetroot");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected float getDefaultMaxHealth() {
|
protected float getDefaultMaxHealth() {
|
||||||
return 10f;
|
return 10f;
|
||||||
|
|
|
@ -44,4 +44,9 @@ public class PolarBearEntity extends AnimalEntity {
|
||||||
}
|
}
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,4 +59,9 @@ public class RabbitEntity extends AnimalEntity {
|
||||||
metadata.put(EntityData.VARIANT, variant);
|
metadata.put(EntityData.VARIANT, variant);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.equals("dandelion") || javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("golden_carrot");
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -85,4 +85,9 @@ public class StriderEntity extends AnimalEntity {
|
||||||
|
|
||||||
super.updateBedrockMetadata(session);
|
super.updateBedrockMetadata(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.equals("warped_fungus");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,4 +46,9 @@ public class TurtleEntity extends AnimalEntity {
|
||||||
}
|
}
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.equals("seagrass");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
package org.geysermc.connector.entity.living.animal.horse;
|
package org.geysermc.connector.entity.living.animal.horse;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
||||||
|
@ -38,7 +39,15 @@ import org.geysermc.connector.entity.type.EntityType;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class AbstractHorseEntity extends AnimalEntity {
|
public class AbstractHorseEntity extends AnimalEntity {
|
||||||
|
/**
|
||||||
|
* A list of all foods a horse/donkey can eat on Java Edition.
|
||||||
|
* Used to display interactive tag if needed.
|
||||||
|
*/
|
||||||
|
private static final Set<String> DONKEY_AND_HORSE_FOODS = ImmutableSet.of("golden_apple", "enchanted_golden_apple",
|
||||||
|
"golden_carrot", "sugar", "apple", "wheat", "hay_block");
|
||||||
|
|
||||||
public AbstractHorseEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
public AbstractHorseEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||||
|
@ -101,4 +110,9 @@ public class AbstractHorseEntity extends AnimalEntity {
|
||||||
updateBedrockAttributes(session);
|
updateBedrockAttributes(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return DONKEY_AND_HORSE_FOODS.contains(javaIdentifierStripped);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,4 +75,9 @@ public class LlamaEntity extends ChestedHorseEntity {
|
||||||
}
|
}
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.equals("wheat") || javaIdentifierStripped.equals("hay_block");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,4 +83,9 @@ public class CatEntity extends TameableEntity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,4 +45,9 @@ public class ParrotEntity extends TameableEntity {
|
||||||
}
|
}
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
return javaIdentifierStripped.contains("seeds") || javaIdentifierStripped.equals("cookie");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,13 +26,23 @@
|
||||||
package org.geysermc.connector.entity.living.animal.tameable;
|
package org.geysermc.connector.entity.living.animal.tameable;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||||
import org.geysermc.connector.entity.type.EntityType;
|
import org.geysermc.connector.entity.type.EntityType;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class WolfEntity extends TameableEntity {
|
public class WolfEntity extends TameableEntity {
|
||||||
|
/**
|
||||||
|
* A list of all foods a wolf can eat on Java Edition.
|
||||||
|
* Used to display interactive tag or particles if needed.
|
||||||
|
*/
|
||||||
|
private static final Set<String> WOLF_FOODS = ImmutableSet.of("pufferfish", "tropical_fish", "chicken", "cooked_chicken",
|
||||||
|
"porkchop", "beef", "rabbit", "cooked_porkchop", "cooked_beef", "rotten_flesh", "mutton", "cooked_mutton",
|
||||||
|
"cooked_rabbit");
|
||||||
|
|
||||||
private byte collarColor;
|
private byte collarColor;
|
||||||
|
|
||||||
|
@ -75,4 +85,10 @@ public class WolfEntity extends TameableEntity {
|
||||||
|
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canEat(String javaIdentifierStripped) {
|
||||||
|
// Cannot be a baby to eat these foods
|
||||||
|
return WOLF_FOODS.contains(javaIdentifierStripped) && !metadata.getFlags().getFlag(EntityFlag.BABY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class AbstractSkeletonEntity extends MonsterEntity {
|
||||||
if (entityMetadata.getId() == 14) {
|
if (entityMetadata.getId() == 14) {
|
||||||
byte xd = (byte) entityMetadata.getValue();
|
byte xd = (byte) entityMetadata.getValue();
|
||||||
// A bit of a loophole so the hands get raised - set the target ID to its own ID
|
// A bit of a loophole so the hands get raised - set the target ID to its own ID
|
||||||
metadata.put(EntityData.TARGET_EID, (xd == 4) ? geyserId : 0);
|
metadata.put(EntityData.TARGET_EID, ((xd & 4) == 4) ? geyserId : 0);
|
||||||
}
|
}
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,13 +25,43 @@
|
||||||
|
|
||||||
package org.geysermc.connector.entity.living.monster.raid;
|
package org.geysermc.connector.entity.living.monster.raid;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
import org.geysermc.connector.entity.living.monster.raid.AbstractIllagerEntity;
|
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.entity.type.EntityType;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
|
||||||
public class SpellcasterIllagerEntity extends AbstractIllagerEntity {
|
public class SpellcasterIllagerEntity extends AbstractIllagerEntity {
|
||||||
|
private static final int SUMMON_VEX_PARTICLE_COLOR = (179 << 16) | (179 << 8) | 204;
|
||||||
|
private static final int ATTACK_PARTICLE_COLOR = (102 << 16) | (77 << 8) | 89;
|
||||||
|
private static final int WOLOLO_PARTICLE_COLOR = (179 << 16) | (128 << 8) | 51;
|
||||||
|
|
||||||
public SpellcasterIllagerEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
public SpellcasterIllagerEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||||
|
if (entityMetadata.getId() == 16) {
|
||||||
|
int spellType = (int) (byte) entityMetadata.getValue();
|
||||||
|
// Summon vex, attack, or wololo
|
||||||
|
metadata.getFlags().setFlag(EntityFlag.CASTING, spellType == 1 || spellType == 2 || spellType == 3);
|
||||||
|
int rgbData = 0;
|
||||||
|
// Set the spell color based on Java values
|
||||||
|
switch (spellType) {
|
||||||
|
case 1:
|
||||||
|
rgbData = SUMMON_VEX_PARTICLE_COLOR;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
rgbData = ATTACK_PARTICLE_COLOR;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
rgbData = WOLOLO_PARTICLE_COLOR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
metadata.put(EntityData.EVOKER_SPELL_COLOR, rgbData);
|
||||||
|
}
|
||||||
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.entity.living.monster.raid;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||||
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||||
|
import org.geysermc.connector.entity.type.EntityType;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
|
||||||
|
public class VindicatorEntity extends AbstractIllagerEntity {
|
||||||
|
|
||||||
|
public VindicatorEntity(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) {
|
||||||
|
// Allow the axe to be shown if necessary
|
||||||
|
if (entityMetadata.getId() == 14) {
|
||||||
|
byte xd = (byte) entityMetadata.getValue();
|
||||||
|
metadata.getFlags().setFlag(EntityFlag.ANGRY, (xd & 4) == 4);
|
||||||
|
}
|
||||||
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,10 +36,7 @@ import org.geysermc.connector.entity.living.animal.tameable.WolfEntity;
|
||||||
import org.geysermc.connector.entity.living.merchant.AbstractMerchantEntity;
|
import org.geysermc.connector.entity.living.merchant.AbstractMerchantEntity;
|
||||||
import org.geysermc.connector.entity.living.merchant.VillagerEntity;
|
import org.geysermc.connector.entity.living.merchant.VillagerEntity;
|
||||||
import org.geysermc.connector.entity.living.monster.*;
|
import org.geysermc.connector.entity.living.monster.*;
|
||||||
import org.geysermc.connector.entity.living.monster.raid.AbstractIllagerEntity;
|
import org.geysermc.connector.entity.living.monster.raid.*;
|
||||||
import org.geysermc.connector.entity.living.monster.raid.PillagerEntity;
|
|
||||||
import org.geysermc.connector.entity.living.monster.raid.RaidParticipantEntity;
|
|
||||||
import org.geysermc.connector.entity.living.monster.raid.SpellcasterIllagerEntity;
|
|
||||||
import org.geysermc.connector.entity.player.PlayerEntity;
|
import org.geysermc.connector.entity.player.PlayerEntity;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -48,7 +45,7 @@ import java.util.List;
|
||||||
@Getter
|
@Getter
|
||||||
public enum EntityType {
|
public enum EntityType {
|
||||||
|
|
||||||
CHICKEN(AnimalEntity.class, 10, 0.7f, 0.4f),
|
CHICKEN(ChickenEntity.class, 10, 0.7f, 0.4f),
|
||||||
COW(AnimalEntity.class, 11, 1.4f, 0.9f),
|
COW(AnimalEntity.class, 11, 1.4f, 0.9f),
|
||||||
PIG(PigEntity.class, 12, 0.9f),
|
PIG(PigEntity.class, 12, 0.9f),
|
||||||
SHEEP(SheepEntity.class, 13, 1.3f, 0.9f),
|
SHEEP(SheepEntity.class, 13, 1.3f, 0.9f),
|
||||||
|
@ -97,7 +94,7 @@ public enum EntityType {
|
||||||
SHULKER(ShulkerEntity.class, 54, 1f, 1f),
|
SHULKER(ShulkerEntity.class, 54, 1f, 1f),
|
||||||
ENDERMITE(MonsterEntity.class, 55, 0.3f, 0.4f),
|
ENDERMITE(MonsterEntity.class, 55, 0.3f, 0.4f),
|
||||||
AGENT(Entity.class, 56, 0f),
|
AGENT(Entity.class, 56, 0f),
|
||||||
VINDICATOR(AbstractIllagerEntity.class, 57, 1.8f, 0.6f, 0.6f, 1.62f),
|
VINDICATOR(VindicatorEntity.class, 57, 1.8f, 0.6f, 0.6f, 1.62f),
|
||||||
PILLAGER(PillagerEntity.class, 114, 1.8f, 0.6f, 0.6f, 1.62f),
|
PILLAGER(PillagerEntity.class, 114, 1.8f, 0.6f, 0.6f, 1.62f),
|
||||||
WANDERING_TRADER(AbstractMerchantEntity.class, 118, 1.8f, 0.6f, 0.6f, 1.62f),
|
WANDERING_TRADER(AbstractMerchantEntity.class, 118, 1.8f, 0.6f, 0.6f, 1.62f),
|
||||||
PHANTOM(FlyingEntity.class, 58, 0.5f, 0.9f, 0.9f, 0.6f),
|
PHANTOM(FlyingEntity.class, 58, 0.5f, 0.9f, 0.9f, 0.6f),
|
||||||
|
@ -188,7 +185,7 @@ public enum EntityType {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
List<String> allJavaIdentifiers = new ArrayList<>();
|
List<String> allJavaIdentifiers = new ArrayList<>();
|
||||||
for (EntityType type : values()) {
|
for (EntityType type : VALUES) {
|
||||||
if (type == AGENT || type == BALLOON || type == CHALKBOARD || type == NPC || type == TRIPOD_CAMERA || type == ENDER_DRAGON_PART) {
|
if (type == AGENT || type == BALLOON || type == CHALKBOARD || type == NPC || type == TRIPOD_CAMERA || type == ENDER_DRAGON_PART) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,6 +77,7 @@ import lombok.Setter;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.command.CommandSender;
|
import org.geysermc.connector.command.CommandSender;
|
||||||
import org.geysermc.connector.common.AuthType;
|
import org.geysermc.connector.common.AuthType;
|
||||||
|
import org.geysermc.connector.configuration.EmoteOffhandWorkaroundOption;
|
||||||
import org.geysermc.connector.entity.Entity;
|
import org.geysermc.connector.entity.Entity;
|
||||||
import org.geysermc.connector.entity.Tickable;
|
import org.geysermc.connector.entity.Tickable;
|
||||||
import org.geysermc.connector.entity.attribute.Attribute;
|
import org.geysermc.connector.entity.attribute.Attribute;
|
||||||
|
@ -427,9 +428,7 @@ public class GeyserSession implements CommandSender {
|
||||||
@Setter
|
@Setter
|
||||||
private boolean waitingForStatistics = false;
|
private boolean waitingForStatistics = false;
|
||||||
|
|
||||||
@Setter
|
private final Set<UUID> emotes;
|
||||||
private List<UUID> selectedEmotes = new ArrayList<>();
|
|
||||||
private final Set<UUID> emotes = new HashSet<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The thread that will run every 50 milliseconds - one Minecraft tick.
|
* The thread that will run every 50 milliseconds - one Minecraft tick.
|
||||||
|
@ -464,9 +463,14 @@ public class GeyserSession implements CommandSender {
|
||||||
this.spawned = false;
|
this.spawned = false;
|
||||||
this.loggedIn = false;
|
this.loggedIn = false;
|
||||||
|
|
||||||
// Make a copy to prevent ConcurrentModificationException
|
if (connector.getConfig().getEmoteOffhandWorkaround() != EmoteOffhandWorkaroundOption.NO_EMOTES) {
|
||||||
final List<GeyserSession> tmpPlayers = new ArrayList<>(connector.getPlayers());
|
this.emotes = new HashSet<>();
|
||||||
tmpPlayers.forEach(player -> this.emotes.addAll(player.getEmotes()));
|
// Make a copy to prevent ConcurrentModificationException
|
||||||
|
final List<GeyserSession> tmpPlayers = new ArrayList<>(connector.getPlayers());
|
||||||
|
tmpPlayers.forEach(player -> this.emotes.addAll(player.getEmotes()));
|
||||||
|
} else {
|
||||||
|
this.emotes = null;
|
||||||
|
}
|
||||||
|
|
||||||
bedrockServerSession.addDisconnectHandler(disconnectReason -> {
|
bedrockServerSession.addDisconnectHandler(disconnectReason -> {
|
||||||
InetAddress address = bedrockServerSession.getRealAddress().getAddress();
|
InetAddress address = bedrockServerSession.getRealAddress().getAddress();
|
||||||
|
@ -668,37 +672,50 @@ public class GeyserSession implements CommandSender {
|
||||||
@Override
|
@Override
|
||||||
public void packetSending(PacketSendingEvent event) {
|
public void packetSending(PacketSendingEvent event) {
|
||||||
//todo move this somewhere else
|
//todo move this somewhere else
|
||||||
if (event.getPacket() instanceof HandshakePacket && floodgate) {
|
if (event.getPacket() instanceof HandshakePacket) {
|
||||||
byte[] encryptedData;
|
String addressSuffix;
|
||||||
|
if (floodgate) {
|
||||||
|
byte[] encryptedData;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
FloodgateSkinUploader skinUploader = connector.getSkinUploader();
|
FloodgateSkinUploader skinUploader = connector.getSkinUploader();
|
||||||
FloodgateCipher cipher = connector.getCipher();
|
FloodgateCipher cipher = connector.getCipher();
|
||||||
|
|
||||||
encryptedData = cipher.encryptFromString(BedrockData.of(
|
encryptedData = cipher.encryptFromString(BedrockData.of(
|
||||||
clientData.getGameVersion(),
|
clientData.getGameVersion(),
|
||||||
authData.getName(),
|
authData.getName(),
|
||||||
authData.getXboxUUID(),
|
authData.getXboxUUID(),
|
||||||
clientData.getDeviceOs().ordinal(),
|
clientData.getDeviceOs().ordinal(),
|
||||||
clientData.getLanguageCode(),
|
clientData.getLanguageCode(),
|
||||||
clientData.getUiProfile().ordinal(),
|
clientData.getUiProfile().ordinal(),
|
||||||
clientData.getCurrentInputMode().ordinal(),
|
clientData.getCurrentInputMode().ordinal(),
|
||||||
upstream.getAddress().getAddress().getHostAddress(),
|
upstream.getAddress().getAddress().getHostAddress(),
|
||||||
skinUploader.getId(),
|
skinUploader.getId(),
|
||||||
skinUploader.getVerifyCode()
|
skinUploader.getVerifyCode()
|
||||||
).toString());
|
).toString());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.auth.floodgate.encrypt_fail"), e);
|
connector.getLogger().error(LanguageUtils.getLocaleStringLog("geyser.auth.floodgate.encrypt_fail"), e);
|
||||||
disconnect(LanguageUtils.getPlayerLocaleString("geyser.auth.floodgate.encryption_fail", getClientData().getLanguageCode()));
|
disconnect(LanguageUtils.getPlayerLocaleString("geyser.auth.floodgate.encryption_fail", getClientData().getLanguageCode()));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
addressSuffix = '\0' + new String(encryptedData, StandardCharsets.UTF_8);
|
||||||
|
} else {
|
||||||
|
addressSuffix = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
String finalDataString = new String(encryptedData, StandardCharsets.UTF_8);
|
|
||||||
|
|
||||||
HandshakePacket handshakePacket = event.getPacket();
|
HandshakePacket handshakePacket = event.getPacket();
|
||||||
|
|
||||||
|
String address;
|
||||||
|
if (connector.getConfig().getRemote().isForwardHost()) {
|
||||||
|
address = clientData.getServerAddress().split(":")[0];
|
||||||
|
} else {
|
||||||
|
address = handshakePacket.getHostname();
|
||||||
|
}
|
||||||
|
|
||||||
event.setPacket(new HandshakePacket(
|
event.setPacket(new HandshakePacket(
|
||||||
handshakePacket.getProtocolVersion(),
|
handshakePacket.getProtocolVersion(),
|
||||||
handshakePacket.getHostname() + '\0' + finalDataString,
|
address + addressSuffix,
|
||||||
handshakePacket.getPort(),
|
handshakePacket.getPort(),
|
||||||
handshakePacket.getIntent()
|
handshakePacket.getIntent()
|
||||||
));
|
));
|
||||||
|
@ -825,7 +842,7 @@ public class GeyserSession implements CommandSender {
|
||||||
/**
|
/**
|
||||||
* Called every 50 milliseconds - one Minecraft tick.
|
* Called every 50 milliseconds - one Minecraft tick.
|
||||||
*/
|
*/
|
||||||
public void tick() {
|
protected void tick() {
|
||||||
// Check to see if the player's position needs updating - a position update should be sent once every 3 seconds
|
// Check to see if the player's position needs updating - a position update should be sent once every 3 seconds
|
||||||
if (spawned && (System.currentTimeMillis() - lastMovementTimestamp) > 3000) {
|
if (spawned && (System.currentTimeMillis() - lastMovementTimestamp) > 3000) {
|
||||||
// Recalculate in case something else changed position
|
// Recalculate in case something else changed position
|
||||||
|
@ -997,7 +1014,6 @@ public class GeyserSession implements CommandSender {
|
||||||
startGamePacket.setLightningLevel(0);
|
startGamePacket.setLightningLevel(0);
|
||||||
startGamePacket.setMultiplayerGame(true);
|
startGamePacket.setMultiplayerGame(true);
|
||||||
startGamePacket.setBroadcastingToLan(true);
|
startGamePacket.setBroadcastingToLan(true);
|
||||||
startGamePacket.getGamerules().add(new GameRuleData<>("showcoordinates", connector.getConfig().isShowCoordinates()));
|
|
||||||
startGamePacket.setPlatformBroadcastMode(GamePublishSetting.PUBLIC);
|
startGamePacket.setPlatformBroadcastMode(GamePublishSetting.PUBLIC);
|
||||||
startGamePacket.setXblBroadcastMode(GamePublishSetting.PUBLIC);
|
startGamePacket.setXblBroadcastMode(GamePublishSetting.PUBLIC);
|
||||||
startGamePacket.setCommandsEnabled(!connector.getConfig().isXboxAchievementsEnabled());
|
startGamePacket.setCommandsEnabled(!connector.getConfig().isXboxAchievementsEnabled());
|
||||||
|
@ -1189,13 +1205,14 @@ public class GeyserSession implements CommandSender {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the cached value for the reduced debug info gamerule.
|
* Update the cached value for the reduced debug info gamerule.
|
||||||
* This also toggles the coordinates display
|
* If enabled, also hides the player's coordinates.
|
||||||
*
|
*
|
||||||
* @param value The new value for reducedDebugInfo
|
* @param value The new value for reducedDebugInfo
|
||||||
*/
|
*/
|
||||||
public void setReducedDebugInfo(boolean value) {
|
public void setReducedDebugInfo(boolean value) {
|
||||||
worldCache.setShowCoordinates(!value);
|
|
||||||
reducedDebugInfo = value;
|
reducedDebugInfo = value;
|
||||||
|
// Set the showCoordinates data. This is done because updateShowCoordinates() uses this gamerule as a variable.
|
||||||
|
getWorldCache().updateShowCoordinates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1281,7 +1298,6 @@ public class GeyserSession implements CommandSender {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshEmotes(List<UUID> emotes) {
|
public void refreshEmotes(List<UUID> emotes) {
|
||||||
this.selectedEmotes = emotes;
|
|
||||||
this.emotes.addAll(emotes);
|
this.emotes.addAll(emotes);
|
||||||
for (GeyserSession player : connector.getPlayers()) {
|
for (GeyserSession player : connector.getPlayers()) {
|
||||||
List<UUID> pieces = new ArrayList<>();
|
List<UUID> pieces = new ArrayList<>();
|
||||||
|
|
|
@ -28,6 +28,7 @@ package org.geysermc.connector.network.session.cache;
|
||||||
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
import org.geysermc.connector.configuration.GeyserConfiguration;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.scoreboard.Objective;
|
import org.geysermc.connector.scoreboard.Objective;
|
||||||
import org.geysermc.connector.scoreboard.Scoreboard;
|
import org.geysermc.connector.scoreboard.Scoreboard;
|
||||||
|
@ -38,7 +39,13 @@ public class WorldCache {
|
||||||
private final GeyserSession session;
|
private final GeyserSession session;
|
||||||
@Setter
|
@Setter
|
||||||
private Difficulty difficulty = Difficulty.EASY;
|
private Difficulty difficulty = Difficulty.EASY;
|
||||||
private boolean showCoordinates = true;
|
|
||||||
|
/**
|
||||||
|
* True if the client prefers being shown their coordinates, regardless if they're being shown or not.
|
||||||
|
* This will be true everytime the client joins the server because neither the client nor server store the preference permanently.
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
private boolean prefersShowCoordinates = true;
|
||||||
|
|
||||||
private Scoreboard scoreboard;
|
private Scoreboard scoreboard;
|
||||||
private final ScoreboardUpdater scoreboardUpdater;
|
private final ScoreboardUpdater scoreboardUpdater;
|
||||||
|
@ -66,12 +73,15 @@ public class WorldCache {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tell the client to hide or show the coordinates
|
* Tell the client to hide or show the coordinates.
|
||||||
*
|
*
|
||||||
* @param value True to show, false to hide
|
* If {@link #prefersShowCoordinates} is true, coordinates will be shown, unless either of the following conditions apply: <br>
|
||||||
|
* <br>
|
||||||
|
* {@link GeyserSession#reducedDebugInfo} is enabled
|
||||||
|
* {@link GeyserConfiguration#isShowCoordinates()} is disabled
|
||||||
*/
|
*/
|
||||||
public void setShowCoordinates(boolean value) {
|
public void updateShowCoordinates() {
|
||||||
showCoordinates = value;
|
boolean allowShowCoordinates = !session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates();
|
||||||
session.sendGameRule("showcoordinates", value);
|
session.sendGameRule("showcoordinates", allowShowCoordinates && prefersShowCoordinates);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -26,6 +26,7 @@
|
||||||
package org.geysermc.connector.network.translators.bedrock;
|
package org.geysermc.connector.network.translators.bedrock;
|
||||||
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.EmoteListPacket;
|
import com.nukkitx.protocol.bedrock.packet.EmoteListPacket;
|
||||||
|
import org.geysermc.connector.configuration.EmoteOffhandWorkaroundOption;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.Translator;
|
import org.geysermc.connector.network.translators.Translator;
|
||||||
|
@ -35,6 +36,10 @@ public class BedrockEmoteListTranslator extends PacketTranslator<EmoteListPacket
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(EmoteListPacket packet, GeyserSession session) {
|
public void translate(EmoteListPacket packet, GeyserSession session) {
|
||||||
|
if (session.getConnector().getConfig().getEmoteOffhandWorkaround() == EmoteOffhandWorkaroundOption.NO_EMOTES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
session.refreshEmotes(packet.getPieceIds());
|
session.refreshEmotes(packet.getPieceIds());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -321,7 +321,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||||
session.sendUpstreamPacket(openPacket);
|
session.sendUpstreamPacket(openPacket);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Vector3f vector = packet.getClickPosition();
|
Vector3f vector = packet.getClickPosition().sub(entity.getPosition());
|
||||||
ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
|
ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
|
||||||
InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking());
|
InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking());
|
||||||
ClientPlayerInteractEntityPacket interactAtPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
|
ClientPlayerInteractEntityPacket interactAtPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
|
||||||
|
@ -329,7 +329,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||||
session.sendDownstreamPacket(interactPacket);
|
session.sendDownstreamPacket(interactPacket);
|
||||||
session.sendDownstreamPacket(interactAtPacket);
|
session.sendDownstreamPacket(interactAtPacket);
|
||||||
|
|
||||||
EntitySoundInteractionHandler.handleEntityInteraction(session, vector, entity);
|
EntitySoundInteractionHandler.handleEntityInteraction(session, packet.getClickPosition(), entity);
|
||||||
break;
|
break;
|
||||||
case 1: //Attack
|
case 1: //Attack
|
||||||
if (entity.getEntityType() == EntityType.ENDER_DRAGON) {
|
if (entity.getEntityType() == EntityType.ENDER_DRAGON) {
|
||||||
|
|
|
@ -54,7 +54,7 @@ public class BedrockLecternUpdateTranslator extends PacketTranslator<LecternUpda
|
||||||
// Emulate an interact packet
|
// Emulate an interact packet
|
||||||
ClientPlayerPlaceBlockPacket blockPacket = new ClientPlayerPlaceBlockPacket(
|
ClientPlayerPlaceBlockPacket blockPacket = new ClientPlayerPlaceBlockPacket(
|
||||||
new Position(packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ()),
|
new Position(packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ()),
|
||||||
BlockFace.values()[0],
|
BlockFace.DOWN,
|
||||||
Hand.MAIN_HAND,
|
Hand.MAIN_HAND,
|
||||||
0, 0, 0, // Java doesn't care about these when dealing with a lectern
|
0, 0, 0, // Java doesn't care about these when dealing with a lectern
|
||||||
false);
|
false);
|
||||||
|
|
|
@ -25,25 +25,43 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.bedrock.entity.player;
|
package org.geysermc.connector.network.translators.bedrock.entity.player;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.EmotePacket;
|
import com.nukkitx.protocol.bedrock.packet.EmotePacket;
|
||||||
|
import org.geysermc.connector.configuration.EmoteOffhandWorkaroundOption;
|
||||||
import org.geysermc.connector.entity.Entity;
|
import org.geysermc.connector.entity.Entity;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
import org.geysermc.connector.network.translators.Translator;
|
import org.geysermc.connector.network.translators.Translator;
|
||||||
|
import org.geysermc.connector.utils.BlockUtils;
|
||||||
|
|
||||||
@Translator(packet = EmotePacket.class)
|
@Translator(packet = EmotePacket.class)
|
||||||
public class BedrockEmoteTranslator extends PacketTranslator<EmotePacket> {
|
public class BedrockEmoteTranslator extends PacketTranslator<EmotePacket> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(EmotePacket packet, GeyserSession session) {
|
public void translate(EmotePacket packet, GeyserSession session) {
|
||||||
|
if (session.getConnector().getConfig().getEmoteOffhandWorkaround() != EmoteOffhandWorkaroundOption.DISABLED) {
|
||||||
|
// Activate the workaround - we should trigger the offhand now
|
||||||
|
ClientPlayerActionPacket swapHandsPacket = new ClientPlayerActionPacket(PlayerAction.SWAP_HANDS, BlockUtils.POSITION_ZERO,
|
||||||
|
BlockFace.DOWN);
|
||||||
|
session.sendDownstreamPacket(swapHandsPacket);
|
||||||
|
|
||||||
|
if (session.getConnector().getConfig().getEmoteOffhandWorkaround() == EmoteOffhandWorkaroundOption.NO_EMOTES) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
long javaId = session.getPlayerEntity().getEntityId();
|
long javaId = session.getPlayerEntity().getEntityId();
|
||||||
for (GeyserSession otherSession : session.getConnector().getPlayers()) {
|
for (GeyserSession otherSession : session.getConnector().getPlayers()) {
|
||||||
if (otherSession != session) {
|
if (otherSession != session) {
|
||||||
if (otherSession.isClosed()) continue;
|
if (otherSession.isClosed()) continue;
|
||||||
Entity otherEntity = otherSession.getEntityCache().getEntityByJavaId(javaId);
|
Entity otherEntity = otherSession.getEntityCache().getEntityByJavaId(javaId);
|
||||||
if (otherEntity == null) continue;
|
if (otherEntity == null) continue;
|
||||||
packet.setRuntimeEntityId(otherEntity.getGeyserId());
|
EmotePacket otherEmotePacket = new EmotePacket();
|
||||||
otherSession.sendUpstreamPacket(packet);
|
otherEmotePacket.setEmoteId(packet.getEmoteId());
|
||||||
|
otherEmotePacket.setRuntimeEntityId(otherEntity.getGeyserId());
|
||||||
|
otherSession.sendUpstreamPacket(otherEmotePacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla
|
||||||
// The Bedrock index might need changed, so let's look it up and see.
|
// The Bedrock index might need changed, so let's look it up and see.
|
||||||
int bedrockIndex = value;
|
int bedrockIndex = value;
|
||||||
if (bedrockIndex != -1) {
|
if (bedrockIndex != -1) {
|
||||||
Enchantment enchantment = Enchantment.getByJavaIdentifier("minecraft:" + JavaEnchantment.values()[bedrockIndex].name().toLowerCase());
|
Enchantment enchantment = Enchantment.getByJavaIdentifier("minecraft:" + Enchantment.JavaEnchantment.of(bedrockIndex).name().toLowerCase());
|
||||||
if (enchantment != null) {
|
if (enchantment != null) {
|
||||||
// Convert the Java enchantment index to Bedrock's
|
// Convert the Java enchantment index to Bedrock's
|
||||||
bedrockIndex = enchantment.ordinal();
|
bedrockIndex = enchantment.ordinal();
|
||||||
|
@ -170,48 +170,4 @@ public class EnchantingInventoryTranslator extends AbstractBlockInventoryTransla
|
||||||
public Inventory createInventory(String name, int windowId, WindowType windowType, PlayerInventory playerInventory) {
|
public Inventory createInventory(String name, int windowId, WindowType windowType, PlayerInventory playerInventory) {
|
||||||
return new EnchantingContainer(name, windowId, this.size, windowType, playerInventory);
|
return new EnchantingContainer(name, windowId, this.size, windowType, playerInventory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Enchantments classified by their Java index
|
|
||||||
*/
|
|
||||||
public enum JavaEnchantment {
|
|
||||||
PROTECTION,
|
|
||||||
FIRE_PROTECTION,
|
|
||||||
FEATHER_FALLING,
|
|
||||||
BLAST_PROTECTION,
|
|
||||||
PROJECTILE_PROTECTION,
|
|
||||||
RESPIRATION,
|
|
||||||
AQUA_AFFINITY,
|
|
||||||
THORNS,
|
|
||||||
DEPTH_STRIDER,
|
|
||||||
FROST_WALKER,
|
|
||||||
BINDING_CURSE,
|
|
||||||
SOUL_SPEED,
|
|
||||||
SHARPNESS,
|
|
||||||
SMITE,
|
|
||||||
BANE_OF_ARTHROPODS,
|
|
||||||
KNOCKBACK,
|
|
||||||
FIRE_ASPECT,
|
|
||||||
LOOTING,
|
|
||||||
SWEEPING,
|
|
||||||
EFFICIENCY,
|
|
||||||
SILK_TOUCH,
|
|
||||||
UNBREAKING,
|
|
||||||
FORTUNE,
|
|
||||||
POWER,
|
|
||||||
PUNCH,
|
|
||||||
FLAME,
|
|
||||||
INFINITY,
|
|
||||||
LUCK_OF_THE_SEA,
|
|
||||||
LURE,
|
|
||||||
LOYALTY,
|
|
||||||
IMPALING,
|
|
||||||
RIPTIDE,
|
|
||||||
CHANNELING,
|
|
||||||
MULTISHOT,
|
|
||||||
QUICK_CHARGE,
|
|
||||||
PIERCING,
|
|
||||||
MENDING,
|
|
||||||
VANISHING_CURSE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,17 +69,7 @@ public enum Enchantment {
|
||||||
QUICK_CHARGE,
|
QUICK_CHARGE,
|
||||||
SOUL_SPEED;
|
SOUL_SPEED;
|
||||||
|
|
||||||
/**
|
private static final Enchantment[] VALUES = values();
|
||||||
* A list of all enchantment Java identifiers for use with command suggestions.
|
|
||||||
*/
|
|
||||||
public static final String[] ALL_JAVA_IDENTIFIERS;
|
|
||||||
|
|
||||||
static {
|
|
||||||
ALL_JAVA_IDENTIFIERS = new String[values().length];
|
|
||||||
for (int i = 0; i < ALL_JAVA_IDENTIFIERS.length; i++) {
|
|
||||||
ALL_JAVA_IDENTIFIERS[i] = values()[i].javaIdentifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final String javaIdentifier;
|
private final String javaIdentifier;
|
||||||
|
|
||||||
|
@ -88,7 +78,7 @@ public enum Enchantment {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Enchantment getByJavaIdentifier(String javaIdentifier) {
|
public static Enchantment getByJavaIdentifier(String javaIdentifier) {
|
||||||
for (Enchantment enchantment : Enchantment.values()) {
|
for (Enchantment enchantment : VALUES) {
|
||||||
if (enchantment.javaIdentifier.equals(javaIdentifier) || enchantment.name().toLowerCase(Locale.ENGLISH).equalsIgnoreCase(javaIdentifier)) {
|
if (enchantment.javaIdentifier.equals(javaIdentifier) || enchantment.name().toLowerCase(Locale.ENGLISH).equalsIgnoreCase(javaIdentifier)) {
|
||||||
return enchantment;
|
return enchantment;
|
||||||
}
|
}
|
||||||
|
@ -97,9 +87,71 @@ public enum Enchantment {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Enchantment getByBedrockId(int bedrockId) {
|
public static Enchantment getByBedrockId(int bedrockId) {
|
||||||
if (bedrockId >= 0 && bedrockId < Enchantment.values().length) {
|
if (bedrockId >= 0 && bedrockId < VALUES.length) {
|
||||||
return Enchantment.values()[bedrockId];
|
return VALUES[bedrockId];
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enchantments classified by their Java index
|
||||||
|
*/
|
||||||
|
public enum JavaEnchantment {
|
||||||
|
PROTECTION,
|
||||||
|
FIRE_PROTECTION,
|
||||||
|
FEATHER_FALLING,
|
||||||
|
BLAST_PROTECTION,
|
||||||
|
PROJECTILE_PROTECTION,
|
||||||
|
RESPIRATION,
|
||||||
|
AQUA_AFFINITY,
|
||||||
|
THORNS,
|
||||||
|
DEPTH_STRIDER,
|
||||||
|
FROST_WALKER,
|
||||||
|
BINDING_CURSE,
|
||||||
|
SOUL_SPEED,
|
||||||
|
SHARPNESS,
|
||||||
|
SMITE,
|
||||||
|
BANE_OF_ARTHROPODS,
|
||||||
|
KNOCKBACK,
|
||||||
|
FIRE_ASPECT,
|
||||||
|
LOOTING,
|
||||||
|
SWEEPING,
|
||||||
|
EFFICIENCY,
|
||||||
|
SILK_TOUCH,
|
||||||
|
UNBREAKING,
|
||||||
|
FORTUNE,
|
||||||
|
POWER,
|
||||||
|
PUNCH,
|
||||||
|
FLAME,
|
||||||
|
INFINITY,
|
||||||
|
LUCK_OF_THE_SEA,
|
||||||
|
LURE,
|
||||||
|
LOYALTY,
|
||||||
|
IMPALING,
|
||||||
|
RIPTIDE,
|
||||||
|
CHANNELING,
|
||||||
|
MULTISHOT,
|
||||||
|
QUICK_CHARGE,
|
||||||
|
PIERCING,
|
||||||
|
MENDING,
|
||||||
|
VANISHING_CURSE;
|
||||||
|
|
||||||
|
private static final JavaEnchantment[] VALUES = JavaEnchantment.values();
|
||||||
|
|
||||||
|
public static JavaEnchantment of(int index) {
|
||||||
|
return VALUES[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of all enchantment Java identifiers for use with command suggestions.
|
||||||
|
*/
|
||||||
|
public static final String[] ALL_JAVA_IDENTIFIERS;
|
||||||
|
|
||||||
|
static {
|
||||||
|
ALL_JAVA_IDENTIFIERS = new String[VALUES.length];
|
||||||
|
for (int i = 0; i < ALL_JAVA_IDENTIFIERS.length; i++) {
|
||||||
|
ALL_JAVA_IDENTIFIERS[i] = "minecraft:" + VALUES[i].name().toLowerCase(Locale.ENGLISH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -408,6 +408,13 @@ public class ItemRegistry {
|
||||||
"", bedrockBlockId,
|
"", bedrockBlockId,
|
||||||
stackSize);
|
stackSize);
|
||||||
}
|
}
|
||||||
|
} else if (entry.getKey().equals("minecraft:spectral_arrow") || entry.getKey().equals("minecraft:knowledge_book")) {
|
||||||
|
// These items don't exist on Java, so set up a container that indicates they should have custom names
|
||||||
|
itemEntry = new TranslatableItemEntry(
|
||||||
|
entry.getKey(), bedrockIdentifier, itemIndex, bedrockId,
|
||||||
|
entry.getValue().get("bedrock_data").intValue(),
|
||||||
|
bedrockBlockId,
|
||||||
|
stackSize);
|
||||||
} else {
|
} else {
|
||||||
itemEntry = new ItemEntry(
|
itemEntry = new ItemEntry(
|
||||||
entry.getKey(), bedrockIdentifier, itemIndex, bedrockId,
|
entry.getKey(), bedrockIdentifier, itemIndex, bedrockId,
|
||||||
|
@ -471,7 +478,6 @@ public class ItemRegistry {
|
||||||
}
|
}
|
||||||
|
|
||||||
itemNames.add("minecraft:furnace_minecart");
|
itemNames.add("minecraft:furnace_minecart");
|
||||||
itemNames.add("minecraft:spectral_arrow");
|
|
||||||
|
|
||||||
if (lodestoneCompassId == 0) {
|
if (lodestoneCompassId == 0) {
|
||||||
throw new RuntimeException("Lodestone compass not found in item palette!");
|
throw new RuntimeException("Lodestone compass not found in item palette!");
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.geysermc.connector.network.translators.ItemRemapper;
|
||||||
import org.geysermc.connector.network.translators.chat.MessageTranslator;
|
import org.geysermc.connector.network.translators.chat.MessageTranslator;
|
||||||
import org.geysermc.connector.utils.FileUtils;
|
import org.geysermc.connector.utils.FileUtils;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
import org.geysermc.connector.utils.LanguageUtils;
|
||||||
|
import org.geysermc.connector.utils.LocaleUtils;
|
||||||
import org.reflections.Reflections;
|
import org.reflections.Reflections;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -137,8 +138,6 @@ public abstract class ItemTranslator {
|
||||||
nbt.put(new IntTag("map", 0));
|
nbt.put(new IntTag("map", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemStack itemStack = new ItemStack(stack.getId(), stack.getAmount(), nbt);
|
|
||||||
|
|
||||||
if (nbt != null) {
|
if (nbt != null) {
|
||||||
for (NbtItemStackTranslator translator : NBT_TRANSLATORS) {
|
for (NbtItemStackTranslator translator : NBT_TRANSLATORS) {
|
||||||
if (translator.acceptItem(bedrockItem)) {
|
if (translator.acceptItem(bedrockItem)) {
|
||||||
|
@ -147,7 +146,9 @@ public abstract class ItemTranslator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
translateDisplayProperties(session, nbt);
|
nbt = translateDisplayProperties(session, nbt, bedrockItem);
|
||||||
|
|
||||||
|
ItemStack itemStack = new ItemStack(stack.getId(), stack.getAmount(), nbt);
|
||||||
|
|
||||||
ItemData.Builder builder;
|
ItemData.Builder builder;
|
||||||
ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.get(bedrockItem.getJavaId());
|
ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.get(bedrockItem.getJavaId());
|
||||||
|
@ -393,8 +394,20 @@ public abstract class ItemTranslator {
|
||||||
* Translates the display name of the item
|
* Translates the display name of the item
|
||||||
* @param session the Bedrock client's session
|
* @param session the Bedrock client's session
|
||||||
* @param tag the tag to translate
|
* @param tag the tag to translate
|
||||||
|
* @param itemEntry the item entry, in case it requires translation
|
||||||
|
*
|
||||||
|
* @return the new tag to use, should the current one be null
|
||||||
*/
|
*/
|
||||||
public static void translateDisplayProperties(GeyserSession session, CompoundTag tag) {
|
public static CompoundTag translateDisplayProperties(GeyserSession session, CompoundTag tag, ItemEntry itemEntry) {
|
||||||
|
return translateDisplayProperties(session, tag, itemEntry, 'f');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param translationColor if this item is not available on Java, the color that the new name should be.
|
||||||
|
* Normally, this should just be white, but for shulker boxes this should be gray.
|
||||||
|
*/
|
||||||
|
public static CompoundTag translateDisplayProperties(GeyserSession session, CompoundTag tag, ItemEntry itemEntry, char translationColor) {
|
||||||
|
boolean hasCustomName = false;
|
||||||
if (tag != null) {
|
if (tag != null) {
|
||||||
CompoundTag display = tag.get("display");
|
CompoundTag display = tag.get("display");
|
||||||
if (display != null && display.contains("Name")) {
|
if (display != null && display.contains("Name")) {
|
||||||
|
@ -405,11 +418,32 @@ public abstract class ItemTranslator {
|
||||||
|
|
||||||
// Add the new name tag
|
// Add the new name tag
|
||||||
display.put(new StringTag("Name", name));
|
display.put(new StringTag("Name", name));
|
||||||
|
// Indicate that a custom name is present
|
||||||
|
hasCustomName = true;
|
||||||
|
|
||||||
// Add to the new root tag
|
// Add to the new root tag
|
||||||
tag.put(display);
|
tag.put(display);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!hasCustomName && itemEntry instanceof TranslatableItemEntry) {
|
||||||
|
// No custom name, but we need to localize the item's name
|
||||||
|
if (tag == null) {
|
||||||
|
tag = new CompoundTag("");
|
||||||
|
}
|
||||||
|
CompoundTag display = tag.get("display");
|
||||||
|
if (display == null) {
|
||||||
|
display = new CompoundTag("display");
|
||||||
|
// Add to the new root tag
|
||||||
|
tag.put(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
String translationKey = ((TranslatableItemEntry) itemEntry).getTranslationString();
|
||||||
|
// Reset formatting since Bedrock defaults to italics
|
||||||
|
display.put(new StringTag("Name", "§r§" + translationColor + LocaleUtils.getLocaleString(translationKey, session.getLocale())));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -74,6 +74,8 @@ public enum Potion {
|
||||||
SLOW_FALLING(40),
|
SLOW_FALLING(40),
|
||||||
LONG_SLOW_FALLING(41);
|
LONG_SLOW_FALLING(41);
|
||||||
|
|
||||||
|
public static final Potion[] VALUES = values();
|
||||||
|
|
||||||
private final String javaIdentifier;
|
private final String javaIdentifier;
|
||||||
private final short bedrockId;
|
private final short bedrockId;
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ public enum Potion {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Potion getByJavaIdentifier(String javaIdentifier) {
|
public static Potion getByJavaIdentifier(String javaIdentifier) {
|
||||||
for (Potion potion : Potion.values()) {
|
for (Potion potion : VALUES) {
|
||||||
if (potion.javaIdentifier.equals(javaIdentifier)) {
|
if (potion.javaIdentifier.equals(javaIdentifier)) {
|
||||||
return potion;
|
return potion;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +94,7 @@ public enum Potion {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Potion getByBedrockId(int bedrockId) {
|
public static Potion getByBedrockId(int bedrockId) {
|
||||||
for (Potion potion : Potion.values()) {
|
for (Potion potion : VALUES) {
|
||||||
if (potion.bedrockId == bedrockId) {
|
if (potion.bedrockId == bedrockId) {
|
||||||
return potion;
|
return potion;
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ public class PotionMixRegistry {
|
||||||
// Add all types of potions as inputs
|
// Add all types of potions as inputs
|
||||||
ItemEntry fillerIngredient = ingredients.get(0);
|
ItemEntry fillerIngredient = ingredients.get(0);
|
||||||
for (ItemEntry input : inputs) {
|
for (ItemEntry input : inputs) {
|
||||||
for (Potion potion : Potion.values()) {
|
for (Potion potion : Potion.VALUES) {
|
||||||
potionMixes.add(new PotionMixData(
|
potionMixes.add(new PotionMixData(
|
||||||
input.getBedrockId(), potion.getBedrockId(),
|
input.getBedrockId(), potion.getBedrockId(),
|
||||||
fillerIngredient.getBedrockId(), fillerIngredient.getBedrockData(),
|
fillerIngredient.getBedrockId(), fillerIngredient.getBedrockData(),
|
||||||
|
|
|
@ -77,6 +77,8 @@ public enum TippedArrowPotion {
|
||||||
SLOW_FALLING(41, ArrowParticleColors.SLOW_FALLING),
|
SLOW_FALLING(41, ArrowParticleColors.SLOW_FALLING),
|
||||||
LONG_SLOW_FALLING(42, ArrowParticleColors.SLOW_FALLING);
|
LONG_SLOW_FALLING(42, ArrowParticleColors.SLOW_FALLING);
|
||||||
|
|
||||||
|
private static final TippedArrowPotion[] VALUES = values();
|
||||||
|
|
||||||
private final String javaIdentifier;
|
private final String javaIdentifier;
|
||||||
private final short bedrockId;
|
private final short bedrockId;
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +94,7 @@ public enum TippedArrowPotion {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TippedArrowPotion getByJavaIdentifier(String javaIdentifier) {
|
public static TippedArrowPotion getByJavaIdentifier(String javaIdentifier) {
|
||||||
for (TippedArrowPotion potion : TippedArrowPotion.values()) {
|
for (TippedArrowPotion potion : VALUES) {
|
||||||
if (potion.javaIdentifier.equals(javaIdentifier)) {
|
if (potion.javaIdentifier.equals(javaIdentifier)) {
|
||||||
return potion;
|
return potion;
|
||||||
}
|
}
|
||||||
|
@ -101,7 +103,7 @@ public enum TippedArrowPotion {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TippedArrowPotion getByBedrockId(int bedrockId) {
|
public static TippedArrowPotion getByBedrockId(int bedrockId) {
|
||||||
for (TippedArrowPotion potion : TippedArrowPotion.values()) {
|
for (TippedArrowPotion potion : VALUES) {
|
||||||
if (potion.bedrockId == bedrockId) {
|
if (potion.bedrockId == bedrockId) {
|
||||||
return potion;
|
return potion;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +116,7 @@ public enum TippedArrowPotion {
|
||||||
* @return the tipped arrow potion that most closely resembles that color.
|
* @return the tipped arrow potion that most closely resembles that color.
|
||||||
*/
|
*/
|
||||||
public static TippedArrowPotion getByJavaColor(int color) {
|
public static TippedArrowPotion getByJavaColor(int color) {
|
||||||
for (TippedArrowPotion potion : TippedArrowPotion.values()) {
|
for (TippedArrowPotion potion : VALUES) {
|
||||||
if (potion.javaColor == color) {
|
if (potion.javaColor == color) {
|
||||||
return potion;
|
return potion;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.network.translators.item;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used when an item should have a custom name applied, if there already isn't one.
|
||||||
|
*/
|
||||||
|
public class TranslatableItemEntry extends ItemEntry {
|
||||||
|
@Getter
|
||||||
|
private final String translationString;
|
||||||
|
|
||||||
|
public TranslatableItemEntry(String javaIdentifier, String bedrockIdentifier, int javaId, int bedrockId, int bedrockData, int bedrockBlockId, int stackSize) {
|
||||||
|
super(javaIdentifier, bedrockIdentifier, javaId, bedrockId, bedrockData, bedrockBlockId, stackSize);
|
||||||
|
this.translationString = "item." + javaIdentifier.replace(":", ".");
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,10 +28,7 @@ package org.geysermc.connector.network.translators.item.translators.nbt;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.*;
|
import com.github.steveice10.opennbt.tag.builtin.*;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.ItemRemapper;
|
import org.geysermc.connector.network.translators.ItemRemapper;
|
||||||
import org.geysermc.connector.network.translators.item.ItemEntry;
|
import org.geysermc.connector.network.translators.item.*;
|
||||||
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
|
||||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
|
||||||
import org.geysermc.connector.network.translators.item.NbtItemStackTranslator;
|
|
||||||
|
|
||||||
@ItemRemapper
|
@ItemRemapper
|
||||||
public class ShulkerBoxItemTranslator extends NbtItemStackTranslator {
|
public class ShulkerBoxItemTranslator extends NbtItemStackTranslator {
|
||||||
|
@ -54,11 +51,13 @@ public class ShulkerBoxItemTranslator extends NbtItemStackTranslator {
|
||||||
boxItemTag.put(new StringTag("Name", boxItemEntry.getBedrockIdentifier()));
|
boxItemTag.put(new StringTag("Name", boxItemEntry.getBedrockIdentifier()));
|
||||||
boxItemTag.put(new ShortTag("Damage", (short) boxItemEntry.getBedrockData()));
|
boxItemTag.put(new ShortTag("Damage", (short) boxItemEntry.getBedrockData()));
|
||||||
boxItemTag.put(new ByteTag("Count", ((ByteTag) itemData.get("Count")).getValue()));
|
boxItemTag.put(new ByteTag("Count", ((ByteTag) itemData.get("Count")).getValue()));
|
||||||
if (itemData.contains("tag")) {
|
// Only the display name is what we have interest in, so just translate that if relevant
|
||||||
// Only the display name is what we have interest in, so just translate that if relevant
|
CompoundTag displayTag = itemData.get("tag");
|
||||||
CompoundTag displayTag = itemData.get("tag");
|
if (displayTag == null && boxItemEntry instanceof TranslatableItemEntry) {
|
||||||
ItemTranslator.translateDisplayProperties(session, displayTag);
|
displayTag = new CompoundTag("tag");
|
||||||
boxItemTag.put(displayTag);
|
}
|
||||||
|
if (displayTag != null) {
|
||||||
|
boxItemTag.put(ItemTranslator.translateDisplayProperties(session, displayTag, boxItemEntry, '7'));
|
||||||
}
|
}
|
||||||
|
|
||||||
itemsList.add(boxItemTag);
|
itemsList.add(boxItemTag);
|
||||||
|
|
|
@ -249,7 +249,7 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator<ServerDeclar
|
||||||
return ItemRegistry.ITEM_NAMES;
|
return ItemRegistry.ITEM_NAMES;
|
||||||
|
|
||||||
case ITEM_ENCHANTMENT:
|
case ITEM_ENCHANTMENT:
|
||||||
return Enchantment.ALL_JAVA_IDENTIFIERS; //TODO: inventory branch use Java enums
|
return Enchantment.JavaEnchantment.ALL_JAVA_IDENTIFIERS;
|
||||||
|
|
||||||
case ENTITY_SUMMON:
|
case ENTITY_SUMMON:
|
||||||
return EntityType.ALL_JAVA_IDENTIFIERS;
|
return EntityType.ALL_JAVA_IDENTIFIERS;
|
||||||
|
|
|
@ -47,6 +47,8 @@ import java.util.List;
|
||||||
|
|
||||||
@Translator(packet = ServerJoinGamePacket.class)
|
@Translator(packet = ServerJoinGamePacket.class)
|
||||||
public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacket> {
|
public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacket> {
|
||||||
|
private static final List<SkinPart> SKIN_PART_VALUES = Arrays.asList(SkinPart.values());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(ServerJoinGamePacket packet, GeyserSession session) {
|
public void translate(ServerJoinGamePacket packet, GeyserSession session) {
|
||||||
PlayerEntity entity = session.getPlayerEntity();
|
PlayerEntity entity = session.getPlayerEntity();
|
||||||
|
@ -86,12 +88,13 @@ public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacke
|
||||||
gamerulePacket.getGameRules().add(new GameRuleData<>("doimmediaterespawn", !packet.isEnableRespawnScreen()));
|
gamerulePacket.getGameRules().add(new GameRuleData<>("doimmediaterespawn", !packet.isEnableRespawnScreen()));
|
||||||
session.sendUpstreamPacket(gamerulePacket);
|
session.sendUpstreamPacket(gamerulePacket);
|
||||||
|
|
||||||
|
session.setReducedDebugInfo(packet.isReducedDebugInfo());
|
||||||
|
|
||||||
session.setRenderDistance(packet.getViewDistance());
|
session.setRenderDistance(packet.getViewDistance());
|
||||||
|
|
||||||
// We need to send our skin parts to the server otherwise java sees us with no hat, jacket etc
|
// We need to send our skin parts to the server otherwise java sees us with no hat, jacket etc
|
||||||
String locale = session.getLocale();
|
String locale = session.getLocale();
|
||||||
List<SkinPart> skinParts = Arrays.asList(SkinPart.values());
|
ClientSettingsPacket clientSettingsPacket = new ClientSettingsPacket(locale, (byte) session.getRenderDistance(), ChatVisibility.FULL, true, SKIN_PART_VALUES, HandPreference.RIGHT_HAND);
|
||||||
ClientSettingsPacket clientSettingsPacket = new ClientSettingsPacket(locale, (byte) session.getRenderDistance(), ChatVisibility.FULL, true, skinParts, HandPreference.RIGHT_HAND);
|
|
||||||
session.sendDownstreamPacket(clientSettingsPacket);
|
session.sendDownstreamPacket(clientSettingsPacket);
|
||||||
|
|
||||||
session.sendDownstreamPacket(new ClientPluginMessagePacket("minecraft:brand", PluginMessageUtils.getGeyserBrandData()));
|
session.sendDownstreamPacket(new ClientPluginMessagePacket("minecraft:brand", PluginMessageUtils.getGeyserBrandData()));
|
||||||
|
|
|
@ -30,12 +30,14 @@ import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.inventory.ItemData;
|
||||||
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
|
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.LevelSoundEvent2Packet;
|
import com.nukkitx.protocol.bedrock.packet.LevelSoundEvent2Packet;
|
||||||
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
|
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket;
|
import com.nukkitx.protocol.bedrock.packet.SetEntityMotionPacket;
|
||||||
import org.geysermc.connector.entity.Entity;
|
import org.geysermc.connector.entity.Entity;
|
||||||
|
import org.geysermc.connector.entity.LivingEntity;
|
||||||
import org.geysermc.connector.entity.type.EntityType;
|
import org.geysermc.connector.entity.type.EntityType;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
|
@ -47,9 +49,11 @@ public class JavaEntityStatusTranslator extends PacketTranslator<ServerEntitySta
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(ServerEntityStatusPacket packet, GeyserSession session) {
|
public void translate(ServerEntityStatusPacket packet, GeyserSession session) {
|
||||||
Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
|
Entity entity;
|
||||||
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
|
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
|
||||||
entity = session.getPlayerEntity();
|
entity = session.getPlayerEntity();
|
||||||
|
} else {
|
||||||
|
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
|
||||||
}
|
}
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
return;
|
return;
|
||||||
|
@ -196,6 +200,19 @@ public class JavaEntityStatusTranslator extends PacketTranslator<ServerEntitySta
|
||||||
equipmentBreakPacket.setIdentifier("");
|
equipmentBreakPacket.setIdentifier("");
|
||||||
session.sendUpstreamPacket(equipmentBreakPacket);
|
session.sendUpstreamPacket(equipmentBreakPacket);
|
||||||
return;
|
return;
|
||||||
|
case PLAYER_SWAP_SAME_ITEM: // Not just used for players
|
||||||
|
if (entity instanceof LivingEntity) {
|
||||||
|
LivingEntity livingEntity = (LivingEntity) entity;
|
||||||
|
ItemData newMainHand = livingEntity.getOffHand();
|
||||||
|
livingEntity.setOffHand(livingEntity.getHand());
|
||||||
|
livingEntity.setHand(newMainHand);
|
||||||
|
|
||||||
|
livingEntity.updateMainHand(session);
|
||||||
|
livingEntity.updateOffHand(session);
|
||||||
|
} else {
|
||||||
|
session.getConnector().getLogger().debug("Got status message to swap hands for a non-living entity.");
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
session.sendUpstreamPacket(entityEventPacket);
|
session.sendUpstreamPacket(entityEventPacket);
|
||||||
|
|
|
@ -25,11 +25,9 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.sound;
|
package org.geysermc.connector.network.translators.sound;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
import org.geysermc.connector.inventory.GeyserItemStack;
|
import org.geysermc.connector.inventory.GeyserItemStack;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -47,6 +45,9 @@ public interface BlockSoundInteractionHandler extends SoundInteractionHandler<St
|
||||||
* @param identifier the identifier of the block
|
* @param identifier the identifier of the block
|
||||||
*/
|
*/
|
||||||
static void handleBlockInteraction(GeyserSession session, Vector3f position, String identifier) {
|
static void handleBlockInteraction(GeyserSession session, Vector3f position, String identifier) {
|
||||||
|
// If we need to get the hand identifier, only get it once and save it to a variable
|
||||||
|
String handIdentifier = null;
|
||||||
|
|
||||||
for (Map.Entry<SoundHandler, SoundInteractionHandler<?>> interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) {
|
for (Map.Entry<SoundHandler, SoundInteractionHandler<?>> interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) {
|
||||||
if (!(interactionEntry.getValue() instanceof BlockSoundInteractionHandler)) {
|
if (!(interactionEntry.getValue() instanceof BlockSoundInteractionHandler)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -66,7 +67,9 @@ public interface BlockSoundInteractionHandler extends SoundInteractionHandler<St
|
||||||
if (itemInHand.isEmpty()) {
|
if (itemInHand.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String handIdentifier = itemInHand.getItemEntry().getJavaIdentifier();
|
if (handIdentifier == null) {
|
||||||
|
handIdentifier = itemInHand.getItemEntry().getJavaIdentifier();
|
||||||
|
}
|
||||||
boolean contains = false;
|
boolean contains = false;
|
||||||
for (String itemIdentifier : interactionEntry.getKey().items()) {
|
for (String itemIdentifier : interactionEntry.getKey().items()) {
|
||||||
if (handIdentifier.contains(itemIdentifier)) {
|
if (handIdentifier.contains(itemIdentifier)) {
|
||||||
|
|
|
@ -25,12 +25,10 @@
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.sound;
|
package org.geysermc.connector.network.translators.sound;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
import org.geysermc.connector.entity.Entity;
|
import org.geysermc.connector.entity.Entity;
|
||||||
import org.geysermc.connector.inventory.GeyserItemStack;
|
import org.geysermc.connector.inventory.GeyserItemStack;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -48,6 +46,9 @@ public interface EntitySoundInteractionHandler extends SoundInteractionHandler<E
|
||||||
* @param entity the entity interacted with
|
* @param entity the entity interacted with
|
||||||
*/
|
*/
|
||||||
static void handleEntityInteraction(GeyserSession session, Vector3f position, Entity entity) {
|
static void handleEntityInteraction(GeyserSession session, Vector3f position, Entity entity) {
|
||||||
|
// If we need to get the hand identifier, only get it once and save it to a variable
|
||||||
|
String handIdentifier = null;
|
||||||
|
|
||||||
for (Map.Entry<SoundHandler, SoundInteractionHandler<?>> interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) {
|
for (Map.Entry<SoundHandler, SoundInteractionHandler<?>> interactionEntry : SoundHandlerRegistry.INTERACTION_HANDLERS.entrySet()) {
|
||||||
if (!(interactionEntry.getValue() instanceof EntitySoundInteractionHandler)) {
|
if (!(interactionEntry.getValue() instanceof EntitySoundInteractionHandler)) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -67,7 +68,10 @@ public interface EntitySoundInteractionHandler extends SoundInteractionHandler<E
|
||||||
if (itemInHand.isEmpty()) {
|
if (itemInHand.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String handIdentifier = itemInHand.getItemEntry().getJavaIdentifier();
|
if (handIdentifier == null) {
|
||||||
|
// Don't get the identifier unless we need it
|
||||||
|
handIdentifier = itemInHand.getItemEntry().getJavaIdentifier();
|
||||||
|
}
|
||||||
boolean contains = false;
|
boolean contains = false;
|
||||||
for (String itemIdentifier : interactionEntry.getKey().items()) {
|
for (String itemIdentifier : interactionEntry.getKey().items()) {
|
||||||
if (handIdentifier.contains(itemIdentifier)) {
|
if (handIdentifier.contains(itemIdentifier)) {
|
||||||
|
|
|
@ -59,7 +59,7 @@ public @interface SoundHandler {
|
||||||
* Leave empty to ignore.
|
* Leave empty to ignore.
|
||||||
*
|
*
|
||||||
* Only applies to interaction handlers that are an
|
* Only applies to interaction handlers that are an
|
||||||
* instance of {@link BlockSoundInteractionHandler}.
|
* instance of {@link EntitySoundInteractionHandler}.
|
||||||
*
|
*
|
||||||
* @return the value the item in the player's hand must contain
|
* @return the value the item in the player's hand must contain
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.geysermc.connector.network.translators.sound.BlockSoundInteractionHan
|
||||||
import org.geysermc.connector.network.translators.sound.SoundHandler;
|
import org.geysermc.connector.network.translators.sound.SoundHandler;
|
||||||
|
|
||||||
@SoundHandler(blocks = "comparator")
|
@SoundHandler(blocks = "comparator")
|
||||||
public class ComparatorSoundInteractHandler implements BlockSoundInteractionHandler {
|
public class ComparatorSoundInteractionHandler implements BlockSoundInteractionHandler {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleInteraction(GeyserSession session, Vector3f position, String identifier) {
|
public void handleInteraction(GeyserSession session, Vector3f position, String identifier) {
|
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.network.translators.sound.entity;
|
||||||
|
|
||||||
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
|
||||||
|
import org.geysermc.connector.entity.Entity;
|
||||||
|
import org.geysermc.connector.entity.living.animal.AnimalEntity;
|
||||||
|
import org.geysermc.connector.entity.living.animal.OcelotEntity;
|
||||||
|
import org.geysermc.connector.entity.living.animal.tameable.CatEntity;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.translators.sound.EntitySoundInteractionHandler;
|
||||||
|
import org.geysermc.connector.network.translators.sound.SoundHandler;
|
||||||
|
|
||||||
|
@SoundHandler
|
||||||
|
public class FeedBabySoundInteractionHandler implements EntitySoundInteractionHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleInteraction(GeyserSession session, Vector3f position, Entity entity) {
|
||||||
|
if (entity instanceof AnimalEntity && !(entity instanceof CatEntity || entity instanceof OcelotEntity)) {
|
||||||
|
String handIdentifier = session.getPlayerInventory().getItemInHand().getItemEntry().getJavaIdentifier();
|
||||||
|
boolean isBaby = entity.getMetadata().getFlags().getFlag(EntityFlag.BABY);
|
||||||
|
if (isBaby && ((AnimalEntity) entity).canEat(handIdentifier.replace("minecraft:", ""))) {
|
||||||
|
// Play the "feed child" effect
|
||||||
|
EntityEventPacket feedEvent = new EntityEventPacket();
|
||||||
|
feedEvent.setRuntimeEntityId(entity.getGeyserId());
|
||||||
|
feedEvent.setType(EntityEventType.BABY_ANIMAL_FEED);
|
||||||
|
session.sendUpstreamPacket(feedEvent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,10 +62,6 @@ public class BlockStorage {
|
||||||
return (version.getId() << 1) | (runtime ? 1 : 0);
|
return (version.getId() << 1) | (runtime ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BitArrayVersion getVersionFromHeader(byte header) {
|
|
||||||
return BitArrayVersion.get(header >> 1, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getFullBlock(int index) {
|
public int getFullBlock(int index) {
|
||||||
return this.palette.getInt(this.bitArray.get(index));
|
return this.palette.getInt(this.bitArray.get(index));
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,12 @@
|
||||||
|
|
||||||
package org.geysermc.connector.utils;
|
package org.geysermc.connector.utils;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityDataMap;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.geysermc.connector.entity.Entity;
|
import org.geysermc.connector.entity.Entity;
|
||||||
|
import org.geysermc.connector.entity.living.animal.AnimalEntity;
|
||||||
import org.geysermc.connector.entity.living.animal.horse.HorseEntity;
|
import org.geysermc.connector.entity.living.animal.horse.HorseEntity;
|
||||||
import org.geysermc.connector.entity.type.EntityType;
|
import org.geysermc.connector.entity.type.EntityType;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
@ -40,20 +40,6 @@ import java.util.EnumSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class InteractiveTagManager {
|
public class InteractiveTagManager {
|
||||||
/**
|
|
||||||
* A list of all foods a horse/donkey can eat on Java Edition.
|
|
||||||
* Used to display interactive tag if needed.
|
|
||||||
*/
|
|
||||||
private static final Set<String> DONKEY_AND_HORSE_FOODS = ImmutableSet.of("golden_apple", "enchanted_golden_apple",
|
|
||||||
"golden_carrot", "sugar", "apple", "wheat", "hay_block");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of all flowers. Used for feeding bees.
|
|
||||||
*/
|
|
||||||
private static final Set<String> FLOWERS = ImmutableSet.of("dandelion", "poppy", "blue_orchid", "allium", "azure_bluet",
|
|
||||||
"red_tulip", "pink_tulip", "white_tulip", "orange_tulip", "cornflower", "lily_of_the_valley", "wither_rose",
|
|
||||||
"sunflower", "lilac", "rose_bush", "peony");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All entity types that can be leashed on Java Edition
|
* All entity types that can be leashed on Java Edition
|
||||||
*/
|
*/
|
||||||
|
@ -66,14 +52,6 @@ public class InteractiveTagManager {
|
||||||
private static final Set<EntityType> SADDLEABLE_WHEN_TAMED_MOB_TYPES = EnumSet.of(EntityType.DONKEY, EntityType.HORSE,
|
private static final Set<EntityType> SADDLEABLE_WHEN_TAMED_MOB_TYPES = EnumSet.of(EntityType.DONKEY, EntityType.HORSE,
|
||||||
EntityType.ZOMBIE_HORSE, EntityType.MULE);
|
EntityType.ZOMBIE_HORSE, EntityType.MULE);
|
||||||
|
|
||||||
/**
|
|
||||||
* A list of all foods a wolf can eat on Java Edition.
|
|
||||||
* Used to display interactive tag if needed.
|
|
||||||
*/
|
|
||||||
private static final Set<String> WOLF_FOODS = ImmutableSet.of("pufferfish", "tropical_fish", "chicken", "cooked_chicken",
|
|
||||||
"porkchop", "beef", "rabbit", "cooked_porkchop", "cooked_beef", "rotten_flesh", "mutton", "cooked_mutton",
|
|
||||||
"cooked_rabbit");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the suggestion that the client currently has on their screen for this entity (for example, "Feed" or "Ride")
|
* Update the suggestion that the client currently has on their screen for this entity (for example, "Feed" or "Ride")
|
||||||
*
|
*
|
||||||
|
@ -85,9 +63,8 @@ public class InteractiveTagManager {
|
||||||
ItemEntry itemEntry = session.getPlayerInventory().getItemInHand().getItemEntry();
|
ItemEntry itemEntry = session.getPlayerInventory().getItemInHand().getItemEntry();
|
||||||
String javaIdentifierStripped = itemEntry.getJavaIdentifier().replace("minecraft:", "");
|
String javaIdentifierStripped = itemEntry.getJavaIdentifier().replace("minecraft:", "");
|
||||||
|
|
||||||
// TODO - in the future, update these in the metadata? So the client doesn't have to wiggle their cursor around for it to happen
|
|
||||||
// TODO - also, might be good to abstract out the eating thing. I know there will need to be food tracked for https://github.com/GeyserMC/Geyser/issues/1005 but not all food is breeding food
|
|
||||||
InteractiveTag interactiveTag = InteractiveTag.NONE;
|
InteractiveTag interactiveTag = InteractiveTag.NONE;
|
||||||
|
|
||||||
if (entityMetadata.getLong(EntityData.LEASH_HOLDER_EID) == session.getPlayerEntity().getGeyserId()) {
|
if (entityMetadata.getLong(EntityData.LEASH_HOLDER_EID) == session.getPlayerEntity().getGeyserId()) {
|
||||||
// Unleash the entity
|
// Unleash the entity
|
||||||
interactiveTag = InteractiveTag.REMOVE_LEASH;
|
interactiveTag = InteractiveTag.REMOVE_LEASH;
|
||||||
|
@ -105,31 +82,24 @@ public class InteractiveTagManager {
|
||||||
// Holding a leash and the mob is leashable for sure
|
// Holding a leash and the mob is leashable for sure
|
||||||
// (Plugins can change this behavior so that's something to look into in the far far future)
|
// (Plugins can change this behavior so that's something to look into in the far far future)
|
||||||
interactiveTag = InteractiveTag.LEASH;
|
interactiveTag = InteractiveTag.LEASH;
|
||||||
|
} else if (interactEntity instanceof AnimalEntity && ((AnimalEntity) interactEntity).canEat(javaIdentifierStripped)) {
|
||||||
|
// This animal can be fed
|
||||||
|
interactiveTag = InteractiveTag.FEED;
|
||||||
} else {
|
} else {
|
||||||
switch (interactEntity.getEntityType()) {
|
switch (interactEntity.getEntityType()) {
|
||||||
case BEE:
|
case BOAT:
|
||||||
if (FLOWERS.contains(javaIdentifierStripped)) {
|
if (interactEntity.getPassengers().size() < 2) {
|
||||||
interactiveTag = InteractiveTag.FEED;
|
interactiveTag = InteractiveTag.BOARD_BOAT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BOAT:
|
|
||||||
interactiveTag = InteractiveTag.BOARD_BOAT;
|
|
||||||
break;
|
|
||||||
case CAT:
|
case CAT:
|
||||||
if (javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon")) {
|
if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED) &&
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
} else if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED) &&
|
|
||||||
entityMetadata.getLong(EntityData.OWNER_EID) == session.getPlayerEntity().getGeyserId()) {
|
entityMetadata.getLong(EntityData.OWNER_EID) == session.getPlayerEntity().getGeyserId()) {
|
||||||
// Tamed and owned by player - can sit/stand
|
// Tamed and owned by player - can sit/stand
|
||||||
interactiveTag = entityMetadata.getFlags().getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
|
interactiveTag = entityMetadata.getFlags().getFlag(EntityFlag.SITTING) ? InteractiveTag.STAND : InteractiveTag.SIT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CHICKEN:
|
|
||||||
if (javaIdentifierStripped.contains("seeds")) {
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MOOSHROOM:
|
case MOOSHROOM:
|
||||||
// Shear the mooshroom
|
// Shear the mooshroom
|
||||||
if (javaIdentifierStripped.equals("shears")) {
|
if (javaIdentifierStripped.equals("shears")) {
|
||||||
|
@ -143,9 +113,7 @@ public class InteractiveTagManager {
|
||||||
}
|
}
|
||||||
// Fall down to COW as this works on mooshrooms
|
// Fall down to COW as this works on mooshrooms
|
||||||
case COW:
|
case COW:
|
||||||
if (javaIdentifierStripped.equals("wheat")) {
|
if (javaIdentifierStripped.equals("bucket")) {
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
} else if (javaIdentifierStripped.equals("bucket")) {
|
|
||||||
// Milk the cow
|
// Milk the cow
|
||||||
interactiveTag = InteractiveTag.MILK;
|
interactiveTag = InteractiveTag.MILK;
|
||||||
}
|
}
|
||||||
|
@ -175,69 +143,28 @@ public class InteractiveTagManager {
|
||||||
interactiveTag = InteractiveTag.OPEN_CONTAINER;
|
interactiveTag = InteractiveTag.OPEN_CONTAINER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// have another switch statement as, while these share mount attributes they don't share food
|
|
||||||
switch (interactEntity.getEntityType()) {
|
|
||||||
case LLAMA:
|
|
||||||
case TRADER_LLAMA:
|
|
||||||
if (javaIdentifierStripped.equals("wheat") || javaIdentifierStripped.equals("hay_block")) {
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DONKEY:
|
|
||||||
case HORSE:
|
|
||||||
// Undead can't eat
|
|
||||||
if (DONKEY_AND_HORSE_FOODS.contains(javaIdentifierStripped)) {
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!entityMetadata.getFlags().getFlag(EntityFlag.BABY)) {
|
if (!entityMetadata.getFlags().getFlag(EntityFlag.BABY)) {
|
||||||
// Can't ride a baby
|
// Can't ride a baby
|
||||||
if (tamed) {
|
if (tamed) {
|
||||||
interactiveTag = InteractiveTag.RIDE_HORSE;
|
interactiveTag = InteractiveTag.RIDE_HORSE;
|
||||||
} else if (itemEntry.equals(ItemEntry.AIR)) {
|
} else if (itemEntry.getJavaId() == 0) {
|
||||||
// Can't hide an untamed entity without having your hand empty
|
// Can't hide an untamed entity without having your hand empty
|
||||||
interactiveTag = InteractiveTag.MOUNT;
|
interactiveTag = InteractiveTag.MOUNT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FOX:
|
|
||||||
if (javaIdentifierStripped.equals("sweet_berries")) {
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case HOGLIN:
|
|
||||||
if (javaIdentifierStripped.equals("crimson_fungus")) {
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MINECART:
|
case MINECART:
|
||||||
interactiveTag = InteractiveTag.RIDE_MINECART;
|
if (interactEntity.getPassengers().isEmpty()) {
|
||||||
|
interactiveTag = InteractiveTag.RIDE_MINECART;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case MINECART_CHEST:
|
case MINECART_CHEST:
|
||||||
case MINECART_COMMAND_BLOCK:
|
case MINECART_COMMAND_BLOCK:
|
||||||
case MINECART_HOPPER:
|
case MINECART_HOPPER:
|
||||||
interactiveTag = InteractiveTag.OPEN_CONTAINER;
|
interactiveTag = InteractiveTag.OPEN_CONTAINER;
|
||||||
break;
|
break;
|
||||||
case OCELOT:
|
|
||||||
if (javaIdentifierStripped.equals("cod") || javaIdentifierStripped.equals("salmon")) {
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PANDA:
|
|
||||||
if (javaIdentifierStripped.equals("bamboo")) {
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PARROT:
|
|
||||||
if (javaIdentifierStripped.contains("seeds") || javaIdentifierStripped.equals("cookie")) {
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PIG:
|
case PIG:
|
||||||
if (javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("potato") || javaIdentifierStripped.equals("beetroot")) {
|
if (entityMetadata.getFlags().getFlag(EntityFlag.SADDLED)) {
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
} else if (entityMetadata.getFlags().getFlag(EntityFlag.SADDLED)) {
|
|
||||||
interactiveTag = InteractiveTag.MOUNT;
|
interactiveTag = InteractiveTag.MOUNT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -246,15 +173,8 @@ public class InteractiveTagManager {
|
||||||
interactiveTag = InteractiveTag.BARTER;
|
interactiveTag = InteractiveTag.BARTER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RABBIT:
|
|
||||||
if (javaIdentifierStripped.equals("dandelion") || javaIdentifierStripped.equals("carrot") || javaIdentifierStripped.equals("golden_carrot")) {
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SHEEP:
|
case SHEEP:
|
||||||
if (javaIdentifierStripped.equals("wheat")) {
|
if (!entityMetadata.getFlags().getFlag(EntityFlag.SHEARED)) {
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
} else if (!entityMetadata.getFlags().getFlag(EntityFlag.SHEARED)) {
|
|
||||||
if (javaIdentifierStripped.equals("shears")) {
|
if (javaIdentifierStripped.equals("shears")) {
|
||||||
// Shear the sheep
|
// Shear the sheep
|
||||||
interactiveTag = InteractiveTag.SHEAR;
|
interactiveTag = InteractiveTag.SHEAR;
|
||||||
|
@ -265,17 +185,10 @@ public class InteractiveTagManager {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case STRIDER:
|
case STRIDER:
|
||||||
if (javaIdentifierStripped.equals("warped_fungus")) {
|
if (entityMetadata.getFlags().getFlag(EntityFlag.SADDLED)) {
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
} else if (entityMetadata.getFlags().getFlag(EntityFlag.SADDLED)) {
|
|
||||||
interactiveTag = InteractiveTag.RIDE_STRIDER;
|
interactiveTag = InteractiveTag.RIDE_STRIDER;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TURTLE:
|
|
||||||
if (javaIdentifierStripped.equals("seagrass")) {
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case VILLAGER:
|
case VILLAGER:
|
||||||
if (entityMetadata.getInt(EntityData.VARIANT) != 14 && entityMetadata.getInt(EntityData.VARIANT) != 0
|
if (entityMetadata.getInt(EntityData.VARIANT) != 14 && entityMetadata.getInt(EntityData.VARIANT) != 0
|
||||||
&& entityMetadata.getFloat(EntityData.SCALE) >= 0.75f) { // Not a nitwit, has a profession and is not a baby
|
&& entityMetadata.getFloat(EntityData.SCALE) >= 0.75f) { // Not a nitwit, has a profession and is not a baby
|
||||||
|
@ -289,10 +202,6 @@ public class InteractiveTagManager {
|
||||||
if (javaIdentifierStripped.equals("bone") && !entityMetadata.getFlags().getFlag(EntityFlag.TAMED)) {
|
if (javaIdentifierStripped.equals("bone") && !entityMetadata.getFlags().getFlag(EntityFlag.TAMED)) {
|
||||||
// Bone and untamed - can tame
|
// Bone and untamed - can tame
|
||||||
interactiveTag = InteractiveTag.TAME;
|
interactiveTag = InteractiveTag.TAME;
|
||||||
} else if (WOLF_FOODS.contains(javaIdentifierStripped)) {
|
|
||||||
// Compatible food in hand - feed
|
|
||||||
// Sometimes just sits/stands when the wolf isn't hungry - there doesn't appear to be a way to fix this
|
|
||||||
interactiveTag = InteractiveTag.FEED;
|
|
||||||
} else if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED) &&
|
} else if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED) &&
|
||||||
entityMetadata.getLong(EntityData.OWNER_EID) == session.getPlayerEntity().getGeyserId()) {
|
entityMetadata.getLong(EntityData.OWNER_EID) == session.getPlayerEntity().getGeyserId()) {
|
||||||
// Tamed and owned by player - can sit/stand
|
// Tamed and owned by player - can sit/stand
|
||||||
|
|
|
@ -35,7 +35,6 @@ import org.geysermc.cumulus.component.DropdownComponent;
|
||||||
import org.geysermc.cumulus.response.CustomFormResponse;
|
import org.geysermc.cumulus.response.CustomFormResponse;
|
||||||
|
|
||||||
public class SettingsUtils {
|
public class SettingsUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a settings form for the given session and store it for later
|
* Build a settings form for the given session and store it for later
|
||||||
*
|
*
|
||||||
|
@ -48,9 +47,13 @@ public class SettingsUtils {
|
||||||
CustomForm.Builder builder = CustomForm.builder()
|
CustomForm.Builder builder = CustomForm.builder()
|
||||||
.translator(LanguageUtils::getPlayerLocaleString, language)
|
.translator(LanguageUtils::getPlayerLocaleString, language)
|
||||||
.title("geyser.settings.title.main")
|
.title("geyser.settings.title.main")
|
||||||
.iconPath("textures/ui/settings_glyph_color_2x.png")
|
.iconPath("textures/ui/settings_glyph_color_2x.png");
|
||||||
.label("geyser.settings.title.client")
|
|
||||||
.toggle("geyser.settings.option.coordinates");
|
// Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config.
|
||||||
|
if (!session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates()) {
|
||||||
|
builder.label("geyser.settings.title.client")
|
||||||
|
.toggle("geyser.settings.option.coordinates", session.getWorldCache().isPrefersShowCoordinates());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
||||||
|
@ -94,7 +97,13 @@ public class SettingsUtils {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
session.getWorldCache().setShowCoordinates(response.next());
|
// Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config.
|
||||||
|
if (!session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates()) {
|
||||||
|
response.skip(); // Client settings title
|
||||||
|
|
||||||
|
session.getWorldCache().setPrefersShowCoordinates(response.next());
|
||||||
|
session.getWorldCache().updateShowCoordinates();
|
||||||
|
}
|
||||||
|
|
||||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
||||||
GameMode gameMode = GameMode.values()[(int) response.next()];
|
GameMode gameMode = GameMode.values()[(int) response.next()];
|
||||||
|
|
|
@ -53,6 +53,9 @@ remote:
|
||||||
# 2) You run Velocity or BungeeCord with the option enabled in the proxy's main config.
|
# 2) You run Velocity or BungeeCord with the option enabled in the proxy's main config.
|
||||||
# IF YOU DON'T KNOW WHAT THIS IS, DON'T TOUCH IT!
|
# IF YOU DON'T KNOW WHAT THIS IS, DON'T TOUCH IT!
|
||||||
use-proxy-protocol: false
|
use-proxy-protocol: false
|
||||||
|
# Forward the hostname that the Bedrock client used to connect over to the Java server
|
||||||
|
# This is designed to be used for forced hosts on proxies
|
||||||
|
forward-hostname: false
|
||||||
|
|
||||||
# Floodgate uses encryption to ensure use from authorised sources.
|
# Floodgate uses encryption to ensure use from authorised sources.
|
||||||
# This should point to the public key generated by Floodgate (BungeeCord, Spigot or Velocity)
|
# This should point to the public key generated by Floodgate (BungeeCord, Spigot or Velocity)
|
||||||
|
@ -121,6 +124,13 @@ show-cooldown: title
|
||||||
# Controls if coordinates are shown to players.
|
# Controls if coordinates are shown to players.
|
||||||
show-coordinates: true
|
show-coordinates: true
|
||||||
|
|
||||||
|
# If set, when a Bedrock player performs any emote, it will swap the offhand and mainhand items, just like the Java Edition keybind
|
||||||
|
# There are three options this can be set to:
|
||||||
|
# disabled - the default/fallback, which doesn't apply this workaround
|
||||||
|
# no-emotes - emotes will NOT be sent to other Bedrock clients and offhand will be swapped. This effectively disables all emotes from being seen.
|
||||||
|
# emotes-and-offhand - emotes will be sent to Bedrock clients and offhand will be swapped
|
||||||
|
emote-offhand-workaround: "disabled"
|
||||||
|
|
||||||
# The default locale if we dont have the one the client requested. Uncomment to not use the default system language.
|
# The default locale if we dont have the one the client requested. Uncomment to not use the default system language.
|
||||||
# default-locale: en_us
|
# default-locale: en_us
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue