Delete player when deleting account

This commit is contained in:
Melledy
2025-11-14 06:14:31 -08:00
parent 3b9cbf88a9
commit 66c6554bb9
8 changed files with 98 additions and 25 deletions

View File

@@ -6,7 +6,7 @@ import emu.nebula.command.CommandHandler;
import emu.nebula.game.account.AccountHelper;
import emu.nebula.util.Utils;
@Command(label = "account", permission = "admin.account", desc = "/account {create | delete} [username] (reserved player uid). Creates or deletes an account.")
@Command(label = "account", permission = "admin.account", desc = "/account {create | delete} [email] (reserved player uid). Creates or deletes an account.")
public class AccountCommand implements CommandHandler {
@Override

View File

@@ -5,6 +5,7 @@ import java.security.SecureRandom;
import java.util.Base64;
import emu.nebula.Nebula;
import emu.nebula.game.player.Player;
/**
* Helper class for handling account related stuff
@@ -40,14 +41,23 @@ public class AccountHelper {
return Nebula.getAccountDatabase().getObjectByField(Account.class, "loginToken", token);
}
public static boolean deleteAccount(String username) {
Account account = Nebula.getAccountDatabase().getObjectByField(Account.class, "username", username);
public static boolean deleteAccount(String email) {
// Get account
Account account = Nebula.getAccountDatabase().getObjectByField(Account.class, "email", email);
if (account == null) {
return false;
}
// Delete the account first
// Delete player
if (Nebula.getGameContext() != null) {
var player = Nebula.getGameDatabase().getObjectByField(Player.class, "accountUid", account.getUid());
if (player != null) {
Nebula.getGameContext().getPlayerModule().deletePlayer(player.getUid());
}
}
// Delete the account
return Nebula.getAccountDatabase().delete(account);
}

View File

@@ -12,7 +12,6 @@ import emu.nebula.Nebula;
import emu.nebula.database.GameDatabaseObject;
import emu.nebula.game.player.Player;
import emu.nebula.proto.Public.FormationInfo;
import emu.nebula.proto.Public.TowerFormation;
import lombok.Getter;
@Getter
@@ -71,12 +70,4 @@ public class FormationManager extends PlayerManager implements GameDatabaseObjec
return true;
}
// Proto
public TowerFormation toProto() {
var proto = TowerFormation.newInstance();
return proto;
}
}

View File

@@ -139,7 +139,7 @@ public class FriendList extends PlayerManager {
theirFriendship.save();
} else {
// Request declined - Delete from my pending friends
this.removePendingFriendship(myFriendship.getOwnerUid());
this.removePendingFriendship(myFriendship.getPlayerUid());
if (target.isLoaded()) {
target.getFriendList().removePendingFriendship(getPlayer().getUid());
@@ -251,7 +251,7 @@ public class FriendList extends PlayerManager {
friendships.forEach(friendship -> {
// Set ownership first
friendship.setOwner(getPlayer());
friendship.setPlayer(this.getPlayer());
// Finally, load to our friends list
if (friendship.isFriend()) {

View File

@@ -15,7 +15,7 @@ import lombok.Setter;
public class Friendship implements GameDatabaseObject {
@Id private long key;
@Indexed private int ownerUid;
@Indexed private int playerUid;
@Indexed private int friendUid;
private int askerUid;
@@ -24,17 +24,17 @@ public class Friendship implements GameDatabaseObject {
private boolean star;
private int energy;
@Setter private transient Player owner;
@Setter private transient Player player;
@Deprecated // Morphia use only
public Friendship() { }
public Friendship(Player owner, Player friend, Player asker) {
this.owner = owner;
this.ownerUid = owner.getUid();
public Friendship(Player player, Player friend, Player asker) {
this.player = player;
this.playerUid = player.getUid();
this.friendUid = friend.getUid();
this.askerUid = asker.getUid();
this.key = Friendship.generateUniqueKey(owner.getUid(), friend.getUid());
this.key = Friendship.generateUniqueKey(player.getUid(), friend.getUid());
}
// Database functions

View File

@@ -4,6 +4,7 @@ import org.bson.types.ObjectId;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import dev.morphia.annotations.Indexed;
import emu.nebula.data.resources.GachaDef;
import emu.nebula.data.resources.GachaDef.GachaPackage;
import emu.nebula.data.resources.GachaPkgDef;
@@ -18,8 +19,9 @@ public class GachaBannerInfo implements GameDatabaseObject {
@Id
private ObjectId id;
private int bannerId;
@Indexed
private int playerUid;
private int bannerId;
private int total;
private int missTimesA;

View File

@@ -4,12 +4,28 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import com.mongodb.client.model.Filters;
import emu.nebula.Nebula;
import emu.nebula.game.GameContext;
import emu.nebula.game.GameContextModule;
import emu.nebula.game.account.Account;
import emu.nebula.game.agent.AgentManager;
import emu.nebula.game.battlepass.BattlePass;
import emu.nebula.game.character.Character;
import emu.nebula.game.character.GameDisc;
import emu.nebula.game.formation.FormationManager;
import emu.nebula.game.friends.Friendship;
import emu.nebula.game.gacha.GachaBannerInfo;
import emu.nebula.game.inventory.GameItem;
import emu.nebula.game.inventory.GameResource;
import emu.nebula.game.inventory.Inventory;
import emu.nebula.game.mail.Mailbox;
import emu.nebula.game.quest.QuestManager;
import emu.nebula.game.story.StoryManager;
import emu.nebula.game.tower.StarTowerBuild;
import emu.nebula.net.GameSession;
import emu.nebula.proto.ScoreBossRank;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
@@ -125,6 +141,60 @@ public class PlayerModule extends GameContextModule {
return player;
}
/**
* Deletes a player from the database. The player must be offline.
* @param uid
* @return
*/
public synchronized boolean deletePlayer(int uid) {
// Make sure player is not online when we are deleting the player
Player player = this.getCachedPlayerByUid(uid);
if (player != null) {
return false;
}
// Get player from database
player = Nebula.getGameDatabase().getObjectByUid(Player.class, uid);
if (player == null) {
return false;
}
// Cache filter objects so we can reuse it for our delete queries
var multiFilter = Filters.eq("playerUid", uid);
var idFilter = Filters.eq("_id", uid);
// Get datastore
var datastore = Nebula.getGameDatabase().getDatastore();
// Delete data from collections
datastore.getCollection(Character.class).deleteMany(multiFilter);
datastore.getCollection(GameDisc.class).deleteMany(multiFilter);
datastore.getCollection(GameItem.class).deleteMany(multiFilter);
datastore.getCollection(GameResource.class).deleteMany(multiFilter);
datastore.getCollection(StarTowerBuild.class).deleteMany(multiFilter);
datastore.getCollection(GachaBannerInfo.class).deleteMany(multiFilter);
datastore.getCollection(Inventory.class).deleteOne(idFilter);
datastore.getCollection(FormationManager.class).deleteOne(idFilter);
datastore.getCollection(Mailbox.class).deleteOne(idFilter);
datastore.getCollection(PlayerProgress.class).deleteOne(idFilter);
datastore.getCollection(StoryManager.class).deleteOne(idFilter);
datastore.getCollection(QuestManager.class).deleteOne(idFilter);
datastore.getCollection(AgentManager.class).deleteOne(idFilter);
datastore.getCollection(BattlePass.class).deleteOne(idFilter);
datastore.getCollection(ScoreBossRank.class).deleteOne(idFilter);
// Delete friendships
datastore.getCollection(Friendship.class).deleteMany(Filters.or(Filters.eq("playerUid", uid), Filters.eq("friendUid", uid)));
// Finally delete the player
datastore.getCollection(Player.class).deleteOne(idFilter);
// Success
return true;
}
/**
* Returns a list of recent players that have logged on
* @param player Player that requested this