DatabaseManager.java 3.97 KB
Newer Older
Melledy's avatar
Melledy committed
1
2
3
4
package emu.grasscutter.database;

import com.mongodb.MongoClientURI;
import com.mongodb.MongoCommandException;
KingRainbow44's avatar
KingRainbow44 committed
5
6
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
Melledy's avatar
Melledy committed
7
8
9
10
11
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;

import dev.morphia.Datastore;
import dev.morphia.Morphia;
KingRainbow44's avatar
KingRainbow44 committed
12
13
import dev.morphia.mapping.MapperOptions;
import dev.morphia.query.experimental.filters.Filters;
Melledy's avatar
Melledy committed
14
import emu.grasscutter.Grasscutter;
15
import emu.grasscutter.Grasscutter.ServerRunMode;
Melledy's avatar
Melledy committed
16
import emu.grasscutter.game.Account;
17
import emu.grasscutter.game.avatar.Avatar;
Melledy's avatar
Melledy committed
18
import emu.grasscutter.game.friends.Friendship;
19
import emu.grasscutter.game.gacha.GachaRecord;
20
import emu.grasscutter.game.inventory.GameItem;
Melledy's avatar
Melledy committed
21
import emu.grasscutter.game.player.Player;
Melledy's avatar
Melledy committed
22

KingRainbow44's avatar
KingRainbow44 committed
23
public final class DatabaseManager {
24

Melledy's avatar
Melledy committed
25
	private static MongoClient mongoClient;
26
27
	private static MongoClient dispatchMongoClient;

Melledy's avatar
Melledy committed
28
	private static Datastore datastore;
29
	private static Datastore dispatchDatastore;
Melledy's avatar
Melledy committed
30
	
KingRainbow44's avatar
KingRainbow44 committed
31
	private static final Class<?>[] mappedClasses = new Class<?>[] {
32
		DatabaseCounter.class, Account.class, Player.class, Avatar.class, GameItem.class, Friendship.class, GachaRecord.class
Melledy's avatar
Melledy committed
33
34
35
36
37
38
39
40
41
	};
    
    public static Datastore getDatastore() {
    	return datastore;
    }
    
    public static MongoDatabase getDatabase() {
    	return getDatastore().getDatabase();
    }
42

Benjamin Elsdon's avatar
Benjamin Elsdon committed
43
44
	// Yes. I very dislike this method. However, this will be good for now.
	// TODO: Add dispatch routes for player account management
45
	public static Datastore getAccountDatastore() {
46
		if(Grasscutter.getConfig().RunMode == ServerRunMode.GAME_ONLY) {
47
48
49
50
51
			return dispatchDatastore;
		} else {
			return datastore;
		}
	}
Melledy's avatar
Melledy committed
52
53
54
	
	public static void initialize() {
		// Initialize
55
		MongoClient mongoClient = MongoClients.create(Grasscutter.getConfig().DatabaseUrl);
Melledy's avatar
Melledy committed
56
		
KingRainbow44's avatar
KingRainbow44 committed
57
58
59
60
61
62
63
		// Set mapper options.
		MapperOptions mapperOptions = MapperOptions.builder()
				.storeEmpties(true).storeNulls(false).build();
		// Create data store.
		datastore = Morphia.createDatastore(mongoClient, Grasscutter.getConfig().DatabaseCollection, mapperOptions);
		// Map classes.
		datastore.getMapper().map(mappedClasses);
Melledy's avatar
Melledy committed
64
65
66
67
		
		// Ensure indexes
		try {
			datastore.ensureIndexes();
KingRainbow44's avatar
KingRainbow44 committed
68
69
		} catch (MongoCommandException exception) {
			Grasscutter.getLogger().info("Mongo index error: ", exception);
Melledy's avatar
Melledy committed
70
			// Duplicate index error
KingRainbow44's avatar
KingRainbow44 committed
71
			if (exception.getCode() == 85) {
Melledy's avatar
Melledy committed
72
73
74
75
76
77
78
79
80
				// Drop all indexes and re add them
				MongoIterable<String> collections = datastore.getDatabase().listCollectionNames();
				for (String name : collections) {
					datastore.getDatabase().getCollection(name).dropIndexes();
				}
				// Add back indexes
				datastore.ensureIndexes();
			}
		}
81

82
		if(Grasscutter.getConfig().RunMode == ServerRunMode.GAME_ONLY) {
83
84
			dispatchMongoClient = MongoClients.create(Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseUrl);
			dispatchDatastore = Morphia.createDatastore(dispatchMongoClient, Grasscutter.getConfig().getGameServerOptions().DispatchServerDatabaseCollection);
Benjamin Elsdon's avatar
Benjamin Elsdon committed
85
86
87

			// Ensure indexes for dispatch server
			try {
88
				dispatchDatastore.ensureIndexes();
Benjamin Elsdon's avatar
Benjamin Elsdon committed
89
90
91
92
93
94
95
96
97
98
99
100
			} catch (MongoCommandException e) {
				Grasscutter.getLogger().info("Mongo index error: ", e);
				// Duplicate index error
				if (e.getCode() == 85) {
					// Drop all indexes and re add them
					MongoIterable<String> collections = dispatchDatastore.getDatabase().listCollectionNames();
					for (String name : collections) {
						dispatchDatastore.getDatabase().getCollection(name).dropIndexes();
					}
					// Add back indexes
					dispatchDatastore.ensureIndexes();
				}
101
102
			}
		}
Melledy's avatar
Melledy committed
103
	}
KingRainbow44's avatar
KingRainbow44 committed
104

Melledy's avatar
Melledy committed
105
	public static synchronized int getNextId(Class<?> c) {
Miyucchi's avatar
Miyucchi committed
106
		DatabaseCounter counter = getDatastore().find(DatabaseCounter.class).filter(Filters.eq("_id", c.getSimpleName())).first();
Melledy's avatar
Melledy committed
107
108
109
110
111
112
113
114
115
		if (counter == null) {
			counter = new DatabaseCounter(c.getSimpleName());
		}
		try {
			return counter.getNextId();
		} finally {
			getDatastore().save(counter);
		}
	}
KingRainbow44's avatar
KingRainbow44 committed
116

Melledy's avatar
Melledy committed
117
118
119
120
	public static synchronized int getNextId(Object o) {
		return getNextId(o.getClass());
	}
}