Only allow one session per player

This commit is contained in:
Melledy
2025-11-04 06:05:07 -08:00
parent 9e7167a5ad
commit 6b1582459a
3 changed files with 25 additions and 31 deletions

View File

@@ -65,12 +65,12 @@ public class GameContext {
while (it.hasNext()) { while (it.hasNext()) {
var session = it.next().getValue(); var session = it.next().getValue();
if (timeout > session.getLastActiveTime()) { if (timeout > session.getLastActiveTime() || session.isRemove()) {
// Remove from session map // Remove from session map
it.remove(); it.remove();
// Clear player // Clear player
session.clearPlayer(this); session.clearPlayer();
} }
} }
} }

View File

@@ -1,7 +1,5 @@
package emu.nebula.game.player; package emu.nebula.game.player;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack; import java.util.Stack;
import dev.morphia.annotations.Entity; import dev.morphia.annotations.Entity;
@@ -44,7 +42,7 @@ public class Player implements GameDatabaseObject {
@Indexed private String accountUid; @Indexed private String accountUid;
private transient Account account; private transient Account account;
private transient Set<GameSession> sessions; private transient GameSession session;
// Details // Details
private String name; private String name;
@@ -80,7 +78,6 @@ public class Player implements GameDatabaseObject {
@Deprecated // Morphia only @Deprecated // Morphia only
public Player() { public Player() {
this.sessions = new HashSet<>();
this.characters = new CharacterStorage(this); this.characters = new CharacterStorage(this);
this.gachaManager = new GachaManager(this); this.gachaManager = new GachaManager(this);
@@ -135,22 +132,17 @@ public class Player implements GameDatabaseObject {
return this.account; return this.account;
} }
public void addSession(GameSession session) { public void setSession(GameSession session) {
synchronized (this.sessions) { if (this.session != null) {
this.sessions.add(session); this.session.clearPlayer();
} }
this.session = session;
} }
public void removeSession(GameSession session) { public void removeSession() {
synchronized (this.sessions) { this.session = null;
this.sessions.remove(session); Nebula.getGameContext().getPlayerModule().removeFromCache(this);
}
}
public boolean hasSessions() {
synchronized (this.sessions) {
return !this.sessions.isEmpty();
}
} }
public boolean getGender() { public boolean getGender() {

View File

@@ -7,7 +7,6 @@ import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import emu.nebula.Nebula; import emu.nebula.Nebula;
import emu.nebula.game.GameContext;
import emu.nebula.game.account.Account; import emu.nebula.game.account.Account;
import emu.nebula.game.account.AccountHelper; import emu.nebula.game.account.AccountHelper;
import emu.nebula.game.player.Player; import emu.nebula.game.player.Player;
@@ -32,19 +31,24 @@ public class GameSession {
private byte[] serverPrivateKey; private byte[] serverPrivateKey;
private byte[] key; private byte[] key;
// // Session cleanup
private boolean remove;
private long lastActiveTime; private long lastActiveTime;
public GameSession() { public GameSession() {
this.updateLastActiveTime(); this.updateLastActiveTime();
} }
public void setPlayer(Player player) { public synchronized Player getPlayer() {
this.player = player; return this.player;
this.player.addSession(this);
} }
public void clearPlayer(GameContext context) { public synchronized void setPlayer(Player player) {
this.player = player;
this.player.setSession(this);
}
public synchronized void clearPlayer() {
// Sanity check // Sanity check
if (this.player == null) { if (this.player == null) {
return; return;
@@ -55,15 +59,13 @@ public class GameSession {
this.player = null; this.player = null;
// Remove session from player // Remove session from player
player.removeSession(this); player.removeSession();
// Clean up from player module // Set remove flag
if (!player.hasSessions()) { this.remove = true;
context.getPlayerModule().removeFromCache(player);
}
} }
public boolean hasPlayer() { public synchronized boolean hasPlayer() {
return this.player != null; return this.player != null;
} }