Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-27 16:40:14 +01:00
Merge branch 'master' of https://github.com/GeyserMC/Geyser into server-inventory
Dieser Commit ist enthalten in:
Commit
1705f1034c
30
README.md
30
README.md
@ -18,7 +18,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
|
|||||||
|
|
||||||
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have now joined us here!
|
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have now joined us here!
|
||||||
|
|
||||||
### Currently supporting Minecraft Bedrock v1.16.100 and Minecraft Java v1.16.4.
|
### Currently supporting Minecraft Bedrock v1.16.100/v1.16.101/v1.16.200 and Minecraft Java v1.16.4.
|
||||||
|
|
||||||
## Setting Up
|
## Setting Up
|
||||||
Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set up Geyser.
|
Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set up Geyser.
|
||||||
@ -34,16 +34,26 @@ Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set
|
|||||||
- Test Server: `test.geysermc.org` port `25565` for Java and `19132` for Bedrock
|
- Test Server: `test.geysermc.org` port `25565` for Java and `19132` for Bedrock
|
||||||
|
|
||||||
## What's Left to be Added/Fixed
|
## What's Left to be Added/Fixed
|
||||||
- The Following Inventories
|
- Lecterns
|
||||||
- [ ] Enchantment Table (as a proper GUI)
|
- Near-perfect movement (to the point where anticheat on large servers is unlikely to ban you)
|
||||||
- [ ] Beacon
|
- Resource pack conversion/CustomModelData
|
||||||
- [ ] Cartography Table
|
|
||||||
- [ ] Stonecutter
|
|
||||||
- [ ] Structure Block
|
|
||||||
- [ ] Horse Inventory
|
|
||||||
- [ ] Loom
|
|
||||||
- [ ] Smithing Table
|
|
||||||
- Some Entity Flags
|
- Some Entity Flags
|
||||||
|
- The Following Inventories
|
||||||
|
- Enchantment Table (as a proper GUI)
|
||||||
|
- Beacon
|
||||||
|
- Cartography Table
|
||||||
|
- Stonecutter
|
||||||
|
- Structure Block
|
||||||
|
- Horse Inventory
|
||||||
|
- Loom
|
||||||
|
- Smithing Table
|
||||||
|
|
||||||
|
## What can't be fixed
|
||||||
|
The following things can't be fixed because of Bedrock limitations. They might be fixable in the future, but not as of now.
|
||||||
|
|
||||||
|
- Custom heads in inventories
|
||||||
|
- Clickable links in chat
|
||||||
|
- Glowing effect
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
1. Clone the repo to your computer
|
1. Clone the repo to your computer
|
||||||
|
@ -93,7 +93,16 @@
|
|||||||
<artifactSet>
|
<artifactSet>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>com.google.code.gson:*</exclude>
|
<exclude>com.google.code.gson:*</exclude>
|
||||||
<exclude>io.netty:*</exclude>
|
<!-- Needed because Velocity provides every dependency except netty-resolver-dns -->
|
||||||
|
<exclude>io.netty:netty-transport-native-epoll:*</exclude>
|
||||||
|
<exclude>io.netty:netty-transport-native-unix-common:*</exclude>
|
||||||
|
<exclude>io.netty:netty-transport-native-kqueue:*</exclude>
|
||||||
|
<exclude>io.netty:netty-handler:*</exclude>
|
||||||
|
<exclude>io.netty:netty-common:*</exclude>
|
||||||
|
<exclude>io.netty:netty-buffer:*</exclude>
|
||||||
|
<exclude>io.netty:netty-resolver:*</exclude>
|
||||||
|
<exclude>io.netty:netty-transport:*</exclude>
|
||||||
|
<exclude>io.netty:netty-codec:*</exclude>
|
||||||
<exclude>org.slf4j:*</exclude>
|
<exclude>org.slf4j:*</exclude>
|
||||||
<exclude>org.ow2.asm:*</exclude>
|
<exclude>org.ow2.asm:*</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
|
@ -153,19 +153,25 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-api</artifactId>
|
<artifactId>adventure-api</artifactId>
|
||||||
<version>4.2.0</version>
|
<version>4.3.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-text-serializer-gson</artifactId>
|
<artifactId>adventure-text-serializer-gson</artifactId>
|
||||||
<version>4.2.0</version>
|
<version>4.3.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.kyori</groupId>
|
<groupId>net.kyori</groupId>
|
||||||
<artifactId>adventure-text-serializer-legacy</artifactId>
|
<artifactId>adventure-text-serializer-legacy</artifactId>
|
||||||
<version>4.2.0</version>
|
<version>4.3.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.kyori</groupId>
|
||||||
|
<artifactId>adventure-text-serializer-gson-legacy-impl</artifactId>
|
||||||
|
<version>4.3.0</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -230,8 +236,12 @@
|
|||||||
</includes>
|
</includes>
|
||||||
<replacements>
|
<replacements>
|
||||||
<replacement>
|
<replacement>
|
||||||
<token>VERSION = ".*"</token>
|
<token>String VERSION = ".*"</token>
|
||||||
<value>VERSION = "${project.version} (git-${git.branch}-${git.commit.id.abbrev})"</value>
|
<value>String VERSION = "${project.version} (" + GIT_VERSION + ")"</value>
|
||||||
|
</replacement>
|
||||||
|
<replacement>
|
||||||
|
<token>String GIT_VERSION = ".*"</token>
|
||||||
|
<value>String GIT_VERSION = "git-${git.branch}-${git.commit.id.abbrev}"</value>
|
||||||
</replacement>
|
</replacement>
|
||||||
</replacements>
|
</replacements>
|
||||||
</configuration>
|
</configuration>
|
||||||
@ -249,8 +259,12 @@
|
|||||||
</includes>
|
</includes>
|
||||||
<replacements>
|
<replacements>
|
||||||
<replacement>
|
<replacement>
|
||||||
<token>VERSION = ".*"</token>
|
<token>String VERSION = ".*"</token>
|
||||||
<value>VERSION = "DEV"</value>
|
<value>String VERSION = "DEV"</value>
|
||||||
|
</replacement>
|
||||||
|
<replacement>
|
||||||
|
<token>String GIT_VERSION = ".*"</token>
|
||||||
|
<value>String GIT_VERSION = "DEV"</value>
|
||||||
</replacement>
|
</replacement>
|
||||||
</replacements>
|
</replacements>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -44,6 +44,7 @@ import org.geysermc.connector.network.session.GeyserSession;
|
|||||||
import org.geysermc.connector.network.translators.BiomeTranslator;
|
import org.geysermc.connector.network.translators.BiomeTranslator;
|
||||||
import org.geysermc.connector.network.translators.EntityIdentifierRegistry;
|
import org.geysermc.connector.network.translators.EntityIdentifierRegistry;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslatorRegistry;
|
import org.geysermc.connector.network.translators.PacketTranslatorRegistry;
|
||||||
|
import org.geysermc.connector.network.translators.collision.CollisionTranslator;
|
||||||
import org.geysermc.connector.network.translators.effect.EffectRegistry;
|
import org.geysermc.connector.network.translators.effect.EffectRegistry;
|
||||||
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
import org.geysermc.connector.network.translators.item.ItemRegistry;
|
||||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||||
@ -54,7 +55,6 @@ import org.geysermc.connector.network.translators.sound.SoundRegistry;
|
|||||||
import org.geysermc.connector.network.translators.world.WorldManager;
|
import org.geysermc.connector.network.translators.world.WorldManager;
|
||||||
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||||
import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator;
|
import org.geysermc.connector.network.translators.world.block.entity.BlockEntityTranslator;
|
||||||
import org.geysermc.connector.network.translators.collision.CollisionTranslator;
|
|
||||||
import org.geysermc.connector.network.translators.world.block.entity.SkullBlockEntityTranslator;
|
import org.geysermc.connector.network.translators.world.block.entity.SkullBlockEntityTranslator;
|
||||||
import org.geysermc.connector.utils.DimensionUtils;
|
import org.geysermc.connector.utils.DimensionUtils;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
import org.geysermc.connector.utils.LanguageUtils;
|
||||||
@ -67,10 +67,7 @@ import java.net.InetAddress;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
@ -86,6 +83,7 @@ public class GeyserConnector {
|
|||||||
.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
|
.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
|
||||||
|
|
||||||
public static final String NAME = "Geyser";
|
public static final String NAME = "Geyser";
|
||||||
|
public static final String GIT_VERSION = "DEV"; // A fallback for running in IDEs
|
||||||
public static final String VERSION = "DEV"; // A fallback for running in IDEs
|
public static final String VERSION = "DEV"; // A fallback for running in IDEs
|
||||||
|
|
||||||
private static final String IP_REGEX = "\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b";
|
private static final String IP_REGEX = "\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b";
|
||||||
@ -325,6 +323,38 @@ public class GeyserConnector {
|
|||||||
players.remove(player);
|
players.remove(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a player by their current UUID
|
||||||
|
*
|
||||||
|
* @param uuid the uuid
|
||||||
|
* @return the player or <code>null</code> if there is no player online with this UUID
|
||||||
|
*/
|
||||||
|
public GeyserSession getPlayerByUuid(UUID uuid) {
|
||||||
|
for (GeyserSession session : players) {
|
||||||
|
if (session.getPlayerEntity().getUuid().equals(uuid)) {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a player by their Xbox user identifier
|
||||||
|
*
|
||||||
|
* @param xuid the Xbox user identifier
|
||||||
|
* @return the player or <code>null</code> if there is no player online with this xuid
|
||||||
|
*/
|
||||||
|
public GeyserSession getPlayerByXuid(String xuid) {
|
||||||
|
for (GeyserSession session : players) {
|
||||||
|
if (session.getAuthData() != null && session.getAuthData().getXboxUUID().equals(xuid)) {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public static GeyserConnector start(PlatformType platformType, GeyserBootstrap bootstrap) {
|
public static GeyserConnector start(PlatformType platformType, GeyserBootstrap bootstrap) {
|
||||||
return new GeyserConnector(platformType, bootstrap);
|
return new GeyserConnector(platformType, bootstrap);
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ public abstract class CommandManager {
|
|||||||
registerCommand(new OffhandCommand(connector, "offhand", "geyser.commands.offhand.desc", "geyser.command.offhand"));
|
registerCommand(new OffhandCommand(connector, "offhand", "geyser.commands.offhand.desc", "geyser.command.offhand"));
|
||||||
registerCommand(new DumpCommand(connector, "dump", "geyser.commands.dump.desc", "geyser.command.dump"));
|
registerCommand(new DumpCommand(connector, "dump", "geyser.commands.dump.desc", "geyser.command.dump"));
|
||||||
registerCommand(new VersionCommand(connector, "version", "geyser.commands.version.desc", "geyser.command.version"));
|
registerCommand(new VersionCommand(connector, "version", "geyser.commands.version.desc", "geyser.command.version"));
|
||||||
|
registerCommand(new SettingsCommand(connector, "settings", "geyser.commands.settings.desc", "geyser.command.settings"));
|
||||||
registerCommand(new StatisticsCommand(connector, "statistics", "geyser.commands.statistics.desc", "geyser.command.statistics"));
|
registerCommand(new StatisticsCommand(connector, "statistics", "geyser.commands.statistics.desc", "geyser.command.statistics"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.command.defaults;
|
||||||
|
|
||||||
|
import org.geysermc.connector.GeyserConnector;
|
||||||
|
import org.geysermc.connector.command.CommandSender;
|
||||||
|
import org.geysermc.connector.command.GeyserCommand;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.utils.SettingsUtils;
|
||||||
|
|
||||||
|
public class SettingsCommand extends GeyserCommand {
|
||||||
|
|
||||||
|
private final GeyserConnector connector;
|
||||||
|
|
||||||
|
public SettingsCommand(GeyserConnector connector, String name, String description, String permission) {
|
||||||
|
super(name, description, permission);
|
||||||
|
|
||||||
|
this.connector = connector;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandSender sender, String[] args) {
|
||||||
|
// Make sure the sender is a Bedrock edition client
|
||||||
|
GeyserSession session = null;
|
||||||
|
if (sender instanceof GeyserSession) {
|
||||||
|
session = (GeyserSession) sender;
|
||||||
|
} else {
|
||||||
|
// Needed for Spigot - sender is not an instance of GeyserSession
|
||||||
|
for (GeyserSession otherSession : connector.getPlayers()) {
|
||||||
|
if (sender.getName().equals(otherSession.getPlayerEntity().getUsername())) {
|
||||||
|
session = otherSession;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (session == null) return;
|
||||||
|
SettingsUtils.buildForm(session);
|
||||||
|
session.sendForm(session.getSettingsForm(), SettingsUtils.SETTINGS_FORM_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isExecutableOnConsole() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -71,6 +71,8 @@ public interface GeyserConfiguration {
|
|||||||
|
|
||||||
boolean isShowCooldown();
|
boolean isShowCooldown();
|
||||||
|
|
||||||
|
boolean isShowCoordinates();
|
||||||
|
|
||||||
String getDefaultLocale();
|
String getDefaultLocale();
|
||||||
|
|
||||||
Path getFloodgateKeyPath();
|
Path getFloodgateKeyPath();
|
||||||
|
@ -89,6 +89,9 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
|
|||||||
@JsonProperty("show-cooldown")
|
@JsonProperty("show-cooldown")
|
||||||
private boolean showCooldown = true;
|
private boolean showCooldown = true;
|
||||||
|
|
||||||
|
@JsonProperty("show-coordinates")
|
||||||
|
private boolean showCoordinates = true;
|
||||||
|
|
||||||
@JsonProperty("allow-third-party-ears")
|
@JsonProperty("allow-third-party-ears")
|
||||||
private boolean allowThirdPartyEars = false;
|
private boolean allowThirdPartyEars = false;
|
||||||
|
|
||||||
|
@ -35,6 +35,16 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
public class BoatEntity extends Entity {
|
public class BoatEntity extends Entity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required when IS_BUOYANT is sent in order for boats to work in the water. <br>
|
||||||
|
*
|
||||||
|
* Taken from BDS 1.16.200, with the modification of <code>simulate_waves</code> since Java doesn't bob the boat up and down
|
||||||
|
* like Bedrock.
|
||||||
|
*/
|
||||||
|
private static final String BUOYANCY_DATA = "{\"apply_gravity\":true,\"base_buoyancy\":1.0,\"big_wave_probability\":0.02999999932944775," +
|
||||||
|
"\"big_wave_speed\":10.0,\"drag_down_on_buoyancy_removed\":0.0,\"liquid_blocks\":[\"minecraft:water\"," +
|
||||||
|
"\"minecraft:flowing_water\"],\"simulate_waves\":false}}";
|
||||||
|
|
||||||
private boolean isPaddlingLeft;
|
private boolean isPaddlingLeft;
|
||||||
private float paddleTimeLeft;
|
private float paddleTimeLeft;
|
||||||
private boolean isPaddlingRight;
|
private boolean isPaddlingRight;
|
||||||
@ -45,6 +55,10 @@ public class BoatEntity extends Entity {
|
|||||||
|
|
||||||
public BoatEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
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(90, 0, 90));
|
super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation.add(90, 0, 90));
|
||||||
|
|
||||||
|
// Required to be able to move on land 1.16.200+ or apply gravity not in the water 1.16.100+
|
||||||
|
metadata.put(EntityData.IS_BUOYANT, (byte) 1);
|
||||||
|
metadata.put(EntityData.BUOYANCY_DATA, BUOYANCY_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -39,6 +39,8 @@ public class EnderCrystalEntity extends Entity {
|
|||||||
public EnderCrystalEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
public EnderCrystalEntity(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);
|
||||||
|
|
||||||
|
// Bedrock 1.16.100+ - prevents the entity from appearing on fire itself when fire is underneath it
|
||||||
|
metadata.getFlags().setFlag(EntityFlag.FIRE_IMMUNE, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -36,7 +36,20 @@ import org.geysermc.connector.network.translators.item.ItemTranslator;
|
|||||||
public class ItemEntity extends Entity {
|
public class ItemEntity extends Entity {
|
||||||
|
|
||||||
public ItemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
public ItemEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
super(entityId, geyserId, entityType, position.add(0d, entityType.getOffset(), 0d), motion, rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMotion(Vector3f motion) {
|
||||||
|
if (isOnGround())
|
||||||
|
motion = Vector3f.from(motion.getX(), 0, motion.getZ());
|
||||||
|
|
||||||
|
super.setMotion(motion);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveAbsolute(GeyserSession session, Vector3f position, Vector3f rotation, boolean isOnGround, boolean teleported) {
|
||||||
|
super.moveAbsolute(session, position.add(0d, this.entityType.getOffset(), 0d), rotation, isOnGround, teleported);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -44,7 +57,7 @@ public class ItemEntity extends Entity {
|
|||||||
if (entityMetadata.getId() == 7) {
|
if (entityMetadata.getId() == 7) {
|
||||||
AddItemEntityPacket itemPacket = new AddItemEntityPacket();
|
AddItemEntityPacket itemPacket = new AddItemEntityPacket();
|
||||||
itemPacket.setRuntimeEntityId(geyserId);
|
itemPacket.setRuntimeEntityId(geyserId);
|
||||||
itemPacket.setPosition(position);
|
itemPacket.setPosition(position.add(0d, this.entityType.getOffset(), 0d));
|
||||||
itemPacket.setMotion(motion);
|
itemPacket.setMotion(motion);
|
||||||
itemPacket.setUniqueEntityId(geyserId);
|
itemPacket.setUniqueEntityId(geyserId);
|
||||||
itemPacket.setFromFishing(false);
|
itemPacket.setFromFishing(false);
|
||||||
|
@ -53,7 +53,7 @@ public class ArmorStandEntity extends LivingEntity {
|
|||||||
position = position.add(0d, entityType.getHeight() * (isSmall ? 0.55d : 1d), 0d);
|
position = position.add(0d, entityType.getHeight() * (isSmall ? 0.55d : 1d), 0d);
|
||||||
}
|
}
|
||||||
|
|
||||||
super.moveAbsolute(session, position, rotation, isOnGround, teleported);
|
super.moveAbsolute(session, position, Vector3f.from(rotation.getX(), rotation.getX(), rotation.getX()), isOnGround, teleported);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -95,4 +95,10 @@ public class ArmorStandEntity extends LivingEntity {
|
|||||||
}
|
}
|
||||||
super.updateBedrockMetadata(entityMetadata, session);
|
super.updateBedrockMetadata(entityMetadata, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void spawnEntity(GeyserSession session) {
|
||||||
|
this.rotation = Vector3f.from(rotation.getX(), rotation.getX(), rotation.getX());
|
||||||
|
super.spawnEntity(session);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ public enum EntityType {
|
|||||||
ARMOR_STAND(ArmorStandEntity.class, 61, 1.975f, 0.5f),
|
ARMOR_STAND(ArmorStandEntity.class, 61, 1.975f, 0.5f),
|
||||||
TRIPOD_CAMERA(Entity.class, 62, 0f),
|
TRIPOD_CAMERA(Entity.class, 62, 0f),
|
||||||
PLAYER(PlayerEntity.class, 63, 1.8f, 0.6f, 0.6f, 1.62f),
|
PLAYER(PlayerEntity.class, 63, 1.8f, 0.6f, 0.6f, 1.62f),
|
||||||
ITEM(ItemEntity.class, 64, 0.25f, 0.25f),
|
ITEM(ItemEntity.class, 64, 0.25f, 0.25f, 0.25f, 0.125f),
|
||||||
PRIMED_TNT(TNTEntity.class, 65, 0.98f, 0.98f, 0.98f, 0f, "minecraft:tnt"),
|
PRIMED_TNT(TNTEntity.class, 65, 0.98f, 0.98f, 0.98f, 0f, "minecraft:tnt"),
|
||||||
FALLING_BLOCK(FallingBlockEntity.class, 66, 0.98f, 0.98f),
|
FALLING_BLOCK(FallingBlockEntity.class, 66, 0.98f, 0.98f),
|
||||||
MOVING_BLOCK(Entity.class, 67, 0f),
|
MOVING_BLOCK(Entity.class, 67, 0f),
|
||||||
|
@ -174,7 +174,7 @@ public class QueryPacketHandler {
|
|||||||
gameData.put("hostname", motd);
|
gameData.put("hostname", motd);
|
||||||
gameData.put("gametype", "SMP");
|
gameData.put("gametype", "SMP");
|
||||||
gameData.put("game_id", "MINECRAFT");
|
gameData.put("game_id", "MINECRAFT");
|
||||||
gameData.put("version", BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion());
|
gameData.put("version", GeyserConnector.NAME + " (" + GeyserConnector.GIT_VERSION + ") " + BedrockProtocol.DEFAULT_BEDROCK_CODEC.getMinecraftVersion());
|
||||||
gameData.put("plugins", "");
|
gameData.put("plugins", "");
|
||||||
gameData.put("map", map);
|
gameData.put("map", map);
|
||||||
gameData.put("numplayers", currentPlayerCount);
|
gameData.put("numplayers", currentPlayerCount);
|
||||||
|
@ -210,12 +210,6 @@ public class GeyserSession implements CommandSender {
|
|||||||
@Setter
|
@Setter
|
||||||
private long lastWindowCloseTime = 0;
|
private long lastWindowCloseTime = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves the timestamp of the last keep alive packet
|
|
||||||
*/
|
|
||||||
@Setter
|
|
||||||
private long lastKeepAliveTimestamp = 0;
|
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private VillagerTrade[] villagerTrades;
|
private VillagerTrade[] villagerTrades;
|
||||||
@Setter
|
@Setter
|
||||||
@ -237,6 +231,17 @@ public class GeyserSession implements CommandSender {
|
|||||||
@Setter
|
@Setter
|
||||||
private long lastHitTime;
|
private long lastHitTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves if the client is steering left on a boat.
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
private boolean steeringLeft;
|
||||||
|
/**
|
||||||
|
* Saves if the client is steering right on a boat.
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
private boolean steeringRight;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the last time the player interacted. Used to fix a right-click spam bug.
|
* Store the last time the player interacted. Used to fix a right-click spam bug.
|
||||||
* See https://github.com/GeyserMC/Geyser/issues/503 for context.
|
* See https://github.com/GeyserMC/Geyser/issues/503 for context.
|
||||||
@ -406,6 +411,8 @@ public class GeyserSession implements CommandSender {
|
|||||||
// Don't let the client modify the inventory on death
|
// Don't let the client modify the inventory on death
|
||||||
// Setting this to true allows keep inventory to work if enabled but doesn't break functionality being false
|
// Setting this to true allows keep inventory to work if enabled but doesn't break functionality being false
|
||||||
gamerulePacket.getGameRules().add(new GameRuleData<>("keepinventory", true));
|
gamerulePacket.getGameRules().add(new GameRuleData<>("keepinventory", true));
|
||||||
|
// Ensure client doesn't try and do anything funky; the server handles this for us
|
||||||
|
gamerulePacket.getGameRules().add(new GameRuleData<>("spawnradius", 0));
|
||||||
upstream.sendPacket(gamerulePacket);
|
upstream.sendPacket(gamerulePacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,7 +694,7 @@ 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", 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());
|
||||||
|
@ -25,23 +25,19 @@
|
|||||||
|
|
||||||
package org.geysermc.connector.network.translators.bedrock;
|
package org.geysermc.connector.network.translators.bedrock;
|
||||||
|
|
||||||
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.data.game.entity.player.Hand;
|
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerSwingArmPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerSwingArmPacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientSteerBoatPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientSteerBoatPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.AnimatePacket;
|
import com.nukkitx.protocol.bedrock.packet.AnimatePacket;
|
||||||
|
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;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Translator(packet = AnimatePacket.class)
|
@Translator(packet = AnimatePacket.class)
|
||||||
public class BedrockAnimateTranslator extends PacketTranslator<AnimatePacket> {
|
public class BedrockAnimateTranslator extends PacketTranslator<AnimatePacket> {
|
||||||
|
|
||||||
private boolean isSteeringLeft;
|
|
||||||
private boolean isSteeringRight;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(AnimatePacket packet, GeyserSession session) {
|
public void translate(AnimatePacket packet, GeyserSession session) {
|
||||||
// Stop the player sending animations before they have fully spawned into the server
|
// Stop the player sending animations before they have fully spawned into the server
|
||||||
@ -61,13 +57,13 @@ public class BedrockAnimateTranslator extends PacketTranslator<AnimatePacket> {
|
|||||||
// These two might need to be flipped, but my recommendation is getting moving working first
|
// These two might need to be flipped, but my recommendation is getting moving working first
|
||||||
case ROW_LEFT:
|
case ROW_LEFT:
|
||||||
// Packet value is a float of how long one has been rowing, so we convert that into a boolean
|
// Packet value is a float of how long one has been rowing, so we convert that into a boolean
|
||||||
isSteeringLeft = packet.getRowingTime() > 0.0;
|
session.setSteeringLeft(packet.getRowingTime() > 0.0);
|
||||||
ClientSteerBoatPacket steerLeftPacket = new ClientSteerBoatPacket(isSteeringRight, isSteeringLeft);
|
ClientSteerBoatPacket steerLeftPacket = new ClientSteerBoatPacket(session.isSteeringLeft(), session.isSteeringRight());
|
||||||
session.sendDownstreamPacket(steerLeftPacket);
|
session.sendDownstreamPacket(steerLeftPacket);
|
||||||
break;
|
break;
|
||||||
case ROW_RIGHT:
|
case ROW_RIGHT:
|
||||||
isSteeringRight = packet.getRowingTime() > 0.0;
|
session.setSteeringRight(packet.getRowingTime() > 0.0);
|
||||||
ClientSteerBoatPacket steerRightPacket = new ClientSteerBoatPacket(isSteeringRight, isSteeringLeft);
|
ClientSteerBoatPacket steerRightPacket = new ClientSteerBoatPacket(session.isSteeringLeft(), session.isSteeringRight());
|
||||||
session.sendDownstreamPacket(steerRightPacket);
|
session.sendDownstreamPacket(steerRightPacket);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@ package org.geysermc.connector.network.translators.bedrock;
|
|||||||
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientVehicleMovePacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientVehicleMovePacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
||||||
|
import org.geysermc.connector.entity.BoatEntity;
|
||||||
|
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;
|
||||||
import org.geysermc.connector.network.translators.Translator;
|
import org.geysermc.connector.network.translators.Translator;
|
||||||
@ -39,8 +41,14 @@ public class BedrockMoveEntityAbsoluteTranslator extends PacketTranslator<MoveEn
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(MoveEntityAbsolutePacket packet, GeyserSession session) {
|
public void translate(MoveEntityAbsolutePacket packet, GeyserSession session) {
|
||||||
|
float y = packet.getPosition().getY();
|
||||||
|
if (session.getRidingVehicleEntity() instanceof BoatEntity) {
|
||||||
|
// Remove some Y position to prevents boats from looking like they're floating in water
|
||||||
|
// Not by the full boat offset because 1.16.100 complains and that's probably not good for the future
|
||||||
|
y -= (EntityType.BOAT.getOffset() - 0.5f);
|
||||||
|
}
|
||||||
ClientVehicleMovePacket clientVehicleMovePacket = new ClientVehicleMovePacket(
|
ClientVehicleMovePacket clientVehicleMovePacket = new ClientVehicleMovePacket(
|
||||||
packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ(),
|
packet.getPosition().getX(), y, packet.getPosition().getZ(),
|
||||||
packet.getRotation().getY() - 90, packet.getRotation().getX()
|
packet.getRotation().getY() - 90, packet.getRotation().getX()
|
||||||
);
|
);
|
||||||
session.sendDownstreamPacket(clientVehicleMovePacket);
|
session.sendDownstreamPacket(clientVehicleMovePacket);
|
||||||
|
@ -30,6 +30,7 @@ import com.nukkitx.protocol.bedrock.packet.NetworkStackLatencyPacket;
|
|||||||
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.floodgate.util.DeviceOS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to send the keep alive packet back to the server
|
* Used to send the keep alive packet back to the server
|
||||||
@ -39,8 +40,16 @@ public class BedrockNetworkStackLatencyTranslator extends PacketTranslator<Netwo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(NetworkStackLatencyPacket packet, GeyserSession session) {
|
public void translate(NetworkStackLatencyPacket packet, GeyserSession session) {
|
||||||
// The client sends a timestamp back but it's rounded and therefore unreliable when we need the exact number
|
long pingId;
|
||||||
ClientKeepAlivePacket keepAlivePacket = new ClientKeepAlivePacket(session.getLastKeepAliveTimestamp());
|
// so apparently, as of 1.16.200
|
||||||
session.sendDownstreamPacket(keepAlivePacket);
|
// PS4 divides the network stack latency timestamp FOR US!!!
|
||||||
|
// WTF
|
||||||
|
if (session.getClientData().getDeviceOS().equals(DeviceOS.NX)) {
|
||||||
|
// Ignore the weird DeviceOS, our order is wrong and will be fixed in Floodgate 2.0
|
||||||
|
pingId = packet.getTimestamp();
|
||||||
|
} else {
|
||||||
|
pingId = packet.getTimestamp() / 1000;
|
||||||
|
}
|
||||||
|
session.sendDownstreamPacket(new ClientKeepAlivePacket(pingId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ public class BedrockTextTranslator extends PacketTranslator<TextPacket> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(TextPacket packet, GeyserSession session) {
|
public void translate(TextPacket packet, GeyserSession session) {
|
||||||
String message = packet.getMessage().replaceAll("^\\.", "/").trim();
|
String message = packet.getMessage();
|
||||||
|
|
||||||
if (MessageTranslator.isTooLong(message, session)) {
|
if (MessageTranslator.isTooLong(message, session)) {
|
||||||
return;
|
return;
|
||||||
|
@ -25,26 +25,32 @@
|
|||||||
|
|
||||||
package org.geysermc.connector.network.translators.chat;
|
package org.geysermc.connector.network.translators.chat;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.DefaultComponentSerializer;
|
||||||
import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor;
|
import com.github.steveice10.mc.protocol.data.game.scoreboard.TeamColor;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
import net.kyori.adventure.text.format.TextDecoration;
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
import net.kyori.adventure.text.renderer.TranslatableComponentRenderer;
|
import net.kyori.adventure.text.renderer.TranslatableComponentRenderer;
|
||||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
|
import net.kyori.adventure.text.serializer.gson.legacyimpl.NBTLegacyHoverEventSerializer;
|
||||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
import org.geysermc.connector.utils.LanguageUtils;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class MessageTranslator {
|
public class MessageTranslator {
|
||||||
|
|
||||||
// These are used for handling the translations of the messages
|
// These are used for handling the translations of the messages
|
||||||
private static final TranslatableComponentRenderer<Locale> RENDERER = TranslatableComponentRenderer.usingTranslationSource(new MinecraftTranslationRegistry());
|
private static final TranslatableComponentRenderer<Locale> RENDERER = TranslatableComponentRenderer.usingTranslationSource(new MinecraftTranslationRegistry());
|
||||||
|
|
||||||
// Construct our own {@link GsonComponentSerializer} encase we need to change anything
|
// Construct our own {@link GsonComponentSerializer} since we need to change a setting
|
||||||
private static final GsonComponentSerializer GSON_SERIALIZER = GsonComponentSerializer.builder()
|
private static final GsonComponentSerializer GSON_SERIALIZER = GsonComponentSerializer.builder()
|
||||||
|
// Specify that we may be expecting legacy hover events
|
||||||
|
.legacyHoverEventSerializer(NBTLegacyHoverEventSerializer.get())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
// Store team colors for player names
|
// Store team colors for player names
|
||||||
@ -61,6 +67,9 @@ public class MessageTranslator {
|
|||||||
TEAM_FORMATS.put(TeamColor.BOLD, TextDecoration.BOLD);
|
TEAM_FORMATS.put(TeamColor.BOLD, TextDecoration.BOLD);
|
||||||
TEAM_FORMATS.put(TeamColor.STRIKETHROUGH, TextDecoration.STRIKETHROUGH);
|
TEAM_FORMATS.put(TeamColor.STRIKETHROUGH, TextDecoration.STRIKETHROUGH);
|
||||||
TEAM_FORMATS.put(TeamColor.ITALIC, TextDecoration.ITALIC);
|
TEAM_FORMATS.put(TeamColor.ITALIC, TextDecoration.ITALIC);
|
||||||
|
|
||||||
|
// Tell MCProtocolLib to use our serializer
|
||||||
|
DefaultComponentSerializer.set(GSON_SERIALIZER);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,8 +45,39 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
@ItemRemapper
|
@ItemRemapper
|
||||||
public class BannerTranslator extends ItemTranslator {
|
public class BannerTranslator extends ItemTranslator {
|
||||||
|
/**
|
||||||
|
* Holds what a Java ominous banner pattern looks like.
|
||||||
|
*
|
||||||
|
* Translating the patterns over to Bedrock does not work effectively, but Bedrock has a dedicated type for
|
||||||
|
* ominous banners that we set instead. This variable is used to detect Java ominous banner patterns, and apply
|
||||||
|
* the correct ominous banner pattern if Bedrock pulls the item from creative.
|
||||||
|
*/
|
||||||
|
public static final ListTag OMINOUS_BANNER_PATTERN;
|
||||||
|
|
||||||
private final List<ItemEntry> appliedItems;
|
private final List<ItemEntry> appliedItems;
|
||||||
|
|
||||||
|
static {
|
||||||
|
OMINOUS_BANNER_PATTERN = new ListTag("Patterns");
|
||||||
|
// Construct what an ominous banner is supposed to look like
|
||||||
|
OMINOUS_BANNER_PATTERN.add(getPatternTag("mr", 9));
|
||||||
|
OMINOUS_BANNER_PATTERN.add(getPatternTag("bs", 8));
|
||||||
|
OMINOUS_BANNER_PATTERN.add(getPatternTag("cs", 7));
|
||||||
|
OMINOUS_BANNER_PATTERN.add(getPatternTag("bo", 8));
|
||||||
|
OMINOUS_BANNER_PATTERN.add(getPatternTag("ms", 15));
|
||||||
|
OMINOUS_BANNER_PATTERN.add(getPatternTag("hh", 8));
|
||||||
|
OMINOUS_BANNER_PATTERN.add(getPatternTag("mc", 8));
|
||||||
|
OMINOUS_BANNER_PATTERN.add(getPatternTag("bo", 15));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CompoundTag getPatternTag(String pattern, int color) {
|
||||||
|
StringTag patternType = new StringTag("Pattern", pattern);
|
||||||
|
IntTag colorTag = new IntTag("Color", color);
|
||||||
|
CompoundTag tag = new CompoundTag("");
|
||||||
|
tag.put(patternType);
|
||||||
|
tag.put(colorTag);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
public BannerTranslator() {
|
public BannerTranslator() {
|
||||||
appliedItems = ItemRegistry.ITEM_ENTRIES.values()
|
appliedItems = ItemRegistry.ITEM_ENTRIES.values()
|
||||||
.stream()
|
.stream()
|
||||||
@ -62,7 +93,7 @@ public class BannerTranslator extends ItemTranslator {
|
|||||||
*/
|
*/
|
||||||
public static NbtList<NbtMap> convertBannerPattern(ListTag patterns) {
|
public static NbtList<NbtMap> convertBannerPattern(ListTag patterns) {
|
||||||
List<NbtMap> tagsList = new ArrayList<>();
|
List<NbtMap> tagsList = new ArrayList<>();
|
||||||
for (com.github.steveice10.opennbt.tag.builtin.Tag patternTag : patterns.getValue()) {
|
for (Tag patternTag : patterns.getValue()) {
|
||||||
NbtMap newPatternTag = getBedrockBannerPattern((CompoundTag) patternTag);
|
NbtMap newPatternTag = getBedrockBannerPattern((CompoundTag) patternTag);
|
||||||
if (newPatternTag != null) {
|
if (newPatternTag != null) {
|
||||||
tagsList.add(newPatternTag);
|
tagsList.add(newPatternTag);
|
||||||
@ -134,7 +165,13 @@ public class BannerTranslator extends ItemTranslator {
|
|||||||
ListTag patterns = blockEntityTag.get("Patterns");
|
ListTag patterns = blockEntityTag.get("Patterns");
|
||||||
|
|
||||||
NbtMapBuilder builder = itemData.getTag().toBuilder();
|
NbtMapBuilder builder = itemData.getTag().toBuilder();
|
||||||
builder.put("Patterns", convertBannerPattern(patterns));
|
if (patterns.equals(OMINOUS_BANNER_PATTERN)) {
|
||||||
|
// Remove the current patterns and set the ominous banner type
|
||||||
|
builder.remove("Patterns");
|
||||||
|
builder.putInt("Type", 1);
|
||||||
|
} else {
|
||||||
|
builder.put("Patterns", convertBannerPattern(patterns));
|
||||||
|
}
|
||||||
|
|
||||||
itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.build());
|
itemData = ItemData.of(itemData.getId(), itemData.getDamage(), itemData.getCount(), builder.build());
|
||||||
}
|
}
|
||||||
@ -151,7 +188,14 @@ public class BannerTranslator extends ItemTranslator {
|
|||||||
ItemStack itemStack = super.translateToJava(itemData, itemEntry);
|
ItemStack itemStack = super.translateToJava(itemData, itemEntry);
|
||||||
|
|
||||||
NbtMap nbtTag = itemData.getTag();
|
NbtMap nbtTag = itemData.getTag();
|
||||||
if (nbtTag.containsKey("Patterns", NbtType.COMPOUND)) {
|
if (nbtTag.containsKey("Type", NbtType.INT) && nbtTag.getInt("Type") == 1) {
|
||||||
|
// Ominous banner pattern
|
||||||
|
itemStack.getNbt().remove("Type");
|
||||||
|
CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag");
|
||||||
|
blockEntityTag.put(OMINOUS_BANNER_PATTERN);
|
||||||
|
|
||||||
|
itemStack.getNbt().put(blockEntityTag);
|
||||||
|
} else if (nbtTag.containsKey("Patterns", NbtType.COMPOUND)) {
|
||||||
List<NbtMap> patterns = nbtTag.getList("Patterns", NbtType.COMPOUND);
|
List<NbtMap> patterns = nbtTag.getList("Patterns", NbtType.COMPOUND);
|
||||||
|
|
||||||
CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag");
|
CompoundTag blockEntityTag = new CompoundTag("BlockEntityTag");
|
||||||
|
@ -52,9 +52,14 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator<ServerDeclar
|
|||||||
public void translate(ServerDeclareCommandsPacket packet, GeyserSession session) {
|
public void translate(ServerDeclareCommandsPacket packet, GeyserSession session) {
|
||||||
// Don't send command suggestions if they are disabled
|
// Don't send command suggestions if they are disabled
|
||||||
if (!session.getConnector().getConfig().isCommandSuggestions()) {
|
if (!session.getConnector().getConfig().isCommandSuggestions()) {
|
||||||
session.getConnector().getLogger().debug("Not sending command suggestions as they are disabled.");
|
session.getConnector().getLogger().debug("Not sending translated command suggestions as they are disabled.");
|
||||||
|
|
||||||
|
// Send an empty packet so Bedrock doesn't override /help with its own, built-in help command.
|
||||||
|
AvailableCommandsPacket emptyPacket = new AvailableCommandsPacket();
|
||||||
|
session.sendUpstreamPacket(emptyPacket);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<CommandData> commandData = new ArrayList<>();
|
List<CommandData> commandData = new ArrayList<>();
|
||||||
Int2ObjectMap<String> commands = new Int2ObjectOpenHashMap<>();
|
Int2ObjectMap<String> commands = new Int2ObjectOpenHashMap<>();
|
||||||
Int2ObjectMap<List<CommandNode>> commandArgs = new Int2ObjectOpenHashMap<>();
|
Int2ObjectMap<List<CommandNode>> commandArgs = new Int2ObjectOpenHashMap<>();
|
||||||
@ -83,14 +88,14 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator<ServerDeclar
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The command flags, not sure what these do apart from break things
|
// The command flags, not sure what these do apart from break things
|
||||||
List<CommandData.Flag> flags = new ArrayList<>();
|
List<CommandData.Flag> flags = Collections.emptyList();
|
||||||
|
|
||||||
// Loop through all the found commands
|
// Loop through all the found commands
|
||||||
for (int commandID : commands.keySet()) {
|
for (int commandID : commands.keySet()) {
|
||||||
String commandName = commands.get(commandID);
|
String commandName = commands.get(commandID);
|
||||||
|
|
||||||
// Create a basic alias
|
// Create a basic alias
|
||||||
CommandEnumData aliases = new CommandEnumData( commandName + "Aliases", new String[] { commandName.toLowerCase() }, false);
|
CommandEnumData aliases = new CommandEnumData(commandName + "Aliases", new String[] { commandName.toLowerCase() }, false);
|
||||||
|
|
||||||
// Get and parse all params
|
// Get and parse all params
|
||||||
CommandParamData[][] params = getParams(packet.getNodes()[commandID], packet.getNodes());
|
CommandParamData[][] params = getParams(packet.getNodes()[commandID], packet.getNodes());
|
||||||
@ -102,9 +107,7 @@ public class JavaDeclareCommandsTranslator extends PacketTranslator<ServerDeclar
|
|||||||
|
|
||||||
// Add our commands to the AvailableCommandsPacket for the bedrock client
|
// Add our commands to the AvailableCommandsPacket for the bedrock client
|
||||||
AvailableCommandsPacket availableCommandsPacket = new AvailableCommandsPacket();
|
AvailableCommandsPacket availableCommandsPacket = new AvailableCommandsPacket();
|
||||||
for (CommandData data : commandData) {
|
availableCommandsPacket.getCommands().addAll(commandData);
|
||||||
availableCommandsPacket.getCommands().add(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
GeyserConnector.getInstance().getLogger().debug("Sending command packet of " + commandData.size() + " commands");
|
GeyserConnector.getInstance().getLogger().debug("Sending command packet of " + commandData.size() + " commands");
|
||||||
|
|
||||||
|
@ -39,10 +39,9 @@ public class JavaKeepAliveTranslator extends PacketTranslator<ServerKeepAlivePac
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(ServerKeepAlivePacket packet, GeyserSession session) {
|
public void translate(ServerKeepAlivePacket packet, GeyserSession session) {
|
||||||
session.setLastKeepAliveTimestamp(packet.getPingId());
|
|
||||||
NetworkStackLatencyPacket latencyPacket = new NetworkStackLatencyPacket();
|
NetworkStackLatencyPacket latencyPacket = new NetworkStackLatencyPacket();
|
||||||
latencyPacket.setFromServer(true);
|
latencyPacket.setFromServer(true);
|
||||||
latencyPacket.setTimestamp(packet.getPingId());
|
latencyPacket.setTimestamp(packet.getPingId() * 1000);
|
||||||
session.sendUpstreamPacket(latencyPacket);
|
session.sendUpstreamPacket(latencyPacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,9 +86,9 @@ public class JavaEntitySetPassengersTranslator extends PacketTranslator<ServerEn
|
|||||||
passenger.getMetadata().put(EntityData.RIDER_MAX_ROTATION, 90f);
|
passenger.getMetadata().put(EntityData.RIDER_MAX_ROTATION, 90f);
|
||||||
passenger.getMetadata().put(EntityData.RIDER_MIN_ROTATION, !passengers.isEmpty() ? -90f : 0f);
|
passenger.getMetadata().put(EntityData.RIDER_MIN_ROTATION, !passengers.isEmpty() ? -90f : 0f);
|
||||||
} else {
|
} else {
|
||||||
passenger.getMetadata().remove(EntityData.RIDER_ROTATION_LOCKED);
|
passenger.getMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
|
||||||
passenger.getMetadata().remove(EntityData.RIDER_MAX_ROTATION);
|
passenger.getMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
|
||||||
passenger.getMetadata().remove(EntityData.RIDER_MIN_ROTATION);
|
passenger.getMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
passenger.updateBedrockMetadata(session);
|
passenger.updateBedrockMetadata(session);
|
||||||
@ -110,6 +110,9 @@ public class JavaEntitySetPassengersTranslator extends PacketTranslator<ServerEn
|
|||||||
linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), EntityLinkData.Type.REMOVE, false));
|
linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), EntityLinkData.Type.REMOVE, false));
|
||||||
session.sendUpstreamPacket(linkPacket);
|
session.sendUpstreamPacket(linkPacket);
|
||||||
passengers.remove(passenger.getEntityId());
|
passengers.remove(passenger.getEntityId());
|
||||||
|
passenger.getMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
|
||||||
|
passenger.getMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
|
||||||
|
passenger.getMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
|
||||||
|
|
||||||
this.updateOffset(passenger, entity, session, false, false, (packet.getPassengerIds().length > 1));
|
this.updateOffset(passenger, entity, session, false, false, (packet.getPassengerIds().length > 1));
|
||||||
} else {
|
} else {
|
||||||
|
@ -78,7 +78,7 @@ public class JavaSpawnParticleTranslator extends PacketTranslator<ServerSpawnPar
|
|||||||
int r = (int) (data.getRed()*255);
|
int r = (int) (data.getRed()*255);
|
||||||
int g = (int) (data.getGreen()*255);
|
int g = (int) (data.getGreen()*255);
|
||||||
int b = (int) (data.getBlue()*255);
|
int b = (int) (data.getBlue()*255);
|
||||||
particle.setType(LevelEventType.PARTICLE_REDSTONE);
|
particle.setType(LevelEventType.PARTICLE_FALLING_DUST);
|
||||||
particle.setData(((0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff));
|
particle.setData(((0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff));
|
||||||
particle.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
|
particle.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));
|
||||||
session.sendUpstreamPacket(particle);
|
session.sendUpstreamPacket(particle);
|
||||||
|
@ -47,7 +47,13 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator implement
|
|||||||
|
|
||||||
if (tag.contains("Patterns")) {
|
if (tag.contains("Patterns")) {
|
||||||
ListTag patterns = tag.get("Patterns");
|
ListTag patterns = tag.get("Patterns");
|
||||||
builder.put("Patterns", BannerTranslator.convertBannerPattern(patterns));
|
if (patterns.equals(BannerTranslator.OMINOUS_BANNER_PATTERN)) {
|
||||||
|
// This is an ominous banner; don't try to translate the raw patterns (it doesn't translate correctly)
|
||||||
|
// and tell the Bedrock client that this is an ominous banner
|
||||||
|
builder.putInt("Type", 1);
|
||||||
|
} else {
|
||||||
|
builder.put("Patterns", BannerTranslator.convertBannerPattern(patterns));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tag.contains("CustomName")) {
|
if (tag.contains("CustomName")) {
|
||||||
|
@ -36,8 +36,14 @@ public final class Score {
|
|||||||
private final String name;
|
private final String name;
|
||||||
private ScoreInfo cachedInfo;
|
private ScoreInfo cachedInfo;
|
||||||
|
|
||||||
private ScoreData currentData;
|
/**
|
||||||
private ScoreData cachedData;
|
* Changes that have been made since the last cached data.
|
||||||
|
*/
|
||||||
|
private Score.ScoreData currentData;
|
||||||
|
/**
|
||||||
|
* The data that is currently displayed to the Bedrock client.
|
||||||
|
*/
|
||||||
|
private Score.ScoreData cachedData;
|
||||||
|
|
||||||
public Score(long id, String name) {
|
public Score(long id, String name) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@ -79,7 +85,7 @@ public final class Score {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public UpdateType getUpdateType() {
|
public UpdateType getUpdateType() {
|
||||||
return cachedData != null ? cachedData.updateType : currentData.updateType;
|
return currentData.updateType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Score setUpdateType(UpdateType updateType) {
|
public Score setUpdateType(UpdateType updateType) {
|
||||||
|
@ -189,7 +189,10 @@ public final class Scoreboard {
|
|||||||
remove = false;
|
remove = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (score.shouldUpdate()) {
|
if (objectiveRemove && score.getCachedData() != null) {
|
||||||
|
// This score has been sent to the client and needs to be removed since the objective is being removed
|
||||||
|
remove = true;
|
||||||
|
} else if (score.shouldUpdate()) {
|
||||||
score.update(objective.getObjectiveName());
|
score.update(objective.getObjectiveName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,11 +81,10 @@ public class SkinManager {
|
|||||||
|
|
||||||
// This attempts to find the xuid of the player so profile images show up for xbox accounts
|
// This attempts to find the xuid of the player so profile images show up for xbox accounts
|
||||||
String xuid = "";
|
String xuid = "";
|
||||||
for (GeyserSession player : GeyserConnector.getInstance().getPlayers()) {
|
GeyserSession player = GeyserConnector.getInstance().getPlayerByUuid(uuid);
|
||||||
if (player.getPlayerEntity().getUuid().equals(uuid)) {
|
|
||||||
xuid = player.getAuthData().getXboxUUID();
|
if (player != null) {
|
||||||
break;
|
xuid = player.getAuthData().getXboxUUID();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerListPacket.Entry entry;
|
PlayerListPacket.Entry entry;
|
||||||
@ -268,11 +267,10 @@ public class SkinManager {
|
|||||||
// return default skin with default cape when texture data is invalid
|
// return default skin with default cape when texture data is invalid
|
||||||
String skinUrl = isAlex ? SkinProvider.EMPTY_SKIN_ALEX.getTextureUrl() : SkinProvider.EMPTY_SKIN.getTextureUrl();
|
String skinUrl = isAlex ? SkinProvider.EMPTY_SKIN_ALEX.getTextureUrl() : SkinProvider.EMPTY_SKIN.getTextureUrl();
|
||||||
if ("steve".equals(skinUrl) || "alex".equals(skinUrl)) {
|
if ("steve".equals(skinUrl) || "alex".equals(skinUrl)) {
|
||||||
for (GeyserSession session : GeyserConnector.getInstance().getPlayers()) {
|
GeyserSession session = GeyserConnector.getInstance().getPlayerByUuid(profile.getId());
|
||||||
if (session.getPlayerEntity().getUuid().equals(profile.getId())) {
|
|
||||||
skinUrl = session.getClientData().getSkinId();
|
if (session != null) {
|
||||||
break;
|
skinUrl = session.getClientData().getSkinId();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new GameProfileData(skinUrl, SkinProvider.EMPTY_CAPE.getTextureUrl(), isAlex);
|
return new GameProfileData(skinUrl, SkinProvider.EMPTY_CAPE.getTextureUrl(), isAlex);
|
||||||
|
@ -144,12 +144,10 @@ public class SkinProvider {
|
|||||||
String newSkinUrl = skinUrl;
|
String newSkinUrl = skinUrl;
|
||||||
|
|
||||||
if ("steve".equals(skinUrl) || "alex".equals(skinUrl)) {
|
if ("steve".equals(skinUrl) || "alex".equals(skinUrl)) {
|
||||||
// TODO: Don't have a for loop for this? Have a proper map?
|
GeyserSession session = GeyserConnector.getInstance().getPlayerByUuid(playerId);
|
||||||
for (GeyserSession session : GeyserConnector.getInstance().getPlayers()) {
|
|
||||||
if (session.getPlayerEntity().getUuid().equals(playerId)) {
|
if (session != null) {
|
||||||
newSkinUrl = session.getClientData().getSkinId();
|
newSkinUrl = session.getClientData().getSkinId();
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,6 +112,9 @@ public class SettingsUtils {
|
|||||||
settingsForm.setResponse(response);
|
settingsForm.setResponse(response);
|
||||||
|
|
||||||
CustomFormResponse settingsResponse = (CustomFormResponse) settingsForm.getResponse();
|
CustomFormResponse settingsResponse = (CustomFormResponse) settingsForm.getResponse();
|
||||||
|
if (settingsResponse == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
offset++; // Client settings title
|
offset++; // Client settings title
|
||||||
|
@ -90,6 +90,9 @@ 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
|
# 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
|
show-cooldown: true
|
||||||
|
|
||||||
|
# Controls if coordinates are shown to players.
|
||||||
|
show-coordinates: true
|
||||||
|
|
||||||
# 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
|
||||||
|
|
||||||
@ -119,8 +122,8 @@ allow-custom-skulls: true
|
|||||||
above-bedrock-nether-building: false
|
above-bedrock-nether-building: false
|
||||||
|
|
||||||
# Force clients to load all resource packs if there are any.
|
# Force clients to load all resource packs if there are any.
|
||||||
# If set to false it allows the user to disconnect from the server if they don't
|
# If set to false, it allows the user to connect to the server even if they don't
|
||||||
# want to download the resource packs
|
# want to download the resource packs.
|
||||||
force-resource-packs: true
|
force-resource-packs: true
|
||||||
|
|
||||||
# Allows Xbox achievements to be unlocked.
|
# Allows Xbox achievements to be unlocked.
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 1e2815bdd9c78fa6865656db0d8b580b20aa87f1
|
Subproject commit 1a00766840baf1f512d98f5a75c177c8bcfba6f3
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren