mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-22 22:45:04 +01:00
Merge remote-tracking branch 'origin/master' into floodgate-2.0
# Conflicts: # connector/src/main/java/org/geysermc/connector/GeyserConnector.java # connector/src/main/java/org/geysermc/connector/utils/SettingsUtils.java
This commit is contained in:
commit
776fc4e933
15 changed files with 213 additions and 85 deletions
|
@ -40,13 +40,7 @@ Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set
|
||||||
- Structure block UI
|
- Structure block UI
|
||||||
|
|
||||||
## What can't be fixed
|
## What can't be fixed
|
||||||
The following things cannot be fixed without changes to Bedrock. As of now, they are not fixable in Geyser.
|
There are a few things Geyser is unable to support due to various differences between Minecraft Bedrock and Java. For a list of these limitations, see the [Current Limitations](https://github.com/GeyserMC/Geyser/wiki/Current-Limitations) page.
|
||||||
|
|
||||||
- Custom heads in inventories
|
|
||||||
- Clickable links in chat
|
|
||||||
- Glowing effect
|
|
||||||
|
|
||||||
Do note that some things require the [GeyserOptionalPack](https://github.com/GeyserMC/Geyser/wiki/GeyserOptionalPack) in order to function, such as custom armor stand poses.
|
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
1. Clone the repo to your computer
|
1. Clone the repo to your computer
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>net.md-5</groupId>
|
<groupId>net.md-5</groupId>
|
||||||
<artifactId>bungeecord-api</artifactId>
|
<artifactId>bungeecord-api</artifactId>
|
||||||
<version>1.16-R0.4-SNAPSHOT</version>
|
<version>1.16-R0.5-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
@ -66,8 +66,10 @@
|
||||||
<shadedPattern>org.geysermc.platform.bungeecord.shaded.jackson</shadedPattern>
|
<shadedPattern>org.geysermc.platform.bungeecord.shaded.jackson</shadedPattern>
|
||||||
</relocation>
|
</relocation>
|
||||||
<relocation>
|
<relocation>
|
||||||
<pattern>io.netty</pattern>
|
<!-- This is not used because relocating breaks natives, but we must include it
|
||||||
<shadedPattern>org.geysermc.platform.bungeecord.shaded.netty</shadedPattern>
|
or else we get ClassDefNotFound -->
|
||||||
|
<pattern>io.netty.channel.kqueue</pattern>
|
||||||
|
<shadedPattern>org.geysermc.platform.bungeecord.shaded.io.netty.channel.kqueue</shadedPattern>
|
||||||
</relocation>
|
</relocation>
|
||||||
<relocation>
|
<relocation>
|
||||||
<pattern>org.reflections</pattern>
|
<pattern>org.reflections</pattern>
|
||||||
|
@ -98,6 +100,15 @@
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>com.google.code.gson:*</exclude>
|
<exclude>com.google.code.gson:*</exclude>
|
||||||
<exclude>org.yaml:*</exclude>
|
<exclude>org.yaml:*</exclude>
|
||||||
|
<exclude>io.netty:netty-transport-native-epoll:*</exclude>
|
||||||
|
<exclude>io.netty:netty-transport-native-unix-common:*</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>io.netty:netty-resolver-dns:*</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</artifactSet>
|
</artifactSet>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -68,10 +68,6 @@
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<relocations>
|
<relocations>
|
||||||
<relocation>
|
|
||||||
<pattern>io.netty</pattern>
|
|
||||||
<shadedPattern>org.geysermc.platform.spigot.shaded.netty</shadedPattern>
|
|
||||||
</relocation>
|
|
||||||
<relocation>
|
<relocation>
|
||||||
<pattern>it.unimi.dsi.fastutil</pattern>
|
<pattern>it.unimi.dsi.fastutil</pattern>
|
||||||
<shadedPattern>org.geysermc.platform.spigot.shaded.fastutil</shadedPattern>
|
<shadedPattern>org.geysermc.platform.spigot.shaded.fastutil</shadedPattern>
|
||||||
|
@ -109,6 +105,20 @@
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>com.google.code.gson:*</exclude>
|
<exclude>com.google.code.gson:*</exclude>
|
||||||
<exclude>org.yaml:*</exclude>
|
<exclude>org.yaml:*</exclude>
|
||||||
|
<!-- We cannot shade Netty, or else native libraries will not load -->
|
||||||
|
<!-- Needed because older Spigot builds do not provide the haproxy module -->
|
||||||
|
<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>io.netty:netty-codec-dns:*</exclude>
|
||||||
|
<exclude>io.netty:netty-resolver-dns:*</exclude>
|
||||||
|
<exclude>io.netty:netty-resolver-dns-native-macos:*</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</artifactSet>
|
</artifactSet>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -95,6 +95,23 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Required for the Cloudburst Network dependency to initialize.
|
||||||
|
Class.forName("io.netty.channel.kqueue.KQueue");
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// While we could support these older versions, the downside is not having KQueue working at all
|
||||||
|
// And since there are alternative ways to get Geyser working for these aging platforms, it's not worth it.
|
||||||
|
getLogger().severe("*********************************************");
|
||||||
|
getLogger().severe("");
|
||||||
|
getLogger().severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.unsupported_server.header"));
|
||||||
|
getLogger().severe(LanguageUtils.getLocaleStringLog("geyser.bootstrap.unsupported_server.message", "1.12.2"));
|
||||||
|
getLogger().severe("");
|
||||||
|
getLogger().severe("*********************************************");
|
||||||
|
|
||||||
|
Bukkit.getPluginManager().disablePlugin(this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// By default this should be localhost but may need to be changed in some circumstances
|
// By default this should be localhost but may need to be changed in some circumstances
|
||||||
if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) {
|
if (this.geyserConfig.getRemote().getAddress().equalsIgnoreCase("auto")) {
|
||||||
geyserConfig.setAutoconfiguredRemote(true);
|
geyserConfig.setAutoconfiguredRemote(true);
|
||||||
|
|
|
@ -103,6 +103,7 @@
|
||||||
<exclude>io.netty:netty-resolver:*</exclude>
|
<exclude>io.netty:netty-resolver:*</exclude>
|
||||||
<exclude>io.netty:netty-transport:*</exclude>
|
<exclude>io.netty:netty-transport:*</exclude>
|
||||||
<exclude>io.netty:netty-codec:*</exclude>
|
<exclude>io.netty:netty-codec:*</exclude>
|
||||||
|
<exclude>io.netty:netty-codec-haproxy:*</exclude>
|
||||||
<exclude>org.slf4j:*</exclude>
|
<exclude>org.slf4j:*</exclude>
|
||||||
<exclude>org.ow2.asm:*</exclude>
|
<exclude>org.ow2.asm:*</exclude>
|
||||||
<!-- Exclude all Kyori dependencies except the legacy NBT serializer -->
|
<!-- Exclude all Kyori dependencies except the legacy NBT serializer -->
|
||||||
|
|
|
@ -133,7 +133,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.steveice10</groupId>
|
<groupId>com.github.steveice10</groupId>
|
||||||
<artifactId>mcprotocollib</artifactId>
|
<artifactId>mcprotocollib</artifactId>
|
||||||
<version>26201a4</version>
|
<version>8c204eb</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
|
@ -153,7 +153,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.GeyserMC</groupId>
|
<groupId>com.github.GeyserMC</groupId>
|
||||||
<artifactId>PacketLib</artifactId>
|
<artifactId>PacketLib</artifactId>
|
||||||
<version>b77a427</version>
|
<version>6e5dea9</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion> <!-- Move this exclusion back to MCProtocolLib it gets the latest PacketLib -->
|
<exclusion> <!-- Move this exclusion back to MCProtocolLib it gets the latest PacketLib -->
|
||||||
|
|
|
@ -31,6 +31,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.nukkitx.network.raknet.RakNetConstants;
|
import com.nukkitx.network.raknet.RakNetConstants;
|
||||||
import com.nukkitx.network.util.EventLoops;
|
import com.nukkitx.network.util.EventLoops;
|
||||||
import com.nukkitx.protocol.bedrock.BedrockServer;
|
import com.nukkitx.protocol.bedrock.BedrockServer;
|
||||||
|
import io.netty.channel.epoll.Epoll;
|
||||||
|
import io.netty.channel.kqueue.KQueue;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.geysermc.common.PlatformType;
|
import org.geysermc.common.PlatformType;
|
||||||
|
@ -211,7 +213,7 @@ public class GeyserConnector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CooldownUtils.setShowCooldown(config.getShowCooldown());
|
CooldownUtils.setDefaultShowCooldown(config.getShowCooldown());
|
||||||
DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether
|
DimensionUtils.changeBedrockNetherId(config.isAboveBedrockNetherBuilding()); // Apply End dimension ID workaround to Nether
|
||||||
SkullBlockEntityTranslator.ALLOW_CUSTOM_SKULLS = config.isAllowCustomSkulls();
|
SkullBlockEntityTranslator.ALLOW_CUSTOM_SKULLS = config.isAllowCustomSkulls();
|
||||||
|
|
||||||
|
@ -226,6 +228,19 @@ public class GeyserConnector {
|
||||||
EventLoops.commonGroup(),
|
EventLoops.commonGroup(),
|
||||||
enableProxyProtocol
|
enableProxyProtocol
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (config.isDebugMode()) {
|
||||||
|
logger.debug("EventLoop type: " + EventLoops.getChannelType());
|
||||||
|
if (EventLoops.getChannelType() == EventLoops.ChannelType.NIO) {
|
||||||
|
if (System.getProperties().contains("disableNativeEventLoop")) {
|
||||||
|
logger.debug("EventLoop type is NIO because native event loops are disabled.");
|
||||||
|
} else {
|
||||||
|
logger.debug("Reason for no Epoll: " + Epoll.unavailabilityCause().toString());
|
||||||
|
logger.debug("Reason for no KQueue: " + KQueue.unavailabilityCause().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bedrockServer.setHandler(new ConnectorServerEventHandler(this));
|
bedrockServer.setHandler(new ConnectorServerEventHandler(this));
|
||||||
bedrockServer.bind().whenComplete((avoid, throwable) -> {
|
bedrockServer.bind().whenComplete((avoid, throwable) -> {
|
||||||
if (throwable == null) {
|
if (throwable == null) {
|
||||||
|
|
|
@ -46,10 +46,9 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTelepo
|
||||||
import com.github.steveice10.mc.protocol.packet.login.client.LoginPluginResponsePacket;
|
import com.github.steveice10.mc.protocol.packet.login.client.LoginPluginResponsePacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.login.server.LoginSuccessPacket;
|
import com.github.steveice10.mc.protocol.packet.login.server.LoginSuccessPacket;
|
||||||
import com.github.steveice10.packetlib.BuiltinFlags;
|
import com.github.steveice10.packetlib.BuiltinFlags;
|
||||||
import com.github.steveice10.packetlib.Client;
|
|
||||||
import com.github.steveice10.packetlib.event.session.*;
|
import com.github.steveice10.packetlib.event.session.*;
|
||||||
import com.github.steveice10.packetlib.packet.Packet;
|
import com.github.steveice10.packetlib.packet.Packet;
|
||||||
import com.github.steveice10.packetlib.tcp.TcpSessionFactory;
|
import com.github.steveice10.packetlib.tcp.TcpClientSession;
|
||||||
import com.nukkitx.math.GenericMath;
|
import com.nukkitx.math.GenericMath;
|
||||||
import com.nukkitx.math.vector.*;
|
import com.nukkitx.math.vector.*;
|
||||||
import com.nukkitx.protocol.bedrock.BedrockPacket;
|
import com.nukkitx.protocol.bedrock.BedrockPacket;
|
||||||
|
@ -115,7 +114,7 @@ public class GeyserSession implements CommandSender {
|
||||||
|
|
||||||
private final GeyserConnector connector;
|
private final GeyserConnector connector;
|
||||||
private final UpstreamSession upstream;
|
private final UpstreamSession upstream;
|
||||||
private Client downstream;
|
private TcpClientSession downstream;
|
||||||
@Setter
|
@Setter
|
||||||
private AuthData authData;
|
private AuthData authData;
|
||||||
@Setter
|
@Setter
|
||||||
|
@ -141,6 +140,7 @@ public class GeyserSession implements CommandSender {
|
||||||
private ChunkCache chunkCache;
|
private ChunkCache chunkCache;
|
||||||
private EntityCache entityCache;
|
private EntityCache entityCache;
|
||||||
private EntityEffectCache effectCache;
|
private EntityEffectCache effectCache;
|
||||||
|
private final PreferencesCache preferencesCache;
|
||||||
private final TagCache tagCache;
|
private final TagCache tagCache;
|
||||||
private WorldCache worldCache;
|
private WorldCache worldCache;
|
||||||
private FormCache formCache;
|
private FormCache formCache;
|
||||||
|
@ -445,6 +445,7 @@ public class GeyserSession implements CommandSender {
|
||||||
this.chunkCache = new ChunkCache(this);
|
this.chunkCache = new ChunkCache(this);
|
||||||
this.entityCache = new EntityCache(this);
|
this.entityCache = new EntityCache(this);
|
||||||
this.effectCache = new EntityEffectCache();
|
this.effectCache = new EntityEffectCache();
|
||||||
|
this.preferencesCache = new PreferencesCache(this);
|
||||||
this.tagCache = new TagCache();
|
this.tagCache = new TagCache();
|
||||||
this.worldCache = new WorldCache(this);
|
this.worldCache = new WorldCache(this);
|
||||||
this.formCache = new FormCache(this);
|
this.formCache = new FormCache(this);
|
||||||
|
@ -578,7 +579,7 @@ public class GeyserSession implements CommandSender {
|
||||||
authenticationService.setPassword(password);
|
authenticationService.setPassword(password);
|
||||||
authenticationService.login();
|
authenticationService.login();
|
||||||
|
|
||||||
protocol = new MinecraftProtocol(authenticationService);
|
protocol = new MinecraftProtocol(authenticationService.getSelectedProfile(), authenticationService.getAccessToken());
|
||||||
} else {
|
} else {
|
||||||
protocol = new MinecraftProtocol(username);
|
protocol = new MinecraftProtocol(username);
|
||||||
}
|
}
|
||||||
|
@ -636,7 +637,7 @@ public class GeyserSession implements CommandSender {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
msaAuthenticationService.login();
|
msaAuthenticationService.login();
|
||||||
protocol = new MinecraftProtocol(msaAuthenticationService);
|
protocol = new MinecraftProtocol(msaAuthenticationService.getSelectedProfile(), msaAuthenticationService.getAccessToken());
|
||||||
|
|
||||||
connectDownstream();
|
connectDownstream();
|
||||||
} catch (RequestException e) {
|
} catch (RequestException e) {
|
||||||
|
@ -658,17 +659,17 @@ public class GeyserSession implements CommandSender {
|
||||||
// Start ticking
|
// Start ticking
|
||||||
tickThread = connector.getGeneralThreadPool().scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS);
|
tickThread = connector.getGeneralThreadPool().scheduleAtFixedRate(this::tick, 50, 50, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
downstream = new Client(this.remoteAddress, this.remotePort, protocol, new TcpSessionFactory());
|
downstream = new TcpClientSession(this.remoteAddress, this.remotePort, protocol);
|
||||||
disableSrvResolving();
|
disableSrvResolving();
|
||||||
if (connector.getConfig().getRemote().isUseProxyProtocol()) {
|
if (connector.getConfig().getRemote().isUseProxyProtocol()) {
|
||||||
downstream.getSession().setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
|
downstream.setFlag(BuiltinFlags.ENABLE_CLIENT_PROXY_PROTOCOL, true);
|
||||||
downstream.getSession().setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
|
downstream.setFlag(BuiltinFlags.CLIENT_PROXIED_ADDRESS, upstream.getAddress());
|
||||||
}
|
}
|
||||||
if (connector.getConfig().isForwardPlayerPing()) {
|
if (connector.getConfig().isForwardPlayerPing()) {
|
||||||
// Let Geyser handle sending the keep alive
|
// Let Geyser handle sending the keep alive
|
||||||
downstream.getSession().setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false);
|
downstream.setFlag(MinecraftConstants.AUTOMATIC_KEEP_ALIVE_MANAGEMENT, false);
|
||||||
}
|
}
|
||||||
downstream.getSession().addListener(new SessionAdapter() {
|
downstream.addListener(new SessionAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void packetSending(PacketSendingEvent event) {
|
public void packetSending(PacketSendingEvent event) {
|
||||||
//todo move this somewhere else
|
//todo move this somewhere else
|
||||||
|
@ -805,15 +806,15 @@ public class GeyserSession implements CommandSender {
|
||||||
if (!daylightCycle) {
|
if (!daylightCycle) {
|
||||||
setDaylightCycle(true);
|
setDaylightCycle(true);
|
||||||
}
|
}
|
||||||
downstream.getSession().connect();
|
downstream.connect();
|
||||||
connector.addPlayer(this);
|
connector.addPlayer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect(String reason) {
|
public void disconnect(String reason) {
|
||||||
if (!closed) {
|
if (!closed) {
|
||||||
loggedIn = false;
|
loggedIn = false;
|
||||||
if (downstream != null && downstream.getSession() != null) {
|
if (downstream != null) {
|
||||||
downstream.getSession().disconnect(reason);
|
downstream.disconnect(reason);
|
||||||
}
|
}
|
||||||
if (upstream != null && !upstream.isClosed()) {
|
if (upstream != null && !upstream.isClosed()) {
|
||||||
connector.getPlayers().remove(this);
|
connector.getPlayers().remove(this);
|
||||||
|
@ -941,7 +942,7 @@ public class GeyserSession implements CommandSender {
|
||||||
* Will be overwritten for GeyserConnect.
|
* Will be overwritten for GeyserConnect.
|
||||||
*/
|
*/
|
||||||
protected void disableSrvResolving() {
|
protected void disableSrvResolving() {
|
||||||
this.downstream.getSession().setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, false);
|
this.downstream.setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1197,8 +1198,8 @@ public class GeyserSession implements CommandSender {
|
||||||
* @param packet the java edition packet from MCProtocolLib
|
* @param packet the java edition packet from MCProtocolLib
|
||||||
*/
|
*/
|
||||||
public void sendDownstreamPacket(Packet packet) {
|
public void sendDownstreamPacket(Packet packet) {
|
||||||
if (downstream != null && downstream.getSession() != null && (protocol.getSubProtocol().equals(SubProtocol.GAME) || packet.getClass() == LoginPluginResponsePacket.class)) {
|
if (downstream != null && (protocol.getSubProtocol().equals(SubProtocol.GAME) || packet.getClass() == LoginPluginResponsePacket.class)) {
|
||||||
downstream.getSession().send(packet);
|
downstream.send(packet);
|
||||||
} else {
|
} else {
|
||||||
connector.getLogger().debug("Tried to send downstream packet " + packet.getClass().getSimpleName() + " before connected to the server");
|
connector.getLogger().debug("Tried to send downstream packet " + packet.getClass().getSimpleName() + " before connected to the server");
|
||||||
}
|
}
|
||||||
|
@ -1213,7 +1214,7 @@ public class GeyserSession implements CommandSender {
|
||||||
public void setReducedDebugInfo(boolean value) {
|
public void setReducedDebugInfo(boolean value) {
|
||||||
reducedDebugInfo = value;
|
reducedDebugInfo = value;
|
||||||
// Set the showCoordinates data. This is done because updateShowCoordinates() uses this gamerule as a variable.
|
// Set the showCoordinates data. This is done because updateShowCoordinates() uses this gamerule as a variable.
|
||||||
getWorldCache().updateShowCoordinates();
|
preferencesCache.updateShowCoordinates();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -68,7 +68,7 @@ public class BookEditCache {
|
||||||
packet = null;
|
packet = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
session.getDownstream().getSession().send(packet);
|
session.sendDownstreamPacket(packet);
|
||||||
packet = null;
|
packet = null;
|
||||||
lastBookUpdate = System.currentTimeMillis();
|
lastBookUpdate = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
|
|
71
connector/src/main/java/org/geysermc/connector/network/session/cache/PreferencesCache.java
vendored
Normal file
71
connector/src/main/java/org/geysermc/connector/network/session/cache/PreferencesCache.java
vendored
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2021 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.connector.network.session.cache;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.geysermc.connector.configuration.GeyserConfiguration;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.utils.CooldownUtils;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class PreferencesCache {
|
||||||
|
private final GeyserSession session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the client prefers being shown their coordinates, regardless if they're being shown or not.
|
||||||
|
* This will be true everytime the client joins the server because neither the client nor server store the preference permanently.
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
private boolean prefersShowCoordinates = true;
|
||||||
|
/**
|
||||||
|
* If the client's preference will be ignored, this will return false.
|
||||||
|
*/
|
||||||
|
private boolean allowShowCoordinates;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which CooldownType the client prefers. Initially set to {@link CooldownUtils#getDefaultShowCooldown()}.
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
private CooldownUtils.CooldownType cooldownPreference = CooldownUtils.getDefaultShowCooldown();
|
||||||
|
|
||||||
|
public PreferencesCache(GeyserSession session) {
|
||||||
|
this.session = session;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tell the client to hide or show the coordinates.
|
||||||
|
*
|
||||||
|
* If {@link #prefersShowCoordinates} is true, coordinates will be shown, unless either of the following conditions apply: <br>
|
||||||
|
* <br>
|
||||||
|
* {@link GeyserSession#reducedDebugInfo} is enabled
|
||||||
|
* {@link GeyserConfiguration#isShowCoordinates()} is disabled
|
||||||
|
*/
|
||||||
|
public void updateShowCoordinates() {
|
||||||
|
allowShowCoordinates = !session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates();
|
||||||
|
session.sendGameRule("showcoordinates", allowShowCoordinates && prefersShowCoordinates);
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,6 @@ package org.geysermc.connector.network.session.cache;
|
||||||
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.geysermc.connector.configuration.GeyserConfiguration;
|
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.scoreboard.Objective;
|
import org.geysermc.connector.scoreboard.Objective;
|
||||||
import org.geysermc.connector.scoreboard.Scoreboard;
|
import org.geysermc.connector.scoreboard.Scoreboard;
|
||||||
|
@ -40,13 +39,6 @@ public class WorldCache {
|
||||||
@Setter
|
@Setter
|
||||||
private Difficulty difficulty = Difficulty.EASY;
|
private Difficulty difficulty = Difficulty.EASY;
|
||||||
|
|
||||||
/**
|
|
||||||
* True if the client prefers being shown their coordinates, regardless if they're being shown or not.
|
|
||||||
* This will be true everytime the client joins the server because neither the client nor server store the preference permanently.
|
|
||||||
*/
|
|
||||||
@Setter
|
|
||||||
private boolean prefersShowCoordinates = true;
|
|
||||||
|
|
||||||
private Scoreboard scoreboard;
|
private Scoreboard scoreboard;
|
||||||
private final ScoreboardUpdater scoreboardUpdater;
|
private final ScoreboardUpdater scoreboardUpdater;
|
||||||
|
|
||||||
|
@ -71,17 +63,4 @@ public class WorldCache {
|
||||||
int pps = scoreboardUpdater.getPacketsPerSecond();
|
int pps = scoreboardUpdater.getPacketsPerSecond();
|
||||||
return Math.max(pps, pendingPps);
|
return Math.max(pps, pendingPps);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Tell the client to hide or show the coordinates.
|
|
||||||
*
|
|
||||||
* If {@link #prefersShowCoordinates} is true, coordinates will be shown, unless either of the following conditions apply: <br>
|
|
||||||
* <br>
|
|
||||||
* {@link GeyserSession#reducedDebugInfo} is enabled
|
|
||||||
* {@link GeyserConfiguration#isShowCoordinates()} is disabled
|
|
||||||
*/
|
|
||||||
public void updateShowCoordinates() {
|
|
||||||
boolean allowShowCoordinates = !session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates();
|
|
||||||
session.sendGameRule("showcoordinates", allowShowCoordinates && prefersShowCoordinates);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -39,10 +39,7 @@ import com.nukkitx.math.vector.Vector3f;
|
||||||
import com.nukkitx.math.vector.Vector3i;
|
import com.nukkitx.math.vector.Vector3i;
|
||||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||||
import com.nukkitx.protocol.bedrock.data.entity.EntityFlags;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityFlags;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerId;
|
import com.nukkitx.protocol.bedrock.data.inventory.*;
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.InventoryActionData;
|
|
||||||
import com.nukkitx.protocol.bedrock.data.inventory.InventorySource;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.*;
|
import com.nukkitx.protocol.bedrock.packet.*;
|
||||||
import org.geysermc.connector.entity.CommandBlockMinecartEntity;
|
import org.geysermc.connector.entity.CommandBlockMinecartEntity;
|
||||||
import org.geysermc.connector.entity.Entity;
|
import org.geysermc.connector.entity.Entity;
|
||||||
|
@ -241,9 +238,10 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
||||||
session.setInteracting(true);
|
session.setInteracting(true);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (packet.getActions().size() == 1) {
|
if (packet.getActions().size() == 1 && packet.getLegacySlots().size() > 0) {
|
||||||
InventoryActionData actionData = packet.getActions().get(0);
|
InventoryActionData actionData = packet.getActions().get(0);
|
||||||
if (actionData.getSlot() == 6 && actionData.getToItem().getId() != 0) {
|
LegacySetItemSlotData slotData = packet.getLegacySlots().get(0);
|
||||||
|
if (slotData.getContainerId() == 6 && actionData.getToItem().getId() != 0) {
|
||||||
// The player is trying to swap out an armor piece that already has an item in it
|
// The player is trying to swap out an armor piece that already has an item in it
|
||||||
// Java Edition does not allow this; let's revert it
|
// Java Edition does not allow this; let's revert it
|
||||||
session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory());
|
session.getInventoryTranslator().updateInventory(session, session.getPlayerInventory());
|
||||||
|
|
|
@ -28,6 +28,7 @@ package org.geysermc.connector.utils;
|
||||||
import com.nukkitx.protocol.bedrock.packet.SetTitlePacket;
|
import com.nukkitx.protocol.bedrock.packet.SetTitlePacket;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.network.session.cache.PreferencesCache;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -36,18 +37,25 @@ import java.util.concurrent.TimeUnit;
|
||||||
* Much of the work here is from the wonderful folks from ViaRewind: https://github.com/ViaVersion/ViaRewind
|
* Much of the work here is from the wonderful folks from ViaRewind: https://github.com/ViaVersion/ViaRewind
|
||||||
*/
|
*/
|
||||||
public class CooldownUtils {
|
public class CooldownUtils {
|
||||||
private static CooldownType SHOW_COOLDOWN;
|
private static CooldownType DEFAULT_SHOW_COOLDOWN;
|
||||||
|
|
||||||
public static void setShowCooldown(String showCooldown) {
|
public static void setDefaultShowCooldown(String showCooldown) {
|
||||||
SHOW_COOLDOWN = CooldownType.getByName(showCooldown);
|
DEFAULT_SHOW_COOLDOWN = CooldownType.getByName(showCooldown);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CooldownType getDefaultShowCooldown() {
|
||||||
|
return DEFAULT_SHOW_COOLDOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts sending the fake cooldown to the Bedrock client.
|
* Starts sending the fake cooldown to the Bedrock client. If the cooldown is not disabled, the sent type is the cooldownPreference in {@link PreferencesCache}
|
||||||
* @param session GeyserSession
|
* @param session GeyserSession
|
||||||
*/
|
*/
|
||||||
public static void sendCooldown(GeyserSession session) {
|
public static void sendCooldown(GeyserSession session) {
|
||||||
if (SHOW_COOLDOWN == CooldownType.DISABLED) return;
|
if (DEFAULT_SHOW_COOLDOWN == CooldownType.DISABLED) return;
|
||||||
|
CooldownType sessionPreference = session.getPreferencesCache().getCooldownPreference();
|
||||||
|
if (sessionPreference == CooldownType.DISABLED) return;
|
||||||
|
|
||||||
if (session.getAttackSpeed() == 0.0 || session.getAttackSpeed() > 20) return; // 0.0 usually happens on login and causes issues with visuals; anything above 20 means a plugin like OldCombatMechanics is being used
|
if (session.getAttackSpeed() == 0.0 || session.getAttackSpeed() > 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
|
// Needs to be sent or no subtitle packet is recognized by the client
|
||||||
SetTitlePacket titlePacket = new SetTitlePacket();
|
SetTitlePacket titlePacket = new SetTitlePacket();
|
||||||
|
@ -56,19 +64,20 @@ public class CooldownUtils {
|
||||||
session.sendUpstreamPacket(titlePacket);
|
session.sendUpstreamPacket(titlePacket);
|
||||||
session.setLastHitTime(System.currentTimeMillis());
|
session.setLastHitTime(System.currentTimeMillis());
|
||||||
long lastHitTime = session.getLastHitTime(); // Used later to prevent multiple scheduled cooldown threads
|
long lastHitTime = session.getLastHitTime(); // Used later to prevent multiple scheduled cooldown threads
|
||||||
computeCooldown(session, lastHitTime);
|
computeCooldown(session, sessionPreference, lastHitTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps updating the cooldown until the bar is complete.
|
* Keeps updating the cooldown until the bar is complete.
|
||||||
* @param session GeyserSession
|
* @param session GeyserSession
|
||||||
|
* @param sessionPreference The type of cooldown the client prefers
|
||||||
* @param lastHitTime The time of the last hit. Used to gauge how long the cooldown is taking.
|
* @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) {
|
private static void computeCooldown(GeyserSession session, CooldownType sessionPreference, long lastHitTime) {
|
||||||
if (session.isClosed()) return; // Don't run scheduled tasks if the client left
|
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
|
if (lastHitTime != session.getLastHitTime()) return; // Means another cooldown has started so there's no need to continue this one
|
||||||
SetTitlePacket titlePacket = new SetTitlePacket();
|
SetTitlePacket titlePacket = new SetTitlePacket();
|
||||||
if (SHOW_COOLDOWN == CooldownType.ACTIONBAR) {
|
if (sessionPreference == CooldownType.ACTIONBAR) {
|
||||||
titlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
|
titlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
|
||||||
} else {
|
} else {
|
||||||
titlePacket.setType(SetTitlePacket.Type.SUBTITLE);
|
titlePacket.setType(SetTitlePacket.Type.SUBTITLE);
|
||||||
|
@ -79,10 +88,10 @@ public class CooldownUtils {
|
||||||
titlePacket.setStayTime(2);
|
titlePacket.setStayTime(2);
|
||||||
session.sendUpstreamPacket(titlePacket);
|
session.sendUpstreamPacket(titlePacket);
|
||||||
if (hasCooldown(session)) {
|
if (hasCooldown(session)) {
|
||||||
session.getConnector().getGeneralThreadPool().schedule(() -> computeCooldown(session, lastHitTime), 50, TimeUnit.MILLISECONDS); // Updated per tick. 1000 divided by 20 ticks equals 50
|
session.getConnector().getGeneralThreadPool().schedule(() -> computeCooldown(session, sessionPreference, lastHitTime), 50, TimeUnit.MILLISECONDS); // Updated per tick. 1000 divided by 20 ticks equals 50
|
||||||
} else {
|
} else {
|
||||||
SetTitlePacket removeTitlePacket = new SetTitlePacket();
|
SetTitlePacket removeTitlePacket = new SetTitlePacket();
|
||||||
if (SHOW_COOLDOWN == CooldownType.ACTIONBAR) {
|
if (sessionPreference == CooldownType.ACTIONBAR) {
|
||||||
removeTitlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
|
removeTitlePacket.setType(SetTitlePacket.Type.ACTIONBAR);
|
||||||
} else {
|
} else {
|
||||||
removeTitlePacket.setType(SetTitlePacket.Type.SUBTITLE);
|
removeTitlePacket.setType(SetTitlePacket.Type.SUBTITLE);
|
||||||
|
@ -133,7 +142,7 @@ public class CooldownUtils {
|
||||||
public static final CooldownType[] VALUES = values();
|
public static final CooldownType[] VALUES = values();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the CooldownType string (from config) to the enum, TITLE on fail
|
* Convert the CooldownType string (from config) to the enum, DISABLED on fail
|
||||||
*
|
*
|
||||||
* @param name CooldownType string
|
* @param name CooldownType string
|
||||||
*
|
*
|
||||||
|
|
|
@ -34,6 +34,8 @@ import org.geysermc.cumulus.CustomForm;
|
||||||
import org.geysermc.cumulus.component.DropdownComponent;
|
import org.geysermc.cumulus.component.DropdownComponent;
|
||||||
import org.geysermc.cumulus.response.CustomFormResponse;
|
import org.geysermc.cumulus.response.CustomFormResponse;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public class SettingsUtils {
|
public class SettingsUtils {
|
||||||
/**
|
/**
|
||||||
* Build a settings form for the given session and store it for later
|
* Build a settings form for the given session and store it for later
|
||||||
|
@ -49,12 +51,23 @@ public class SettingsUtils {
|
||||||
.title("geyser.settings.title.main")
|
.title("geyser.settings.title.main")
|
||||||
.iconPath("textures/ui/settings_glyph_color_2x.png");
|
.iconPath("textures/ui/settings_glyph_color_2x.png");
|
||||||
|
|
||||||
// Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config.
|
// Only show the client title if any of the client settings are available
|
||||||
if (!session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates()) {
|
if (session.getPreferencesCache().isAllowShowCoordinates() || CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) {
|
||||||
builder.label("geyser.settings.title.client")
|
builder.label("geyser.settings.title.client");
|
||||||
.toggle("geyser.settings.option.coordinates", session.getWorldCache().isPrefersShowCoordinates());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config.
|
||||||
|
if (session.getPreferencesCache().isAllowShowCoordinates()) {
|
||||||
|
builder.toggle("geyser.settings.option.coordinates", session.getPreferencesCache().isPrefersShowCoordinates());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) {
|
||||||
|
DropdownComponent.Builder cooldownDropdown = DropdownComponent.builder("options.attackIndicator");
|
||||||
|
cooldownDropdown.option("options.attack.crosshair", session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.TITLE);
|
||||||
|
cooldownDropdown.option("options.attack.hotbar", session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.ACTIONBAR);
|
||||||
|
cooldownDropdown.option("options.off", session.getPreferencesCache().getCooldownPreference() == CooldownUtils.CooldownType.DISABLED);
|
||||||
|
builder.dropdown(cooldownDropdown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
||||||
builder.label("geyser.settings.title.server");
|
builder.label("geyser.settings.title.server");
|
||||||
|
@ -97,13 +110,22 @@ public class SettingsUtils {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config.
|
if (session.getPreferencesCache().isAllowShowCoordinates() || CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) {
|
||||||
if (!session.isReducedDebugInfo() && session.getConnector().getConfig().isShowCoordinates()) {
|
response.skip(); // Client settings title
|
||||||
response.skip(); // Client settings title
|
|
||||||
|
|
||||||
session.getWorldCache().setPrefersShowCoordinates(response.next());
|
// Client can only see its coordinates if reducedDebugInfo is disabled and coordinates are enabled in geyser config.
|
||||||
session.getWorldCache().updateShowCoordinates();
|
if (session.getPreferencesCache().isAllowShowCoordinates()) {
|
||||||
}
|
session.getPreferencesCache().setPrefersShowCoordinates(response.next());
|
||||||
|
session.getPreferencesCache().updateShowCoordinates();
|
||||||
|
response.skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CooldownUtils.getDefaultShowCooldown() != CooldownUtils.CooldownType.DISABLED) {
|
||||||
|
CooldownUtils.CooldownType cooldownType = CooldownUtils.CooldownType.VALUES[(int) response.next()];
|
||||||
|
session.getPreferencesCache().setCooldownPreference(cooldownType);
|
||||||
|
response.skip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
if (session.getOpPermissionLevel() >= 2 || session.hasPermission("geyser.settings.server")) {
|
||||||
GameMode gameMode = GameMode.values()[(int) response.next()];
|
GameMode gameMode = GameMode.values()[(int) response.next()];
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 96e7ed66ccdafea0cc991b8004566d448e8f6e6a
|
Subproject commit e1e8fd6c2b8abf366e60085c23a55a2c943806ae
|
Loading…
Reference in a new issue