Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-20 06:50:09 +01:00
Refactor GeyserSession tracking for better concurrency
Dieser Commit ist enthalten in:
Ursprung
62cded2daf
Commit
09e3793fb2
@ -49,6 +49,8 @@ import org.geysermc.connector.utils.Direction;
|
|||||||
import org.geysermc.platform.spigot.world.manager.GeyserSpigotWorldManager;
|
import org.geysermc.platform.spigot.world.manager.GeyserSpigotWorldManager;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class GeyserPistonListener implements Listener {
|
public class GeyserPistonListener implements Listener {
|
||||||
private final GeyserConnector connector;
|
private final GeyserConnector connector;
|
||||||
@ -86,11 +88,12 @@ public class GeyserPistonListener implements Listener {
|
|||||||
Object2IntMap<Vector3i> attachedBlocks = new Object2IntOpenHashMap<>();
|
Object2IntMap<Vector3i> attachedBlocks = new Object2IntOpenHashMap<>();
|
||||||
boolean blocksFilled = false;
|
boolean blocksFilled = false;
|
||||||
|
|
||||||
for (GeyserSession session : connector.getPlayers()) {
|
for (Map.Entry<UUID, GeyserSession> entry : connector.getSessionManager().getSessions().entrySet()) {
|
||||||
Player player = Bukkit.getPlayer(session.getPlayerEntity().getUuid());
|
Player player = Bukkit.getPlayer(entry.getKey());
|
||||||
if (player == null || !player.getWorld().equals(world)) {
|
if (player == null || !player.getWorld().equals(world)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
GeyserSession session = entry.getValue();
|
||||||
|
|
||||||
int dX = Math.abs(location.getBlockX() - player.getLocation().getBlockX()) >> 4;
|
int dX = Math.abs(location.getBlockX() - player.getLocation().getBlockX()) >> 4;
|
||||||
int dZ = Math.abs(location.getBlockZ() - player.getLocation().getBlockZ()) >> 4;
|
int dZ = Math.abs(location.getBlockZ() - player.getLocation().getBlockZ()) >> 4;
|
||||||
|
@ -80,7 +80,7 @@ public class GeyserSpigot1_11CraftingListener implements Listener {
|
|||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||||
GeyserSession session = null;
|
GeyserSession session = null;
|
||||||
for (GeyserSession otherSession : connector.getPlayers()) {
|
for (GeyserSession otherSession : connector.getSessionManager().getSessions().values()) {
|
||||||
if (otherSession.getName().equals(event.getPlayer().getName())) {
|
if (otherSession.getName().equals(event.getPlayer().getName())) {
|
||||||
session = otherSession;
|
session = otherSession;
|
||||||
break;
|
break;
|
||||||
|
@ -29,7 +29,6 @@ import com.nukkitx.math.vector.Vector3f;
|
|||||||
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
import com.nukkitx.protocol.bedrock.data.SoundEvent;
|
||||||
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
|
import com.nukkitx.protocol.bedrock.packet.LevelSoundEventPacket;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
@ -41,32 +40,30 @@ import org.geysermc.platform.spigot.world.manager.GeyserSpigotWorldManager;
|
|||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class GeyserSpigotBlockPlaceListener implements Listener {
|
public class GeyserSpigotBlockPlaceListener implements Listener {
|
||||||
|
|
||||||
private final GeyserConnector connector;
|
private final GeyserConnector connector;
|
||||||
private final GeyserSpigotWorldManager worldManager;
|
private final GeyserSpigotWorldManager worldManager;
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void place(final BlockPlaceEvent event) {
|
public void place(final BlockPlaceEvent event) {
|
||||||
for (GeyserSession session : connector.getPlayers()) {
|
GeyserSession session = connector.getPlayerByUuid(event.getPlayer().getUniqueId());
|
||||||
if (event.getPlayer() == Bukkit.getPlayer(session.getPlayerEntity().getUsername())) {
|
if (session == null) {
|
||||||
LevelSoundEventPacket placeBlockSoundPacket = new LevelSoundEventPacket();
|
return;
|
||||||
placeBlockSoundPacket.setSound(SoundEvent.PLACE);
|
|
||||||
placeBlockSoundPacket.setPosition(Vector3f.from(event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ()));
|
|
||||||
placeBlockSoundPacket.setBabySound(false);
|
|
||||||
if (worldManager.isLegacy()) {
|
|
||||||
placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(worldManager.getBlockAt(session,
|
|
||||||
event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ())));
|
|
||||||
} else {
|
|
||||||
String javaBlockId = event.getBlockPlaced().getBlockData().getAsString();
|
|
||||||
placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIERS.get().getOrDefault(javaBlockId, BlockStateValues.JAVA_AIR_ID)));
|
|
||||||
}
|
|
||||||
placeBlockSoundPacket.setIdentifier(":");
|
|
||||||
session.sendUpstreamPacket(placeBlockSoundPacket);
|
|
||||||
session.setLastBlockPlacePosition(null);
|
|
||||||
session.setLastBlockPlacedId(null);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
LevelSoundEventPacket placeBlockSoundPacket = new LevelSoundEventPacket();
|
||||||
|
placeBlockSoundPacket.setSound(SoundEvent.PLACE);
|
||||||
|
placeBlockSoundPacket.setPosition(Vector3f.from(event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ()));
|
||||||
|
placeBlockSoundPacket.setBabySound(false);
|
||||||
|
if (worldManager.isLegacy()) {
|
||||||
|
placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(worldManager.getBlockAt(session,
|
||||||
|
event.getBlockPlaced().getX(), event.getBlockPlaced().getY(), event.getBlockPlaced().getZ())));
|
||||||
|
} else {
|
||||||
|
String javaBlockId = event.getBlockPlaced().getBlockData().getAsString();
|
||||||
|
placeBlockSoundPacket.setExtraData(session.getBlockMappings().getBedrockBlockId(BlockRegistries.JAVA_IDENTIFIERS.get().getOrDefault(javaBlockId, BlockStateValues.JAVA_AIR_ID)));
|
||||||
|
}
|
||||||
|
placeBlockSoundPacket.setIdentifier(":");
|
||||||
|
session.sendUpstreamPacket(placeBlockSoundPacket);
|
||||||
|
session.setLastBlockPlacePosition(null);
|
||||||
|
session.setLastBlockPlacedId(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,7 +306,7 @@ public class GeyserStandaloneGUI {
|
|||||||
// Update player table
|
// Update player table
|
||||||
playerTableModel.getDataVector().removeAllElements();
|
playerTableModel.getDataVector().removeAllElements();
|
||||||
|
|
||||||
for (GeyserSession player : GeyserConnector.getInstance().getPlayers()) {
|
for (GeyserSession player : GeyserConnector.getInstance().getSessionManager().getSessions().values()) {
|
||||||
Vector<String> row = new Vector<>();
|
Vector<String> row = new Vector<>();
|
||||||
row.add(player.getSocketAddress().getHostName());
|
row.add(player.getSocketAddress().getHostName());
|
||||||
row.add(player.getPlayerEntity().getUsername());
|
row.add(player.getPlayerEntity().getUsername());
|
||||||
|
@ -52,7 +52,6 @@ import org.geysermc.connector.registry.Registries;
|
|||||||
import org.geysermc.connector.network.translators.PacketTranslatorRegistry;
|
import org.geysermc.connector.network.translators.PacketTranslatorRegistry;
|
||||||
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
import org.geysermc.connector.network.translators.item.ItemTranslator;
|
||||||
import org.geysermc.connector.network.translators.world.WorldManager;
|
import org.geysermc.connector.network.translators.world.WorldManager;
|
||||||
import org.geysermc.connector.network.translators.world.block.entity.SkullBlockEntityTranslator;
|
|
||||||
import org.geysermc.connector.scoreboard.ScoreboardUpdater;
|
import org.geysermc.connector.scoreboard.ScoreboardUpdater;
|
||||||
import org.geysermc.connector.skin.FloodgateSkinUploader;
|
import org.geysermc.connector.skin.FloodgateSkinUploader;
|
||||||
import org.geysermc.connector.utils.*;
|
import org.geysermc.connector.utils.*;
|
||||||
@ -72,10 +71,7 @@ import java.net.UnknownHostException;
|
|||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -100,7 +96,7 @@ public class GeyserConnector {
|
|||||||
|
|
||||||
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";
|
||||||
|
|
||||||
private final List<GeyserSession> players = new ArrayList<>();
|
private final SessionManager sessionManager = new SessionManager();
|
||||||
|
|
||||||
private static GeyserConnector instance;
|
private static GeyserConnector instance;
|
||||||
|
|
||||||
@ -115,7 +111,7 @@ public class GeyserConnector {
|
|||||||
private FloodgateSkinUploader skinUploader;
|
private FloodgateSkinUploader skinUploader;
|
||||||
private final NewsHandler newsHandler;
|
private final NewsHandler newsHandler;
|
||||||
|
|
||||||
private boolean shuttingDown = false;
|
private volatile boolean shuttingDown = false;
|
||||||
|
|
||||||
private final ScheduledExecutorService generalThreadPool;
|
private final ScheduledExecutorService generalThreadPool;
|
||||||
|
|
||||||
@ -123,7 +119,7 @@ public class GeyserConnector {
|
|||||||
private final PlatformType platformType;
|
private final PlatformType platformType;
|
||||||
private final GeyserBootstrap bootstrap;
|
private final GeyserBootstrap bootstrap;
|
||||||
|
|
||||||
private Metrics metrics;
|
private final Metrics metrics;
|
||||||
|
|
||||||
private GeyserConnector(PlatformType platformType, GeyserBootstrap bootstrap) {
|
private GeyserConnector(PlatformType platformType, GeyserBootstrap bootstrap) {
|
||||||
long startupTime = System.currentTimeMillis();
|
long startupTime = System.currentTimeMillis();
|
||||||
@ -277,7 +273,7 @@ public class GeyserConnector {
|
|||||||
|
|
||||||
if (config.getMetrics().isEnabled()) {
|
if (config.getMetrics().isEnabled()) {
|
||||||
metrics = new Metrics(this, "GeyserMC", config.getMetrics().getUniqueId(), false, java.util.logging.Logger.getLogger(""));
|
metrics = new Metrics(this, "GeyserMC", config.getMetrics().getUniqueId(), false, java.util.logging.Logger.getLogger(""));
|
||||||
metrics.addCustomChart(new Metrics.SingleLineChart("players", players::size));
|
metrics.addCustomChart(new Metrics.SingleLineChart("players", sessionManager::size));
|
||||||
// Prevent unwanted words best we can
|
// Prevent unwanted words best we can
|
||||||
metrics.addCustomChart(new Metrics.SimplePie("authMode", () -> config.getRemote().getAuthType().toString().toLowerCase()));
|
metrics.addCustomChart(new Metrics.SimplePie("authMode", () -> config.getRemote().getAuthType().toString().toLowerCase()));
|
||||||
metrics.addCustomChart(new Metrics.SimplePie("platform", platformType::getPlatformName));
|
metrics.addCustomChart(new Metrics.SimplePie("platform", platformType::getPlatformName));
|
||||||
@ -285,7 +281,7 @@ public class GeyserConnector {
|
|||||||
metrics.addCustomChart(new Metrics.SimplePie("version", () -> GeyserConnector.VERSION));
|
metrics.addCustomChart(new Metrics.SimplePie("version", () -> GeyserConnector.VERSION));
|
||||||
metrics.addCustomChart(new Metrics.AdvancedPie("playerPlatform", () -> {
|
metrics.addCustomChart(new Metrics.AdvancedPie("playerPlatform", () -> {
|
||||||
Map<String, Integer> valueMap = new HashMap<>();
|
Map<String, Integer> valueMap = new HashMap<>();
|
||||||
for (GeyserSession session : players) {
|
for (GeyserSession session : sessionManager.getAllSessions()) {
|
||||||
if (session == null) continue;
|
if (session == null) continue;
|
||||||
if (session.getClientData() == null) continue;
|
if (session.getClientData() == null) continue;
|
||||||
String os = session.getClientData().getDeviceOs().toString();
|
String os = session.getClientData().getDeviceOs().toString();
|
||||||
@ -299,7 +295,7 @@ public class GeyserConnector {
|
|||||||
}));
|
}));
|
||||||
metrics.addCustomChart(new Metrics.AdvancedPie("playerVersion", () -> {
|
metrics.addCustomChart(new Metrics.AdvancedPie("playerVersion", () -> {
|
||||||
Map<String, Integer> valueMap = new HashMap<>();
|
Map<String, Integer> valueMap = new HashMap<>();
|
||||||
for (GeyserSession session : players) {
|
for (GeyserSession session : sessionManager.getAllSessions()) {
|
||||||
if (session == null) continue;
|
if (session == null) continue;
|
||||||
if (session.getClientData() == null) continue;
|
if (session.getClientData() == null) continue;
|
||||||
String version = session.getClientData().getGameVersion();
|
String version = session.getClientData().getGameVersion();
|
||||||
@ -359,6 +355,8 @@ public class GeyserConnector {
|
|||||||
map.put(release, entry);
|
map.put(release, entry);
|
||||||
return map;
|
return map;
|
||||||
}));
|
}));
|
||||||
|
} else {
|
||||||
|
metrics = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isGui = false;
|
boolean isGui = false;
|
||||||
@ -392,40 +390,10 @@ public class GeyserConnector {
|
|||||||
bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown"));
|
bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown"));
|
||||||
shuttingDown = true;
|
shuttingDown = true;
|
||||||
|
|
||||||
if (players.size() >= 1) {
|
if (sessionManager.size() >= 1) {
|
||||||
bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.kick.log", players.size()));
|
bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.kick.log", sessionManager.size()));
|
||||||
|
sessionManager.disconnectAll("geyser.core.shutdown.kick.message");
|
||||||
// Make a copy to prevent ConcurrentModificationException
|
bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.kick.done"));
|
||||||
final List<GeyserSession> tmpPlayers = new ArrayList<>(players);
|
|
||||||
for (GeyserSession playerSession : tmpPlayers) {
|
|
||||||
playerSession.disconnect(LanguageUtils.getPlayerLocaleString("geyser.core.shutdown.kick.message", playerSession.getLocale()));
|
|
||||||
}
|
|
||||||
|
|
||||||
CompletableFuture<Void> future = CompletableFuture.runAsync(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
// Simulate a long-running Job
|
|
||||||
try {
|
|
||||||
while (true) {
|
|
||||||
if (players.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeUnit.MILLISECONDS.sleep(100);
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Block and wait for the future to complete
|
|
||||||
try {
|
|
||||||
future.get();
|
|
||||||
bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.kick.done"));
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Quietly fail
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generalThreadPool.shutdown();
|
generalThreadPool.shutdown();
|
||||||
@ -437,20 +405,11 @@ public class GeyserConnector {
|
|||||||
skinUploader.close();
|
skinUploader.close();
|
||||||
}
|
}
|
||||||
newsHandler.shutdown();
|
newsHandler.shutdown();
|
||||||
players.clear();
|
|
||||||
this.getCommandManager().getCommands().clear();
|
this.getCommandManager().getCommands().clear();
|
||||||
|
|
||||||
bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.done"));
|
bootstrap.getGeyserLogger().info(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.done"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPlayer(GeyserSession player) {
|
|
||||||
players.add(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removePlayer(GeyserSession player) {
|
|
||||||
players.remove(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a player by their current UUID
|
* Gets a player by their current UUID
|
||||||
*
|
*
|
||||||
@ -463,13 +422,7 @@ public class GeyserConnector {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (GeyserSession session : players) {
|
return sessionManager.getSessions().get(uuid);
|
||||||
if (uuid.equals(session.getPlayerEntity().getUuid())) {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -480,8 +433,13 @@ public class GeyserConnector {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("unused") // API usage
|
@SuppressWarnings("unused") // API usage
|
||||||
public GeyserSession getPlayerByXuid(String xuid) {
|
public GeyserSession getPlayerByXuid(String xuid) {
|
||||||
for (GeyserSession session : players) {
|
for (GeyserSession session : sessionManager.getPendingSessions()) {
|
||||||
if (session.getAuthData() != null && session.getAuthData().getXboxUUID().equals(xuid)) {
|
if (session.getAuthData().getXboxUUID().equals(xuid)) {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (GeyserSession session : sessionManager.getSessions().values()) {
|
||||||
|
if (session.getAuthData().getXboxUUID().equals(xuid)) {
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
94
connector/src/main/java/org/geysermc/connector/SessionManager.java
Normale Datei
94
connector/src/main/java/org/geysermc/connector/SessionManager.java
Normale Datei
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import lombok.AccessLevel;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
|
import org.geysermc.connector.utils.LanguageUtils;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public final class SessionManager {
|
||||||
|
/**
|
||||||
|
* A list of all players who don't currently have a permanent UUID attached yet.
|
||||||
|
*/
|
||||||
|
@Getter(AccessLevel.PACKAGE)
|
||||||
|
private final Set<GeyserSession> pendingSessions = ConcurrentHashMap.newKeySet();
|
||||||
|
/**
|
||||||
|
* A list of all players who are currently in-game.
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
private final Map<UUID, GeyserSession> sessions = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called once the player has successfully authenticated to the Geyser server.
|
||||||
|
*/
|
||||||
|
public void addPendingSession(GeyserSession session) {
|
||||||
|
pendingSessions.add(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called once a player has successfully logged into their Java server.
|
||||||
|
*/
|
||||||
|
public void addSession(UUID uuid, GeyserSession session) {
|
||||||
|
pendingSessions.remove(session);
|
||||||
|
sessions.put(uuid, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSession(GeyserSession session) {
|
||||||
|
if (sessions.remove(session.getPlayerEntity().getUuid()) == null) {
|
||||||
|
// Session was likely pending
|
||||||
|
pendingSessions.remove(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new, immutable list containing all pending and active sessions.
|
||||||
|
*/
|
||||||
|
public Collection<GeyserSession> getAllSessions() {
|
||||||
|
return ImmutableList.<GeyserSession>builder() // builderWithExpectedSize is probably not a good idea yet as older Spigot builds probably won't have it.
|
||||||
|
.addAll(pendingSessions)
|
||||||
|
.addAll(sessions.values())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnectAll(String message) {
|
||||||
|
Collection<GeyserSession> sessions = getAllSessions();
|
||||||
|
for (GeyserSession session : sessions) {
|
||||||
|
session.disconnect(LanguageUtils.getPlayerLocaleString(message, session.getLocale()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the total amount of sessions, including those pending.
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return pendingSessions.size() + sessions.size();
|
||||||
|
}
|
||||||
|
}
|
@ -53,7 +53,7 @@ public class CommandExecutor {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (GeyserSession session : connector.getPlayers()) {
|
for (GeyserSession session : connector.getSessionManager().getSessions().values()) {
|
||||||
if (sender.getName().equals(session.getPlayerEntity().getUsername())) {
|
if (sender.getName().equals(session.getPlayerEntity().getUsername())) {
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,8 @@ public class ListCommand extends GeyserCommand {
|
|||||||
@Override
|
@Override
|
||||||
public void execute(GeyserSession session, CommandSender sender, String[] args) {
|
public void execute(GeyserSession session, CommandSender sender, String[] args) {
|
||||||
String message = LanguageUtils.getPlayerLocaleString("geyser.commands.list.message", sender.getLocale(),
|
String message = LanguageUtils.getPlayerLocaleString("geyser.commands.list.message", sender.getLocale(),
|
||||||
connector.getPlayers().size(),
|
connector.getSessionManager().size(),
|
||||||
connector.getPlayers().stream().map(GeyserSession::getName).collect(Collectors.joining(" ")));
|
connector.getSessionManager().getAllSessions().stream().map(GeyserSession::getName).collect(Collectors.joining(" ")));
|
||||||
|
|
||||||
sender.sendMessage(message);
|
sender.sendMessage(message);
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,6 @@ import org.geysermc.connector.command.GeyserCommand;
|
|||||||
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.ArrayList;
|
|
||||||
|
|
||||||
public class ReloadCommand extends GeyserCommand {
|
public class ReloadCommand extends GeyserCommand {
|
||||||
|
|
||||||
private final GeyserConnector connector;
|
private final GeyserConnector connector;
|
||||||
@ -53,9 +51,7 @@ public class ReloadCommand extends GeyserCommand {
|
|||||||
|
|
||||||
sender.sendMessage(message);
|
sender.sendMessage(message);
|
||||||
|
|
||||||
for (GeyserSession otherSession : new ArrayList<>(connector.getPlayers())) {
|
connector.getSessionManager().disconnectAll("geyser.commands.reload.kick");
|
||||||
otherSession.disconnect(LanguageUtils.getPlayerLocaleString("geyser.commands.reload.kick", otherSession.getLocale()));
|
|
||||||
}
|
|
||||||
connector.reload();
|
connector.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ public class DumpInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.userPlatforms = new Object2IntOpenHashMap<>();
|
this.userPlatforms = new Object2IntOpenHashMap<>();
|
||||||
for (GeyserSession session : GeyserConnector.getInstance().getPlayers()) {
|
for (GeyserSession session : GeyserConnector.getInstance().getSessionManager().getAllSessions()) {
|
||||||
DeviceOs device = session.getClientData().getDeviceOs();
|
DeviceOs device = session.getClientData().getDeviceOs();
|
||||||
userPlatforms.put(device, userPlatforms.getOrDefault(device, 0) + 1);
|
userPlatforms.put(device, userPlatforms.getOrDefault(device, 0) + 1);
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ public class ConnectorServerEventHandler implements BedrockServerEventHandler {
|
|||||||
pong.setPlayerCount(pingInfo.getPlayers().getOnline());
|
pong.setPlayerCount(pingInfo.getPlayers().getOnline());
|
||||||
pong.setMaximumPlayerCount(pingInfo.getPlayers().getMax());
|
pong.setMaximumPlayerCount(pingInfo.getPlayers().getMax());
|
||||||
} else {
|
} else {
|
||||||
pong.setPlayerCount(connector.getPlayers().size());
|
pong.setPlayerCount(connector.getSessionManager().getSessions().size());
|
||||||
pong.setMaximumPlayerCount(config.getMaxPlayers());
|
pong.setMaximumPlayerCount(config.getMaxPlayers());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ public class QueryPacketHandler {
|
|||||||
currentPlayerCount = String.valueOf(pingInfo.getPlayers().getOnline());
|
currentPlayerCount = String.valueOf(pingInfo.getPlayers().getOnline());
|
||||||
maxPlayerCount = String.valueOf(pingInfo.getPlayers().getMax());
|
maxPlayerCount = String.valueOf(pingInfo.getPlayers().getMax());
|
||||||
} else {
|
} else {
|
||||||
currentPlayerCount = String.valueOf(connector.getPlayers().size());
|
currentPlayerCount = String.valueOf(connector.getSessionManager().getSessions().size());
|
||||||
maxPlayerCount = String.valueOf(connector.getConfig().getMaxPlayers());
|
maxPlayerCount = String.valueOf(connector.getConfig().getMaxPlayers());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,12 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(LoginPacket loginPacket) {
|
public boolean handle(LoginPacket loginPacket) {
|
||||||
|
if (connector.isShuttingDown()) {
|
||||||
|
// Don't allow new players in if we're no longer operating
|
||||||
|
session.disconnect(LanguageUtils.getLocaleStringLog("geyser.core.shutdown.kick.message"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
BedrockPacketCodec packetCodec = BedrockProtocol.getBedrockCodec(loginPacket.getProtocolVersion());
|
BedrockPacketCodec packetCodec = BedrockProtocol.getBedrockCodec(loginPacket.getProtocolVersion());
|
||||||
if (packetCodec == null) {
|
if (packetCodec == null) {
|
||||||
String supportedVersions = BedrockProtocol.getAllSupportedVersions();
|
String supportedVersions = BedrockProtocol.getAllSupportedVersions();
|
||||||
@ -86,6 +92,8 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
|
|||||||
playStatus.setStatus(PlayStatusPacket.Status.LOGIN_SUCCESS);
|
playStatus.setStatus(PlayStatusPacket.Status.LOGIN_SUCCESS);
|
||||||
session.sendUpstreamPacket(playStatus);
|
session.sendUpstreamPacket(playStatus);
|
||||||
|
|
||||||
|
connector.getSessionManager().addPendingSession(session);
|
||||||
|
|
||||||
ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket();
|
ResourcePacksInfoPacket resourcePacksInfo = new ResourcePacksInfoPacket();
|
||||||
for(ResourcePack resourcePack : ResourcePack.PACKS.values()) {
|
for(ResourcePack resourcePack : ResourcePack.PACKS.values()) {
|
||||||
ResourcePackManifest.Header header = resourcePack.getManifest().getHeader();
|
ResourcePackManifest.Header header = resourcePack.getManifest().getHeader();
|
||||||
|
@ -486,9 +486,7 @@ public class GeyserSession implements CommandSender {
|
|||||||
|
|
||||||
if (connector.getConfig().getEmoteOffhandWorkaround() != EmoteOffhandWorkaroundOption.NO_EMOTES) {
|
if (connector.getConfig().getEmoteOffhandWorkaround() != EmoteOffhandWorkaroundOption.NO_EMOTES) {
|
||||||
this.emotes = new HashSet<>();
|
this.emotes = new HashSet<>();
|
||||||
// Make a copy to prevent ConcurrentModificationException
|
connector.getSessionManager().getSessions().values().forEach(player -> this.emotes.addAll(player.getEmotes()));
|
||||||
final List<GeyserSession> tmpPlayers = new ArrayList<>(connector.getPlayers());
|
|
||||||
tmpPlayers.forEach(player -> this.emotes.addAll(player.getEmotes()));
|
|
||||||
} else {
|
} else {
|
||||||
this.emotes = null;
|
this.emotes = null;
|
||||||
}
|
}
|
||||||
@ -498,7 +496,7 @@ public class GeyserSession implements CommandSender {
|
|||||||
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.disconnect", address, disconnectReason));
|
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.disconnect", address, disconnectReason));
|
||||||
|
|
||||||
disconnect(disconnectReason.name());
|
disconnect(disconnectReason.name());
|
||||||
connector.removePlayer(this);
|
connector.getSessionManager().removeSession(this);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -911,7 +909,6 @@ public class GeyserSession implements CommandSender {
|
|||||||
if (!internalConnect) {
|
if (!internalConnect) {
|
||||||
downstream.connect();
|
downstream.connect();
|
||||||
}
|
}
|
||||||
connector.addPlayer(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect(String reason) {
|
public void disconnect(String reason) {
|
||||||
@ -921,7 +918,7 @@ public class GeyserSession implements CommandSender {
|
|||||||
downstream.disconnect(reason);
|
downstream.disconnect(reason);
|
||||||
}
|
}
|
||||||
if (upstream != null && !upstream.isClosed()) {
|
if (upstream != null && !upstream.isClosed()) {
|
||||||
connector.getPlayers().remove(this);
|
connector.getSessionManager().removeSession(this);
|
||||||
upstream.disconnect(reason);
|
upstream.disconnect(reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1442,7 +1439,7 @@ public class GeyserSession implements CommandSender {
|
|||||||
|
|
||||||
public void refreshEmotes(List<UUID> emotes) {
|
public void refreshEmotes(List<UUID> emotes) {
|
||||||
this.emotes.addAll(emotes);
|
this.emotes.addAll(emotes);
|
||||||
for (GeyserSession player : connector.getPlayers()) {
|
for (GeyserSession player : connector.getSessionManager().getSessions().values()) {
|
||||||
List<UUID> pieces = new ArrayList<>();
|
List<UUID> pieces = new ArrayList<>();
|
||||||
for (UUID piece : emotes) {
|
for (UUID piece : emotes) {
|
||||||
if (!player.getEmotes().contains(piece)) {
|
if (!player.getEmotes().contains(piece)) {
|
||||||
|
@ -53,7 +53,7 @@ public class BedrockEmoteTranslator extends PacketTranslator<EmotePacket> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
long javaId = session.getPlayerEntity().getEntityId();
|
long javaId = session.getPlayerEntity().getEntityId();
|
||||||
for (GeyserSession otherSession : session.getConnector().getPlayers()) {
|
for (GeyserSession otherSession : session.getConnector().getSessionManager().getSessions().values()) {
|
||||||
if (otherSession != session) {
|
if (otherSession != session) {
|
||||||
if (otherSession.isClosed()) continue;
|
if (otherSession.isClosed()) continue;
|
||||||
if (otherSession.getEventLoop().inEventLoop()) {
|
if (otherSession.getEventLoop().inEventLoop()) {
|
||||||
|
@ -47,6 +47,8 @@ public class JavaLoginSuccessTranslator extends PacketTranslator<LoginSuccessPac
|
|||||||
playerEntity.setUsername(profile.getName());
|
playerEntity.setUsername(profile.getName());
|
||||||
playerEntity.setUuid(profile.getId());
|
playerEntity.setUuid(profile.getId());
|
||||||
|
|
||||||
|
session.getConnector().getSessionManager().addSession(playerEntity.getUuid(), session);
|
||||||
|
|
||||||
// Check if they are not using a linked account
|
// Check if they are not using a linked account
|
||||||
if (remoteAuthType == AuthType.OFFLINE || playerEntity.getUuid().getMostSignificantBits() == 0) {
|
if (remoteAuthType == AuthType.OFFLINE || playerEntity.getUuid().getMostSignificantBits() == 0) {
|
||||||
SkinManager.handleBedrockSkin(playerEntity, session.getClientData());
|
SkinManager.handleBedrockSkin(playerEntity, session.getClientData());
|
||||||
|
@ -33,6 +33,7 @@ import org.geysermc.connector.network.session.GeyserSession;
|
|||||||
import org.geysermc.connector.network.session.cache.WorldCache;
|
import org.geysermc.connector.network.session.cache.WorldCache;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
import org.geysermc.connector.utils.LanguageUtils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public final class ScoreboardUpdater extends Thread {
|
public final class ScoreboardUpdater extends Thread {
|
||||||
@ -72,9 +73,10 @@ public final class ScoreboardUpdater extends Thread {
|
|||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
|
|
||||||
// reset score-packets per second every second
|
// reset score-packets per second every second
|
||||||
|
Collection<GeyserSession> sessions = connector.getSessionManager().getSessions().values();
|
||||||
if (currentTime - lastPacketsPerSecondUpdate >= 1000) {
|
if (currentTime - lastPacketsPerSecondUpdate >= 1000) {
|
||||||
lastPacketsPerSecondUpdate = currentTime;
|
lastPacketsPerSecondUpdate = currentTime;
|
||||||
for (GeyserSession session : connector.getPlayers()) {
|
for (GeyserSession session : sessions) {
|
||||||
ScoreboardSession scoreboardSession = session.getWorldCache().getScoreboardSession();
|
ScoreboardSession scoreboardSession = session.getWorldCache().getScoreboardSession();
|
||||||
|
|
||||||
int oldPps = scoreboardSession.getPacketsPerSecond();
|
int oldPps = scoreboardSession.getPacketsPerSecond();
|
||||||
@ -94,7 +96,7 @@ public final class ScoreboardUpdater extends Thread {
|
|||||||
if (currentTime - lastUpdate >= FIRST_MILLIS_BETWEEN_UPDATES) {
|
if (currentTime - lastUpdate >= FIRST_MILLIS_BETWEEN_UPDATES) {
|
||||||
lastUpdate = currentTime;
|
lastUpdate = currentTime;
|
||||||
|
|
||||||
for (GeyserSession session : connector.getPlayers()) {
|
for (GeyserSession session : sessions) {
|
||||||
WorldCache worldCache = session.getWorldCache();
|
WorldCache worldCache = session.getWorldCache();
|
||||||
ScoreboardSession scoreboardSession = worldCache.getScoreboardSession();
|
ScoreboardSession scoreboardSession = worldCache.getScoreboardSession();
|
||||||
|
|
||||||
@ -132,7 +134,7 @@ public final class ScoreboardUpdater extends Thread {
|
|||||||
if (timeSpent > 0) {
|
if (timeSpent > 0) {
|
||||||
connector.getLogger().info(String.format(
|
connector.getLogger().info(String.format(
|
||||||
"Scoreboard updater: took %s ms. Updated %s players",
|
"Scoreboard updater: took %s ms. Updated %s players",
|
||||||
timeSpent, connector.getPlayers().size()
|
timeSpent, sessions.size()
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ public class NewsHandler {
|
|||||||
// }
|
// }
|
||||||
break;
|
break;
|
||||||
case BROADCAST_TO_OPERATORS:
|
case BROADCAST_TO_OPERATORS:
|
||||||
for (GeyserSession player : GeyserConnector.getInstance().getPlayers()) {
|
for (GeyserSession player : GeyserConnector.getInstance().getSessionManager().getSessions().values()) {
|
||||||
if (player.getOpPermissionLevel() >= 2) {
|
if (player.getOpPermissionLevel() >= 2) {
|
||||||
session.sendMessage(ChatColor.GREEN + news.getMessage());
|
session.sendMessage(ChatColor.GREEN + news.getMessage());
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren