Skip to content

Commit

Permalink
Add support for client side settings (#1035)
Browse files Browse the repository at this point in the history
* Port code from #486

Co-authored-by: Luke <[email protected]>

* Fix and clean code and add default gamemode changing

* Clean copyright

* Remove direct modification of server, clean up code and add player list xuid fetching.

* Move to custom settings menu

* Move sendAdventureSettings to GeyserSession

* Add javadoc comments

* Add translation support

* Remove updated copyright

* Clean up

* Clarify some javadoc comments

* Remove obsolete code

* Update languages submodule

* Fix javadoc comments

* Fix compile

Co-authored-by: Luke <[email protected]>
Co-authored-by: Redned <[email protected]>
  • Loading branch information
3 people authored Aug 8, 2020
1 parent 0fde30f commit 0a50482
Show file tree
Hide file tree
Showing 29 changed files with 668 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,19 @@

package org.geysermc.platform.spigot.world;

import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import lombok.AllArgsConstructor;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.world.WorldManager;
import org.geysermc.connector.network.translators.world.GeyserWorldManager;
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.utils.GameRule;
import us.myles.ViaVersion.protocols.protocol1_13_1to1_13.Protocol1_13_1To1_13;
import us.myles.ViaVersion.protocols.protocol1_16to1_15_2.data.MappingData;

@AllArgsConstructor
public class GeyserSpigotWorldManager extends WorldManager {
public class GeyserSpigotWorldManager extends GeyserWorldManager {

private final boolean isLegacy;
// You need ViaVersion to connect to an older server with Geyser.
Expand Down Expand Up @@ -69,4 +71,19 @@ public static int getLegacyBlock(GeyserSession session, int x, int y, int z, boo
return BlockTranslator.AIR;
}
}

@Override
public Boolean getGameRuleBool(GeyserSession session, GameRule gameRule) {
return Boolean.parseBoolean(Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getGameRuleValue(gameRule.getJavaID()));
}

@Override
public int getGameRuleInt(GeyserSession session, GameRule gameRule) {
return Integer.parseInt(Bukkit.getPlayer(session.getPlayerEntity().getUsername()).getWorld().getGameRuleValue(gameRule.getJavaID()));
}

@Override
public boolean hasPermission(GeyserSession session, String permission) {
return Bukkit.getPlayer(session.getPlayerEntity().getUsername()).hasPermission(permission);
}
}
6 changes: 6 additions & 0 deletions connector/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@
<version>8.3.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.nukkitx.fastutil</groupId>
<artifactId>fastutil-object-object-maps</artifactId>
<version>8.3.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.GeyserLogger;
import org.geysermc.connector.command.CommandManager;
import org.geysermc.connector.network.translators.world.CachedChunkManager;
import org.geysermc.connector.network.translators.world.GeyserWorldManager;
import org.geysermc.connector.network.translators.world.WorldManager;

import java.nio.file.Path;

public interface GeyserBootstrap {

CachedChunkManager DEFAULT_CHUNK_MANAGER = new CachedChunkManager();
GeyserWorldManager DEFAULT_CHUNK_MANAGER = new GeyserWorldManager();

/**
* Called when the GeyserBootstrap is enabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.github.steveice10.mc.protocol.data.message.TextMessage;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.AdventureSetting;
import com.nukkitx.protocol.bedrock.data.AttributeData;
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
Expand All @@ -47,10 +48,7 @@
import org.geysermc.connector.utils.AttributeUtils;
import org.geysermc.connector.utils.MessageUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Getter @Setter
Expand Down Expand Up @@ -95,7 +93,7 @@ public void spawnEntity(GeyserSession session) {
addPlayerPacket.setMotion(motion);
addPlayerPacket.setHand(hand);
addPlayerPacket.getAdventureSettings().setCommandPermission(CommandPermission.NORMAL);
addPlayerPacket.getAdventureSettings().setPlayerPermission(PlayerPermission.VISITOR);
addPlayerPacket.getAdventureSettings().setPlayerPermission(PlayerPermission.MEMBER);
addPlayerPacket.setDeviceId("");
addPlayerPacket.setPlatformChatId("");
addPlayerPacket.getMetadata().putAll(metadata);
Expand Down Expand Up @@ -212,7 +210,7 @@ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession s

if (entityMetadata.getId() == 2) {
// System.out.println(session.getScoreboardCache().getScoreboard().getObjectives().keySet());
for (Team team : session.getScoreboardCache().getScoreboard().getTeams().values()) {
for (Team team : session.getWorldCache().getScoreboard().getTeams().values()) {
// session.getConnector().getLogger().info("team name " + team.getName());
// session.getConnector().getLogger().info("team entities " + team.getEntities());
}
Expand All @@ -221,7 +219,7 @@ public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession s
if (name != null) {
username = MessageUtils.getBedrockMessage(name);
}
Team team = session.getScoreboardCache().getScoreboard().getTeamFor(username);
Team team = session.getWorldCache().getScoreboard().getTeamFor(username);
if (team != null) {
// session.getConnector().getLogger().info("team name es " + team.getName() + " with prefix " + team.getPrefix() + " and suffix " + team.getSuffix());
metadata.put(EntityData.NAMETAG, team.getPrefix() + MessageUtils.toChatColor(team.getColor()) + username + team.getSuffix());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.geysermc.connector.network.translators.PacketTranslatorRegistry;
import org.geysermc.connector.utils.LoginEncryptionUtils;
import org.geysermc.connector.utils.LanguageUtils;
import org.geysermc.connector.utils.SettingsUtils;

public class UpstreamPacketHandler extends LoggingPacketHandler {

Expand Down Expand Up @@ -91,6 +92,10 @@ public boolean handle(ResourcePackClientResponsePacket packet) {

@Override
public boolean handle(ModalFormResponsePacket packet) {
if (packet.getFormId() == SettingsUtils.SETTINGS_FORM_ID) {
return SettingsUtils.handleSettingsForm(session, packet.getFormData());
}

return LoginEncryptionUtils.authenticateFromForm(session, connector, packet.getFormId(), packet.getFormData());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
import com.nukkitx.protocol.bedrock.BedrockPacket;
import com.nukkitx.protocol.bedrock.BedrockServerSession;
import com.nukkitx.protocol.bedrock.data.*;
import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
import com.nukkitx.protocol.bedrock.packet.*;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMaps;
Expand All @@ -54,6 +55,7 @@
import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.common.window.CustomFormWindow;
import org.geysermc.common.window.FormWindow;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
Expand All @@ -79,9 +81,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

@Getter
Expand All @@ -102,7 +102,7 @@ public class GeyserSession implements CommandSender {
private ChunkCache chunkCache;
private EntityCache entityCache;
private InventoryCache inventoryCache;
private ScoreboardCache scoreboardCache;
private WorldCache worldCache;
private WindowCache windowCache;
@Setter
private TeleportCache teleportCache;
Expand Down Expand Up @@ -191,14 +191,49 @@ public class GeyserSession implements CommandSender {

private MinecraftProtocol protocol;

private boolean reducedDebugInfo = false;

@Setter
private CustomFormWindow settingsForm;

/**
* The op permission level set by the server
*/
@Setter
private int opPermissionLevel = 0;

/**
* If the current player can fly
*/
@Setter
private boolean canFly = false;

/**
* If the current player is flying
*/
@Setter
private boolean flying = false;

/**
* If the current player is in noclip
*/
@Setter
private boolean noClip = false;

/**
* If the current player can not interact with the world
*/
@Setter
private boolean worldImmutable = false;

public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) {
this.connector = connector;
this.upstream = new UpstreamSession(bedrockServerSession);

this.chunkCache = new ChunkCache(this);
this.entityCache = new EntityCache(this);
this.inventoryCache = new InventoryCache(this);
this.scoreboardCache = new ScoreboardCache(this);
this.worldCache = new WorldCache(this);
this.windowCache = new WindowCache(this);

this.playerEntity = new PlayerEntity(new GameProfile(UUID.randomUUID(), "unknown"), 1, 1, Vector3f.ZERO, Vector3f.ZERO, Vector3f.ZERO);
Expand Down Expand Up @@ -440,7 +475,7 @@ public void disconnect(String reason) {

this.chunkCache = null;
this.entityCache = null;
this.scoreboardCache = null;
this.worldCache = null;
this.inventoryCache = null;
this.windowCache = null;

Expand Down Expand Up @@ -605,4 +640,66 @@ public void sendDownstreamPacket(Packet packet) {
connector.getLogger().debug("Tried to send downstream packet " + packet.getClass().getSimpleName() + " before connected to the server");
}
}

/**
* Update the cached value for the reduced debug info gamerule.
* This also toggles the coordinates display
*
* @param value The new value for reducedDebugInfo
*/
public void setReducedDebugInfo(boolean value) {
worldCache.setShowCoordinates(!value);
reducedDebugInfo = value;
}

/**
* Send a gamerule value to the client
*
* @param gameRule The gamerule to send
* @param value The value of the gamerule
*/
public void sendGameRule(String gameRule, Object value) {
GameRulesChangedPacket gameRulesChangedPacket = new GameRulesChangedPacket();
gameRulesChangedPacket.getGameRules().add(new GameRuleData<>(gameRule, value));
upstream.sendPacket(gameRulesChangedPacket);
}

/**
* @see org.geysermc.connector.network.translators.world.WorldManager#hasPermission(GeyserSession, String)
*/
public Boolean hasPermission(String permission) {
return connector.getWorldManager().hasPermission(this, permission);
}

/**
* Send an AdventureSettingsPacket to the client with the latest flags
*/
public void sendAdventureSettings() {
AdventureSettingsPacket adventureSettingsPacket = new AdventureSettingsPacket();
adventureSettingsPacket.setUniqueEntityId(playerEntity.getGeyserId());
adventureSettingsPacket.setCommandPermission(CommandPermission.NORMAL);
adventureSettingsPacket.setPlayerPermission(PlayerPermission.MEMBER);

Set<AdventureSetting> flags = new HashSet<>();
if (canFly) {
flags.add(AdventureSetting.MAY_FLY);
}

if (flying) {
flags.add(AdventureSetting.FLYING);
}

if (worldImmutable) {
flags.add(AdventureSetting.WORLD_IMMUTABLE);
}

if (noClip) {
flags.add(AdventureSetting.NO_CLIP);
}

flags.add(AdventureSetting.AUTO_JUMP);

adventureSettingsPacket.getSettings().addAll(flags);
sendUpstreamPacket(adventureSettingsPacket);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,28 @@

package org.geysermc.connector.network.session.cache;

import com.github.steveice10.mc.protocol.data.game.setting.Difficulty;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.scoreboard.Objective;
import org.geysermc.connector.scoreboard.Scoreboard;

import java.util.Collection;

@Getter
public class ScoreboardCache {
public class WorldCache {

private GeyserSession session;

@Setter
private Difficulty difficulty = Difficulty.EASY;

private boolean showCoordinates = true;

private Scoreboard scoreboard;

public ScoreboardCache(GeyserSession session) {
public WorldCache(GeyserSession session) {
this.session = session;
this.scoreboard = new Scoreboard(session);
}
Expand All @@ -52,4 +61,14 @@ public void removeScoreboard() {
}
}
}

/**
* Tell the client to hide or show the coordinates
*
* @param value True to show, false to hide
*/
public void setShowCoordinates(boolean value) {
showCoordinates = value;
session.sendGameRule("showcoordinates", value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,25 @@
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.connector.network.translators.world;
package org.geysermc.connector.network.translators.bedrock;

import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.nukkitx.protocol.bedrock.packet.ServerSettingsRequestPacket;
import com.nukkitx.protocol.bedrock.packet.ServerSettingsResponsePacket;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.utils.SettingsUtils;

public class CachedChunkManager extends WorldManager {
@Translator(packet = ServerSettingsRequestPacket.class)
public class BedrockServerSettingsRequestTranslator extends PacketTranslator<ServerSettingsRequestPacket> {

@Override
public int getBlockAt(GeyserSession session, int x, int y, int z) {
return session.getChunkCache().getBlockAt(new Position(x, y, z));
public void translate(ServerSettingsRequestPacket packet, GeyserSession session) {
SettingsUtils.buildForm(session);

ServerSettingsResponsePacket serverSettingsResponsePacket = new ServerSettingsResponsePacket();
serverSettingsResponsePacket.setFormData(session.getSettingsForm().getJSONData());
serverSettingsResponsePacket.setFormId(SettingsUtils.SETTINGS_FORM_ID);
session.sendUpstreamPacket(serverSettingsResponsePacket);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.connector.network.translators.bedrock;
package org.geysermc.connector.network.translators.bedrock.entity;

import com.github.steveice10.mc.protocol.data.game.window.VillagerTrade;
import com.github.steveice10.mc.protocol.data.game.window.WindowType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
* @link https://github.com/GeyserMC/Geyser
*/

package org.geysermc.connector.network.translators.bedrock;
package org.geysermc.connector.network.translators.bedrock.entity.player;

import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
Expand Down
Loading

0 comments on commit 0a50482

Please sign in to comment.