diff --git a/.gitignore b/.gitignore
index 42797ab5..f003e014 100644
--- a/.gitignore
+++ b/.gitignore
@@ -223,4 +223,4 @@ nbdist/
### Geyser ###
config.yml
-logs/
\ No newline at end of file
+logs/
diff --git a/README.md b/README.md
index 0ec6f094..f37c1373 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-
+
[![forthebadge made-with-java](http://ForTheBadge.com/images/badges/made-with-java.svg)](https://java.com/)
@@ -15,9 +15,14 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
### Please note, this project is still a work in progress and should not be used on production.
+## Setting Up
+Please note, Geyser is **not** a plugin. Watch the video below or take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set it up.
+
+[![YouTube Video](https://img.youtube.com/vi/OmLxwl7_UzQ/0.jpg)](https://www.youtube.com/watch?v=OmLxwl7_UzQ)
+
Links:
- Website: https://geysermc.org
-- Docs: https://geysermc.org/docs
+- Docs: https://github.com/GeyserMC/Geyser/wiki
- Download: http://ci.geysermc.org
- Discord: http://discord.geysermc.org/
@@ -41,7 +46,7 @@ Links:
- [ ] Block entities
- [ ] Extra data
- [ ] Biome colors
-- [ ] Block break/place support
+- [x] Block break/place support
## Compiling
1. Clone the repo to your computer
diff --git a/connector/pom.xml b/connector/pom.xml
index 891551ce..c135c245 100644
--- a/connector/pom.xml
+++ b/connector/pom.xml
@@ -11,6 +11,7 @@
connector
+
org.geysermc
api
1.0-SNAPSHOT
diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
index 6cede858..1a192892 100644
--- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
+++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
@@ -96,6 +96,7 @@ public class GeyserConnector implements Connector {
}
private GeyserConnector() {
+
long startupTime = System.currentTimeMillis();
// Metric
@@ -159,6 +160,7 @@ public class GeyserConnector implements Connector {
metrics = new Metrics("GeyserMC", config.getMetrics().getUUID(), true, java.util.logging.Logger.getLogger(""));
metrics.addCustomChart(new Metrics.SingleLineChart("servers", () -> 1));
metrics.addCustomChart(new Metrics.SingleLineChart("players", Geyser::getPlayerCount));
+ metrics.addCustomChart(new Metrics.SimplePie("authMode", config.getRemote()::getAuthType));
}
double completeTime = (System.currentTimeMillis() - startupTime) / 1000D;
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 213ca100..b78fc227 100644
--- a/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java
+++ b/connector/src/main/java/org/geysermc/connector/configuration/GeyserConfiguration.java
@@ -25,11 +25,13 @@
package org.geysermc.connector.configuration;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import java.util.Map;
+@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
public class GeyserConfiguration {
private BedrockConfiguration bedrock;
@@ -53,4 +55,4 @@ public class GeyserConfiguration {
private boolean allowThirdPartyCapes;
private MetricInfo metrics;
-}
\ No newline at end of file
+}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java
index b0f62d62..3bb1b82c 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java
@@ -51,7 +51,7 @@ public enum EntityType {
POLAR_BEAR(28, 1.4f, 1.3f),
LLAMA(29, 1.87f, 0.9f),
PARROT(30, 0.9f, 0.5f),
- DOLPHIN(31, 0f), //TODO
+ DOLPHIN(31, 0.6f, 0.9f),
ZOMBIE(32, 1.8f, 0.6f, 0.6f, 1.62f),
CREEPER(33, 1.7f, 0.6f, 0.6f, 1.62f),
SKELETON(34, 1.8f, 0.6f, 0.6f, 1.62f),
@@ -96,6 +96,8 @@ public enum EntityType {
ENDER_CRYSTAL(71, 0f),
FIREWORK_ROCKET(72, 0f),
TRIDENT(73, 0f),
+ TURTLE(74, 0.4f, 1.2f),
+ // TODO CAT (need to figure out how to deal with baby cats) https://github.com/NukkitX/Nukkit/blob/master/src/main/java/cn/nukkit/entity/passive/EntityCat.java
SHULKER_BULLET(76, 0f),
FISHING_HOOK(77, 0f),
@@ -130,8 +132,10 @@ public enum EntityType {
BALLOON(107, 0f), //TODO
PUFFERFISH(108, 0.7f, 0.7f),
SALMON(109, 0.5f, 0.7f),
+ DROWNED(110, 1.95f, 0.6f),
TROPICAL_FISH(111, 0.6f, 0.6f),
- COD(112, 0.25f, 0.5f);
+ COD(112, 0.25f, 0.5f),
+ PANDA(113, 1.25f, 1.125f, 1.825f);
private final int type;
private final float height;
diff --git a/connector/src/main/java/org/geysermc/connector/metrics/Metrics.java b/connector/src/main/java/org/geysermc/connector/metrics/Metrics.java
index e0cd6baa..9b149ba1 100644
--- a/connector/src/main/java/org/geysermc/connector/metrics/Metrics.java
+++ b/connector/src/main/java/org/geysermc/connector/metrics/Metrics.java
@@ -81,7 +81,7 @@ public class Metrics {
* Starts the Scheduler which submits our data every 30 minutes.
*/
private void startSubmitting() {
- Geyser.getGeneralThreadPool().scheduleAtFixedRate(this::submitData, 5, 30, TimeUnit.MINUTES);
+ Geyser.getGeneralThreadPool().scheduleAtFixedRate(this::submitData, 1, 30, TimeUnit.MINUTES);
// Submit the data every 30 minutes, first time after 5 minutes to give other plugins enough time to start
// WARNING: Changing the frequency has no effect but your plugin WILL be blocked/deleted!
// WARNING: Just don't do it!
diff --git a/connector/src/main/java/org/geysermc/connector/metrics/SentryMetrics.java b/connector/src/main/java/org/geysermc/connector/metrics/SentryMetrics.java
new file mode 100644
index 00000000..88926fd5
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/metrics/SentryMetrics.java
@@ -0,0 +1,107 @@
+package org.geysermc.connector.metrics;
+
+import io.sentry.Sentry;
+import io.sentry.SentryClient;
+import io.sentry.SentryClientFactory;
+import io.sentry.context.Context;
+import io.sentry.event.BreadcrumbBuilder;
+import io.sentry.event.UserBuilder;
+
+public class SentryMetrics {
+ private static SentryClient sentry;
+
+ public static void init() {
+ /*
+ It is recommended that you use the DSN detection system, which
+ will check the environment variable "SENTRY_DSN", the Java
+ System Property "sentry.dsn", or the "sentry.properties" file
+ in your classpath. This makes it easier to provide and adjust
+ your DSN without needing to change your code. See the configuration
+ page for more information.
+ */
+ Sentry.init();
+
+ // You can also manually provide the DSN to the ``init`` method.
+ Sentry.init();
+
+ /*
+ It is possible to go around the static ``Sentry`` API, which means
+ you are responsible for making the SentryClient instance available
+ to your code.
+ */
+ sentry = SentryClientFactory.sentryClient();
+
+ SentryMetrics metrics = new SentryMetrics();
+ metrics.logWithStaticAPI();
+ metrics.logWithInstanceAPI();
+ }
+
+ /**
+ * An example method that throws an exception.
+ */
+ void unsafeMethod() {
+ throw new UnsupportedOperationException("You shouldn't call this!");
+ }
+
+ /**
+ * Examples using the (recommended) static API.
+ */
+ void logWithStaticAPI() {
+ // Note that all fields set on the context are optional. Context data is copied onto
+ // all future events in the current context (until the context is cleared).
+
+ // Record a breadcrumb in the current context. By default the last 100 breadcrumbs are kept.
+ Sentry.getContext().recordBreadcrumb(
+ new BreadcrumbBuilder().setMessage("User made an action").build()
+ );
+
+ // Set the user in the current context.
+ Sentry.getContext().setUser(
+ new UserBuilder().setEmail("hello@sentry.io").build()
+ );
+
+ // Add extra data to future events in this context.
+ Sentry.getContext().addExtra("extra", "thing");
+
+ // Add an additional tag to future events in this context.
+ Sentry.getContext().addTag("tagName", "tagValue");
+
+ /*
+ This sends a simple event to Sentry using the statically stored instance
+ that was created in the ``main`` method.
+ */
+ Sentry.capture("This is a test");
+
+ try {
+ unsafeMethod();
+ } catch (Exception e) {
+ // This sends an exception event to Sentry using the statically stored instance
+ // that was created in the ``main`` method.
+ Sentry.capture(e);
+ }
+ }
+
+ /**
+ * Examples that use the SentryClient instance directly.
+ */
+ void logWithInstanceAPI() {
+ // Retrieve the current context.
+ Context context = sentry.getContext();
+
+ // Record a breadcrumb in the current context. By default the last 100 breadcrumbs are kept.
+ context.recordBreadcrumb(new BreadcrumbBuilder().setMessage("User made an action").build());
+
+ // Set the user in the current context.
+ context.setUser(new UserBuilder().setEmail("geyser.project@gmail.com").build());
+
+ // This sends a simple event to Sentry.
+ sentry.sendMessage("This is a test");
+
+ try {
+ unsafeMethod();
+ } catch (Exception e) {
+ // This sends an exception event to Sentry.
+ sentry.sendException(e);
+ }
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
index b1165243..c4e6f92b 100644
--- a/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
+++ b/connector/src/main/java/org/geysermc/connector/network/UpstreamPacketHandler.java
@@ -127,4 +127,9 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
boolean defaultHandler(BedrockPacket packet) {
return translateAndDefault(packet);
}
+
+ @Override
+ public boolean handle(InventoryTransactionPacket packet) {
+ return translateAndDefault(packet);
+ }
}
\ No newline at end of file
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 146edefb..22d20355 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
@@ -32,6 +32,7 @@ import com.flowpowered.math.vector.Vector3i;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.auth.exception.request.RequestException;
import com.github.steveice10.mc.protocol.MinecraftProtocol;
+import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
import com.github.steveice10.packetlib.Client;
import com.github.steveice10.packetlib.event.session.ConnectedEvent;
import com.github.steveice10.packetlib.event.session.DisconnectedEvent;
@@ -63,6 +64,7 @@ import java.util.UUID;
@Getter
public class GeyserSession implements Player {
+
private final GeyserConnector connector;
private final UpstreamSession upstream;
private RemoteServer remoteServer;
@@ -92,6 +94,11 @@ public class GeyserSession implements Player {
private boolean spawned;
private boolean closed;
+ @Setter
+ private Vector3i blockDiggingPos = Vector3i.ZERO;
+ @Setter
+ private BlockFace blockDiggingFace = BlockFace.DOWN;
+
public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) {
this.connector = connector;
this.upstream = new UpstreamSession(bedrockServerSession);
@@ -290,7 +297,7 @@ public class GeyserSession implements Player {
startGamePacket.setCurrentTick(0);
startGamePacket.setEnchantmentSeed(0);
startGamePacket.setMultiplayerCorrelationId("");
- startGamePacket.setCachedPalette(Toolbox.CACHED_PALLETE);
+ startGamePacket.setCachedPalette(Toolbox.CACHED_PALLETE.copy());
startGamePacket.setItemEntries(Toolbox.ITEMS);
upstream.sendPacket(startGamePacket);
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java
index f9bb11cf..8c80ac3b 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java
@@ -28,6 +28,7 @@ package org.geysermc.connector.network.translators;
import com.github.steveice10.mc.protocol.data.game.window.WindowType;
import com.github.steveice10.mc.protocol.packet.ingame.server.*;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.*;
+import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerHealthPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerSetExperiencePacket;
@@ -53,6 +54,7 @@ import org.geysermc.connector.network.translators.inventory.InventoryTranslator;
import org.geysermc.connector.network.translators.item.ItemTranslator;
import org.geysermc.connector.network.translators.java.*;
import org.geysermc.connector.network.translators.java.entity.*;
+import org.geysermc.connector.network.translators.java.entity.player.JavaPlayerActionAckTranslator;
import org.geysermc.connector.network.translators.java.entity.player.JavaPlayerHealthTranslator;
import org.geysermc.connector.network.translators.java.entity.player.JavaPlayerPositionRotationTranslator;
import org.geysermc.connector.network.translators.java.entity.player.JavaPlayerSetExperienceTranslator;
@@ -130,6 +132,7 @@ public class TranslatorsInit {
Registry.registerJava(ServerPlayerPositionRotationPacket.class, new JavaPlayerPositionRotationTranslator());
Registry.registerJava(ServerPlayerSetExperiencePacket.class, new JavaPlayerSetExperienceTranslator());
Registry.registerJava(ServerPlayerHealthPacket.class, new JavaPlayerHealthTranslator());
+ Registry.registerJava(ServerPlayerActionAckPacket.class, new JavaPlayerActionAckTranslator());
Registry.registerJava(ServerNotifyClientPacket.class, new JavaNotifyClientTranslator());
Registry.registerJava(ServerChunkDataPacket.class, new JavaChunkDataTranslator());
@@ -146,6 +149,7 @@ public class TranslatorsInit {
Registry.registerBedrock(AnimatePacket.class, new BedrockAnimateTranslator());
Registry.registerBedrock(CommandRequestPacket.class, new BedrockCommandRequestTranslator());
+ Registry.registerBedrock(InventoryTransactionPacket.class, new BedrockInventoryTransactionTranslator());
Registry.registerBedrock(MobEquipmentPacket.class, new BedrockMobEquipmentTranslator());
Registry.registerBedrock(MovePlayerPacket.class, new BedrockMovePlayerTranslator());
Registry.registerBedrock(PlayerActionPacket.class, new BedrockActionTranslator());
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java
index d0b2989d..fdab51ba 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java
@@ -25,11 +25,14 @@
package org.geysermc.connector.network.translators.bedrock;
+import com.flowpowered.math.vector.Vector3i;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
+import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerState;
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.ClientPlayerPlaceBlockPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket;
import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket;
import org.geysermc.connector.entity.Entity;
@@ -44,6 +47,9 @@ public class BedrockActionTranslator extends PacketTranslator {
+
+ @Override
+ public void translate(InteractPacket packet, GeyserSession session) {
+ Vector3f vector = packet.getMousePosition();
+ InteractAction action;
+
+ if(packet.getAction() == 1) {
+ action = InteractAction.ATTACK;
+ } else {
+ action = InteractAction.INTERACT;
+ }
+
+ ClientPlayerInteractEntityPacket entityPacket = new ClientPlayerInteractEntityPacket((int) packet.getRuntimeEntityId(),
+ action, vector.getX(), vector.getY(), vector.getZ(), Hand.MAIN_HAND);
+
+ session.getDownstream().getSession().send(entityPacket);
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java
new file mode 100644
index 00000000..dd6b9c07
--- /dev/null
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockInventoryTransactionTranslator.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2019 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.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
+import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
+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.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket;
+import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket;
+import org.geysermc.connector.network.session.GeyserSession;
+import org.geysermc.connector.network.translators.PacketTranslator;
+
+public class BedrockInventoryTransactionTranslator extends PacketTranslator {
+
+ @Override
+ public void translate(InventoryTransactionPacket packet, GeyserSession session) {
+ switch (packet.getTransactionType()) {
+ case ITEM_USE:
+ if (packet.getActionType() == 1) {
+ ClientPlayerUseItemPacket useItemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
+ session.getDownstream().getSession().send(useItemPacket);
+ }
+ break;
+ case ITEM_RELEASE:
+ if (packet.getActionType() == 0) {
+ ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, new Position(0, 0, 0), BlockFace.DOWN);
+ session.getDownstream().getSession().send(releaseItemPacket);
+ }
+ break;
+ }
+ }
+}
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java
index 17782ec1..717b0e8e 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java
@@ -37,6 +37,7 @@ public class JavaJoinGameTranslator extends PacketTranslator {
+
+ @Override
+ public void translate(ServerPlayerActionAckPacket packet, GeyserSession session) {
+ switch (packet.getAction()) {
+ case FINISH_DIGGING:
+ UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
+ BedrockItem bedrockItem = TranslatorsInit.getBlockTranslator().getBedrockBlock(packet.getNewState());
+ updateBlockPacket.setBlockPosition(Vector3i.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()));
+ updateBlockPacket.setRuntimeId(GlobalBlockPalette.getOrCreateRuntimeId(bedrockItem.hashCode()));
+ session.getUpstream().sendPacket(updateBlockPacket);
+ break;
+ }
+ }
+}