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.game.account.AccountHelper;
import emu.nebula.util.Utils; 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 { public class AccountCommand implements CommandHandler {
@Override @Override

View File

@@ -5,6 +5,7 @@ import java.security.SecureRandom;
import java.util.Base64; import java.util.Base64;
import emu.nebula.Nebula; import emu.nebula.Nebula;
import emu.nebula.game.player.Player;
/** /**
* Helper class for handling account related stuff * Helper class for handling account related stuff
@@ -40,14 +41,23 @@ public class AccountHelper {
return Nebula.getAccountDatabase().getObjectByField(Account.class, "loginToken", token); return Nebula.getAccountDatabase().getObjectByField(Account.class, "loginToken", token);
} }
public static boolean deleteAccount(String username) { public static boolean deleteAccount(String email) {
Account account = Nebula.getAccountDatabase().getObjectByField(Account.class, "username", username); // Get account
Account account = Nebula.getAccountDatabase().getObjectByField(Account.class, "email", email);
if (account == null) { if (account == null) {
return false; 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); return Nebula.getAccountDatabase().delete(account);
} }

View File

@@ -12,7 +12,6 @@ import emu.nebula.Nebula;
import emu.nebula.database.GameDatabaseObject; import emu.nebula.database.GameDatabaseObject;
import emu.nebula.game.player.Player; import emu.nebula.game.player.Player;
import emu.nebula.proto.Public.FormationInfo; import emu.nebula.proto.Public.FormationInfo;
import emu.nebula.proto.Public.TowerFormation;
import lombok.Getter; import lombok.Getter;
@Getter @Getter
@@ -70,13 +69,5 @@ public class FormationManager extends PlayerManager implements GameDatabaseObjec
// Success // Success
return true; 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(); theirFriendship.save();
} else { } else {
// Request declined - Delete from my pending friends // Request declined - Delete from my pending friends
this.removePendingFriendship(myFriendship.getOwnerUid()); this.removePendingFriendship(myFriendship.getPlayerUid());
if (target.isLoaded()) { if (target.isLoaded()) {
target.getFriendList().removePendingFriendship(getPlayer().getUid()); target.getFriendList().removePendingFriendship(getPlayer().getUid());
@@ -251,7 +251,7 @@ public class FriendList extends PlayerManager {
friendships.forEach(friendship -> { friendships.forEach(friendship -> {
// Set ownership first // Set ownership first
friendship.setOwner(getPlayer()); friendship.setPlayer(this.getPlayer());
// Finally, load to our friends list // Finally, load to our friends list
if (friendship.isFriend()) { if (friendship.isFriend()) {

View File

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

View File

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

View File

@@ -29,8 +29,8 @@ public class GachaManager extends PlayerManager {
} }
return this.bannerInfos.computeIfAbsent( return this.bannerInfos.computeIfAbsent(
gachaData.getId(), gachaData.getId(),
i -> new GachaBannerInfo(this.getPlayer(), gachaData) i -> new GachaBannerInfo(this.getPlayer(), gachaData)
); );
} }

View File

@@ -4,12 +4,28 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.mongodb.client.model.Filters;
import emu.nebula.Nebula; import emu.nebula.Nebula;
import emu.nebula.game.GameContext; import emu.nebula.game.GameContext;
import emu.nebula.game.GameContextModule; import emu.nebula.game.GameContextModule;
import emu.nebula.game.account.Account; 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.net.GameSession;
import emu.nebula.proto.ScoreBossRank;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectMap; import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
@@ -125,6 +141,60 @@ public class PlayerModule extends GameContextModule {
return player; 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 * Returns a list of recent players that have logged on
* @param player Player that requested this * @param player Player that requested this