mirror of
https://github.com/Grasscutters/Grasscutter.git
synced 2025-12-22 20:04:56 +01:00
Add async bulk saving of objects
This commit is contained in:
71
src/main/java/emu/grasscutter/database/Database.java
Normal file
71
src/main/java/emu/grasscutter/database/Database.java
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package emu.grasscutter.database;
|
||||||
|
|
||||||
|
import emu.grasscutter.Grasscutter;
|
||||||
|
import emu.grasscutter.utils.objects.DatabaseObject;
|
||||||
|
import org.slf4j.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Complicated manager of the MongoDB database.
|
||||||
|
* Handles caching, data operations, and more.
|
||||||
|
*/
|
||||||
|
public interface Database {
|
||||||
|
Logger logger = LoggerFactory.getLogger("Database");
|
||||||
|
List<DatabaseObject<?>> objects = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queues an object to be saved.
|
||||||
|
*
|
||||||
|
* @param object The object to save.
|
||||||
|
*/
|
||||||
|
static void save(DatabaseObject<?> object) {
|
||||||
|
if (object.saveImmediately()) {
|
||||||
|
object.save();
|
||||||
|
} else {
|
||||||
|
objects.add(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a bulk save of all deferred objects.
|
||||||
|
*/
|
||||||
|
static void saveAll() {
|
||||||
|
var size = objects.size();
|
||||||
|
Database.saveAll(objects);
|
||||||
|
|
||||||
|
logger.debug("Performed auto save on {} objects.", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a bulk save of all deferred objects.
|
||||||
|
*
|
||||||
|
* @param objects The objects to save.
|
||||||
|
*/
|
||||||
|
static void saveAll(List<? extends DatabaseObject<?>> objects) {
|
||||||
|
// Sort all objects into their respective databases.
|
||||||
|
var gameObjects = objects.stream()
|
||||||
|
.filter(DatabaseObject::isGameObject)
|
||||||
|
.toList();
|
||||||
|
var accountObjects = objects.stream()
|
||||||
|
.filter(o -> !o.isGameObject())
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
// Clear the collective list.
|
||||||
|
objects.clear();
|
||||||
|
|
||||||
|
// Save all objects.
|
||||||
|
var executor = DatabaseHelper.getEventExecutor();
|
||||||
|
if (Grasscutter.getRunMode() != Grasscutter.ServerRunMode.DISPATCH_ONLY) {
|
||||||
|
executor.submit(() -> {
|
||||||
|
DatabaseManager.getGameDatastore().save(gameObjects);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (Grasscutter.getRunMode() != Grasscutter.ServerRunMode.GAME_ONLY) {
|
||||||
|
executor.submit(() -> {
|
||||||
|
DatabaseManager.getAccountDatastore().save(accountObjects);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,15 +11,17 @@ import emu.grasscutter.game.props.ActionReason;
|
|||||||
import emu.grasscutter.net.proto.ActivityWatcherInfoOuterClass;
|
import emu.grasscutter.net.proto.ActivityWatcherInfoOuterClass;
|
||||||
import emu.grasscutter.server.packet.send.PacketActivityUpdateWatcherNotify;
|
import emu.grasscutter.server.packet.send.PacketActivityUpdateWatcherNotify;
|
||||||
import emu.grasscutter.utils.JsonUtils;
|
import emu.grasscutter.utils.JsonUtils;
|
||||||
import java.util.*;
|
import emu.grasscutter.utils.objects.DatabaseObject;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.FieldDefaults;
|
import lombok.experimental.FieldDefaults;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
@Entity("activities")
|
@Entity("activities")
|
||||||
@Data
|
@Data
|
||||||
@FieldDefaults(level = AccessLevel.PRIVATE)
|
@FieldDefaults(level = AccessLevel.PRIVATE)
|
||||||
@Builder(builderMethodName = "of")
|
@Builder(builderMethodName = "of")
|
||||||
public class PlayerActivityData {
|
public class PlayerActivityData implements DatabaseObject<PlayerActivityData> {
|
||||||
@Id String id;
|
@Id String id;
|
||||||
int uid;
|
int uid;
|
||||||
int activityId;
|
int activityId;
|
||||||
@@ -34,8 +36,25 @@ public class PlayerActivityData {
|
|||||||
return DatabaseHelper.getPlayerActivityData(player.getUid(), activityId);
|
return DatabaseHelper.getPlayerActivityData(player.getUid(), activityId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves this object to the database.
|
||||||
|
* As of Grasscutter 1.7.1, this is by default a {@link DatabaseObject#deferSave()} call.
|
||||||
|
*/
|
||||||
public void save() {
|
public void save() {
|
||||||
DatabaseHelper.savePlayerActivityData(this);
|
this.deferSave();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves this object to the database.
|
||||||
|
*
|
||||||
|
* @param immediate If true, this will be a {@link DatabaseObject#save()} call instead of a {@link DatabaseObject#deferSave()} call.
|
||||||
|
*/
|
||||||
|
public void save(boolean immediate) {
|
||||||
|
if (immediate) {
|
||||||
|
DatabaseObject.super.save();
|
||||||
|
} else {
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void addWatcherProgress(int watcherId) {
|
public synchronized void addWatcherProgress(int watcherId) {
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package emu.grasscutter.game.avatar;
|
package emu.grasscutter.game.avatar;
|
||||||
|
|
||||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
|
||||||
|
|
||||||
import dev.morphia.annotations.*;
|
import dev.morphia.annotations.*;
|
||||||
import emu.grasscutter.GameConstants;
|
import emu.grasscutter.GameConstants;
|
||||||
import emu.grasscutter.data.GameData;
|
import emu.grasscutter.data.GameData;
|
||||||
@@ -15,7 +13,6 @@ import emu.grasscutter.data.excels.avatar.AvatarSkillDepotData.InherentProudSkil
|
|||||||
import emu.grasscutter.data.excels.reliquary.*;
|
import emu.grasscutter.data.excels.reliquary.*;
|
||||||
import emu.grasscutter.data.excels.trial.TrialAvatarTemplateData;
|
import emu.grasscutter.data.excels.trial.TrialAvatarTemplateData;
|
||||||
import emu.grasscutter.data.excels.weapon.*;
|
import emu.grasscutter.data.excels.weapon.*;
|
||||||
import emu.grasscutter.database.DatabaseHelper;
|
|
||||||
import emu.grasscutter.game.entity.*;
|
import emu.grasscutter.game.entity.*;
|
||||||
import emu.grasscutter.game.inventory.*;
|
import emu.grasscutter.game.inventory.*;
|
||||||
import emu.grasscutter.game.player.Player;
|
import emu.grasscutter.game.player.Player;
|
||||||
@@ -31,15 +28,19 @@ import emu.grasscutter.net.proto.TrialAvatarGrantRecordOuterClass.TrialAvatarGra
|
|||||||
import emu.grasscutter.net.proto.TrialAvatarInfoOuterClass.TrialAvatarInfo;
|
import emu.grasscutter.net.proto.TrialAvatarInfoOuterClass.TrialAvatarInfo;
|
||||||
import emu.grasscutter.server.packet.send.*;
|
import emu.grasscutter.server.packet.send.*;
|
||||||
import emu.grasscutter.utils.helpers.ProtoHelper;
|
import emu.grasscutter.utils.helpers.ProtoHelper;
|
||||||
|
import emu.grasscutter.utils.objects.DatabaseObject;
|
||||||
import it.unimi.dsi.fastutil.ints.*;
|
import it.unimi.dsi.fastutil.ints.*;
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
import javax.annotation.*;
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
|
|
||||||
|
import javax.annotation.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||||
|
|
||||||
@Entity(value = "avatars", useDiscriminator = false)
|
@Entity(value = "avatars", useDiscriminator = false)
|
||||||
public class Avatar {
|
public class Avatar implements DatabaseObject<Avatar> {
|
||||||
@Transient @Getter private final Int2ObjectMap<GameItem> equips;
|
@Transient @Getter private final Int2ObjectMap<GameItem> equips;
|
||||||
@Transient @Getter private final Int2FloatOpenHashMap fightProperties;
|
@Transient @Getter private final Int2FloatOpenHashMap fightProperties;
|
||||||
@Transient @Getter private final Int2FloatOpenHashMap fightPropOverrides;
|
@Transient @Getter private final Int2FloatOpenHashMap fightPropOverrides;
|
||||||
@@ -989,8 +990,25 @@ public class Avatar {
|
|||||||
return entity != null ? entity.getId() : 0;
|
return entity != null ? entity.getId() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves this object to the database.
|
||||||
|
* As of Grasscutter 1.7.1, this is by default a {@link DatabaseObject#deferSave()} call.
|
||||||
|
*/
|
||||||
public void save() {
|
public void save() {
|
||||||
DatabaseHelper.saveAvatar(this);
|
this.deferSave();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves this object to the database.
|
||||||
|
*
|
||||||
|
* @param immediate If true, this will be a {@link DatabaseObject#save()} call instead of a {@link DatabaseObject#deferSave()} call.
|
||||||
|
*/
|
||||||
|
public void save(boolean immediate) {
|
||||||
|
if (immediate) {
|
||||||
|
DatabaseObject.super.save();
|
||||||
|
} else {
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AvatarInfo toProto() {
|
public AvatarInfo toProto() {
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public class AvatarStorage extends BasePlayerManager implements Iterable<Avatar>
|
|||||||
this.avatars.put(avatar.getAvatarId(), avatar);
|
this.avatars.put(avatar.getAvatarId(), avatar);
|
||||||
this.avatarsGuid.put(avatar.getGuid(), avatar);
|
this.avatarsGuid.put(avatar.getGuid(), avatar);
|
||||||
|
|
||||||
avatar.save();
|
avatar.save(true);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ public class AvatarStorage extends BasePlayerManager implements Iterable<Avatar>
|
|||||||
if ((avatar.getAvatarId() == 10000007) || (avatar.getAvatarId() == 10000005)) {
|
if ((avatar.getAvatarId() == 10000007) || (avatar.getAvatarId() == 10000005)) {
|
||||||
avatar.setSkillDepot(skillDepot);
|
avatar.setSkillDepot(skillDepot);
|
||||||
avatar.setSkillDepotData(skillDepot);
|
avatar.setSkillDepotData(skillDepot);
|
||||||
avatar.save();
|
avatar.save(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ import emu.grasscutter.server.game.GameSession.SessionState;
|
|||||||
import emu.grasscutter.server.packet.send.*;
|
import emu.grasscutter.server.packet.send.*;
|
||||||
import emu.grasscutter.utils.*;
|
import emu.grasscutter.utils.*;
|
||||||
import emu.grasscutter.utils.helpers.DateHelper;
|
import emu.grasscutter.utils.helpers.DateHelper;
|
||||||
import emu.grasscutter.utils.objects.FieldFetch;
|
import emu.grasscutter.utils.objects.*;
|
||||||
import it.unimi.dsi.fastutil.ints.*;
|
import it.unimi.dsi.fastutil.ints.*;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ import java.util.concurrent.*;
|
|||||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||||
|
|
||||||
@Entity(value = "players", useDiscriminator = false)
|
@Entity(value = "players", useDiscriminator = false)
|
||||||
public class Player implements PlayerHook, FieldFetch {
|
public class Player implements DatabaseObject<Player>, PlayerHook, FieldFetch {
|
||||||
@Id private int id;
|
@Id private int id;
|
||||||
@Indexed(options = @IndexOptions(unique = true))
|
@Indexed(options = @IndexOptions(unique = true))
|
||||||
@Getter private String accountId;
|
@Getter private String accountId;
|
||||||
@@ -1306,8 +1306,25 @@ public class Player implements PlayerHook, FieldFetch {
|
|||||||
this.getTeamManager().setPlayer(this);
|
this.getTeamManager().setPlayer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves this object to the database.
|
||||||
|
* As of Grasscutter 1.7.1, this is by default a {@link DatabaseObject#deferSave()} call.
|
||||||
|
*/
|
||||||
public void save() {
|
public void save() {
|
||||||
DatabaseHelper.savePlayer(this);
|
this.deferSave();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves this object to the database.
|
||||||
|
*
|
||||||
|
* @param immediate If true, this will be a {@link DatabaseObject#save()} call instead of a {@link DatabaseObject#deferSave()} call.
|
||||||
|
*/
|
||||||
|
public void save(boolean immediate) {
|
||||||
|
if (immediate) {
|
||||||
|
DatabaseObject.super.save();
|
||||||
|
} else {
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from tokenrsp
|
// Called from tokenrsp
|
||||||
@@ -1474,20 +1491,19 @@ public class Player implements PlayerHook, FieldFetch {
|
|||||||
this.getProfile().syncWithCharacter(this);
|
this.getProfile().syncWithCharacter(this);
|
||||||
|
|
||||||
this.getCoopRequests().clear();
|
this.getCoopRequests().clear();
|
||||||
this.getEnterHomeRequests().values().forEach(req -> this.expireEnterHomeRequest(req, true));
|
this.getEnterHomeRequests().values()
|
||||||
|
.forEach(req -> this.expireEnterHomeRequest(req, true));
|
||||||
this.getEnterHomeRequests().clear();
|
this.getEnterHomeRequests().clear();
|
||||||
|
|
||||||
// Save to db
|
// Save to db
|
||||||
this.save();
|
this.save(true);
|
||||||
this.getTeamManager().saveAvatars();
|
this.getTeamManager().saveAvatars();
|
||||||
this.getFriendsList().save();
|
this.getFriendsList().save();
|
||||||
|
|
||||||
// Call quit event.
|
// Call quit event.
|
||||||
PlayerQuitEvent event = new PlayerQuitEvent(this);
|
new PlayerQuitEvent(this).call();
|
||||||
event.call();
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
Grasscutter.getLogger().warn("Player (UID {}) failed to save.", this.getUid(), e);
|
||||||
Grasscutter.getLogger().warn("Player (UID {}) save failure", getUid());
|
|
||||||
} finally {
|
} finally {
|
||||||
removeFromServer();
|
removeFromServer();
|
||||||
}
|
}
|
||||||
@@ -1495,9 +1511,10 @@ public class Player implements PlayerHook, FieldFetch {
|
|||||||
|
|
||||||
public void removeFromServer() {
|
public void removeFromServer() {
|
||||||
// Remove from server.
|
// Remove from server.
|
||||||
//Note: DON'T DELETE BY UID,BECAUSE THERE ARE MULTIPLE SAME UID PLAYERS WHEN DUPLICATED LOGIN!
|
// Note: DON'T DELETE BY UID, BECAUSE THERE ARE MULTIPLE SAME UID PLAYERS WHEN DUPLICATED LOGIN!
|
||||||
//so I decide to delete by object rather than uid
|
//s o I decide to delete by object rather than uid
|
||||||
getServer().getPlayers().values().removeIf(player1 -> player1 == this);
|
this.getServer().getPlayers().values()
|
||||||
|
.removeIf(player1 -> player1 == this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getLegendaryKey() {
|
public int getLegendaryKey() {
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
package emu.grasscutter.game.player;
|
package emu.grasscutter.game.player;
|
||||||
|
|
||||||
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
|
||||||
|
|
||||||
import dev.morphia.annotations.*;
|
import dev.morphia.annotations.*;
|
||||||
import emu.grasscutter.*;
|
import emu.grasscutter.*;
|
||||||
import emu.grasscutter.data.GameData;
|
import emu.grasscutter.data.GameData;
|
||||||
import emu.grasscutter.data.excels.avatar.AvatarSkillDepotData;
|
import emu.grasscutter.data.excels.avatar.AvatarSkillDepotData;
|
||||||
|
import emu.grasscutter.database.Database;
|
||||||
import emu.grasscutter.game.avatar.Avatar;
|
import emu.grasscutter.game.avatar.Avatar;
|
||||||
import emu.grasscutter.game.entity.*;
|
import emu.grasscutter.game.entity.*;
|
||||||
import emu.grasscutter.game.props.*;
|
import emu.grasscutter.game.props.*;
|
||||||
@@ -23,9 +22,12 @@ import emu.grasscutter.server.packet.send.*;
|
|||||||
import emu.grasscutter.utils.Utils;
|
import emu.grasscutter.utils.Utils;
|
||||||
import it.unimi.dsi.fastutil.ints.*;
|
import it.unimi.dsi.fastutil.ints.*;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import lombok.*;
|
|
||||||
|
import static emu.grasscutter.config.Configuration.GAME_OPTIONS;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
public final class TeamManager extends BasePlayerDataManager {
|
public final class TeamManager extends BasePlayerDataManager {
|
||||||
@@ -404,7 +406,7 @@ public final class TeamManager extends BasePlayerDataManager {
|
|||||||
// Unload removed entities
|
// Unload removed entities
|
||||||
for (var entity : existingAvatars.values()) {
|
for (var entity : existingAvatars.values()) {
|
||||||
this.getPlayer().getScene().removeEntity(entity);
|
this.getPlayer().getScene().removeEntity(entity);
|
||||||
entity.getAvatar().save();
|
entity.getAvatar().save(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set new selected character index
|
// Set new selected character index
|
||||||
@@ -965,11 +967,13 @@ public final class TeamManager extends BasePlayerDataManager {
|
|||||||
return respawnPoint.get().getPointData().getTranPos();
|
return respawnPoint.get().getPointData().getTranPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a bulk save operation on all avatars.
|
||||||
|
*/
|
||||||
public void saveAvatars() {
|
public void saveAvatars() {
|
||||||
// Save all avatars from active team
|
Database.saveAll(this.getActiveTeam().stream()
|
||||||
for (EntityAvatar entity : this.getActiveTeam()) {
|
.map(EntityAvatar::getAvatar)
|
||||||
entity.getAvatar().save();
|
.toList());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onPlayerLogin() { // Hack for now to fix resonances on login
|
public void onPlayerLogin() { // Hack for now to fix resonances on login
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package emu.grasscutter.game.world;
|
package emu.grasscutter.game.world;
|
||||||
|
|
||||||
import static emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType.SCRIPT;
|
|
||||||
|
|
||||||
import emu.grasscutter.data.GameData;
|
import emu.grasscutter.data.GameData;
|
||||||
import emu.grasscutter.data.excels.dungeon.DungeonData;
|
import emu.grasscutter.data.excels.dungeon.DungeonData;
|
||||||
import emu.grasscutter.game.entity.*;
|
import emu.grasscutter.game.entity.*;
|
||||||
@@ -20,10 +18,13 @@ import emu.grasscutter.server.game.GameServer;
|
|||||||
import emu.grasscutter.server.packet.send.*;
|
import emu.grasscutter.server.packet.send.*;
|
||||||
import emu.grasscutter.utils.ConversionUtils;
|
import emu.grasscutter.utils.ConversionUtils;
|
||||||
import it.unimi.dsi.fastutil.ints.*;
|
import it.unimi.dsi.fastutil.ints.*;
|
||||||
import java.util.*;
|
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static emu.grasscutter.server.event.player.PlayerTeleportEvent.TeleportType.SCRIPT;
|
||||||
|
|
||||||
public class World implements Iterable<Player> {
|
public class World implements Iterable<Player> {
|
||||||
@Getter private final GameServer server;
|
@Getter private final GameServer server;
|
||||||
@Getter private Player host;
|
@Getter private Player host;
|
||||||
@@ -266,7 +267,7 @@ public class World implements Iterable<Player> {
|
|||||||
scene.removePlayer(player);
|
scene.removePlayer(player);
|
||||||
|
|
||||||
// Info packet for other players
|
// Info packet for other players
|
||||||
if (this.getPlayers().size() > 0) {
|
if (!this.getPlayers().isEmpty()) {
|
||||||
this.updatePlayerInfos(player);
|
this.updatePlayerInfos(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package emu.grasscutter.utils.objects;
|
||||||
|
|
||||||
|
import emu.grasscutter.Grasscutter;
|
||||||
|
import emu.grasscutter.Grasscutter.ServerRunMode;
|
||||||
|
import emu.grasscutter.database.*;
|
||||||
|
|
||||||
|
public interface DatabaseObject<T> {
|
||||||
|
/**
|
||||||
|
* @return Does this object belong in the game database?
|
||||||
|
*/
|
||||||
|
default boolean isGameObject() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Should this object be saved immediately?
|
||||||
|
*/
|
||||||
|
default boolean saveImmediately() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a deferred save.
|
||||||
|
* This object will save as a group with other objects.
|
||||||
|
*/
|
||||||
|
default void deferSave() {
|
||||||
|
Database.save(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to save this object to the database.
|
||||||
|
*/
|
||||||
|
default void save() {
|
||||||
|
if (this.isGameObject()) {
|
||||||
|
DatabaseManager.getGameDatastore().save(this);
|
||||||
|
} else if (Grasscutter.getRunMode() != ServerRunMode.GAME_ONLY) {
|
||||||
|
DatabaseManager.getAccountDatastore().save(this);
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException("Unable to store an account object while in game-only mode.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user