From 0d6c3309e2aae108ba521fe074e909784a1f90f7 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Sun, 14 Jun 2020 01:01:58 +0100 Subject: [PATCH 01/13] Fix form images (#771) --- .../java/org/geysermc/common/window/button/FormImage.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/org/geysermc/common/window/button/FormImage.java b/common/src/main/java/org/geysermc/common/window/button/FormImage.java index b700b046..72579f7a 100644 --- a/common/src/main/java/org/geysermc/common/window/button/FormImage.java +++ b/common/src/main/java/org/geysermc/common/window/button/FormImage.java @@ -32,14 +32,14 @@ public class FormImage { @Getter @Setter - private FormImageType type; + private String type; @Getter @Setter private String data; public FormImage(FormImageType type, String data) { - this.type = type; + this.type = type.getName(); this.data = data; } From 649cf28399301a7e764ac4c6bffd12bf84e8b948 Mon Sep 17 00:00:00 2001 From: Sirawit Thaya <25237131+Noxturnix@users.noreply.github.com> Date: Mon, 15 Jun 2020 03:20:38 -0700 Subject: [PATCH 02/13] Fixed incorrectly arguments parsing (#773) --- .../java/org/geysermc/connector/command/CommandManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/src/main/java/org/geysermc/connector/command/CommandManager.java b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java index 88b9e795..8b1d0bc7 100644 --- a/connector/src/main/java/org/geysermc/connector/command/CommandManager.java +++ b/connector/src/main/java/org/geysermc/connector/command/CommandManager.java @@ -75,7 +75,7 @@ public abstract class CommandManager { args = new String[0]; } else { label = command.substring(0, command.indexOf(" ")).toLowerCase(); - String argLine = command.substring(command.indexOf(" " + 1)); + String argLine = command.substring(command.indexOf(" ") + 1); args = argLine.contains(" ") ? argLine.split(" ") : new String[] { argLine }; } From a6f91d5e153690c3be28132164fb835f286a423f Mon Sep 17 00:00:00 2001 From: rtm516 Date: Mon, 15 Jun 2020 19:24:52 +0100 Subject: [PATCH 03/13] Fix maps not loading in sometimes (#758) * Fix maps not loading in sometimes Adds a default map ID so the map item isnt invisible on bedrock. Respond to the MapInfoRequestPacket so the image loads on first join. * Remove debug log * Add comments --- .../network/session/GeyserSession.java | 6 ++- .../BedrockMapInfoRequestTranslator.java | 51 +++++++++++++++++++ .../translators/item/ItemTranslator.java | 22 ++++---- .../translators/nbt/MapItemTranslator.java | 5 ++ .../java/world/JavaMapDataTranslator.java | 14 ++++- 5 files changed, 87 insertions(+), 11 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestTranslator.java diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 5491d6e5..d9615e16 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -47,6 +47,8 @@ import com.nukkitx.protocol.bedrock.BedrockPacket; import com.nukkitx.protocol.bedrock.BedrockServerSession; import com.nukkitx.protocol.bedrock.data.*; import com.nukkitx.protocol.bedrock.packet.*; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2LongMap; import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import lombok.Getter; @@ -57,7 +59,6 @@ import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.command.CommandSender; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.PlayerEntity; -import org.geysermc.connector.entity.attribute.AttributeType; import org.geysermc.connector.inventory.PlayerInventory; import org.geysermc.connector.network.remote.RemoteServer; import org.geysermc.connector.network.session.auth.AuthData; @@ -108,6 +109,9 @@ public class GeyserSession implements CommandSender { @Setter private TeleportCache teleportCache; + @Getter + private final Long2ObjectMap storedMaps = new Long2ObjectOpenHashMap<>(); + /** * A map of Vector3i positions to Java entity IDs. * Used for translating Bedrock block actions to Java entity actions. diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestTranslator.java new file mode 100644 index 00000000..3c7efa18 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockMapInfoRequestTranslator.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019-2020 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.bedrock; + +import com.nukkitx.protocol.bedrock.packet.MapInfoRequestPacket; +import org.geysermc.connector.GeyserConnector; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; +import org.geysermc.connector.network.translators.Translator; + +import java.util.concurrent.TimeUnit; + +@Translator(packet = MapInfoRequestPacket.class) +public class BedrockMapInfoRequestTranslator extends PacketTranslator { + + @Override + public void translate(MapInfoRequestPacket packet, GeyserSession session) { + long mapID = packet.getUniqueMapId(); + + if (session.getStoredMaps().containsKey(mapID)) { + // Delay the packet 100ms to prevent the client from ignoring the packet + GeyserConnector.getInstance().getGeneralThreadPool().schedule(() -> { + session.sendUpstreamPacket(session.getStoredMaps().get(mapID)); + session.getStoredMaps().remove(mapID); + }, 100, TimeUnit.MILLISECONDS); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java index cb8613c8..1962f62e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/ItemTranslator.java @@ -28,8 +28,8 @@ package org.geysermc.connector.network.translators.item; import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack; import com.github.steveice10.mc.protocol.data.message.Message; -import com.nukkitx.nbt.CompoundTagBuilder; import com.github.steveice10.opennbt.tag.builtin.*; +import com.nukkitx.nbt.CompoundTagBuilder; import com.nukkitx.nbt.tag.CompoundTag; import com.nukkitx.nbt.tag.Tag; import com.nukkitx.protocol.bedrock.data.ItemData; @@ -41,11 +41,7 @@ import org.geysermc.connector.network.translators.ItemRemapper; import org.geysermc.connector.utils.MessageUtils; import org.reflections.Reflections; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; public abstract class ItemTranslator { @@ -126,12 +122,20 @@ public abstract class ItemTranslator { ItemEntry bedrockItem = ItemRegistry.getItem(stack); - ItemStack itemStack = new ItemStack(stack.getId(), stack.getAmount(), stack.getNbt() != null ? stack.getNbt().clone() : null); + com.github.steveice10.opennbt.tag.builtin.CompoundTag nbt = stack.getNbt() != null ? stack.getNbt().clone() : null; - if (itemStack.getNbt() != null) { + // This is a fallback for maps with no nbt + if (nbt == null && bedrockItem.getJavaIdentifier().equals("minecraft:filled_map")) { + nbt = new com.github.steveice10.opennbt.tag.builtin.CompoundTag(""); + nbt.put(new IntTag("map", 0)); + } + + ItemStack itemStack = new ItemStack(stack.getId(), stack.getAmount(), nbt); + + if (nbt != null) { for (NbtItemStackTranslator translator : NBT_TRANSLATORS) { if (translator.acceptItem(bedrockItem)) { - translator.translateToBedrock(itemStack.getNbt(), bedrockItem); + translator.translateToBedrock(nbt, bedrockItem); } } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java index 8c418c0f..51029b83 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/item/translators/nbt/MapItemTranslator.java @@ -57,4 +57,9 @@ public class MapItemTranslator extends NbtItemStackTranslator { itemTag.remove("map_uuid"); } } + + @Override + public boolean acceptItem(ItemEntry itemEntry) { + return itemEntry.getJavaIdentifier().equals("minecraft:filled_map"); + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java index c8be3a56..5a3ebaba 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/world/JavaMapDataTranslator.java @@ -42,6 +42,7 @@ public class JavaMapDataTranslator extends PacketTranslator @Override public void translate(ServerMapDataPacket packet, GeyserSession session) { ClientboundMapItemDataPacket mapItemDataPacket = new ClientboundMapItemDataPacket(); + boolean shouldStore = false; mapItemDataPacket.setUniqueMapId(packet.getMapId()); mapItemDataPacket.setDimensionId(session.getPlayerEntity().getDimension()); @@ -55,6 +56,11 @@ public class JavaMapDataTranslator extends PacketTranslator mapItemDataPacket.setWidth(data.getColumns()); mapItemDataPacket.setHeight(data.getRows()); + // We have a full map image, this usually only happens on spawn for the initial image + if (mapItemDataPacket.getWidth() == 128 && mapItemDataPacket.getHeight() == 128) { + shouldStore = true; + } + // Every int entry is an ABGR color int[] colors = new int[data.getData().length]; @@ -76,6 +82,12 @@ public class JavaMapDataTranslator extends PacketTranslator id++; } - session.getUpstream().getSession().sendPacket(mapItemDataPacket); + // Store the map to send when the client requests it, as bedrock expects the data after a MapInfoRequestPacket + if (shouldStore) { + session.getStoredMaps().put(mapItemDataPacket.getUniqueMapId(), mapItemDataPacket); + } + + // Send anyway just in case + session.sendUpstreamPacket(mapItemDataPacket); } } From 256c62ce88cdb20b5228c7f7ad8c2b427c9e90e5 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Tue, 16 Jun 2020 19:58:06 -0400 Subject: [PATCH 04/13] Entity (mostly rotation) fixes (#675) * Entity (mostly rotation) fixes This PR adds: - Pig health displaying. Doesn't fix pigs being able to be controlled - Entity rotation is *mostly* correct. Villagers and sitting cats still seem to be odd but the ender dragon works great. * Remove debug line * Abstract rotation updating to functions per-entity * Don't include changes from other projects * Minor improvements * Make updateRotation and updatePositionAndRotation cleaner * Javadoc --- .../geysermc/connector/entity/BoatEntity.java | 17 ++++-- .../org/geysermc/connector/entity/Entity.java | 57 ++++++++++++++++++- .../connector/entity/PaintingEntity.java | 5 ++ .../connector/entity/PlayerEntity.java | 36 ++++++++++-- .../entity/living/animal/PigEntity.java | 37 ++++++++++++ .../living/animal/tameable/CatEntity.java | 5 ++ .../merchant/AbstractMerchantEntity.java | 6 ++ .../entity/JavaEntityHeadLookTranslator.java | 24 +------- .../JavaEntityPositionRotationTranslator.java | 11 +--- .../entity/JavaEntityRotationTranslator.java | 26 +-------- .../entity/JavaEntityTeleportTranslator.java | 2 +- .../spawn/JavaSpawnEntityTranslator.java | 9 +-- 12 files changed, 166 insertions(+), 69 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java b/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java index 8f79526d..a59cd08f 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/BoatEntity.java @@ -44,19 +44,28 @@ public class BoatEntity extends Entity { private final float ROWING_SPEED = 0.05f; public BoatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { - super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation.add(0, 0, 90)); + super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation.add(90, 0, 90)); } @Override public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { - // Rotation is basically only called when entering/exiting a boat. // We don't include the rotation (y) as it causes the boat to appear sideways - super.moveAbsolute(session, position.add(0d, this.entityType.getOffset(), 0d), Vector3f.from(0, 0, rotation.getZ() + 90), isOnGround, teleported); + super.moveAbsolute(session, position.add(0d, this.entityType.getOffset(), 0d), Vector3f.from(rotation.getX() + 90, 0, rotation.getX() + 90), isOnGround, teleported); } @Override public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) { - super.moveRelative(session, relX, relY, relZ, Vector3f.from(0, 0, rotation.getZ()), isOnGround); + super.moveRelative(session, relX, relY, relZ, Vector3f.from(rotation.getX(), 0, rotation.getX()), isOnGround); + } + + @Override + public void updatePositionAndRotation(GeyserSession session, double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) { + moveRelative(session, moveX, moveY, moveZ, yaw + 90, pitch, isOnGround); + } + + @Override + public void updateRotation(GeyserSession session, float yaw, float pitch, boolean isOnGround) { + moveRelative(session, 0, 0, 0, Vector3f.from(yaw + 90, 0, 0), isOnGround); } @Override diff --git a/connector/src/main/java/org/geysermc/connector/entity/Entity.java b/connector/src/main/java/org/geysermc/connector/entity/Entity.java index c5fcde9e..d5ae391c 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/Entity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/Entity.java @@ -78,6 +78,11 @@ public class Entity { */ protected Vector3f rotation; + /** + * Saves if the entity should be on the ground. Otherwise entities like parrots are flapping when rotating + */ + protected boolean onGround; + protected float scale = 1; protected EntityType entityType; @@ -150,11 +155,12 @@ public class Entity { } public void moveRelative(GeyserSession session, double relX, double relY, double relZ, float yaw, float pitch, boolean isOnGround) { - moveRelative(session, relX, relY, relZ, Vector3f.from(yaw, pitch, yaw), isOnGround); + moveRelative(session, relX, relY, relZ, Vector3f.from(yaw, pitch, this.rotation.getZ()), isOnGround); } public void moveRelative(GeyserSession session, double relX, double relY, double relZ, Vector3f rotation, boolean isOnGround) { setRotation(rotation); + setOnGround(isOnGround); this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ); MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); @@ -168,12 +174,13 @@ public class Entity { } public void moveAbsolute(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround, boolean teleported) { - moveAbsolute(session, position, Vector3f.from(yaw, pitch, yaw), isOnGround, teleported); + moveAbsolute(session, position, Vector3f.from(yaw, pitch, this.rotation.getZ()), isOnGround, teleported); } public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) { setPosition(position); setRotation(rotation); + setOnGround(isOnGround); MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); moveEntityPacket.setRuntimeEntityId(geyserId); @@ -185,6 +192,52 @@ public class Entity { session.sendUpstreamPacket(moveEntityPacket); } + /** + * Teleports an entity to a new location. Used in JavaEntityTeleportTranslator. + * @param session GeyserSession. + * @param position The new position of the entity. + * @param yaw The new yaw of the entity. + * @param pitch The new pitch of the entity. + * @param isOnGround Whether the entity is currently on the ground. + */ + public void teleport(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround) { + moveAbsolute(session, position, yaw, pitch, isOnGround, false); + } + + /** + * Updates an entity's head position. Used in JavaEntityHeadLookTranslator. + * @param session GeyserSession. + * @param headYaw The new head rotation of the entity. + */ + public void updateHeadLookRotation(GeyserSession session, float headYaw) { + moveRelative(session, 0, 0, 0, Vector3f.from(headYaw, rotation.getY(), rotation.getZ()), onGround); + } + + /** + * Updates an entity's position and rotation. Used in JavaEntityPositionRotationTranslator. + * @param session GeyserSession + * @param moveX The new X offset of the current position. + * @param moveY The new Y offset of the current position. + * @param moveZ The new Z offset of the current position. + * @param yaw The new yaw of the entity. + * @param pitch The new pitch of the entity. + * @param isOnGround Whether the entity is currently on the ground. + */ + public void updatePositionAndRotation(GeyserSession session, double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) { + moveRelative(session, moveX, moveY, moveZ, Vector3f.from(rotation.getX(), pitch, yaw), isOnGround); + } + + /** + * Updates an entity's rotation. Used in JavaEntityRotationTranslator. + * @param session GeyserSession. + * @param yaw The new yaw of the entity. + * @param pitch The new pitch of the entity. + * @param isOnGround Whether the entity is currently on the ground. + */ + public void updateRotation(GeyserSession session, float yaw, float pitch, boolean isOnGround) { + updatePositionAndRotation(session, 0, 0, 0, yaw, pitch, isOnGround); + } + public void updateBedrockAttributes(GeyserSession session) { if (!valid) return; diff --git a/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java index 1711fd38..00cfc8b5 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PaintingEntity.java @@ -62,6 +62,11 @@ public class PaintingEntity extends Entity { session.getConnector().getLogger().debug("Spawned painting on " + position); } + @Override + public void updateHeadLookRotation(GeyserSession session, float headYaw) { + // Do nothing, as head look messes up paintings + } + public Vector3f fixOffset(boolean toBedrock) { if (toBedrock) { Vector3f position = super.position; diff --git a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java index aa7848da..594f139a 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/PlayerEntity.java @@ -57,7 +57,6 @@ public class PlayerEntity extends LivingEntity { private String username; private long lastSkinUpdate = -1; private boolean playerList = true; - private boolean onGround; private final EntityEffectCache effectCache; private Entity leftParrot; @@ -144,7 +143,7 @@ public class PlayerEntity extends LivingEntity { setPosition(position); setRotation(rotation); - this.onGround = isOnGround; + setOnGround(isOnGround); MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); movePlayerPacket.setRuntimeEntityId(geyserId); @@ -171,7 +170,7 @@ public class PlayerEntity extends LivingEntity { setRotation(rotation); this.position = Vector3f.from(position.getX() + relX, position.getY() + relY, position.getZ() + relZ); - this.onGround = isOnGround; + setOnGround(isOnGround); MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); movePlayerPacket.setRuntimeEntityId(geyserId); @@ -188,6 +187,35 @@ public class PlayerEntity extends LivingEntity { } } + @Override + public void updateHeadLookRotation(GeyserSession session, float headYaw) { + moveRelative(session, 0, 0, 0, Vector3f.from(rotation.getX(), rotation.getY(), headYaw), onGround); + MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); + movePlayerPacket.setRuntimeEntityId(geyserId); + movePlayerPacket.setPosition(position); + movePlayerPacket.setRotation(getBedrockRotation()); + movePlayerPacket.setMode(MovePlayerPacket.Mode.ROTATION); + session.sendUpstreamPacket(movePlayerPacket); + } + + @Override + public void updatePositionAndRotation(GeyserSession session, double moveX, double moveY, double moveZ, float yaw, float pitch, boolean isOnGround) { + moveRelative(session, moveX, moveY, moveZ, yaw, pitch, isOnGround); + } + + @Override + public void updateRotation(GeyserSession session, float yaw, float pitch, boolean isOnGround) { + super.updateRotation(session, yaw, pitch, isOnGround); + // Both packets need to be sent or else player head rotation isn't correctly updated + MovePlayerPacket movePlayerPacket = new MovePlayerPacket(); + movePlayerPacket.setRuntimeEntityId(geyserId); + movePlayerPacket.setPosition(position); + movePlayerPacket.setRotation(getBedrockRotation()); + movePlayerPacket.setOnGround(isOnGround); + movePlayerPacket.setMode(MovePlayerPacket.Mode.ROTATION); + session.sendUpstreamPacket(movePlayerPacket); + } + @Override public void setPosition(Vector3f position) { this.position = position.add(0, entityType.getOffset(), 0); @@ -227,7 +255,7 @@ public class PlayerEntity extends LivingEntity { } // Parrot occupying shoulder - if (entityMetadata.getId() == 18 || entityMetadata.getId() == 19) { + if ((entityMetadata.getId() == 18 && leftParrot == null) || (entityMetadata.getId() == 19 && rightParrot == null)) { // null check since this code just creates the parrot CompoundTag tag = (CompoundTag) entityMetadata.getValue(); if (tag != null && !tag.isEmpty()) { // The parrot is a separate entity in Bedrock, but part of the player entity in Java diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java index b28ad99f..fd9fd999 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/PigEntity.java @@ -27,21 +27,58 @@ package org.geysermc.connector.entity.living.animal; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.Attribute; import com.nukkitx.protocol.bedrock.data.EntityFlag; +import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket; +import org.geysermc.connector.entity.attribute.AttributeType; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.AttributeUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; public class PigEntity extends AnimalEntity { + // For updating the pig heart visual easier + private float health = 20f; + public PigEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); } @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 8) { + health = (float) entityMetadata.getValue(); + updateBedrockAttributes(session); + } + if (entityMetadata.getId() == 16) { metadata.getFlags().setFlag(EntityFlag.SADDLED, (boolean) entityMetadata.getValue()); } super.updateBedrockMetadata(entityMetadata, session); } + + @Override + public void updateBedrockAttributes(GeyserSession session) { + if (!valid) return; + + float maxHealth = attributes.containsKey(AttributeType.MAX_HEALTH) ? attributes.get(AttributeType.MAX_HEALTH).getValue() : 20f; + + List attributesLocal = new ArrayList<>(); + for (Map.Entry entry : this.attributes.entrySet()) { + if (!entry.getValue().getType().isBedrockAttribute()) + continue; + + attributesLocal.add(AttributeUtils.getBedrockAttribute(entry.getValue())); + } + attributesLocal.add(new Attribute("minecraft:health", 0.0f, maxHealth, health, maxHealth)); + + UpdateAttributesPacket updateAttributesPacket = new UpdateAttributesPacket(); + updateAttributesPacket.setRuntimeEntityId(geyserId); + updateAttributesPacket.setAttributes(attributesLocal); + session.sendUpstreamPacket(updateAttributesPacket); + } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java index 63a67a0a..de9bcb4e 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/animal/tameable/CatEntity.java @@ -38,6 +38,11 @@ public class CatEntity extends TameableEntity { super(entityId, geyserId, entityType, position, motion, rotation); } + @Override + public void updateRotation(GeyserSession session, float yaw, float pitch, boolean isOnGround) { + moveRelative(session, 0, 0, 0, Vector3f.from(this.rotation.getX(), pitch, yaw), isOnGround); + } + @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 18) { diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/merchant/AbstractMerchantEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/merchant/AbstractMerchantEntity.java index ddeb31bd..11028b79 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/merchant/AbstractMerchantEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/merchant/AbstractMerchantEntity.java @@ -28,10 +28,16 @@ package org.geysermc.connector.entity.living.merchant; import com.nukkitx.math.vector.Vector3f; import org.geysermc.connector.entity.living.AgeableEntity; import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; public class AbstractMerchantEntity extends AgeableEntity { public AbstractMerchantEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); } + + @Override + public void teleport(GeyserSession session, Vector3f position, float yaw, float pitch, boolean isOnGround) { + super.teleport(session, position, yaw - 180, pitch, isOnGround); + } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityHeadLookTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityHeadLookTranslator.java index e26a5880..115cae55 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityHeadLookTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntityHeadLookTranslator.java @@ -25,17 +25,12 @@ package org.geysermc.connector.network.translators.java.entity; +import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityHeadLookPacket; import org.geysermc.connector.entity.Entity; -import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityHeadLookPacket; -import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; -import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket; - @Translator(packet = ServerEntityHeadLookPacket.class) public class JavaEntityHeadLookTranslator extends PacketTranslator { @@ -48,21 +43,6 @@ public class JavaEntityHeadLookTranslator extends PacketTranslator { @@ -43,10 +41,7 @@ public class JavaEntityPositionRotationTranslator extends PacketTranslator { @@ -47,23 +42,6 @@ public class JavaEntityRotationTranslator extends PacketTranslator entityConstructor = entityClass.getConstructor(long.class, long.class, org.geysermc.connector.entity.type.EntityType.class, Vector3f.class, Vector3f.class, Vector3f.class); From 9369b2020907111b9ab10da430e3e254055052cf Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Tue, 16 Jun 2020 20:03:28 -0400 Subject: [PATCH 05/13] Add 1.9+ PvP 'Cooldown' (#768) * Add 1.9+ PvP 'Cooldown' This commit adds a subtitle that acts as the Java cooldown. This is an optional feature disabled in the config with `show-cooldown`. This does not appear on plugins that use OldCombatMechanics. * No need to bump up the config version; I was just tested with OldCombatMechanics * Use simpler casting * Use session variable of lastHitTime for theoretically better performance * Reuse attribute value calculation from AttributeUtils * Remove unused imports * Revert config version update in config.yml --- .../sponge/GeyserSpongeConfiguration.java | 5 + .../configuration/GeyserConfiguration.java | 2 + .../GeyserJacksonConfiguration.java | 3 + .../network/session/GeyserSession.java | 12 ++ .../BedrockLevelSoundEventTranslator.java | 9 ++ .../BedrockMobEquipmentTranslator.java | 4 + .../JavaEntityPropertiesTranslator.java | 14 +- .../connector/utils/AttributeUtils.java | 7 +- .../connector/utils/CooldownUtils.java | 121 ++++++++++++++++++ connector/src/main/resources/config.yml | 3 + 10 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/utils/CooldownUtils.java diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java index 2b02ec0d..79e7621c 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongeConfiguration.java @@ -129,6 +129,11 @@ public class GeyserSpongeConfiguration implements GeyserConfiguration { return node.getNode("allow-third-party-ears").getBoolean(false); } + @Override + public boolean isShowCooldown() { + return node.getNode("show-cooldown").getBoolean(true); + } + @Override public String getDefaultLocale() { return node.getNode("default-locale").getString("en_us"); diff --git a/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java b/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java index 8e59644e..5ea942c1 100644 --- a/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java @@ -62,6 +62,8 @@ public interface GeyserConfiguration { boolean isAllowThirdPartyEars(); + boolean isShowCooldown(); + String getDefaultLocale(); Path getFloodgateKeyFile(); diff --git a/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java b/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java index a1d0db21..576e5ed0 100644 --- a/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java +++ b/connector/src/main/java/org/geysermc/connector/configuration/GeyserJacksonConfiguration.java @@ -75,6 +75,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration @JsonProperty("allow-third-party-capes") private boolean allowThirdPartyCapes; + @JsonProperty("show-cooldown") + private boolean showCooldown = true; + @JsonProperty("allow-third-party-ears") private boolean allowThirdPartyEars; diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index d9615e16..d2b87af1 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -179,6 +179,18 @@ public class GeyserSession implements CommandSender { @Setter private long lastInteractedVillagerEid; + /** + * The current attack speed of the player. Used for sending proper cooldown timings. + */ + @Setter + private double attackSpeed; + /** + * The time of the last hit. Used to gauge how long the cooldown is taking. + * This is a session variable in order to prevent more scheduled threads than necessary. + */ + @Setter + private long lastHitTime; + private MinecraftProtocol protocol; public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockLevelSoundEventTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockLevelSoundEventTranslator.java index 6395f0a1..08ad10bf 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockLevelSoundEventTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockLevelSoundEventTranslator.java @@ -25,10 +25,12 @@ package org.geysermc.connector.network.translators.bedrock; +import com.nukkitx.protocol.bedrock.data.SoundEvent; import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket; import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.Translator; +import org.geysermc.connector.utils.CooldownUtils; @Translator(packet = LevelSoundEventPacket.class) public class BedrockLevelSoundEventTranslator extends PacketTranslator { @@ -37,5 +39,12 @@ public class BedrockLevelSoundEventTranslator extends PacketTranslator { @@ -47,5 +48,8 @@ public class BedrockMobEquipmentTranslator extends PacketTranslator { @Override public void translate(ServerEntityPropertiesPacket packet, GeyserSession session) { + boolean isSessionPlayer = false; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId()); if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) { entity = session.getPlayerEntity(); + isSessionPlayer = true; } if (entity == null) return; @@ -54,6 +55,13 @@ public class JavaEntityPropertiesTranslator extends PacketTranslator 20) return; // 0.0 usually happens on login and causes issues with visuals; anything above 20 means a plugin like OldCombatMechanics is being used + // Needs to be sent or no subtitle packet is recognized by the client + SetTitlePacket titlePacket = new SetTitlePacket(); + titlePacket.setType(SetTitlePacket.Type.SET_TITLE); + titlePacket.setText(" "); + session.sendUpstreamPacket(titlePacket); + session.setLastHitTime(System.currentTimeMillis()); + long lastHitTime = session.getLastHitTime(); // Used later to prevent multiple scheduled cooldown threads + computeCooldown(session, lastHitTime); + } + + /** + * Keeps updating the cooldown until the bar is complete. + * @param session GeyserSession + * @param lastHitTime The time of the last hit. Used to gauge how long the cooldown is taking. + */ + private static void computeCooldown(GeyserSession session, long lastHitTime) { + if (session.isClosed()) return; // Don't run scheduled tasks if the client left + if (lastHitTime != session.getLastHitTime()) return; // Means another cooldown has started so there's no need to continue this one + SetTitlePacket titlePacket = new SetTitlePacket(); + titlePacket.setType(SetTitlePacket.Type.SET_SUBTITLE); + titlePacket.setText(getTitle(session)); + titlePacket.setFadeInTime(0); + titlePacket.setFadeOutTime(5); + titlePacket.setStayTime(2); + session.sendUpstreamPacket(titlePacket); + if (hasCooldown(session)) { + session.getConnector().getGeneralThreadPool().schedule(() -> computeCooldown(session, lastHitTime), 50, TimeUnit.MILLISECONDS); // Updated per tick. 1000 divided by 20 ticks equals 50 + } else { + SetTitlePacket removeTitlePacket = new SetTitlePacket(); + removeTitlePacket.setType(SetTitlePacket.Type.SET_SUBTITLE); + removeTitlePacket.setText(" "); + session.sendUpstreamPacket(removeTitlePacket); + } + } + + private static boolean hasCooldown(GeyserSession session) { + long time = System.currentTimeMillis() - session.getLastHitTime(); + double cooldown = restrain(((double) time) * session.getAttackSpeed() / 1000d, 1.5); + return cooldown < 1.1; + } + + + private static double restrain(double x, double max) { + if (x < 0d) + return 0d; + return Math.min(x, max); + } + + private static String getTitle(GeyserSession session) { + long time = System.currentTimeMillis() - session.getLastHitTime(); + double cooldown = restrain(((double) time) * session.getAttackSpeed() / 1000d, 1); + + int darkGrey = (int) Math.floor(10d * cooldown); + int grey = 10 - darkGrey; + StringBuilder builder = new StringBuilder("§8"); + while (darkGrey > 0) { + builder.append("˙"); + darkGrey--; + } + builder.append("§7"); + while (grey > 0) { + builder.append("˙"); + grey--; + } + return builder.toString(); + } + +} diff --git a/connector/src/main/resources/config.yml b/connector/src/main/resources/config.yml index 931e0a8d..a68f32a1 100644 --- a/connector/src/main/resources/config.yml +++ b/connector/src/main/resources/config.yml @@ -74,6 +74,9 @@ allow-third-party-capes: true # MinecraftCapes allow-third-party-ears: false +# Allow a fake cooldown indicator to be sent. Bedrock players do not see a cooldown as they still use 1.8 combat +show-cooldown: true + # The default locale if we dont have the one the client requested default-locale: en_us From 6388a91587d27052a3441749162d5621affffdd6 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Tue, 16 Jun 2020 20:05:39 -0400 Subject: [PATCH 06/13] Reset color instead of turning color to white for standalone (#759) Allows non-black-back terminals to see the Geyser log. --- .../geysermc/platform/standalone/GeyserStandaloneLogger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java index ffb252b2..7102d206 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneLogger.java @@ -82,7 +82,7 @@ public class GeyserStandaloneLogger extends SimpleTerminalConsole implements org @Override public void info(String message) { - log.info(printConsole(ChatColor.WHITE + message, colored)); + log.info(printConsole(ChatColor.RESET + ChatColor.BOLD + message, colored)); } @Override From 38ee19a32a02fecf0a58ab7776c9c2d770d1c7a3 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Thu, 18 Jun 2020 00:03:52 +0100 Subject: [PATCH 07/13] Fix toggle component json generation (#777) --- .../geysermc/common/window/component/ToggleComponent.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/common/src/main/java/org/geysermc/common/window/component/ToggleComponent.java b/common/src/main/java/org/geysermc/common/window/component/ToggleComponent.java index 50a5c631..f972d590 100644 --- a/common/src/main/java/org/geysermc/common/window/component/ToggleComponent.java +++ b/common/src/main/java/org/geysermc/common/window/component/ToggleComponent.java @@ -25,9 +25,17 @@ package org.geysermc.common.window.component; +import lombok.Getter; +import lombok.Setter; + public class ToggleComponent extends FormComponent { + @Getter + @Setter private String text; + + @Getter + @Setter private boolean defaultValue; public ToggleComponent(String text) { From 5eb7c9d1dcd4b5d4294b1256039c85dc4d9d9cdd Mon Sep 17 00:00:00 2001 From: rtm516 Date: Fri, 19 Jun 2020 13:50:10 +0100 Subject: [PATCH 08/13] Add a setter to the auth type to allow for changing at runtime (#784) This is mainly for GeyserConnect but may be useful in other cases --- .../src/main/java/org/geysermc/connector/GeyserConnector.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java index abd48bc2..d201656a 100644 --- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java +++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java @@ -31,6 +31,7 @@ import com.nukkitx.protocol.bedrock.BedrockPacketCodec; import com.nukkitx.protocol.bedrock.BedrockServer; import com.nukkitx.protocol.bedrock.v390.Bedrock_v390; import lombok.Getter; +import lombok.Setter; import org.geysermc.common.AuthType; import org.geysermc.common.PlatformType; import org.geysermc.connector.bootstrap.GeyserBootstrap; @@ -79,6 +80,7 @@ public class GeyserConnector { private static GeyserConnector instance; private RemoteServer remoteServer; + @Setter private AuthType authType; private boolean shuttingDown = false; From effd7602af673acbc36ebbdd5da65828ed6f4266 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Fri, 19 Jun 2020 14:39:40 -0400 Subject: [PATCH 09/13] Clarify Bedrock remote address change (#787) There's no reason for most users to try changing this. --- connector/src/main/resources/config.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connector/src/main/resources/config.yml b/connector/src/main/resources/config.yml index a68f32a1..e0e0771d 100644 --- a/connector/src/main/resources/config.yml +++ b/connector/src/main/resources/config.yml @@ -8,7 +8,8 @@ # -------------------------------- bedrock: - # The IP address that will listen for connections + # The IP address that will listen for connections. + # There is no reason to change this unless you want to limit what IPs can connect to your server. address: 0.0.0.0 # The port that will listen for connections port: 19132 From 100d7b77598d6710d52944d5fbd385cd13df5969 Mon Sep 17 00:00:00 2001 From: Camotoy <20743703+DoctorMacc@users.noreply.github.com> Date: Sat, 20 Jun 2020 13:44:40 -0400 Subject: [PATCH 10/13] Add villager interactive tag (#788) * Add villager interactive tag This adds a button/controller guide for villager trading, if the villager is able to trade. * Use a broader variable for metadata --- .../bedrock/BedrockInteractTranslator.java | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInteractTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInteractTranslator.java index bfd4a90a..84fb309e 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInteractTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInteractTranslator.java @@ -26,6 +26,7 @@ package org.geysermc.connector.network.translators.bedrock; import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityDataMap; import com.nukkitx.protocol.bedrock.data.EntityFlag; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; @@ -74,33 +75,43 @@ public class BedrockInteractTranslator extends PacketTranslator Entity interactEntity = session.getEntityCache().getEntityByGeyserId(packet.getRuntimeEntityId()); if (interactEntity == null) return; + EntityDataMap entityMetadata = interactEntity.getMetadata(); String interactiveTag; switch (interactEntity.getEntityType()) { - case PIG: - if (interactEntity.getMetadata().getFlags().getFlag(EntityFlag.SADDLED)) { - interactiveTag = "action.interact.mount"; - } else interactiveTag = ""; + case BOAT: + interactiveTag = "action.interact.ride.boat"; break; - case HORSE: - case SKELETON_HORSE: - case ZOMBIE_HORSE: case DONKEY: - case MULE: + case HORSE: case LLAMA: + case MULE: + case SKELETON_HORSE: case TRADER_LLAMA: - if (interactEntity.getMetadata().getFlags().getFlag(EntityFlag.TAMED)) { + case ZOMBIE_HORSE: + if (entityMetadata.getFlags().getFlag(EntityFlag.TAMED)) { interactiveTag = "action.interact.ride.horse"; } else { interactiveTag = "action.interact.mount"; } break; - case BOAT: - interactiveTag = "action.interact.ride.boat"; - break; case MINECART: interactiveTag = "action.interact.ride.minecart"; break; + case PIG: + if (entityMetadata.getFlags().getFlag(EntityFlag.SADDLED)) { + interactiveTag = "action.interact.mount"; + } else interactiveTag = ""; + break; + case VILLAGER: + 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 + interactiveTag = "action.interact.trade"; + } else interactiveTag = ""; + break; + case WANDERING_TRADER: + interactiveTag = "action.interact.trade"; // Since you can always trade with a wandering villager, presumably. + break; default: return; // No need to process any further since there is no interactive tag } From e66f57f9f056b8585ddb7e3693e1b7507d8316ef Mon Sep 17 00:00:00 2001 From: bundabrg Date: Sun, 21 Jun 2020 01:54:40 +0800 Subject: [PATCH 11/13] Provide a platform independent method of retrieving the datafolder (#769) * Provide a platform independent method of retrieving the datafolder * LocaleUtils now uses datafolder * Make use of Path instead of File Changes: * Rename getDataFolder() to getConfigFile() and update to return a Path in each bootstrap * Rename filePath to tmpFilePath * Update Velocity configFile to configFile Path --- .../platform/bukkit/GeyserBukkitPlugin.java | 7 +++++++ .../platform/bungeecord/GeyserBungeePlugin.java | 6 ++++++ .../platform/sponge/GeyserSpongePlugin.java | 6 ++++++ .../standalone/GeyserStandaloneBootstrap.java | 8 ++++++++ .../platform/velocity/GeyserVelocityPlugin.java | 17 +++++++++++------ .../connector/bootstrap/GeyserBootstrap.java | 9 +++++++++ .../geysermc/connector/utils/LocaleUtils.java | 15 +++++++++------ 7 files changed, 56 insertions(+), 12 deletions(-) diff --git a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java index 52893fc8..3a13777b 100644 --- a/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java +++ b/bootstrap/bukkit/src/main/java/org/geysermc/platform/bukkit/GeyserBukkitPlugin.java @@ -44,6 +44,7 @@ import us.myles.ViaVersion.api.Via; import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.UUID; import java.util.logging.Level; @@ -154,6 +155,11 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { return this.geyserWorldManager; } + @Override + public Path getConfigFolder() { + return getDataFolder().toPath(); + } + public boolean isCompatible(String version, String whichVersion) { int[] currentVersion = parseVersion(version); int[] otherVersion = parseVersion(whichVersion); @@ -187,4 +193,5 @@ public class GeyserBukkitPlugin extends JavaPlugin implements GeyserBootstrap { } return temp; } + } diff --git a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java index 24793839..1cf519c0 100644 --- a/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java +++ b/bootstrap/bungeecord/src/main/java/org/geysermc/platform/bungeecord/GeyserBungeePlugin.java @@ -44,6 +44,7 @@ import org.geysermc.platform.bungeecord.command.GeyserBungeeCommandManager; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; +import java.nio.file.Path; import java.util.UUID; import java.util.logging.Level; @@ -134,4 +135,9 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap { public IGeyserPingPassthrough getGeyserPingPassthrough() { return geyserBungeePingPassthrough; } + + @Override + public Path getConfigFolder() { + return getDataFolder().toPath(); + } } diff --git a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java index 2288fc67..c5f13b58 100644 --- a/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java +++ b/bootstrap/sponge/src/main/java/org/geysermc/platform/sponge/GeyserSpongePlugin.java @@ -50,6 +50,7 @@ import org.spongepowered.api.plugin.Plugin; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; +import java.nio.file.Path; import java.util.UUID; @Plugin(id = "geyser", name = GeyserConnector.NAME + "-Sponge", version = GeyserConnector.VERSION, url = "https://geysermc.org", authors = "GeyserMC") @@ -147,6 +148,11 @@ public class GeyserSpongePlugin implements GeyserBootstrap { return geyserSpongePingPassthrough; } + @Override + public Path getConfigFolder() { + return configDir.toPath(); + } + @Listener public void onServerStart(GameStartedServerEvent event) { onEnable(); diff --git a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java index a1c47238..0fca3503 100644 --- a/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java +++ b/bootstrap/standalone/src/main/java/org/geysermc/platform/standalone/GeyserStandaloneBootstrap.java @@ -37,6 +37,8 @@ import org.geysermc.platform.standalone.command.GeyserCommandManager; import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.UUID; public class GeyserStandaloneBootstrap implements GeyserBootstrap { @@ -100,4 +102,10 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap { public IGeyserPingPassthrough getGeyserPingPassthrough() { return geyserPingPassthrough; } + + @Override + public Path getConfigFolder() { + // Return the current working directory + return Paths.get(System.getProperty("user.dir")); + } } diff --git a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java index e2a4787b..5abf3c23 100644 --- a/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java +++ b/bootstrap/velocity/src/main/java/org/geysermc/platform/velocity/GeyserVelocityPlugin.java @@ -34,6 +34,7 @@ import com.velocitypowered.api.event.proxy.ProxyShutdownEvent; import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.proxy.ProxyServer; +import lombok.Getter; import org.geysermc.common.PlatformType; import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.GeyserConnector; @@ -48,6 +49,8 @@ import org.slf4j.Logger; import java.io.File; import java.io.IOException; import java.net.InetSocketAddress; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.UUID; @Plugin(id = "geyser", name = GeyserConnector.NAME + "-Velocity", version = GeyserConnector.VERSION, url = "https://geysermc.org", authors = "GeyserMC") @@ -69,14 +72,16 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { private GeyserConnector connector; + @Getter + private final Path configFolder = Paths.get("plugins/" + GeyserConnector.NAME + "-Velocity/"); + @Override public void onEnable() { - File configDir = new File("plugins/" + GeyserConnector.NAME + "-Velocity/"); - try { - if (!configDir.exists()) - configDir.mkdir(); - File configFile = FileUtils.fileOrCopiedFromResource(new File(configDir, "config.yml"), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString())); + if (!configFolder.toFile().exists()) + //noinspection ResultOfMethodCallIgnored + configFolder.toFile().mkdirs(); + File configFile = FileUtils.fileOrCopiedFromResource(configFolder.resolve("config.yml").toFile(), "config.yml", (x) -> x.replaceAll("generateduuid", UUID.randomUUID().toString())); this.geyserConfig = FileUtils.loadConfig(configFile, GeyserVelocityConfiguration.class); } catch (IOException ex) { logger.warn("Failed to read/create config.yml! Make sure it's up to date and/or readable+writable!", ex); @@ -101,7 +106,7 @@ public class GeyserVelocityPlugin implements GeyserBootstrap { return; } - geyserConfig.loadFloodgate(this, proxyServer, configDir); + geyserConfig.loadFloodgate(this, proxyServer, configFolder.toFile()); this.connector = GeyserConnector.start(PlatformType.VELOCITY, this); diff --git a/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java b/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java index 5cc6d06f..8683f80c 100644 --- a/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java +++ b/connector/src/main/java/org/geysermc/connector/bootstrap/GeyserBootstrap.java @@ -33,6 +33,8 @@ import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.network.translators.world.CachedChunkManager; import org.geysermc.connector.network.translators.world.WorldManager; +import java.nio.file.Path; + public interface GeyserBootstrap { CachedChunkManager DEFAULT_CHUNK_MANAGER = new CachedChunkManager(); @@ -83,4 +85,11 @@ public interface GeyserBootstrap { default WorldManager getWorldManager() { return DEFAULT_CHUNK_MANAGER; } + + /** + * Return the data folder where files get stored + * + * @return Path location of data folder + */ + Path getConfigFolder(); } diff --git a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java index f55cb261..e213fe6c 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java @@ -33,6 +33,7 @@ import org.geysermc.connector.GeyserConnector; import java.io.*; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.*; import java.util.zip.ZipFile; @@ -49,7 +50,8 @@ public class LocaleUtils { static { // Create the locales folder - File localesFolder = new File("locales/"); + File localesFolder = GeyserConnector.getInstance().getBootstrap().getConfigFolder().resolve("locales").toFile(); + //noinspection ResultOfMethodCallIgnored localesFolder.mkdir(); // Download the latest asset list and cache it @@ -132,7 +134,7 @@ public class LocaleUtils { * @param locale Locale to download */ private static void downloadLocale(String locale) { - File localeFile = new File("locales/" + locale + ".json"); + File localeFile = Paths.get(GeyserConnector.getInstance().getBootstrap().getConfigFolder().toString(),"locales",locale + ".json").toFile(); // Check if we have already downloaded the locale file if (localeFile.exists()) { @@ -149,7 +151,7 @@ public class LocaleUtils { // Get the hash and download the locale String hash = ASSET_MAP.get("minecraft/lang/" + locale + ".json").getHash(); - WebUtils.downloadFile("http://resources.download.minecraft.net/" + hash.substring(0, 2) + "/" + hash, "locales/" + locale + ".json"); + WebUtils.downloadFile("http://resources.download.minecraft.net/" + hash.substring(0, 2) + "/" + hash, localeFile.toString()); } /** @@ -205,10 +207,11 @@ public class LocaleUtils { GeyserConnector.getInstance().getLogger().debug("Download URL: " + smallestURL); // Download the smallest JAR (client or server) - WebUtils.downloadFile(smallestURL, "tmp_locale.jar"); + Path tmpFilePath = GeyserConnector.getInstance().getBootstrap().getConfigFolder().resolve("tmp_locale.jar"); + WebUtils.downloadFile(smallestURL, tmpFilePath.toString()); // Load in the JAR as a zip and extract the file - ZipFile localeJar = new ZipFile("tmp_locale.jar"); + ZipFile localeJar = new ZipFile(tmpFilePath.toString()); InputStream inputStream = localeJar.getInputStream(localeJar.getEntry("assets/minecraft/lang/en_us.json")); FileOutputStream outputStream = new FileOutputStream(localeFile); @@ -227,7 +230,7 @@ public class LocaleUtils { localeJar.close(); // Delete the nolonger needed client/server jar - Files.delete(Paths.get("tmp_locale.jar")); + Files.delete(tmpFilePath); } catch (Exception e) { throw new AssertionError("Unable to download and extract en_us locale!", e); } From abf04d5004ae6538a524c4ae509240d39a414aee Mon Sep 17 00:00:00 2001 From: Redned Date: Sat, 20 Jun 2020 14:35:53 -0500 Subject: [PATCH 12/13] Update logo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9878fa5a..c22c246d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Geyser +Geyser [![forthebadge made-with-java](http://ForTheBadge.com/images/badges/made-with-java.svg)](https://java.com/) From d0c95d3969e83000babc88655e0fb33452d055af Mon Sep 17 00:00:00 2001 From: Redned Date: Sat, 20 Jun 2020 14:40:12 -0500 Subject: [PATCH 13/13] Use higher res logo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c22c246d..b8f8749b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Geyser +Geyser [![forthebadge made-with-java](http://ForTheBadge.com/images/badges/made-with-java.svg)](https://java.com/)